RGB LED Steuerung (AVR)

Gast #920645
Lesenswert?

Hallo,

ich möchte eine RGB Led mit einem Atmega8 von meinem PC aus steuern.
Die Led hängt an den 3 PWM Pins des Atmega8.

Die Ansteuerung übernimmt ein Python Programm.
Das Python Programm zeigt eine Farbpalette und übermittelt via serielle 
Schnittstelle die RGB Daten an den Controller.

Die RGB Daten werden in Form von Hexadezimalzahlen (z.B. "FFE0F3") 
verschickt.
Die RGB Daten werden in R, G und B aufgesplittet und dann in einen 
Zahlenwert umgerechnet und den PWM Pins zugewiesen.
Bei "FFFFFF" würde dann Rot, Grün und Blau mit voller Leistung leuchten, 
da FF umgerechnet 255 darstellen.

Leider weiss ich gerade nicht mehr weiter.
Vielleicht seht ihr ja den Fehler oder kann mir eine andere Lösung 
vorschlagen.

Der Code befindet sich im Anhang.

Die Led blinkt sogar für einen sehr kurzen Moment auf (aber nur eine 
Farbe), aber geht dann sofort wieder aus.

Gruss,   Tymm
Angehängte Dateien:
#920760
Lesenswert?

1
  char r[2]; 
2
  char g[2];
3
  char b[2];
4
...
5
    r[0]=Line[0];
6
    r[1]=Line[1];
7
    g[0]=Line[2];
8
    g[1]=Line[3];
9
    b[0]=Line[4];
10
    b[1]=Line[5];
11
    
12
    // Die Hexadezimal Werte welche als char vorhanden sind umwandeln und zuweisen
13
    OCR1A = strtol(g,NULL,16);  
14
    OCR1B = strtol(b,NULL,16);
15
    OCR2 = strtol(r,NULL,16);

Bei den Strings in r, g und b fehlt die Null-Terminierung.
Gast #920902
Lesenswert?

Vielen Dank.
Habe den Code so erweitert:
1
        char r[3];
2
        char g[3];
3
        char b[3];
4
        r[2]='\0';
5
        b[2]='\0';
6
        g[2]='\0';

Bringt aber leider nichts. Die Led blitzt weiterhin nur kurz auf :(

Gruss,   Tymm
Gast #920993
Lesenswert?

@OP:
Werd' mal das '#include "uart.c"' los, das macht man nicht! (die 
.c-Dateien werden im Makefile/im AVR-Studio-Projekt eingetragen).

Bist du sicher, dass dein string vom PC mit "\n"-endet (Unter Windows 
wäre das eher "\r\n") ? (Als ersten Ansatz, mach mal "char Line[7]" zu 
"char Line[10]").

hth. Jörg
ps. Deine Timereinstellungen hab ich mir noch garnicht angeschaut
Gast #921032
Lesenswert?

@Jörg X. :
Ich benutze ausschließlich Linux. Von daher kein AVR Studio und Strings 
die ganz sicher mit \n enden (echo "FFFFFF" > /dev/ttyUSB0).
Danke für den Tipp mit den Makefiles.

Aber wieso Line[10]? Ich habe doch nur 7 Zeichen: "FFFFFF" (6 Zeichen) 
und ein "\0" (1 Zeichen).

Gruss,   Tymm
Gast #921094
Lesenswert?

>Ich benutze ausschließlich Linux.
hättest du evtl. andeuten können ...

Aber wie schon _Stefan Ernst (sternst)_ schrieb:
>> Überprüfe mal deine Timer-Konfiguration.
Die muss nämlich so (bzw. so ähnlich) aussehen:
1
  // Timer1 init 
2
  TCCR1A = (1<<WGM10)|(1<<COM1A1)|(1<<COM1B1);
3
  TCCR1B = (1<<CS10);
4

5
  // Timer2 init for PWM on Pin PB3 
6

7
  TCCR2 = (1<<WGM20) |(1<< CS20)|(1<<COM21);

Du brauchst zwar für eine LED nicht unbedingt drei Hardware 
PWM-Einheiten, aber das kannst du ja später noch ändern ;)

rtfm, Jörg
Gast #921339
Lesenswert?

Die serielle Kommunikation funktioniert, allerdings nicht wirklich gut 
wie ich gerade festgestellt habe.

Komischerweise kommen bei einem 'echo -n "Hallo" > /dev/ttyUSB0' die 
"Hallo"s häufiger vollständig zurück als bei einem 'echo "Hallo" > 
/dev/ttyUSB0'.
(echo -n gibt kein \n am Ende aus, echo ohne option schon)
In einem Terminal gibt es auch häufiger Aussetzer.

Am Atmega8 hängt ein 8Mhz Quarz und die Fuse Bits habe ich bei Low auf 
0xEE und bei High auf 0xD9.

Trotzdem glaube ich dass es nicht am UART liegt, weil irgendwann ja 
immer mal was ganz durchkommt.
In einem anderen Programm steuere ich die Led mit einzelnen Buchstaben 
('R' = Rot wird heller, 'r' = Rot wird dunkler usw.) und das 
funktioniert tadellos.

Langsam verzweifel ich...
Gast #921682
Lesenswert?

Es geht!

Es gab zwei Probleme:
1. Das Problem mit dem kurzen Aufleuchten habe ich gelöst indem ich 
bevor ich die empfangenen Daten verarbeite, abfrage ob es sich um 
hexadezimal Ziffern handelt (UART_NO_DATA funktionierte bei mir nicht).

