Guten Abend,
Ich versuche gerade einen ws2811-LED-Stripe Anzusteuern und Stelle mich
dabei wohl etwas Glatt an.
Ich habe den Stripe an ein Altes PC-Netzteil angeschlossen und die Masse
mit meinem Board Verbunden. Auf dem Board befindet Sich ein ATmega8 der
mit einem Externen Quarz auf 8 MHz Getaktet ist.
Ich Verwende die light_ws2812 V2.2 LIB.
Die light_ws2812.h und light_ws2812.c in ein neues Projekt intigriert
und eine main.c angelegt.
Diese sieht so aus:
1
#define F_CPU 8000000
2
#include<util/delay.h>
3
#include<avr/io.h>
4
#include<avr/interrupt.h>
5
#include"light_ws2812.h"
6
7
structcRGBled[1];
8
9
intmain(void)
10
{
11
12
while(1)
13
{
14
led[0].r=255;led[0].g=00;led[0].b=0;// Write red to array
15
ws2812_setleds(led,1);
16
_delay_ms(500);// wait for 500ms.
17
18
led[0].r=0;led[0].g=255;led[0].b=0;// green
19
ws2812_setleds(led,1);
20
_delay_ms(500);
21
22
led[0].r=0;led[0].g=00;led[0].b=255;// blue
23
ws2812_setleds(led,1);
24
_delay_ms(500);
25
}
26
}
In der Config habe ich auf Port B 0 Gestellt und alles Entsprechend
verdrahtet.
Leider Flimmern die ersten 3 LED's nur Rot auf. Also kein brauchbares
Bild.
Wenn ich das Programm richtig verstanden müsste ja die erste LED einen
Farbwechsel im halb-sekundentakt machen.
Aber hier tut sich nix.
Könnt ihr mir helfen den Fehler zu finden?
>Auf dem Board befindet Sich ein ATmega8 der>mit einem Externen Quarz auf 8 MHz Getaktet ist.
Läuft der auch wirklich mit 8MHz?
Hast du das mal überprüft?
Als erstes würde ich mal
#define F_CPU 8000000
aus der main.c löschen. Das gehört da nicht hin.
>Könnt ihr mir helfen den Fehler zu finden?
Ohne ALLE Projektdateien kann man nur raten.
holger schrieb:> Ohne ALLE Projektdateien kann man nur raten.
Stimmt. Hier sind die Programme, die ich Unverändert eingebunden habe.
light_ws2812.c
https://github.com/cpldcpu/light_ws2812/blob/master/light_ws2812_AVR/Light_WS2812/light_ws2812.c
light_ws2812.h
https://github.com/cpldcpu/light_ws2812/blob/master/light_ws2812_AVR/Light_WS2812/light_ws2812.h
ws2812_config.h
https://github.com/cpldcpu/light_ws2812/blob/master/light_ws2812_AVR/ws2812_config.h
Wenn ich die Readme richtig verstanden habe muss ich die Codes nur in's
Projekt einbinden ohne diese zu bearbeiten, oder anzupassen. Lediglich
die Pinbelegung muss in die Config eingetragen werden. Richtig?
Die main.c wie oben gepostet soll ja nur die LED's ansteuern.
Ob der AVR auch wirklich mit 8 MHz arbeitet kann ich nicht wirklich
prüfen, da ich kein Oszi zur Hand habe. Zum Testen habe ich ein kleines
Blinkprogramm geschrieben, der eine LED im 500ms Takt Ein und Aus
schaltet. Das hat soweit funktioniert.
Ich muss auch dazu sagen, dass sich meine Programmiererischen Kenntnisse
in grenzen halten. Ich beschäftige mich schon länger mir µC's aber
leider aus diversen gründen nur auf halber Lunge. Die Entsprechende
Fachlitereatur, die mir zur verfügung steht beinhaltet auch immer nur
eine *.c und eine *.h File. Und bei der standen die Definitionen wie
z.B. F_CPU immer oben drin.
Ich denke auch nciht, dass das ein Problem darstellt. Sonst hätte der
Compiler schon gemeckert.
Ich will erstmal, dass es funktioniert. Auch wenn mich hier einige dafür
schlagen werden; schön Programmieren ist erstmal zweitrangig.
Zurück zu dem LED-Stripe. Ich bin etwas über das Verhalten der LED's
verwundert. Selbst, wenn ich die Datenleitung auf Masse Lege glimmen die
Ersten 3 LED's in Rot. Ich vermute fast, dass der Stripe selbst das
Problem ist. hat schon jemand erfahrungen damit gemacht?
>> Zurück zu dem LED-Stripe. Ich bin etwas über das Verhalten der LED's> verwundert. Selbst, wenn ich die Datenleitung auf Masse Lege glimmen die> Ersten 3 LED's in Rot. Ich vermute fast, dass der Stripe selbst das> Problem ist. hat schon jemand erfahrungen damit gemacht?
Dann Probier doch den Stripe mal solo und ohne uC aus. Direkt an
Spannung anlegen.
>Wenn ich die Readme richtig verstanden habe muss ich die Codes nur in's>Projekt einbinden ohne diese zu bearbeiten, oder anzupassen. Lediglich>die Pinbelegung muss in die Config eingetragen werden. Richtig?
Ja. Allerdings muss F_CPU auch passen. Hast du ja aber
mit deiner LED schon getestet.
>Ich bin etwas über das Verhalten der LED's>verwundert. Selbst, wenn ich die Datenleitung auf Masse Lege glimmen die>Ersten 3 LED's in Rot. Ich vermute fast, dass der Stripe selbst das>Problem ist. hat schon jemand erfahrungen damit gemacht?
Das hört sich nicht gut an. Die WS2812 sollen sehr empfindlich sein.
Bei Adafruit wird empfohlen vor die Taktleitung einen Reihenwiderstand
mit um die 300 Ohm zu legen und dazu noch einen Pulldown von 100k Ohm.
Auf meiner 8x8 Matrix Platine von Adafruit ist bereits ein 470 Ohm in
der Datenleitung der ersten LED. Den Pulldown hab ich da selber
noch drangebraten.
uC und Stripe sollten auch immer gleichzeitig Spannung bekommen.
Also nicht erst den uC einschalten und danach den Stripe.
Es könnte gut sein das da bereits die ersten LEDs defekt sind.
wurschtel schrieb:> Dann Probier doch den Stripe mal solo und ohne uC aus. Direkt an> Spannung anlegen.
Das habe ich schon Probiert. Auch dann Glimmen die ersten 3 LED'S.
Bin Kurz davor mal an der ersten Trennstelle den Stripe Zu Zerschneiden
und Die Kontakte von Dieser Trennstelle zu benutzen.
Wollte nur den Neuen Stripe nicht direkt Trennen.
Ich habe mich nochmal daran versucht hier ein Licht zum Leuchten zu
bringen.
Den Stripe habe ich an der ersten Trennstelle durchgeschnitten. habe
jetzt also zum probieren 3 LED's zur Verfügung. Hinter der Ersten
Trennstelle reagieren die LED's genauso wie vorher, also wird der Stripe
nicht das Problem sein.
Mein Code sieht gerade so aus:
1
/*
2
* WS2811.c
3
*
4
* Created: 03.01.2015 21:01:27
5
* Author: jack
6
*/
7
8
#include<util/delay.h>
9
#include<avr/io.h>
10
#include<avr/interrupt.h>
11
#include"light_ws2812.h"
12
13
structcRGBled[1];
14
15
intmain(void)
16
{
17
DDRB|=(1<<1);
18
PORTB|=(1<<1);
19
_delay_ms(1500);
20
while(1)
21
{
22
led[0].r=255;led[0].g=00;led[0].b=0;// Write red to array
23
ws2812_setleds(led,1);
24
_delay_ms(500);// wait for 500ms.
25
PORTB^=(1<<1);
26
led[0].r=0;led[0].g=255;led[0].b=0;// green
27
ws2812_setleds(led,1);
28
_delay_ms(500);
29
PORTB^=(1<<1);
30
31
led[0].r=0;led[0].g=00;led[0].b=255;// blue
32
ws2812_setleds(led,1);
33
_delay_ms(500);
34
PORTB^=(1<<1);
35
36
}
37
}
Die LED auf PortB.1 Blinkt fleißig vor sich hin.
Hin und wieder glimmen die ersten 3 LED's Simultan im takt auf.
Mein erster gedanke ist, dass das Timing nicht stimmt. Aber ich habe
gerade keine ahnung, wie ich das Prüfen kann.
Hatte mir neulich auch einen 50 led ws2811 stripe bestellt und nutze die
gleiche library. Bei mir ist die erste LED immer rot und die anderen
nehmen in 50% der Fälle eine Farbe an die ich nicht beabsichtigte.
Werde nal bei Gelegenheit versuchen zu beobachten ob die falschen Farben
wenigstens rreproduzierbar falsch sind.
Mir fallen grad 2 Dinge auf:
1) WS2811 != WS2812 !!!
2) 1.LED feste Farbe, rest bunt deutet häufig auf sowas wie "kein reset"
also hat dein Bus den falschen Pegel im Ruhezustand... Häufig!
Oder auch schon paar mal gehabt. Timing passt nicht, 1. LED kann noch
übermittelt werden, beim 4.Byte tritt ein Takt-fehler auf. Da stolpern
die LEDs sofort und die Farben purzeln...
Oszi oder LogicAnalyzer sind wohl nicht vorhanden oder?
Luigi schrieb:> 1) WS2811 != WS2812 !!!
Stimmt! Die ReadMe besagt folgendes:
> Light weight library to control WS2811/WS2812/WS2812B based LEDS and LED>Strings on 8-Bit AVR and ARM microcontrollers.Luigi schrieb:> 1.LED feste Farbe, rest bunt deutet häufig auf sowas wie "kein reset"> also hat dein Bus den falschen Pegel im Ruhezustand... Häufig! .....
Daran hatte ich auch gedacht. Kann das aber nicht wirklich prüfen, weil
mir die Messgeräte nicht zur verfügung stehen. Und die Blinkende LED bei
mir mit der Stoppuhr zu Testen ist nicht ganz Ziehlführend ;-D
Ich habe die Werte im Programm mal geändert auf:
1
while(1)
2
{
3
led[0].r=255;led[0].g=0;led[0].b=0;
4
ws2812_setleds(led,1);
5
_delay_ms(500);
6
7
led[0].r=128;led[0].g=0;led[0].b=0;
8
ws2812_setleds(led,1);
9
_delay_ms(500);
10
11
12
led[0].r=64;led[0].g=0;led[0].b=0;
13
ws2812_setleds(led,1);
14
_delay_ms(500);
15
16
}
Es ist auf Jeden fall eine sich im Takt ändernde Helligkeit
festzustellen. Allerdings kann man die Helligkeit bei 255 mit der einer
LowCurrent-LED vergleichen.
Das funktioniert aber auch nur bei Rot, Grün und Blau habe ich hier noch
nie gesehen. Und es Leuchten immer alle LED's Simultan und nicht nur
eine.
> 1) WS2811 != WS2812 !!!
Also wenn ich jetzt nicht ganz falsch liege (sorry bin am handy..)
nutzen TO und ich die library von
https://github.com/cpldcpu/light_ws2812
Die kann angeblich sowohl ws281 als auch ws2812
> 2) 1.LED feste Farbe, rest bunt deutet häufig auf sowas wie "kein reset"> also hat dein Bus den falschen Pegel im Ruhezustand... Häufig!> Oder auch schon paar mal gehabt. Timing passt nicht, 1. LED kann noch> übermittelt werden, beim 4.Byte tritt ein Takt-fehler auf. Da stolpern> die LEDs sofort und die Farben purzeln...
Da die erste ja immer rot ist, egal ob sie blau sein soll verstehr ich
das nicht ganz
> Oszi oder LogicAnalyzer sind wohl nicht vorhanden oder?
Bei mir leider noch nicht. Bin sozusagen noch im Aufbau
Irgendetwas stimmt mit Deiner Stromversorgung nicht. Rot benötigt die
geringste Spannung zum leuchten. Wenn an Deinem String deutlich weniger
als 5V anliegen, könnte man sich so einen Fehler vorstellen.
OK. Habe mich gerade nochmal durch die Datenblätter gewälzt. Ich habe
scheinbar wirklich zu wenig Spannung.
Ich glaube das bei meinem Stripe nicht die LED's einzeln angesteuert
werden, sondern immer in 3er Gruppen. Deswegen braucht der auch 12V.
Sobald ich zu hause bin werde ich das prüfen.
Danke für den Denkanstoß Tim.
Tim hatte recht. Nachdem ich die 12V Leitung meines Netzteils an den
Stripe angeschlossen habe Leuchteten auch die anderen Farben. Allerdings
nicht wie geplant.
Ich habe das Programm zum testen mal wie folgt umgeschrieben:
1
led[0].r=255;led[0].g=255;led[0].b=255;
2
led[1].r=0;led[1].g=0;led[1].b=0;
3
ws2812_setleds(led,1);
4
_delay_ms(500);
5
6
led[0].r=128;led[0].g=128;led[0].b=128;
7
led[1].r=128;led[1].g=128;led[1].b=128;
8
ws2812_setleds(led,1);
9
_delay_ms(500);
10
11
led[0].r=0;led[0].g=0;led[0].b=0;
12
led[1].r=255;led[1].g=255;led[1].b=255;
13
ws2812_setleds(led,1);
14
_delay_ms(500);
Bei der Ersten LED leuchtet die Blaue und Rote Konstant auf 255. Die
Grüne folgt den Befehlen aus dem Programm. Blau und Rot nehmen den
Ersten befehl an aber ignorieren alle weiteren.
Die Zweite LED bleibt aus.
Ich komme mit meinem Netzteil aber nur auf ca. 11,9V. Ist der controller
dabei schon so zickig, oder kann ich das ignorieren?
>Nachdem ich die 12V Leitung meines Netzteils an den
Stripe angeschlossen habe Leuchteten auch die anderen Farben.
Gut geraten :)
>ws2812_setleds(led,1);
Für zwei LEDs sollte hier natürlich eine 2 stehen.
Die Library ist von sich aus für den WS2811 high speed mode
konfiguriert. Unterstützt Dein Streifen diesen auch? Beim WS2811 gibt es
auch noch einen low-speed mode.
Außerdem kann es sein, dass die LED-Farben vertauscht sind.
>Ich komme mit meinem Netzteil aber nur auf ca. 11,9V. Ist der controller
dabei schon so zickig, oder kann ich das ignorieren?
Sollte eigentlich kein Problem sein. Der Controller benötigt nur 5V,
allerdings reichen die 5V eben nicht für drei LEDS in Serie.
So, habe mich inzwischen mal angemeldet.
Tim schrieb:> Gut geraten :)
Nix geraten, ich war einfach nur Blind. Auf dem Stripe steht auch 12V
drauf >.<
Tim schrieb:> Für zwei LEDs sollte hier natürlich eine 2 stehen.
Stimmt. mit einer 2 dahinten Leuchtet auch die 2te lampe. Allerdings
auch nicht, wie sie soll. Erst Nur Grün, dann kam Rot dazu und danach
Blau. Habe das Programm einfach laufen Lassen.
Ist irgentwo Dokumentiert, wie man diese Lib genau anwenden muss? Mit
meinen begrenzten kenntnissen kann ich mir aus dem Source-Code die
funktionsweise leider noch nicht herleiten. Die Lib ist inzwischen ja
ziemlich umnfangreich geworden.
Tim schrieb:> Die Library ist von sich aus für den WS2811 high speed mode> konfiguriert. Unterstützt Dein Streifen diesen auch? Beim WS2811 gibt es> auch noch einen low-speed mode.
Im Datenblatt steht, dass man Pin 7 vom Controller auf VDD legen muss um
auf Low-Spped zu configurieren. Ich habe mal die Silikonhülle vom Stripe
gezgen und gemessen. Pin 7 liegt bei mir auf GND. Dürfe also auch nicht
das Problem sein.
> Tim schrieb:>> Für zwei LEDs sollte hier natürlich eine 2 stehen.>> Stimmt. mit einer 2 dahinten Leuchtet auch die 2te lampe. Allerdings> auch nicht, wie sie soll. Erst Nur Grün, dann kam Rot dazu und danach> Blau. Habe das Programm einfach laufen Lassen.
Wahrscheinlich ist die Reihenfolge der Farben dann anders. Du kannst die
Reihenfolge der Farben im Headerfile ändern:
struct cRGB { uint8_t g; uint8_t r; uint8_t b; };
> Ist irgentwo Dokumentiert, wie man diese Lib genau anwenden muss? Mit> meinen begrenzten kenntnissen kann ich mir aus dem Source-Code die> funktionsweise leider noch nicht herleiten. Die Lib ist inzwischen ja> ziemlich umnfangreich geworden.>
Im Readme?
https://github.com/cpldcpu/light_ws2812
Und im Headerfile:
https://github.com/cpldcpu/light_ws2812/blob/master/light_ws2812_AVR/Light_WS2812/light_ws2812.h
jack schrieb:> beinhaltet auch immer nur> eine *.c und eine *.h File. Und bei der standen die Definitionen wie> z.B. F_CPU immer oben drin.
Schön.
Jetzt hast du es aber mit mehreren *.c Files zu tun und die müssen sich
darüber einig sein, welchen Wert F_CPU hat. Daher ist es keine gute Idee
F_CPU nur in ein *.c File zu schreiben. Denn dann wissen die anderen
nichts davon.
> Ich denke auch nciht, dass das ein Problem darstellt.
Doch, das tut es.
Denn die WS-Lib erzeugt ihr Timing mittels delays. Und dazu braucht es
den korrekten Wert von F_CPU
> Sonst hätte der> Compiler schon gemeckert.
Wenns nur so wäre.
Aber (aus heutiger Sicht muss man sagen: leider) tatsächlich ist es so,
dass die delay Routinen dann einfach von einem Wert von 1Mhz für F_CPU
ausgehen. WEnn dein µC also tatsächlich mit 8Mhz läuft stimmt das Timing
nicht.
-> F_CPU gehört in die Projekt-Optionen und muss dort den richtigen Wert
haben.
> Ich will erstmal, dass es funktioniert. Auch wenn mich hier einige dafür> schlagen werden; schön Programmieren ist erstmal zweitrangig.
Es geht nicht um schön. Es geht um korrekt.
Also: Was hast du mit F_CPU gemacht.
Dein Test mit einer blinkenden LED ist grundsätzlich ok. Wenn du eine
LED laut Programm alle 500ms umschalten lässt und das dann in der
Realität auch tatsächlich eine halbe Sekunde ist, dann stimmen deine
8Mhz. Die Alternative wäre 1Mhz und das erkennst du auch ohne Oszi mit
freiem Auge. Den Unterschied zwischen einer halben Sekunde und 4
Sekunden kann man auch so ganz gut erkennen.
Nur: Du musst dann auch bei F_CPU im Projekt die festgestellten 8Mhz
eintragen! Sonst stimmen die ganzen Timings im Programm nicht!
Tim schrieb:> Wahrscheinlich ist die Reihenfolge der Farben dann anders.
Stimmt, die hat nicht gestimmt. Aber die LED's leuchten immernoch nicht
so, wie im Programm. Dieses sieht gerade so aus:
1
uint8_tj=255;
2
3
while(1)
4
{
5
led[0].r=j;led[0].g=j;led[0].b=j;
6
led[1].r=j;led[1].g=j;led[1].b=j;
7
led[2].r=j;led[2].g=j;led[2].b=j;
8
ws2812_setleds(led,3);
9
PORTB|=(1<<1);
10
_delay_ms(1000);
11
12
led[0].r=0;led[0].g=0;led[0].b=0;
13
led[1].r=0;led[1].g=0;led[1].b=0;
14
led[2].r=0;led[2].g=0;led[2].b=0;
15
ws2812_setleds(led,3);
16
PORTB&=~(1<<1);
17
_delay_ms(1000);
18
19
}
Also eigentlich nur RGB an und aus im Sekundentakt. Und das für die
ersten 3 LED's. (In meinem fall die ersten 3 Cluster).
Und das ist, was Passiert: https://www.youtube.com/watch?v=qEHoNA7HDUk
@Karl Heinz
was du schreibst klingt völlig logisch. habe auch gestern in der ReadMe
den hinweis gesehen, dass F_CPU, wie du schon sagtest, in die Optionen
gehört und dem entsprechend auch in meinem Projekt so gemacht.
Das Timing stimmt auch. _delay_ms(1000); entsprechen auch wirklich einer
Sekunde. Habe auch zum Testen mal auf den internen Oszilator die Fuses
gestellt. Keine veränderung. Also wieder zurück auf den Quarz.
Was mich auch irritiert ist die Tatsache, dass wenn ich in meinem oben
geschriebenen Code die Variable j auf z.B. 50 oder 100 stelle Blinkt nur
der erste Cluster in sattem grün. Alles andere bleibt Dunkel.
Also das mutet schon sehr merkwürdig an. Allerdings hast Du auch einen
recht ungewöhnlichen Streifen.
- "Sieht" denn die library auch Dein F_CPU setting?
- Wird Dein AVR mit 5V betrieben? Ich hoffe, dass die 12V nicht andere
Pegel verlangen.
- Ist der Streifen auch an Port B angeschlossen?
Tim schrieb:> "Sieht" denn die library auch Dein F_CPU setting?
Ich weiß nicht wirklich, wie ich das Prüfen kann. Habe mich aber an die
Anweisungen aus der Readme gehalten. Im Atmel Studio 6.2 auf Project
->Properties->Toolchain->AVR/GNU C Compiler->Symbols. Add symbol ->
F_CPU=8000000
Dürfte also nicht das Problem sein. Aber vieleicht kann ich der lib auch
nochmal gesondert den takt zur Verfügung stellen. müsste nur wissen wie.
Tim schrieb:> Wird Dein AVR mit 5V betrieben? Ich hoffe, dass die 12V nicht andere> Pegel verlangen.
Der AVR wird Aktuell mit 4,99V direkt aus dem PC-Netzteil betrieben, an
dem auch der LED-Stripe mit Spannung versorgt wird.
Am Stripe kommen gerade 11,62V an. was für die Paar LED's auch erstmal
reichen sollte.
Tim schrieb:> Allerdings hast Du auch einen> recht ungewöhnlichen Streifen.
Ist mir auch schon aufgefallen. Aber der Treiber ist ein gewöhnlicher
WS2811. Mit dem unterschied, dass ein Chip 3 LED's pro Kanal bestromt
und nicht nur eine. Daher die 12V. Steht auch so im Datenblatt.
Tim schrieb:> Ist der Streifen auch an Port B angeschlossen?
Ja ist er. Der Stripe reagiert auch darauf, wenn ich das Programm
ändere. Wenn ich die Datenleitung falsch angeschlossen hätte, würde er
auch nicht reagieren.