mikrocontroller.net

Forum: Compiler & IDEs RGB LED Steuerung (AVR)


Autor: tymm (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  char r[2]; 
  char g[2];
  char b[2];
...
    r[0]=Line[0];
    r[1]=Line[1];
    g[0]=Line[2];
    g[1]=Line[3];
    b[0]=Line[4];
    b[1]=Line[5];
    
    // Die Hexadezimal Werte welche als char vorhanden sind umwandeln und zuweisen
    OCR1A = strtol(g,NULL,16);  
    OCR1B = strtol(b,NULL,16);
    OCR2 = strtol(r,NULL,16);

Bei den Strings in r, g und b fehlt die Null-Terminierung.

Autor: tymm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank.
Habe den Code so erweitert:
        char r[3];
        char g[3];
        char b[3];
        r[2]='\0';
        b[2]='\0';
        g[2]='\0';

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

Gruss,   Tymm

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stackoverflow?

MW

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Überprüfe mal deine Timer-Konfiguration.
TCCR1A = (1<<WGM10)|(1<<COM1A1)|(1<<CS10)|(1<<COM1B1);
TCCR1B = (1<<CS10);
Ich glaube nämlich nicht, dass das Bit CS10 in beiden Registern ist.

Autor: tymm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Michael Wilhelm wo?

Du meinst in den Registern OCR1A, OCR1B und OCR2?
strtol liefert long int zurück.
Ich weiss jetzt nicht ob das ein Problem ist und wenn ja wie man es 
löst.

Gruss,   Tymm

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: tymm (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
  // Timer1 init 
  TCCR1A = (1<<WGM10)|(1<<COM1A1)|(1<<COM1B1);
  TCCR1B = (1<<CS10);

  // Timer2 init for PWM on Pin PB3 

  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

Autor: tymm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Überprüfe mal deine Timer-Konfiguration.
Danke, das eine |(1<<CS10) war zuviel.
Allerdings funktioniert PWM auch mit dem |(1<<CS10) zuviel.

Am PWM liegt es leider nicht...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert die serielle Kommunikation denn überhaupt?
Mach doch mal ein "echo" in das Programm, und schaue, was auf dem PC so 
zurückkommt. Also z.B. ein "uart_puts(Line);" nach dem uart_gets.

Autor: tymm (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: tymm (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: tymm (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: lkmiller (Gast)
Datum:

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


Aus dem Programm:
/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 8000000L
#endif
trifft die erste Zeile zu?
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'))
    {...
könnte auch so beschrieben werden:
if( (Line[0] >= '0' && Line[0] <= '9') || (Line[0] >= 'A' && (Line[0] <= 'F') )
    {...

Autor: lkmiller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dir ist schon klar, dass du mit
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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: lkmiller (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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__pfle...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.