2. Nachdem ich hinter das uart_gets per Zufall ein paar Befehle 
geschrieben hatte, wurde das UART aufeinmal stabiler.
Ich habe jetzt ein paar delays hinter dem uart_gets und vor der 
Verarbeitung der ankommenden Daten und es geht.

Ein Problem bleibt aber:
Wenn ich sehr schnell viele Farbcodes an den Atmega schicke, wird das 
UART anscheinend wieder instabiler und falsche Farben werden erzeugt.

Im Anhang befindet sich der funktionierende Code + Python Programm zur 
Ansteuerung.

Gruss,   Tymm
Angehängte Dateien:
#922682
Lesenswert?

@ tymm (Gast)

>2. Nachdem ich hinter das uart_gets per Zufall ein paar Befehle
>geschrieben hatte, wurde das UART aufeinmal stabiler.
>Ich habe jetzt ein paar delays hinter dem uart_gets und vor der
>Verarbeitung der ankommenden Daten und es geht.

AUA!

>Ein Problem bleibt aber:
>Wenn ich sehr schnell viele Farbcodes an den Atmega schicke, wird das
>UART anscheinend wieder instabiler und falsche Farben werden erzeugt.

Und das wundert dich?
Du bremmst deinen AVR TIERISCH aus, der muss nach jedem empfangenen 
String 5s! warten, ehe er wieder was machen darf. Da läuft garantiert 
ein Empfangsbuffer über. Solche delays sind totaler Mist.

MfG
Falk
Gast #922983
Lesenswert?

>Du bremmst deinen AVR TIERISCH aus, der muss nach jedem empfangenen
>String 5s! warten, ehe er wieder was machen darf. Da läuft garantiert
>ein Empfangsbuffer über. Solche delays sind totaler Mist.

Ein _delay_ms(1000) sind bei mir lange keine Sekunde, was wohl an 
falschen Einstellungen meinerseits liegt.
Kann auch sein das delays totaler Mist sind.
Ich bin Anfänger, ich habe keine Ahnung.
Ich weiss nur, dass ohne delays oder irgendetwas anderes was Zeit in 
Anspruch nimmt garnichts geht.

>Und das wundert dich?
Trotz der Gefahr noch ein "AUA!" zu kassieren und der Tatsache dass mein 
AVR keine 5s wartet: Mich wundert es schon ein bisschen.
Ich dachte Peter Fleury's UART Lib arbeitet mit Interrupts.
Und wenn ich das richtig verstanden habe, unterbrechen Interrupts das 
Hauptprogramm?

Gruss,   Tymm
Gast #923385
Lesenswert?

>Ein _delay_ms(1000) sind bei mir lange keine Sekunde
Ja, dann ist was mit der Taktfrequenz-Angabe faul.


Aus dem Programm:
1
/* define CPU frequency in Mhz here if not defined in Makefile */
2
#ifndef F_CPU
3
#define F_CPU 8000000L
4
#endif
trifft die erste Zeile zu?
1
if( (Line[0] == '0') | (Line[0] == '1') | (Line[0] == '2') | (Line[0] == '3') | (Line[0] == '4') | (Line[0] == '5') | (Line[0] == '6') | (Line[0] == '7') | (Line[0] == '8') | (Line[0] == '9') | (Line[0] == 'A') | (Line[0] == 'B') | (Line[0] == 'C') | (Line[0] == 'D') | (Line[0] == 'E') | (Line[0] == 'F'))
2
    {...
könnte auch so beschrieben werden:
1
if( (Line[0] >= '0' && Line[0] <= '9') || (Line[0] >= 'A' && (Line[0] <= 'F') )
2
    {...
Gast #923388
Lesenswert?

Dir ist schon klar, dass du mit
1
uart_gets(Line, sizeof(Line));
auch nur mal halbe Zeilen abholen könntest?

Die Funktion holt ab, was gerade im Puffer ist. Da wird nicht bis zum 
CR/LF gewartet. Und du machst keinerlei Plausibilitätsprüfungen, ob 
überhaupt ein ganzer String für deine Line[] gekommen ist.

Kein Wunder, dass längeres Warten dir da etwas hilft.
#923481
Lesenswert?

In der Tat. Ich war davon ausgegangen, dass uart_getc so lange wartet, 
bis auch tatsächlich ein Zeichen empfangen wurde. Ich habe mal einen 
Blick in die Dokumentation der Peter-Fleury-Uart-Lib geworfen, und dem 
ist nicht so.

@ tymm:
Du musst also deine uart_gets ändern. Z.B. uart_getc immer in einer 
Schleife so lange aufrufen, bis kein UART_NO_DATA mehr zurückkommt.
Gast #923516
Lesenswert?

Ja, da scheint mir die Implementierung von uart_gets() die möglichen 
Rückgabewerte von uart_getc() noch nicht richtig abzufangen:

Returns:
    lower byte: received byte from ringbuffer
    higher byte: last receive status
    * 0 successfully received data from UART
    * UART_NO_DATA
      no receive data available
    * UART_BUFFER_OVERFLOW
      Receive ringbuffer overflow. We are not reading the receive buffer
      fast enough, one or more received character have been dropped
    * UART_OVERRUN_ERROR
      Overrun condition by UART. A character already present in the
      UART UDR register was not read by the interrupt handler before
      the next character arrived, one or more received characters have
      been dropped.
    * UART_FRAME_ERROR
      Framing Error by UART

Aus:
http://homepage.hispeed.ch/peterfleury/group__pfleury__uart.html

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren