Forum: Mikrocontroller und Digitale Elektronik PWM mit Eingangswert vom UART steuern


von Thore K. (koppernikus)


Angehängte Dateien:

Lesenswert?

Moin :)

Ich bin noch ein Anfänger auf dem Gebiet der AVR-Programmierung und 
komme jetzt schon ein paar Tage nicht mehr weiter.
Und zwar habe ich eine UART-Verbindung zwischen zwei ATmega328 
realisiert. Der erste Controller ließt über den ADC die Stellung eines 
Potis aus, und sendet einen Wert zwischen 0 - 255 an den zweiten 
Controller.
Dieser soll nun mit diesem Wert ein PWM Signal steuern. Also in das 
OCR1A Register einen Wert schreiben, der dem Eingangswert entspricht.
Anzeigen lassen will ich mir das über einen Servo, der an den OC1A Pin 
angeschlossen ist.
Der zweite Controller empfängt diesen Wert auch, allerdings bekomme ich 
es nicht hin, dass der Servo sich entsprechend meiner Eingabe bewegt.

Vielen Dank und Grüße aus Hamburg!

PS: Anbei ein Bild von meinem Code des Empfänger Controllers

von Falk B. (falk)


Lesenswert?

@Thore Kopper (koppernikus)

>Und zwar habe ich eine UART-Verbindung zwischen zwei ATmega328
>realisiert. Der erste Controller ließt über den ADC die Stellung eines
>Potis aus, und sendet einen Wert zwischen 0 - 255 an den zweiten
>Controller.

Warum? Das kann EIN Controller spielend und es wird auch einfacher.

>PS: Anbei ein Bild von meinem Code des Empfänger Controllers

Bitte? Schon mal dran gedacht, den QuellTEXT als solchen anzuhängen? Das 
wäre deutlich sinnvoller.

Trotzdem sieht das Programm OK aus. Du kannst indirekt mit einem 
Multimeter messen, ob dein Programm reagiert. Es zeigt die mittlere 
Ausgangsspannung an. Möglicherweise will das Servo keine 10ms 
Periodendauer sehen sondern eher 20ms.

von Löser (Gast)


Lesenswert?

Eingang == 0 statt Eingang = 0. Klassiker...

von Thore K. (koppernikus)


Lesenswert?

@Falk Brunner (falk)

> Warum? Das kann EIN Controller spielend und es wird auch einfacher.

Weil ich das später gerne seriell über funk (Bluetooth) übertragen will, 
wenn das so klappt, wie ich mir das vorstelle


> Bitte? Schon mal dran gedacht, den QuellTEXT als solchen anzuhängen? Das
> wäre deutlich sinnvoller.

Das tut mir leid. Das war mein erster Post in diesem Forum und ich 
dachte, dass wäre gängig.


> Eingang == 0 statt Eingang = 0. Klassiker...

Dankeschön für die schnellen Antworten! Habe ich leider übersehen. Davor 
habe ich es mit diversen Codes probiert, aber nie hat es geklappt.

Der Poti sitzt in einem Joystick (Analogstick von Konsolen Controller) 
und stellt sich selbst in seine Mittelstellung zurück. Nun würde ich 
gerne implementieren, dass ich den Stick zu einem Anschlag bewege und 
der Empfängercontroller eine Variable hochzählt, und mit dieser Variable 
einen entsprechenden Wert in das OCR1A Register schreibt.
Der Servo soll sich also nicht mehr Digital verhalten sondern frei 
einstellbar sein.

Mit folgendem Code habe ich dies versucht, allerdings fährt der Servo 
weiterhin bis zum Anschlag, egal wie kurz ich den Stick an den Anschlag 
bringe. Wird der "zaehler" so schnell hochgezählt, dass der Servo jedes 
mal schon ans Maximum gelangt? Und wenn ja, kann mir einer einen anstoß 
in die richtige Richtung geben, wie man das realisieren kann?


1
#define F_CPU 8000000UL
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include "UART.h"
6
7
uint8_t volatile eingang;
8
9
int main(void)
10
{  
11
  uint16_t zaehler = 0;
12
  
13
  DDRB |= (1 << PB1);
14
  
15
  UART_INIT();
16
  
17
  TCCR1A |= (1 << COM1A1) | (1 << WGM11);               //PWM einstellung          
18
  TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS11); //PWM einstellung          
19
20
  ICR1 = 9999;
21
  sei();
22
  
23
  while (1)
24
  {  
25
    //
26
    if (eingang > 150 && zaehler < 60000)
27
    {
28
      zaehler += 1;
29
    }
30
    
31
    if (eingang < 120 && zaehler > 0)
32
    {
33
      zaehler -= 1;      
34
    }
35
    
36
    OCR1A = zaehler / 60000 * 1000 + 1000;
37
  }
38
}
39
40
ISR(USART_RX_vect)
41
{
42
  eingang = UDR0;
43
  UDR0 = eingang;
44
}




Viele Grüße und dankeschön.

von Karl M. (Gast)


Lesenswert?

Hallo,

bitte denke stark darüber nach, was hier real heraus kommt!
1
OCR1A = zaehler / 60000 * 1000 + 1000;
Sicher nicht, dass was Du erwartest.
Eher:
1
OCR1A = zaehler / 34560 + 1000;

von Thore K. (koppernikus)


Lesenswert?

Moin,

ich möchte einen Wert zwischen 1000 und 2000 bekommen.
So wie ich das rechne komme ich damit ganz gut hin.

Wenn "zeahler" bei 60.000 steht möchte ich einen Wert von 2000 und wenn 
"zaehler" bei 0 steht möchte ich einen wert von 1000 haben.

30.000 / 60.000 = 0,5

0,5 * 1000 = 500

500 + 1000 = 1500

1500 will ich auch haben, wenn der "zaehler" die mitte erreicht hat.
Also so wie ich das sehe stimmt das, oder ich stehe komplett auf dem 
Schlauch.

Wie kommst du auf die 34560?

von Karl M. (Gast)


Lesenswert?

Thore K. schrieb:
> Wie kommst du auf die 34560?

Das ist das "Geheimnis" der Programmierung mit 16 Bit Variablen und 
nennt sich Integer Arithmetik.

Positive ganze Zahlen lassen sind in 16 Bit nur von 0 bis 2^16-1 
abbilden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.