Hallo zusammen,
da mir die bisherigen Ansätze zur Ansteuerung der WS2812 RGB-LEDS zu
umständlich (Timergefrickel), zu speziell (Arduino, 100% ASM, C++) oder
zu groß waren, habe ich noch einmal von vorne angefangen.
Bisher sieht es recht vielversprechend aus. Mit einem reinen
Bitbanging-Ansatz lassen sich auch auf einem 8MHz AVR ohne
Loop-Unrolling die notwendigen Timings erreichen. Die compilierte
C-Routine ist bisher gerade einmal 34 bytes groß.
Bisher habe ich nur an einer einzelnen LED testen können. Hat jemand
Lust, den Code auch einmal an einem LED-Streifen zu testen?
Die Nutzung ist ziemlich einfach:
- AVR auf 8Mhz konfigurieren. Sollte auf allen außer XMEGA und Attiny
4/5/9/10/20/40 laufen.
- Code mit Optimierungen compilieren (Mind. -O1)
- Portaddresse und Pin in die Defines eintragen.
- Der Routine eine Addresse auf ein Farb-Array (3 Bytes pro LED,
Reihenfolge GRB) sowie die Länge des Arrays übergeben.
- Nach jedem Update mindesten 50µs warten.
Ich habe vor, das ganze als Library zu verpacken und auch noch an andere
Taktgeschwindigkeiten anzupassen.
1
/*
2
Timing optimized for 8Mhz AVR (excl. XMEGA and reduced instruction set)
3
4
The total length of each bit is 1.25µs (10 cycles @ 8Mhz)
5
* At 0µs the dataline is pulled high. (cycle 4)
6
* To send a zero the dataline is pulled low after 0.375µs (4+3=7 cycles).
7
* To send a one the dataline is pulled low after 0.625µs (4+5=9 cycles).
8
9
10 cycles can not be reached without loop unrolling, or by using byte
10
writes to the ports. However since critical the timing between the rising and
11
falling edge is correct, it seems to be acceptable to slightly increase
12
bit timing
13
14
Final timing:
15
* 11 cycles for bits 7-1
16
* 17 cycles for bit 0
17
*/
18
19
#define ws2812_port 0x18 // Number of the data port register
20
#define ws2812_pin 4 // Number of the data out pin
Hier übrigens die inner-loop mit Taktzyklen. Etwas frickelig war die
unterschiedliche Laufzeit der Sprungbefehle. So wie es jetzt
implementiert ist, heben sich die Verzögerungen beider Befehle
gegenseitig auf.
Bei 8Mhz funktioniert das ganze nur, weil die Dauer der "Low" Periode
anscheinend relativ unkritisch ist. Theoretisch könnte man durch
Loop-Unrolling das Timing auch vollständig korrekt umsetzen können -
aber so lange das nicht notwendig ist...
[code]
" ldi %0,8 \n\t" // 0
"loop%=:lsl %1 \n\t" // 1 Datenbit ins Carry
" dec %0 \n\t" // 2 Schleifenzähler in Z-Flag
" sbi %2, %3 \n\t" // 4
" brcs .+2 \n\t" // 5l / 6h
" cbi %2, %3 \n\t" // 7l / - Überspringen bei C=1
// 7l / 6h
" brcc .+2 \n\t" // 9l / 7h
" cbi %2, %3 \n\t" // - / 9h Überspringen bei C=0
" brne loop%= \n\t" // 11 loop /10nt Weiter, wenn Z=1
[code]
Die Routine funktioniert bei mir mit 12 Leds einwandfrei, danke dafür!
Ich finde diesen Ansatz ohne Timer ganz praktisch (vor allem, wenn nur
wenige Leds gesteuert werden sollen).
Ich habe deine Funktion auf 16MHz 'verlängert', vielleicht kanns ja
jemand brauchen. Diese wurde ebenfalls an 12 Leds getestet.
1
#define ws2812_port 0x18 // Number of the data port register
2
#define ws2812_pin 4 // Number of the data out pin
Hallo Matthias,
freut mich, dass die Routine für Dich nützlich ist und auch mit mehr als
einer LED funktioniert. Das hat mich glatt motiviert, den aktuellen
Stand der Library zu veröffentlichen. Ich habe in der Zwischenzeit den
Code auch noch für eine Reihe anderer Taktgeschwindigkeiten angepasst.
Download hier:
https://github.com/cpldcpu/light_ws2812/tree/master/light_ws2812
1
light_ws2812
2
============
3
4
Light wight library to control WS2811/WS2812 based LEDS and LED Strings for 8-Bit AVR microcontrollers.
5
6
7
8
Description
9
===========
10
11
This is a small Ansi-C library to control WS2811/WS2812 based RGB Leds and strings. Only the 800kHz
12
high-speed mode is supported. This library uses a bit-banging approach with cycle optimized assembler
13
innerloops. Some advantages of this approach compared to existing solutions are:
14
15
* Compatible to all AVR MCUs since it does not rely on special periphery.
16
* Low hardware footprint: Does not rely on any timer or the USI
17
* Low software footprint: Size optimized assembler without unrolled loops (<50 bytes in most cases)
18
* No configuration needed
19
* Supports reduced core AVR such as Attiny 4/5/9/10
20
* Arduino or C++ not required
21
22
A disadvantage of this approach is that the code has to be hand optimized for each cpu clock. However,
23
a number of different routines are provided with support cpu clocks from 8Mhz to 16Mhz (standard AVR)
24
or 4MHz to 8Mhz (reduced core).
25
26
Usage
27
=====
28
29
- Add "light_ws2812.c" and "light_ws2812.h" to your project
30
- Change ws2812_port and ws2812_pin in the include file according to the I/O pin you are using.
31
- Uncomment the #define appropiate for your CPU core and clock settings. If you exact clock is
32
not supported, try a higher or lower clock setting. The WS2811 controller chip is tolerant to
33
some timing inaccuracy.
34
- Please use at least optimizations settings -O1 to compile.
35
36
A simple example is provided as "test_rgb_blinky.c"
37
38
Release History
39
================
40
41
v0.3 2013/05/06 - Initial release
42
43
Please find updates on https://github.com/cpldcpu/light_ws2812
Ein paar Anmerkungen:
- Was spricht gegen dirketes schreiben auf die Ports? Damit kann das
Timing ab 8 Mhz ohne Loop-unrolling eingehalten werden
(Beitrag "Re: C komisches Verhalten"). PWM-Ausgänge und
andere Peripherie wird durch die Port-Register nicht beeinflusst.
Interrupts müssen sowieso gesperrt werden. Ich sehe keinen Nachteil
dabei. Mit dem direkten Schreiben könntest du deine Lib wahrscheinlich
allgmein noch etwas optimieren.
- mehrere nops kann man zusammenfassen um Speicherplatz zu sparen :
2xnop = rjmp .+2
3xnop = lpm (wobei r0 zerstört wird)
Hallo Fallobst,
vielen Dank für die Anmerkungen! Ich habe, basierend auf Deinem Input,
gleiche eine v0.4 erstellt.
- Code durch rjmp verkürzt.
- Die Interrupts werden jetzt optional gesperrt.
Direktes Schreiben habe ich allerdings noch nicht implementiert. Ein
Nachteil ist nämlich längerer Code und die Benutzung von mehr Registern.
Bis 8Mhz funktioniert es noch ohne, auch ohne Loop-Unrolling. Auf den
reduced core AVR benötigen CBI/SBI nur einen Taktzyklus, so dass man
dort generell keinen Vorteil hat. Direktes Schreiben hilft m.E. nur bei
<8Mhz auf den normalen Cores. Dafür werde ich bei Gelegenheit noch eine
Routine implementieren...
Ich habe noch einen Bug im Timing gefunden, der sich durch die
Optimierungen mit eingeschlichen hatte. Interessanterweise hat der Code
trotzdem funktioniert...
v0.5 jetzt hoffentlich wieder fehlerfrei:
https://github.com/cpldcpu/light_ws2812/tree/master/light_ws2812
Ich habe eben v0.6 hochgeladen. Die neue Version unterstützt beliebige
Pins auf einem Port durch Bitmasken. Außerdem wird jetzt 4 Mhz auch auf
den normalen AVRs unterstützt.
https://github.com/cpldcpu/light_ws2812
1
- Major update: Changed all port accesses from SBI/CBI to OUT. This removes
2
a timing inconsistency between reduced core AVR and standard AVR,
3
avoiding separate implementations for different cores. A disadvantage is
4
increased register usage.
5
- Added a "ws2813_sendarray_mask" function which allows to pass a bitmask
6
for the selected port. This allows controlling up to 8 independent LED
7
strips.
8
- Removed functions for interrupt handling. Avoiding interference with
9
interruprs is now up to the user.
10
- 4 MHz clock speed is now also supported for standard core AVRs.
In den Teilen für 8MHz und 12MHz ist ein kleiner Fehler:
Zeile 138 " brvs exit%= \n\t" // 14
und
Zeile 191 " brvs exit%= \n\t" // 11
nicht "brvs" sondern "brcs"
Das Carry-Flag abfrage nicht Overflow.
So benötigt ein Durchlauf 1/2s.
Übrigens geht auch die 9,6MHz-Variante bei 8MHz.
Super Arbeit, hat mir viel Zeit gespart.
>Übrigens geht auch die 9,6MHz-Variante bei 8MHz.
Ja, es gehen so einige Dinge, die laut Datenblatt nicht erlaubt sind :)
Aber es kann ja immer sein, dass man mal eine Bauteilecharge erwischt,
die etwas weniger tolerant ist. Die v0.8 schafft es immerhin jetzt für
alle Taktgeschwindigkeiten das Timing nach Datenblatt einzuhalten. Das
ist bei den meisten anderen Lösungen nicht so (FastSPI-lib etc.)
Hi Nils,
freut mich dass es so gut klappt!
Man kann evtl. recht einfach überprüfen, ob es am Strom liegt: Reduziere
doch einfach mal die Anzahl der angeschalteten LEDS und die Helligkeit.
Wenn Du dann mehr ansteuern kannst ist die Situation relativ klar. Eine
LED zieht bei voller Helligkeit ca 60mA. Pro USB Port sind da eigentlich
nicht mehr als 10 LEDs drin...
Ansonsten würde ich auch defekte LEDS nicht komplett ausschließen.
(Damit hatte ich bei meinen handgelöteten Strips zu kämpfen.)
Liegt wohl am Strom.
Der 4m Stripe (240 LEDs!) geht, wenn ich z.B. eine LED durchlaufen
lasse.
Muss aber fürs Schreiben auf die LEDs die Interrupts sperren, sonst hab
ich Disco...
Nils Nachname schrieb:> Muss aber fürs Schreiben auf die LEDs die Interrupts sperren, sonst hab> ich Disco...
Wenn du dir das Sperren nicht leisten willst, ist es vllt. besser den
Library Aufruf selbst in einen (Timer?)Interrupt zu tun. Dann ist sicher
gestellt, das er nicht unterbrochen wird und Sperren ist unnötig.
Ich habe es mit meinem 4m String auch getestet: Bei niedrigster
Helligkeit (RGB= {0,0,1}) kann man mit einem USB Port den ganzen
Streifen mit 240 LEDs betreiben. Bei voller Helligkeit ist nach ca 20
LEDs Schluss.
Das man Interrupts während des Sendens verhindern muss sollte eigentlich
klar sein. Etwas "professioneller" geht es mit <util/atomic.h>. Der
erzeugte Code ist am Ende jedoch der gleiche wie im Beispiel von Nils.
Matthias Sch. schrieb:
[...]
> Wenn du dir das Sperren nicht leisten willst, ist es vllt. besser den> Library Aufruf selbst in einen (Timer?)Interrupt zu tun. Dann ist sicher> gestellt, das er nicht unterbrochen wird und Sperren ist unnötig.
Für einen Timerinterrupt ist mir das Senden dann doch zu viel/lang bei
240 LEDs.
Obwohl ich gerade gar nicht genau weiß, wie lang es eigentlich dauert.
Aber die 4m waren auch nur zum Testen der LEDs... obwohl... man weiß ja
nie. ;-)
Sehr schön :-) Das gefällt mir deutlich besser als die FastSPI des
Arduino.
Nur: vielleicht sollte man den Thread in die Codesammlung schieben, dort
findet man Codestücke besser.
Peter K. schrieb:> Bei mir zeigt es an: expected ; before led_buffer. Mein Code:> led_buffer[0].green = 255
Ja logisch, denn dieser Zeile fehlt zum Schluss ein Semikolon ;-)
Peter K. schrieb:> mache, blitzt die Led nur alle 500 ms auf und geht gleich wieder aus.
* Stimmt die CPU Taktgeschwindigkeit? Ist in WS2812.h das richtige
Define gesetzt?
* Hat die LED einen Bypasskondensator? (Die WS2812 sind teilweise
ziemlich empfindlich)
Tim . schrieb:> Peter K. schrieb:>> mache, blitzt die Led nur alle 500 ms auf und geht gleich wieder aus.>> * Stimmt die CPU Taktgeschwindigkeit? Ist in WS2812.h das richtige> Define gesetzt?
ja, das ist schon OK. Das passiert nur, wenn alle Werter gleich sind.
> * Hat die LED einen Bypasskondensator? (Die WS2812 sind teilweise> ziemlich empfindlich)
Du meinst nen 100n? Mal probieren.
OK, es liegt tatsächlich daran. Ich hab verbotenerweise auch an den
Mega8 kein 100n dran. Bitte jetzt nicht hauen.
Mal eine Frage zur Helligkeitseinstellung, auch wenn es hier etwas
Offtopic ist.
Da die LEDs ja RGB Daten erwarten, müsste ich vermutlich für eine
saubere Helligkeitsänderung ohne Farbwertänderung einen anderen Farbraum
als Zwischenschritt verwenden, oder wie macht ihr das?
HSV oder L*a*b* wären da vermutlich geeignet, aber evtl. etwas
rechenaufwändig?
Gerne geschehen ;-)
Noch ein kleiner Hinweis: In der geposteten Version habe ich die weiter
oben schon einmal erwähnte Interrupt-Sperre vergessen. Dadurch kommt es
( sehr selten ) zu einem flackern. Wer das verhinder will, solte also
"cli() und sei() " um die Sendefunktion bauen.
Servus,
versuche gerade den Code zu verstehen. Beschäftige mich nicht mit AVRs,
will aber so eine Lib für PICs machen.
Vielleicht könnte einer den Assembler Code etwas kommentieren, damit
man's einfacher versteht?
Danke!
Martin S. schrieb:> versuche gerade den Code zu verstehen. Beschäftige mich nicht mit AVRs,> will aber so eine Lib für PICs machen.>> Vielleicht könnte einer den Assembler Code etwas kommentieren, damit> man's einfacher versteht?
Ich habe einen Wiki-Artikel zur WS2812 Ansteuerung geschrieben.
Vielleicht hilft er Dir weiter...
https://www.mikrocontroller.net/articles/WS2812_Ansteuerung
Hey Leute,
ich nutze o.g. Lib. Bis 100 LEDs klappt alles super, danach gibts aber
(gerade bei unterschiedlichen Farben je LED) Probleme. LEDs hinter
nummer 100 werden nicht mehr angesprochen. Verwende nen Atmega328 mit 16
Mhz. Mit der Adafruit Lib klappt alles.
Jemand ähnliche Probleme?
Viele Grüße
Komische Sache, da so etwas nicht durch Timing-Probleme erklärt werden
kann. Bei mir hat es mit einem kompletten Streifen (240 LEDs) Problemlos
funktioniert. Ein paar Fragen:
- Welche Taktgeschwindigkeit hat die CPU? Ist die in der Lib richtig
gesetzt?
- Hat Dein String eine ausreichende Stromversorgung? Probiere doch
einmal den String mit schwacher Intensität zu beschreiben. Wenn es dann
geht, wird es an der Stromversorgung liegen.
- Die Lib sperrt im Gegensatz zur Neopixel lib keine Interrupts. Nutzt
Du intererupts? Funktioniert es, wenn Du diese manuell sperrst? (sei(),
cli())
Hallo Tim,
danke für deine schnelle Antwort. Ich habe das Problem jetzt mal etwas
weiter untersucht und isoliert, vielleicht finden wir so besser eine
Lösung bzw. den Fehler in der Lib (falls es einen gibt).
> - Welche Taktgeschwindigkeit hat die CPU? Ist die in der Lib richtig> gesetzt?
Die CPU läuft auf 16 Mhz. Es ist ein ArduinoNano Klon. Ich verwende die
Routine die mittels "ws2812_16MHz" aktiviert wird.
> - Hat Dein String eine ausreichende Stromversorgung? Probiere doch> einmal den String mit schwacher Intensität zu beschreiben. Wenn es dann> geht, wird es an der Stromversorgung liegen.
Das Netzteil ist recht kräftig. Der Fehler besteht aber unabhängig von
der Intensität.
(Details siehe unten)
> - Die Lib sperrt im Gegensatz zur Neopixel lib keine Interrupts. Nutzt> Du intererupts? Funktioniert es, wenn Du diese manuell sperrst? (sei(),> cli())
Nein ich nutze in diesem Code keine Interrupts. Habe sie aber auch
sicherheitshalber
gesperrt.
Ich habe mal einen minimal Code zum testen geschrieben. Dieser lässt
alle LEDs ausgeschaltet und schaltet genau eine (an TARGET_POS) an. Wenn
TARGET_POS <= 85 ist, funktioniert alles wie zu erwarten. Wenn
TARGET_POS > 85 ist, dann bleibt die entsprechende LED dunkel. Dafür
geht eine LED am Anfang des Stripes (in einer anderen Farbe) an.
Ich habe mit genau den gleichen Rahmenbedingungen die NeoPixel Library
getestet und es gehen alle Positionen problemlos. Vielleicht doch ein
Timing Problem? Oder irgendwelche Störungen? Ist die NeoPixel library so
viel robuster umgesetzt?
Hallo Tim,
vielen Dank für deine Hilfe.
Tim . schrieb im Beitrag #3312722:
> das sieht soweit alles ok aus. Allerdings werden interrupts mit sei()> gesperrt und mit cli() wieder freigegeben. Außerdem solltest Du nach dem> Aufruf von ws2812_sendarray 50us warten. Vielleicht geht es dann?
Habe den Code gerade noch einmal angepasst mit cli() statt sei().
Weiterhin gleiches
Verhalten. Nach dem ws2812_sendarray Befehl wechselt mein Testprogramm
in
eine leere while(True) Schleife, daher warte ich deutlich länger als
50us ;-).
Interrupts kommen definitiv nicht vor. Sehr seltsam alles.
Tim . schrieb im Beitrag #3312722:
> Dein Fehler klingt, als wenn die Ausführung des calls> nach einer gewissen Zeit einfach kurz unterbrochen wird, so dass die> WS2812 resetten.
Genau. Bis 85 klappt alles. Sobald es dann 86 sind, wird mitten zwischen
zwei bytes resettet, was dazu führt das eine LED weiter vorne (mit
"falscher" Farbe) angeht. Mein Testcode ist maximal einfach, aber
trotzdem klappt es nicht. Mit NeoPixel Lib alles wie gewünscht. Komisch
komisch...
Hi Phillip,
eigentlich sieht das alles ok aus. Einen Timingfehler kann ich mir kaum
vorstellen, da das Signal in den LEDs regeneriert wird. Wenn die Erste
LED funktioniert, sollte es mit allen klappen. Der Fehler, den Du
beschreibst klingt so, als wenn der String während des Schreibens
resetted wird. Das kann passieren wenn der Prozessor kurz hängt.
Hast Du die LEDs vor dem schreiben zurückgesetzt? (Pin auf low, 50us
warten). Passiert der gleiche Fehler, wenn Du zweimal schreibst?
> Habe den Code gerade noch einmal angepasst mit cli() statt sei().> Weiterhin gleiches> Verhalten. Nach dem ws2812_sendarray Befehl wechselt mein Testprogramm> in> eine leere while(True) Schleife, daher warte ich deutlich länger als> 50us ;-).>> Interrupts kommen definitiv nicht vor. Sehr seltsam alles.
Ok, da warst Du schneller :) Auf dem AVR werden interrupts mit cli()
gesperrt. Ich hatte das verwechselt, da es auf dem 6502 genau anders
herum ist. Warum auch immer.
Das liegt m.E. an einem Überlauf. 85 LEDs mal 3 Farben ergeben genau 255
Byte, die in der Reichweite eines 8-Bit Pointers liegen. Ab der 86.
kommt der da nicht mehr mit.
Icke ®. schrieb:> Das liegt m.E. an einem Überlauf. 85 LEDs mal 3 Farben ergeben genau 255> Byte, die in der Reichweite eines 8-Bit Pointers liegen. Ab der 86.> kommt der da nicht mehr mit.
Du hast recht. Es ist auch ganz klar, warum:
1
uint8_tbufPos=3*TARGET_POS;
2
buf[bufPos]=0;
3
buf[bufPos+1]=0;
4
buf[bufPos+2]=255;
Richtig wäre:
1
uint16_tbufPos...
Eigentlich müsste der Compiler da auch eine Warnung ausgeben?!
Tim . schrieb:> Auf dem AVR werden interrupts mit cli() gesperrt.> Ich hatte das verwechselt, da es auf dem 6502 genau anders> herum ist. Warum auch immer.
SEI und CLI setzen bzw. löschen beim AVR das Interrupt-Enable-Flag und
beim 6502 das Interrupt-Disable-Flag. Deshalb wirken sie genau
entgegengesetzt.
Icke ®. schrieb:> Das liegt m.E. an einem Überlauf. 85 LEDs mal 3 Farben ergeben genau 255> Byte, die in der Reichweite eines 8-Bit Pointers liegen. Ab der 86.> kommt der da nicht mehr mit.
Super. Tausend Dank für den Hinweis. Unglaublich wie blind man manchmal
ist. Habe auf uint16_t umgestellt und nun läuft es wie gewünscht.
Vielen Dank auch Tim für deine Mühe bei der Fehlersuche und die tolle
Library. Nun kann der LED Spaß losgehen ;-)
Viele Grüße,
Erlang
Philipp E. schrieb:> Unglaublich wie blind man manchmal ist.
Manchmal sieht man halt den Wald vor lauter Bäume nicht, da muß erst ein
Spaziergänger des Weges kommen ;-)
Die Lib finde ich auch Klasse. Muß man erst mal drauf kommen, das
Datenbit ins Carry zu shiften.. genial.
Tim . schrieb:> Ich frage mich jetzt nur, warum der Fehler bei der Neopixel-Lib nicht> aufgetreten ist? Dann war der code wohl doch nicht der gleiche...
Bei der NeoPixel Lib ist der Buffer ja bereits in der Lib drin, daher
habe ich die manuelle Verwaltung von Position im Buffer, etc. dort nicht
benötigt. Dort habe ich die
Methode strip.setPixelColor(...) verwendet und die Position entsprechend
übergeben.
Viele Grüße und nochmals vielen Dank
Martin S. schrieb:> Vielleicht könnte einer den Assembler Code etwas kommentieren, damit> man's einfacher versteht?
Ich war mal so frech, im Rahmen meiner Möglichkeiten die Routine in
reinem Assemblercode nachzuempfinden. Geeignet ist er für ATmega8,
ATmega16, diverse ATtinys sowie weitere kompatible AVRs bei 16 MHz
Takt. Auf Optimierungen habe ich bewußt verzichtet, da es mir mit den
NOPs übersichtlicher erscheint. Die Länge der RGB-Tabelle wird 16-bittig
ausgewertet, sodaß theoretisch bis zu 21845 LEDs damit abgeklappert
werden können. Praktisch ist die Anzahl jedoch durch den zur Verfügung
stehenden RAM und andere Gegebenheiten begrenzt. Der Code muß natürlich
noch an die tatsächlich verwendete Hardware angepaßt werden, also die
CPU-spezifische Lib inkludieren sowie Port, Pin und Anzahl der LEDs
definieren. Das Y-Register ist durch ein beliebiges anderes Registerpaar
ersetzbar. Für das Befüllen der RGB-Tabelle darf jeder seiner Phantasie
freien Lauf oder es dem Zufall über-lassen.
Testen konnte ich leider nur auf einem 60 LED langen Stripe, was
längeres habe ich nicht am Lager.
Wenn jemand Fehler findet oder Ideen hat, wie man das besser machen
kann, bitte posten. Den Code-Virtuosen hier fällt bestimmt noch was
ein...
1
;Assembler-Routine für Atmega8, Atmega16 und weitere kompatible AVRs
2
;zum Ansteuern der RGB-LED WS2812 per Bit-Banging
3
;für 16 MHz Taktfrequenz ausgelegt
4
;nur die Senderoutine enthalten, das Füllen der RGB-Tabelle erfordert weiteren Code
5
;diverse Anpassungen an die Hardware (Port,Pin,Anzahl LEDs) sind im Header vorzunehmen
6
7
8
.EQU crystal = 16000000 ;Systemtakt in Hz
9
10
.DEF temp = r16 ;temporäres Register
11
.DEF loopcounter = r17 ;Schleifenzähler
12
13
;Hier Port und Pin festlegen, an denen die WS2812 angeschlossen ist:
14
.EQU led_port = PORTx ;WS2812 relevantes PORT Register
15
.EQU led_ddr = DDRx ;WS2812 relevantes Data Direction Register
16
.EQU led_pin = PDx ;WS2812 relevanter I/O Pin
17
18
;Hier die Anzahl der LEDs festlegen (theoretisch bis 21845)
19
.EQU rgb_count = x ;Anzahl der LEDs
20
21
22
.DSEG
23
rgb_table: .BYTE rgb_count*3 ;RGB Tabelle im RAM anlegen
24
25
26
.CSEG
27
.ORG 0x0000
28
29
rgb_length: .DW rgb_count*3 ;Länge der RGB Tabelle (16-Bit)
30
31
rjmp main ;springe zum Hauptprogramm
32
33
34
send_array:
35
ldi ZL,LOW(rgb_table) ;lade die Adresse der RGB-Tabelle in den Z-Pointer
36
ldi ZH,HIGH(rgb_table)
37
outer_loop:
38
ld temp,Z+ ;lade nächstes Datenbyte
39
ldi loopcounter,8 ;setze Schleifenzähler
40
inner_loop:
41
lsl temp ;schiebe nächstes Datenbit ins Carry
42
dec loopcounter ;dekrementiere Schleifenzähler
43
sbi led_port,led_pin ;Datenleitung auf H schalten
44
nop
45
nop
46
brcs PC+2 ;überspringe nächsten Befehl wenn Datenbit = 1
47
cbi led_port,led_pin ;Datenleitung auf L schalten
48
nop
49
nop
50
nop
51
nop
52
brcc PC+2 ;überspringe nächsten Befehl wenn Datenbit = 0
53
cbi led_port,led_pin ;Datenleitung auf L schalten
54
nop
55
nop
56
nop
57
nop
58
brne inner_loop ;wiederhole die innere Schleife bis Zähler Null ist
59
60
cp ZL,YL ;prüfe, ob Ende der RGB-Tabelle erreicht ist
61
cpc ZH,YH
62
brne outer_loop ;wiederhole äußere Schleife, falls noch nicht
ldi ZL,LOW(rgb_length) ;Adresse von rgb_length ins Z-Register laden
2
ldi ZH,HIGH(rgb_length)
Hier hat sich ein kleiner, aber fataler Fehler eingeschlichen, der
unbemerkt bleibt, solange rgb_length auf Adresse 0x0000 des Codesegments
liegt. Aufgrund der WORD-Organisation in CSEG muß beim Laden des
Z-Pointers die Adresse mit 2 multipliziert werden. Richtig lautet es:
1
ldi ZL,LOW(rgb_length*2) ;Adresse von rgb_length ins Z-Register laden
Auch wenn da "rgb_table" steht, die Lib hat mit dem Farbraum nichts zu
tun. Sie reicht einfach nur die in der Tabelle abgelegten Werte an die
LEDs durch.
Rene schrieb:> Moin Moin,> ich habe einen vorschlag undzwar das die Lib statt mit RGB mit dem HSV> fabraum arbeitet.
Die LEDs verarbeiten nur RGB. Die Lib übernimmt lediglich die Aufgabe,
die Daten aus dem Buffer im Speicher in die LEDs zu übertragen.
Um mit HSV-Werten zu arbeiten, müsste man dies vor der Übertragung in
RGB umwandeln.
Okay muss ich mich halt selber drm kümmern, die lib an sich funktioniert
bei mir. Jetzt habe ich aber noch eine frage bitte nicht hauen. Und zwar
währe es möglich an die funktion ws2812_sendarray den PORT und dem PIN
zu übergeben wo er die daten rausschiken soll also sie nicht vorher zu
definiern. Damit man mehere Stips an einen Controller anzu schließen?
MFG
Rene
Rene schrieb:> währe es möglich an die funktion ws2812_sendarray den PORT und dem PIN> zu übergeben wo er die daten rausschiken soll also sie nicht vorher zu> definiern. Damit man mehere Stips an einen Controller anzu schließen?
Dafür gibt es ws2812_sendarray_mask in den neusten Versionen:
https://github.com/cpldcpu/light_ws2812/tree/master/
Damit kann man den Pin frei wählen. Es müssen aber trotzdem alle Strips
an den gleichen Port angeschlossen werden.
Hallo,
erstmal Danke an Tim für das schöne Projekt und den Code.
Danke auch an Ulrich Radig für die HSV-Umrechnung.
Mit dieser habe ich leider ein kleines Problem. Die Farben scheinen
"Sprünge" zu machen, so als ob bei der Berechnung ein paar Bits verloren
gehen.
<math.h> habe ich eingebunden und linke mit -lm (falls das überhaupt
notwendig ist). Leider bin ich im Moment etwas ratlos wo der Fehler
liegen könnte. Evtl kann mir jemand weiterhelfen?
Danke schon mal,
Martin
Sorry,
habe vorhin vergessen mich anzumelden, daher kann ich den Text jetzt
nicht mehr ändern. Noch als Ergänzung: Ich verwende EINE WS2812,
angeschlossen an PORTB0 eines MEGA328P.
Martin
Hallo nochmal,
langsam habe ich den Eindruck, dass der Hund hier begraben ist:
//Berechnung der Dunkelstufe
//v = (englisch value) Wert Dunkelstufe einfacher Dreisatz 0..100%
*r = (*r / 100) * v;
*g = (*g / 100) * v;
*b = (*b / 100) * v;
Ich vermute da wird aufgrund der unsigned chars r,g,b und v irgendwas
gerundet oder läuft über. Wenn ich den Teile auskommentiere, sind die
Abstufungen weg, aber man kann halt die Helligkeit nicht mehr
einstellen.
Grüße,
Martin
Ulrich Radig schrieb:> Hier mein bescheidener Beitrag dazu.
Hallo Ulrich,
super Projekt! Ich glaube das solltest Du noch einmal mit Bildern
posten, so sieht ja niemand, was sich dahinter verbirgt :)
Hat eigentlich schon jemand ein Layout für einen Ring mit 5cm
Außendurchmesser erstellt? Die würden sich schön preiswert bei den
Chinesischen PCB-Herstellern liefern lassen.
Eine Idee noch: Dir normalisierst Sättigung und Helligkeit auf 100. Wenn
Du hier auf 64 oder 128 gehen würdest, würde für den AVR deutlich
kürzerer Code generiert werden.
Ich habe mir einen mit innen 52mm und außen mit 72mm erstellt. Dieser
passt auf den Ring meiner Halogenlampe. Gibt es auch im Download auf
meiner HP.
Gruß
Uli
Radig schrieb:> *g = (425 * h) /100;>> es ist aber anders besser verständlich.
Ich bin mir nicht ganz sicher ob das als Antwort auf meinen Vorschlag
gemeint war. Aber wenn Du hier statt dessen
> *g = (425 * h) /256;
Einsezt, bekommst Du deutlich kürzeren Code. Hier gibt es aber noch ein
paar Fallen mit den richtig Casts. Besser:
> *g = (uint8_t)((425 * h) /256);
und h ist ein int oder uint16_t.
Ich weiß das eine div 256 128 64 32 besser ist als eine div /
100. Ist ja dann nur eine schiebe Operation. Es wird halt immer in den
Beispielen 0 bis 1 oder 0 bis 100% angegeben. Daher auch bei mir nur der
Wertebereich 0 .. 100 ;-) es dient nur als Beispiel. Sonnst könnte ich
gleich auch die allgemeine Berechnungsmatrix verwenden.
Ulrich Radig schrieb:> Sonnst könnte ich> gleich auch die allgemeine Berechnungsmatrix verwenden.
Kannst du bitte mal einen Link posten? Meiner ansicht nach ist eine
Matrix für HSV -> RGB nicht möglich.
Eine interessante Implementierung und auch andere nützliche Farbräume
sind hier:
http://www.cs.rit.edu/~ncs/color/t_convert.html
Radig schrieb:> Ich habe mir einen mit innen 52mm und außen mit 72mm erstellt. Dieser> passt auf den Ring meiner Halogenlampe. Gibt es auch im Download auf> meiner HP.
Ich hatte an dieses Format gedacht:
http://www.adafruit.com/product/1463
Wenn man unter 50mm Außendurchmesser bleibt, kann man die Platinen für
<1EUR pro Stück bei den bekannten Chinesen bestellen.
Hallo Zusammen,
ich verfolge nun schon eine ganze weile dieses Thema, was mich dazu
bewegt hat auch so ne Kette zu bestellen.
So wie es aussieht sind die meisten schon über das Testprogramm hinaus.
Ich leider nicht.
Satt dessen werde ich noch Wahnsinnig mit dem Streifen.
Mein größtes Problem an der Sache bin wahrscheinlich ich selbst, da ich
noch keine wirkliche Programmierleuchte bin, aber das kann ich
dummerweise nicht vorher ändern, sondern nur an diesem Projekt wachsen.
Aber so wie ich gelesen habe gibt es hier Leute die von dem Ahnung haben
was sie tun.
Bis jetzt habe ich den Eindruck gewonnen das die Dinger total
empfindlich sind bezüglich - Wärme und EMV.
Es kommt mir so vor als ob ständig die erste LED hobs geht und dadurch
der Rest macht was er will.
Blinken, gar nicht Leuchten.............
Habt ihr auch solche Probleme oder wie geht ihr mit dem Streifen/LED's
um?
Schon mal Danke für eure Bemühungen.
Gruß Mario
Meine bisherigen Schadensbilder an mehreren abgeschnittenen LED-Streifen
mit 2-10 LED's
Bitmuster kommt sauber und richtig an der ersten LED an.
Stromversorgung steht auch.
# Alle LED's aus --> erste LED gibt nur 0 weiter aber in der richtigen
Anzahl. Deshalb auch alle anderen LED's aus.
# Alle LED's leuchten blau --> vermute default Einstellung. Erste LED
macht nichts somit alle anderen auch nicht.
# Alle LED's leuchten richtig bis auf die erste --> erste Kaputt gibt
aber Bit-Muster richtig weiter.
# Alle LED's blinke und die erste sogar wie sie will --> gibt Bit-Muster
blinkend weiter.
# Alle LED's blinken weiß --> ob wohl blau ausgegeben wird.
Ihr seht ich hab schon fast alles gehabt nur noch keinen voll
Funktionsfähigen Streifen.
Hat jemand eine Quelle wo man noch an kleine Fetzen vom WS2812 ran
kommt?
Da ich selbst nicht in der Lage wäre diese Lib für den WS2812B
umzuschreiben.
Ist es richtig das eine Scene ausgegeben werden kann und der Streifen
hält diese dann bis eine neue Scene ausgegeben wird?
oder muss kontinuierlich gesendet werden mit Reset dazwischen?
Die Ansteuerung von WS2812 und WS2812B ist identisch. Die Library kann
beides.
Ich werde aus Deiner Fehlerbeschreibung noch nicht ganz schlau.
Hast Du die Punkte aus der Liste "Troubleshooting" schon alle durch?
https://github.com/cpldcpu/light_ws2812
Hi Tim,
auch von mir Danke für das Projekt super Arbeit :)
Ja das "Troubleshooting" bin ich soweit durch und kann nichts erkennen
was ich nicht berücksichtigt hab.
Habe gerade ein Oszi dran hängen und dort kann ich auch kein Problem
feststellen.
Der betriebene Streifen hat 5 LED's, im unten stehenden Programm werden
nur 3 angesteuert die weiß leuchten sollen.
Habe dein Beispielprogramm genommen und für 3 LED's angepasst.
Ist-Stand --> die drei sind aus und die zwei nicht angesteuerten
leuchten blau (default).
Oszi sagt: 3x 24bit alles einser mit ca. 650ns high und 650ns low bei
4,7V
und nach der ersten LED kommen nur noch 0er raus im richtigen Timing und
Anzahl. Was aber 1er sein sollten.
Somit ist wahrscheinlich wieder die erste LED kaputt.
Hab mittlerweile die EMV Sandalen an und mit 180C° die Litzen dran
gepappt und trotzdem geht nichts.
Das Programm läuft eigentlich. Ich glaube ich habe 5m Schrott gekauft,
eine andere Erklärung habe ich momentan nicht :(
Ich habe hier auch ein 10er streifen WS2812B. wenn ich den direkt dran
hänge tut der leider auch nicht. Oder muss man da noch was umstellen. Da
laut Datenblatt das Timing anders ist.
Achso Ich verwende ein ATMEGA328P mit 16MHz auf einem Arduino UNO aber
ohne Bootloader. Programmiere mit AtmelStudio 6.1
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "light_ws2812.h"
>Oszi sagt: 3x 24bit alles einser mit ca. 650ns high und 650ns low bei
4,7V
Das ist nach meinen neusten Erkenntnissen marginal. Vielleicht hast Du
wirklich ein abweichenden Fertigungslos erwischt?
Du könntest ja mal die V2 testen. Die ist im Moment noch im Entstehen.
Der aktuelle Entwicklungsstand liegt hier:
https://github.com/cpldcpu/light_ws2812/tree/testing/light_ws2812_AVR
Ha erfolg erfolg.
Habe nach deiner Aussage das die Lib auch für WS2812B funktioniert. Bei
meinem B Streifen die erste LED abgeschnitten und siehe da.
Alles tut wie es soll :)
Also Programm Top, LED-Stripe aus China flop.
Die V2 werde ich dann auch mal probieren und dir berichten.
Danke für den doch so wichtigen Input.
Gruß und schönen abend.
Mario
Hi,
Super Seite, interessant zu lesen. Aber eine Frage zum letzten Satz: "A
'1' can be encoded with pulses of almost arbitrary length as long as
they are longer than ~625 µs (minimum on WS2812B)."
Das sollen eher 625ns sein, oder?
Axel
Axel Heider schrieb:> Super Seite, interessant zu lesen. Aber eine Frage zum letzten Satz: "A> '1' can be encoded with pulses of almost arbitrary length as long as> they are longer than ~625 µs (minimum on WS2812B).">> Das sollen eher 625ns sein, oder?
Oh ja, danke für den Hinweis!
Hier gibt es ein ziemlich schickes Projekt für WS2812-LEDs:
http://forum.43oh.com/topic/4920-120-led-ring-clock/
Der Autor hat auch die Gerber-Files für den Ring gepostet. Den könnte
man auch problemlos mit einem AVR betreiben.
Eigentlich wäre auch ein einfacer 60er Ring interessant.
Hi,
leider hatte ich nicht so viel Glück wie mein Vorredner rossi.
Ich versuche schon eine Weile die Lib auf einem ST23L152 (Cortex-M3) zum
Laufen zu bekommen, aber etwas klappt da nicht.
Ich habe den Assembler-Teil leider nicht ganz verstanden, aber ich denke
es gibt da ein Problem:
1
" sub %[ctr], #1 \n\t"
2
" str %[masklo], [%[clr]] \n\t"
3
" beq end%= \n\t"
und zwar wird mein Register %[ctr] immer weiter verkleinert, ohne dass
die Schleife jemals verlassen wird.
Vielleicht ist der Befehl beq hier irgendwie falsch.
Oder liegt das an meiner MCU?
Ich habe die (hoffentlich) aktuelle Lib:
* light weight WS2812 lib - ARM Cortex M0/M0+ version
* Created: 07.07.2013
Es wäre nett, wenn da mal jemand draufschauen könnte.
HI Fuchs,
ich muss darauf hinweisen, dass ich die ARM-Version bisher noch nicht
auf einem Cortex-M3 getestet habe. Entwickelt wurde sie auf einem M0+.
Gerade bei den größeren Cortexen ist es schwierig, zyklengenaues Timing
zu ermöglichen. Die Implementation geht davon aus, dass es keine
Flash-Waitstates gibt. Dein ST hat wahrscheinlich mindestens 1
Waitstate, so dass das Timing nicht stimmt. Hast Du Dir einmal den
Ausgang angeschaut? Evtl. kannst Du die CPU-Clock verringern und die
Waitstates auf 0 setzen?
Die Schleife im ASM-Teil funktioniert übrigens, da "STR" das Z-Register
nicht setzt.
http://infocenter.arm.com/help/topic/com.arm.doc.dui0497a/BABIHJGA.html
Generell ist es gerade auf den schnelleren Cortexen sinnvoll, auf einen
Hardware-Ansatz zu setzen. Bei STM32 würde sich eine Kombination aus SPI
und DMA anbeiten. Im Wiki-Artikel gibt es ein paar Beispiele:
http://www.mikrocontroller.net/articles/WS2812_Ansteuerung
Ich muss leider zugeben, dass mich mein Glück mit meinem 150 LED
Streifen nun auch ein wenig verlassen hat und ich auch Opfer des "erste
LED hin" Problems geworden bin. Da ich meinen Streifen eh komplett
zerschneiden will hab ich jetzt erst mal die ersten Teilstreifen
abgeschnitten und dabei stellte sich heraus, dass nur die erste LED hin
ist.
Jetzt frage ich mich natürlich - werden jetzt die nächsten ersten LEDs
auch die Grätsche machen bis alle kaputt sind? Was kann man denn dagegen
tun, dass die erste LED mit der Zeit kaputt geht? Sind lange Streifen
mit hohen Einschaltströmen evtl. ein Problem? Versorgt ihr alles aus
einem Netzteil? Also Prozessor und Streifen? Ich hab ein altes
AT-Netzteil am Streifen (20A an 5V) und mein STK500 mit dem Prozessor.
Massen sind verbunden, Signal geht direkt an den Streifen. Sollte man da
vielleicht einen 1k Widerstand in Reihe zum Eingang des Streifens
schalten? Und in welcher Reihenfolge sollte man einschalten? Erst den
Streifen, dann den Controller? Helfen vielleicht dicke Elkos am +/- des
Streifens? Oder gar einen kleinen Spannungsfilter mit Dorssel & Co. um
saubere Spannung zuzuführen?
Hi, danke für die schnelle Antwort.
In meinem Test habe ich 16MHz verwendet und die Waitstates auf 0
gesetzt. Nach Application Note müsste das klappen bei VCore von 1,8V
(und mir ist auch nichts abgestürzt).
Mein Problem beginnt eigentlich schon früher als beim Timing des
Ausgangs.
Und zwar wird (wie erwähnt) die ctr-Schleife im ASM-Teil nie verlassen.
ctr zählt fröhlich bis beliebig negative Werte weiter...
Wenn ich vor dem BEQ ein "compare mit 0" einfüge (ich weiß, das ändert
das Timing, ich probiere nur aus...), dann klappt der Sprung, sobald
ctr=0:
1
" sub %[ctr], #1 \n\t"
2
" str %[masklo], [%[clr]] \n\t"
3
" cmp %[ctr],#0 \n\t" //<-- NEU
4
" beq end%= \n\t"
Ich habe kurz gegoogelt, der ST32L benutzt das THUMB2 instruction set.
Kann es da evtl. Unterschiede geben?
Ok, also so weit, so gut.
Als nächstes habe ich festegestellt, dass (unabhängig vom übergeben
Array) immer 0er gesendet werden. Es scheint so, als würde der
BCS-Befehl nie zuschlagen:
1
" bcs one%= \n\t"
2
" str %[masklo], [%[clr]] \n\t"
3
" one%=: \n\t"
Ich überlege mir jetzt, ob ich:
- den ASM-Teil so anpasse, dass er auf meiner MCU wie gewünscht läuft
(ich habe mal gegoogelt und hab was gefunden, wie man angeblich mit
systick die genaue Anzahl Zyklen messen kann)
- versuche das Timing mit SPI und DMA zu realisieren
Ich tendiere eigentlich eher zum ersten...
In beiden Fällen steckt da für mich noch ein gutes Stück Arbeit drin
(bin noch neu, ist mein erstes "Projekt")
rossi schrieb:> einem Netzteil? Also Prozessor und Streifen? Ich hab ein altes> AT-Netzteil am Streifen (20A an 5V) und mein STK500 mit dem Prozessor.> Massen sind verbunden, Signal geht direkt an den Streifen. Sollte man da> vielleicht einen 1k Widerstand in Reihe zum Eingang des Streifens> schalten? Und in welcher Reihenfolge sollte man einschalten? Erst den> Streifen, dann den Controller? Helfen vielleicht dicke Elkos am +/- des> Streifens? Oder gar einen kleinen Spannungsfilter mit Dorssel & Co. um> saubere Spannung zuzuführen?
Hier im Thread gibt es ja schon einige Infos:
Beitrag "WS2812 und WS2812b Qualitätsprobleme!"
Das Minimum sollte wohl eine Serienterminierung am Ausgang des
Controllers mit 100-150 Ohm sein. 1k ist zuviel.
Fuchs schrieb:> Ich habe kurz gegoogelt, der ST32L benutzt das THUMB2 instruction set.> Kann es da evtl. Unterschiede geben?
Der M3 unterstützt gegenüber dem M0 zusätzliche Befehle. Unterschiede
kann ich mir nur vorstellen, wenn der code anders compiliert wird. Deine
Beobachtungen sind merkwürdig. Meistens ist es aber nicht so, dass die
CPU plötzlich ganz anders funktioniert, sondern es woanders Probleme
gibt :)
Du kannst die Schleife ja mal in C nachprogrammieren, und schauen was
der Compiler daraus macht?
1
inti=8;
2
intdata=xx;
3
4
while(--i){
5
PORT=HI;
6
if(data&128)PORT=LO;
7
data<<=1;
8
PORT=LO;
9
}
oder so ähnlich
Fuchs schrieb:> Ich überlege mir jetzt, ob ich:>> - den ASM-Teil so anpasse, dass er auf meiner MCU wie gewünscht läuft> (ich habe mal gegoogelt und hab was gefunden, wie man angeblich mit> systick die genaue Anzahl Zyklen messen kann)>> - versuche das Timing mit SPI und DMA zu realisieren>> Ich tendiere eigentlich eher zum ersten...> In beiden Fällen steckt da für mich noch ein gutes Stück Arbeit drin> (bin noch neu, ist mein erstes "Projekt")
Ich würde Dir zum Zweiten raten, da es auf deinem M3 ziemlich schwierig
sein wird, nachvollziehbares Timing zu generieren, es aber andererseits
mächtige Peripherie gibt. Im oben verlinkten Artikel gibt es ja schon
Beispiele.
Im Moment scheint das nur eine Vorserie zu sein. Größere Stückzahlen
gibt es erst später.
Hier kann man schon kleinere Stückzahlen kaufen:
http://solderingsunday.com/shop/components/pixelbits-bakers-dozen/
Zum Bild oben Links: Der Pinabstand scheint nur 2.5 mm statt 2.54 mm wie
im Datenblatt zu sein.
btw, nur so als frage zwischen durch warum versucht man mit einem STM32
die 150 WS2812b mit bitbanging an zu steuern?
Anstatt einfach den SPI zu benutzen?
Viele Wege führe nach Rom, und das ist wohl der einfachste und
portabelste um was um leuchten zu bringen.
Mit einem LPC810 habe ich das hier mit SPI und nachgeschaltetem SCT am
laufen. Ist halt ein bisschen mehr Aufwand bis das mal läuft.
BTW: Irgendwer Interesse an eine Sammelbestellung der 8mm version? $15
für den 12er pack und $10 Versand. Und halt noch Zoll.
Axel
Axel Heider schrieb:> Viele Wege führe nach Rom, und das ist wohl der einfachste und> portabelste um was um leuchten zu bringen.> Mit einem LPC810 habe ich das hier mit SPI und nachgeschaltetem SCT am> laufen. Ist halt ein bisschen mehr Aufwand bis das mal läuft.
Die Version aus dem lpc800 Forum?
Axel Heider schrieb:> BTW: Irgendwer Interesse an eine Sammelbestellung der 8mm version? $15> für den 12er pack und $10 Versand. Und halt noch Zoll.
Kam bei mir Zollfrei und EUSt-Frei an, obwohl als Wert $50 deklariert
war. Sind "Hobby Parts" von der EUSt befreit?
> Die Version aus dem lpc800 Forum?
Ja, basierend auf der. Prinzipiell funktioniert der Code super und wenn
man ein paar Kommentare ergänzt, dann ist das sogar verständlich, was da
gemacht wird. :)
> Sind "Hobby Parts" von der EUSt befreit?
Laut Zoll Webseite geht alles bis 45 Eur zollfrei als Geschenk durch. Da
bist du mit den $50 also knapp drunter. Mit dem aktuellen Dollar-Kurs
sollten also 4 Packungen zollfrei sein ($60 ca. 44 EUR).
Axel
Axel Heider schrieb:> Laut Zoll Webseite geht alles bis 45 Eur zollfrei als Geschenk durch.
Als Geschenk gilt es aber nur, wenn es von einer Privatperson an eine
Privatperson geschickt wird. Ich durfte vor ein paar Jahren mal für eine
Sendung mit Werbegeschenken aus Kanada (CD-ROMs und T-Shirts) im Wert
von CAD 50 beim Zoll antanzen und Einfuhrabgaben zahlen.
Axel Heider schrieb:> BTW: Irgendwer Interesse an eine Sammelbestellung der 8mm version? $15> für den 12er pack und $10 Versand. Und halt noch Zoll.
Interessiert, abhängig vom Preis!
Würde so für 30 Dollar kaufen, in der Hoffnung, dass bei einer größeren
Gesamtmenge dann auch 60-100 Stück dafür drin sind...
Lusting, langsam klärt sich auch, woher die LEDs kommen. Ich habe mal
nachgefragt, ob günstigere Preise für größere Mengen möglich sind. Melde
mich, wenn es eine Antwort gibt.
Michael S. schrieb:> Ich habs leider nicht zum laufen bekommen.
Was ist denn genau das Problem?
> Und deine DMA header file ist ja "noch" leer :)
Was für ein DMA header File? :)
Beim xMega haben sich die Portregister etwas geändert. Das konnte ich
auch selbst noch in der Lib aendern. Die Portregister denke ich sind
aber nicht das Problem, sondern das es bei dem ASM Code ein Fehler gibt
und meine ASM Kenntnisse nicht vorhanden sind ;P ist es schwierig es zu
lösen. Ich hab ja nichtmal den Fehler selbst nach googlen nicht
verstehen können gG
light_ws2812.c: In function ‘ws2812_sendarray_mask’:
light_ws2812.c:108:5: warning: asm operand 2 probably doesn’t match
constraints [enabled by default]
light_ws2812.c:108:5: error: impossible constraint in ‘asm’
make: *** [obj/light_ws2812.o] Fehler 1
Ah, ich sehe schon. Das Problem scheint zu sein, dass die Portregister
nicht mehr PORTx und DDRx heissen, sondern OUTx und DIRx.
Versuche mal die Register in light_ws2812.h direkt einzutragen. Dazu
musst Du diese Zeilen ersetzen:
Die Fehlermeldung scheint durch eine ungültige Portregisteraddresse
verursacht zu sein. Evtl. hast Du auch ein Portregister gewählt, welches
nicht mehr durch OUT angesteuert werden kann.
ich möchte die LED-Funktion als Statusanzeige für verschiedene
Funktionen nutzen, also jede .c-Datei soll eine zugewiesene LED
ansteuern.
Allerdings habe ich keine Ahnung, wie ich die Daten der
1
structcRGBled[..];
mit in andere .c Dateien global übernehmen kann.
Wenn ich
1
structcRGBled[..];
in jeder Datei einfüge, sind die bisherigen RGB-Werte der main.c
verloren und es wird nur die aktuell genutzte Status-LED angezeigt.
Wer kennt sich damit aus ???
Wie "Di" Geschrieben hat. Alternativ kannst Du auch auch pointer auf die
Struktur als Funktionsparameter übergeben. Vom Programmierstil her ist
das etwas sauberer.
Mit "extern" hatte ich es vorher auch schon probiert, es hat aber nicht
geklappt.
Mit Pointer geht es nach einigem basteln.
man lern eben nie aus ;-)
Dankeschön
MB schrieb:> Mit "extern" hatte ich es vorher auch schon probiert, es hat aber nicht> geklappt.
Die richtige Vewendung von "extern" ist dabei natürlich entscheidend ;).
In einer c-Datei muss die Variable deklariert (und ggf. initialisiert)
werden. In einer von allen anderen c-Dateien eingebundenen header-Datei
wird diese Variable dann als extern deklariert.
Das bewirkt, dass von allen verteilten Programmteilen auf die selbe
Speicherstelle zugegriffen wird, wenn der name der Variablen fällt.
"extern" signalisiert dem compiler, dass sich die zu kompilierende
c-Datei darauf verlassen kann, dass Speicher für diese Variable
vorhanden sein wird. Wo das ist, macht dann der Linker den einzelnen
o-Dateien klar.
Hi Tim,
ich habs nun nochmal nach langer Zeit versucht mit dem xMega die
WS2812er Leds anzusteuern, aber da ich wie gesagt in inline assembler
nicht wirklich gut bin ;P Hab ichs leider immernoch nicht hinbekommen.
Evtl hast du ja noch eine Idee wie ich das aendern muesste damit das auf
einem xMega32A4 läuft.
Das ist die aktuelle Funktion von dir die ich versucht habe anzupassen
;P
Aber er sagt das er einen Fehler in Parameter 2(3) hat, das
PORTD.OUTSET.
Die Interrupts lass ich bewusst an da ich die Länge des Strips abgreifen
möchte über einen Interrupt. Was ja alles auf nem ATMega wunderbar
funktioniert...
Vielen Dank im Vorraus für deine/eure Hilfe
// sends array to ws2812 port
void ws2812_sendarray(uint8_t *data,uint16_t datlen) {
//irqoff
uint8_t curbyte, ctr, masklo, maskhi;
maskhi = PIN0_bm;
masklo =~ maskhi & PORTD.OUTSET;
maskhi |= PORTD.OUTSET;
while (datlen--) {
curbyte =* data++;
asm volatile(
" ldi %0,8 \n\t"
"loop%=:out %2, %3 \n\t"
" lsl %1 \n\t"
" dec %0 \n\t"
" rjmp .+0 \n\t"
" brcs .+2 \n\t"
" out %2, %4 \n\t"
" rjmp .+0 \n\t"
" nop \n\t"
" out %2, %4 \n\t"
" breq end%= \n\t"
" rjmp .+0 \n\t"
" rjmp .+0 \n\t"
" rjmp .+0 \n\t"
" rjmp loop%= \n\t"
"end%=: \n\t"
: "=&d" (ctr)
: "r" (curbyte), "I" (PORTD.OUTSET), "r" (maskhi), "r"
(masklo)
);
}
//irqon
}
MichaelS98 schrieb:> Evtl hast du ja noch eine Idee wie ich das aendern muesste damit das auf> einem xMega32A4 läuft.>> Das ist die aktuelle Funktion von dir die ich versucht habe anzupassen> ;P> Aber er sagt das er einen Fehler in Parameter 2(3) hat, das> PORTD.OUTSET.
Ich habe leider keinen XMEGA zum testen und kann das Manual nur kurz
überfliegen. Du solltest Dir die Sektionen zu den I/O Ports genauer
durchlesen.
- OUTSET ist der falsche Port. Du benötigst OUT
- Du musst PORTD auf einen der virtuellen I/O Ports mappen, damit er
mit dem Befehl "Out" beschrieben werden kann. Steht ab s. 145 im Manual.
> Die Interrupts lass ich bewusst an da ich die Länge des Strips abgreifen> möchte über einen Interrupt. Was ja alles auf nem ATMega wunderbar> funktioniert...
Ich verstehe nicht so ganz, was Du damit erreichen willst? Bin aber
skeptisch dass es sinnvoll ist, während der Routine einen Interrupt
auszulösen.
Habs mittlerweile hinbekommen :) Kleinen Grundkurs in inline assembler
und dann gings auch ;P
Das mit den Interrupts ist auch nur bei der Initialisierung der Fall bei
den weiteren Ausgaben wird der Interrupt auch ausgeschaltet.
Ich nutze nur einen Interrupt der auf Highlevel auslöst und dort ist
meine "Rückleitung" für die LED Strips (soll heissen der letzte DOUT ist
dadran)
um dynamisch die Lönge des Strips zu ermitteln.
Klappt auch mittlerweile wunderbar
Vielen Dank nochmal für deine Hilfe Tim :)
Gruß
Michael
Hi, ich habe eine Kette von 42 WS2811 Leds und würde am ende gern noch
einen Atmega8 hängen um damit 7 high power Led Stromquellen zu steuern.
Mein erster Ansatz war einfach die Chips dafür zu verwenden leider
pfeift die Stromquelle bei der PWM-Frequenz der WS2811.
Deswegen meine Frage hat jemand schon mal überlegt eine Lib zu bauen die
sich komplett wie ein WS2811 verhält also mit ein und ausgang, damit man
den Transparent in eine kette hängen kann?
Der Grund für das ganze ist einfach ich würde zur Lampe mit den LEDs
einfach gern nur 3 Kabel legen (+,GND,Din) und nicht noch LAN, USB usw.
bzw den Steuer µC einfach beim Netzteil etwas entfernt.
Gruß
Andreas
Andreas schrieb:> Hi, ich habe eine Kette von 42 WS2811 Leds und würde am ende gern noch> einen Atmega8 hängen um damit 7 high power Led Stromquellen zu steuern.> Mein erster Ansatz war einfach die Chips dafür zu verwenden leider> pfeift die Stromquelle bei der PWM-Frequenz der WS2811.
Ist das bei einer PWM-Ansteuerung nicht normal? Was willst Du denn
sonst?
Andreas schrieb:> Deswegen meine Frage hat jemand schon mal überlegt eine Lib zu bauen die> sich komplett wie ein WS2811 verhält also mit ein und ausgang, damit man> den Transparent in eine kette hängen kann?
Interessante Idee. Prinzipiell ist das relativ einfach. Du müsstest nur
die steigende Flanke abwarten und dann nach 0.5µs den Eingang noch
einmal einlesen. Dies ist dann der Bitwert. Siehe auch hier:
http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/
Schwierig ist allerdings, dass bei diesem Ansatz die CPU zu 100%
beschäftigt ist. Abhilfe könnte hier ein Pin-Change Interrupt schaffen.
Der muss allerdings sehr genaue getimed sein.
Andreas schrieb:> Deswegen meine Frage hat jemand schon mal überlegt eine Lib zu bauen die> sich komplett wie ein WS2811 verhält also mit ein und ausgang, damit man> den Transparent in eine kette hängen kann?
Bei dem ohnhin schon arschknappen Timing dürfte es schwierig bis
unmöglich sein, diese Aufgabe mit einem ATmega zu lösen. Dafür brauchts
schon leistungsfähigere Controller.
Icke ®. schrieb:> Bei dem ohnhin schon arschknappen Timing dürfte es schwierig bis> unmöglich sein, diese Aufgabe mit einem ATmega zu lösen. Dafür brauchts> schon leistungsfähigere Controller.
Unsinn. Das kann auch ein ATtiny. Allerdings macht der Controller dann
sonst nicht all zu viel.
Tim schrieb:> Allerdings macht der Controller dann sonst nicht all zu viel.
Das ist aber der Punkt. Was nützt es, wenn der Controller die Daten zwar
weiterreichen kann, aber keinen Takt mehr für andere Aufgaben frei hat?
Icke ®. schrieb:> Das ist aber der Punkt. Was nützt es, wenn der Controller die Daten zwar> weiterreichen kann, aber keinen Takt mehr für andere Aufgaben frei hat?
Kommt darauf an, was der Controller sonst noch machen soll. Zumindest
während des Reset-Pulses wäre noch Zeit für Anderes.
Hallo Tim,
ich habe ein kleines Problem mit deiner Libary und mir ist gerade nicht
bewusst, woran das liegt.
Ich poste hier einmal die kurzen Ausschnitte, die wichtig sein können.
1
/*main.h*/
2
#define NUM_LEDS 60
3
struct cRGB leds[NUM_LEDS];
1
/* Eine kleine Funktion, die das struct beschreibt. Es handelt sich um eine Uhr mit vor/nachlaufenden Leds. Das u.a led == 60 nicht eintritt, eine kurze if Anweisung*/
2
3
void setPixel(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
4
{
5
if(led >= 60 && led < 65) led -= 60;
6
else if(led <= 255 && led > 255) led = 60 - (255 - led);
7
8
leds[led].r = r;
9
leds[led].g = g;
10
leds[led].b = b;
11
}
1
/* wird innerhalb while() aufgerufen, ansonsten läuft nichts nebenbei in der Dauerschleife */
for(int i = 0; i < NUM_LEDS; i++) ws2812_setleds(leds,i);
32
}
33
}
Die Leds 59 kann jedoch nicht angesteuert werden.
Habe zum testen, ob die Led doch einen abbekommen hat, eben mit dem
Arduino getestet und der FastLed lib. Dort konnte 59 Problemlos
angesteuert werden.
Gruß Stefan
Danke, werde es testen. Hatte jetzt nicht nicht dran gedacht, dass damit
das komplette Array geschrieben wird. Dann macht es auch sinn, wieso es
zu Probs kommt, wenn er auf einmal das 60 fache schicken muss.
Hallo,
kann es sein, dass die Methode meinen Timer0 beeinflusst?
Ich nutze die Libary für eine Uhr mit 60 Leds. Was ich jetzt bei dem
ersten Test nicht gemacht habe, ist das Array nur schreiben, wenn sich
etwas ändert. Derzeit ballert er jeden Durchlauf einmal das Array ab.
Blos wie verhält sich das auf Dauer? Ich habe vor, bis zu 16mal in der
Sekunde das Array neu zu beschreiben. Ich habe vor, neben der
gebastelten internen Uhr ebenfalls einen DS3231 einzusetzen, liegt als
SOIC vor.
Jedoch möchte ich diese nicht jede Stunde mit dem dem Atmega abgleichen.
Denn ich mache teils ein Fade und das sähe dann unschön aus.
Eine Abweichung von wenigen Sekunden pro Tag fände ich schon recht viel.
Ich möchte einmal täglich den Wert mit der RTC vergleichen und wenn die
differenz größer 10sec (evtl. noch geringer) und dann aktualisieren.
Sicherlich, meist bekommt man den Abgleich nicht mit, aber mich stört,
dass man ihn mitbekommen kann.
So, noch einmal auf den Test zurück. Wie gesagt, ich habe den nun mal
eine gewisse Zeit laufen lassen. Es waren 52Minuten, welche ich mit
einer Stoppuhr als Referenz gemessen haben. Man konnte beim umschalten
schon sheen, dass der Sekundenzeiger keinesfalls schnell arbeitet.
Eine Sekunde auf dem Atmega328P 16MHz brauchte etwa 79% länger als meine
Stoppuhr (01:32:55)
Kann man das ganze errechnen, wie sich das verhält, wenn ich nur 16x die
Sekunde ein Update machen, wie hoch die Differenz vermutlich sein wird?
time.h
So, ich habe noch einmal einen Test über 2h laufen lassen. Diesmal wird
jede Sekunde einmal das Array neugeschickt.
Nun liegt der Fehler bei ca 1,3% (insgesamt ca 10 Sekunden Differenz).
Damit kann ich leben, zu mal bei diesem Testprobanten sowieso nur SMD
Resonator verbaut ist. Das entspricht in etwa der Fehlerquote.
Werde nun noch mal den Test bis morgen früh durchführen, wenn ich nun
jede Sekunde 16mal den Wert ändere.
Hain schrieb:> kann es sein, dass die Methode meinen Timer0 beeinflusst?
Den Timer nicht, aber die Interrupts werden natürlich gesperrt. Versuche
doch einmal, die Interrupt-Frequenz zu verringern. Der Fehler wird immer
dann auftauschen, wenn während des WS2812 calls zwei interrupts
aufgerufen werden.
Ich habe mir mal ein paar neue LEDs angeschaut, die APA102:
http://cpldcpu.wordpress.com/2014/08/27/apa102/
Diese LEDs lassen sich per SPI ansteuern. Bin etwas unschlüssig, ob es
überhaupt Sinn macht, diese auch in der Lib zu unterstützen.
Tim schrieb:> Diese LEDs lassen sich per SPI ansteuern. Bin etwas unschlüssig, ob es> überhaupt Sinn macht, diese auch in der Lib zu unterstützen.
Ja, aber in DaBla ist von 512KHz und 4 Bytes die Rede. Das ist weniger
als WS28xx.
Tim schrieb:> Diese LEDs lassen sich per SPI ansteuern. Bin etwas unschlüssig, ob es> überhaupt Sinn macht, diese auch in der Lib zu unterstützen.
Ich sehe hierfür keine Notwendigkeit, um ehrlich zu sein. SPI
unterscheidet sich deutlich von dem WS2811/12 "Interface und wird meist
direkt in Hardware umgesetzt. Neben einer kurzen Initialisierung,
beschränkt sich das Senden ja dann letztendlich auf das Schreiben in ein
Register. Bei Controller mit DMA kann das dann sogar vollständig im
Hintergrund ablaufen. Besser geht es kaum.
Mal sehen, ob sich diese LEDs bzw. entsprechend bestückte Streifen
durchsetzen werden und ggf. sogar zu ähnlichen Preisen gehandelt werden.
Wünschenswert wäre es alle Male.
Mit freundlichen Grüßen,
Karol Babioch
Marc Vesely schrieb:> Ja, aber in DaBla ist von 512KHz und 4 Bytes die Rede. Das ist weniger> als WS28xx.
Das scheint mir nur ein Beispiel zu sein. Ich hatte mit 4 MHz noch keine
Probleme. Ich werde mal nachfragen, ob es so etwas wie eine
Spezifikation gibt...
Karol Babioch schrieb:> Mal sehen, ob sich diese LEDs bzw. entsprechend bestückte Streifen> durchsetzen werden und ggf. sogar zu ähnlichen Preisen gehandelt werden.> Wünschenswert wäre es alle Male.
Glaube nicht, dass die so schnell günstiger werden. Für das low-price
Segment hat der Anbeite die APA104, einen WS2812B clone.
Hallo
Ich brauch mal ein bisschen Hilfe! Ich nutze ein Atmega320pu und schaffe
es einfach nicht die LEDs zu laufen zu bringen!
Ich bin mir nicht sicher ob es an meinem Programm liegt oder an dem zu
heißem verlöten der LED liegt!
Kann ich bei der Lib von oben etwas richtig falsch machen?
Was müsste ich alles ändern?
Ich wünsche noch eine schöne Woche
BADCABL1E schrieb:> Kann ich bei der Lib von oben etwas richtig falsch machen?
Ja.
Falls du aber wirklich konkrete Hilfe möchtest, dann musst du Details
(Beispielprogramm, Fehlermeldungen, Beschreibung des Fehlverhaltens, was
hast du überhaupt vor, was sind die Voraussetzungen, usw.) herausrücken.
Dein Beitrag in seiner aktuellen Form ist ungefähr so nützlich wie die
Aussage "Mein Auto springt nicht an".
Mit freundlichen Grüßen,
Karol Babioch
Das ist mir ja auch klar. Vielen Dank für die schnelle Antwort!
Leider kann ich nicht viele mehr sagen... Ich bekomme keine
Fehlermeldung und ein Signal erhalte ich auch. Aber nichts leuchtet.
Ich will die LED nur zum Laufen bringen und dann würde ich weiter
schauen.
Hallo
Ich versuche es noch einmal nach einigem gebastel.
Mein Atmega328pu läuft mit einem internen 16mhz tackt. Ich nutze den
Code von oben (ohne Änderungen) und definiere den PINB1 als Output für
das Signal. Wenn ich nun das alles anschalte bekomme ich ein Weißes
Licht (ändern Läst sich das nicht)
Ich entschuldige mich für meine vorherigen Posts und hoffe diese
Informationen sind hilfreicher ;)
Noch ein schönes Wochenende und vielen Dank!
BADCAB1E schrieb:> Ich nutze den> Code von oben (ohne Änderungen) und definiere den PINB1 als Output für> das Signal. Wenn ich nun das alles anschalte bekomme ich ein Weißes
Welchen Code nutzt Du denn genau?
Die aktuelle Version liegt hier:
https://github.com/cpldcpu/light_ws2812
Hast Du schon die Punkte unter "Troubleshooting" abgearbeitet?
Ansonsten passen vermutlich die tatsächliche Taktfrequenz und die im
Code einstellte nicht zusammen.
"Troubleshooting" hab ich durchgearbeitet... Das was ich nicht verstehe
ist, dass ich weißes Licht erhalte --> Das bedeutet doch ich steuere
R,G,B an?
Ich vermute, da ich ja ein Signal bekomme, dass es an der Frequenz
liegt.
Wo kann ich die Taktfrequenz einstellen/ Prüfen? Ich habe sie zur Zeit
in der Toolchain bei Atmel-studio festgelegt.
Mein freund hat ein Oszilloskop (zum Glück) Ich glaube, dass das zu
schnell ist(Bild)! Wenn das so ist wie kann ich es ändern!
Vielen vielen dank für die schnellen Antworten!
Also ich hab jetzt die Taktfrequenz auf 8mhz runterkorrigier. Jetzt
leuchtet die LED Grün! Reicht mir aber immer noch nicht ;) Was könnte
ich denn anders machen oder noch besser was mache ich denn falsch?
MfG
Ich kenn jetzt das Blinky nicht, aber Deine Frage sagt es ist nicht
grün, was Du wolltest.
Dein Signal sieht nach 0 255 0 aus. Bei den WS2812 wäre das Rot (GRB als
Reihenfolge), bei den WS2811 ist es grün (RGB Reihenfolge).
Vielleicht musst Du der Library noch sagen, welchen Chip Du hast?
Tim schrieb:> Nö. Ist zu langsam. Jeder Puls sollte 1.25µs haben, bei Dir sind> es> 2.5µs.
ich kam mit dieser und fastLED 1 auch nicht so klar, 100 LEDs brauchten
300ms.
Jetzt mit fastLED2 bin ich bei 3ms
BADCAB1E schrieb:> Was könnte ich denn anders machen oder noch besser
Eine halbe Stunde hinsetzen und VERSTEHEN lernen, für was die Routine
zuständig ist und für was nicht. Ihre Aufgabe ist das Senden der Daten
zu den WS2812, nicht aber das Bereitstellen der Daten. Ich bezweifle
auch, daß eine Korrektor des Taktes nach unten hilfreich ist, wenn die
Pulse ohnehin schon zu lang sind.
Icke ®. schrieb:> BADCAB1E schrieb:>> Was könnte ich denn anders machen oder noch besser>> Eine halbe Stunde hinsetzen und VERSTEHEN lernen, für was die Routine> zuständig ist und für was nicht. Ihre Aufgabe ist das Senden der Daten> zu den WS2812, nicht aber das Bereitstellen der Daten. Ich bezweifle> auch, daß eine Korrektor des Taktes nach unten hilfreich ist, wenn die> Pulse ohnehin schon zu lang sind.
Er hat nicht den Takt geändert, sondern F_CPU richtig gesetzt.
Das war mit 16 Mhz das doppelte des realen internen Taktes, also sind
die Delays dann ungewollt doppelt so lang.
Hallo
Ich hab mich heute noch einmal vor den PC gehockt... Nachdem ich den
Code (ohne Änderung) noch einmal auch den Chip geflasht habe, blinkten
die LEDS! Ich verstehe zwar nichts, aber wenn es geht ist es mir auch so
recht;)
Ich bedanke mich herzlichst bei allen die mir geholfen haben!
Mit freundlichen Grüßen
BADCAB1E
Und da ich Icke® nicht ausschließen möchte, bedanke ich mich für den
sinnlosesten Kommentar den ich gelesen habe! Die Zeit den zu schreiben
hätte man sicherlich besser nutzen können.
BADCAB1E schrieb:> Die Zeit den zu schreiben hätte man sicherlich besser nutzen können.
In der Tat Zeitverschwendung. Den Beweis lieferst du gleich mit:
BADCAB1E schrieb:> Ich verstehe zwar nichts, aber wenn es geht ist es mir auch so> recht;)
Tobias N. schrieb:> Selbst ICH habe die lib sofort ans laufen bekommen. Leute gibts :-P
ich habe es ja auch geschafft, aber warum 100 LEDs 300ms brauchen hat
mir niemand sagen können. Dann habe ich fastLED probiert, dito, wieder
nur Sprüche von anderen.
Weitergegoogelt und fastLED2 gefunden und siehe da 3ms für 100 LEDs was
ziemlich genau passt, ein Bit 1,25µs (bei 16MHz) mal 24 Bit für eine LED
in RGB = 30µs x 100 LEDs = 3ms
so dachte ich mir das, aber vorher 2 Libs vergebens probiert und selbst
an mir gezweifelt.
Di Pi schrieb:> Der erste Schritt in die richtige Richtung :)
(wieder so ein Kommentar der kein bischen hilft......)
aber trotzdem gelöst, wenn auch nicht mit der ws2811/12 oder fastLED1
fastLED2 läuft wie erwartet, was soll ich da noch nach den anderen oder
meinen vermeintlichen Fehler suchen falls es den überhaupt gibt.
Joachim B. schrieb:> (wieder so ein Kommentar der kein bischen hilft......)> aber trotzdem gelöst, wenn auch nicht mit der ws2811/12 oder fastLED1>> fastLED2 läuft wie erwartet, was soll ich da noch nach den anderen oder> meinen vermeintlichen Fehler suchen falls es den überhaupt gibt.
Nutze auch die lib von Tim aber ich hab keine Ahnung was dein gelaber
von wegen fastLED dauernd soll. Was ist das? Was hat das hier mit dem
Thread zu tun?
Du hast halt irgendwelche Arduino-Probleme. Kannst du damit nicht in
arduino.cc rumnerven?
cyblord ---- schrieb:> ich hab keine Ahnung was dein gelaber> von wegen fastLED dauernd soll. Was ist das? Was hat das hier mit dem> Thread zu tun?
OK ich erkläre es dir
zuerst hatte ich die wsLIB vom Tim versucht, auf dem puren AVR
(Lochraster, nix Arduino!)
lief für 40 LEDs prima und ich hatte keinen Grund am Timing zu zweifeln,
nicht mal nachgemessen.
Dann wollte ich die wordclock bauen, als ich die 117 LEDs fertig
bestückt hatte kam der erste Test, alle LEDs im Farbwechsel und ich sah
wie die Farben von der ersten zur letzten LED durchgereicht wurden und
habe sagenhafte 300ms gemessen was auch bei den lahmen 800kHz nicht sein
dürfte.
Ich recherchierte und fand fastLED also diese wahlweise mit #defines
installiert und beide gegeneinander vermessen. Kein nennenswerter
Unterschied ca. 5% also im Ergebnis auch zu lahm.
Ich wollte schon des Projekt mit den WS erden und auf LPD umsteigen
(2MHz clock) und fand dann fastLED2 was das gewünschte Ergebnis bringt.
Mir fehlt einfach der Beweis das mit der WS Lib 100 RGB LEDs in 3ms zu
schalten sind, das ist kein Gemecker in Richtung Tim, nur meine
Feststellung und mit euren Komentaren komme ich halt (wie so oft in
Foren) kein Stück weiter.
Tims LIB funkioniert, Anfänger so wie ich freuen sich über die ersten
Farbspiele die leicht umzusetzen sind, trotzdem läuft es nicht rund.
PUNKT
Nichts weiter wollte ich dem TO mitteilen und wo es eventuell klemmt.
Joachim B. schrieb:> Mir fehlt einfach der Beweis das mit der WS Lib 100 RGB LEDs in 3ms zu> schalten sind
Der Beweis ergibt sich schon aus der Tatsache, daß die Ansteuerung der
WS2812 gar nicht funktionieren kann, wenn die Routine grob von dem im
Datenblatt angegegebenen Timing abweichen würde. Die Übertragung eines
Bits dauert 1,25µs, macht also bei 24 Bit 30µs pro LED. 100 mal 30µs
ergeben -tataa- genau 3ms plus ~50µs Reset. Laut Datenblatt kann das
Timing pro Bit bis zu 300ns abweichen, in der Praxis scheinen sie sogar
etwas mehr zu vertragen. Wir reden allerdings von Zeiten im Bereich
einstelliger µs und nicht vom Faktor 100. Wenn bei dir die Übertragung
300ms für 100 LEDs dauern soll, dann kann das schon theoretisch
unmöglich sein. Du hast entweder einen Meßfehler oder du mißt etwas
anderes.
Joachim B. schrieb:> und ich sah> wie die Farben von der ersten zur letzten LED durchgereicht wurden
Auch das ist nicht möglich, weil die Farben in der gesamten Kette erst
nach dem Reset-Puls übernommen werden und zwar nahezu gleichzeitig.
> Joachim B. schrieb:>> Mir fehlt einfach der Beweis das mit der WS Lib 100 RGB LEDs in 3ms zu>> schalten sind
Allein schon wenn man den Code von Tim anschaut, sieht dass hier
nirgendwo so eine große Verzögerung auftreten kann. Der druchläuft die
Hauptschleife so schnell wie möglich und somit ergibt sich die Zeit für
X LEDs automatisch.
Icke ®. schrieb:> Joachim B. schrieb:>> und ich sah>> wie die Farben von der ersten zur letzten LED durchgereicht wurden>> Auch das ist nicht möglich, weil die Farben in der gesamten Kette erst> nach dem Reset-Puls übernommen werden und zwar nahezu gleichzeitig.
Möglich schon. Aber das liegt dann nicht an der lib sondern am Programm
welches die lib mit Daten füttert. Er hat halt ein Lauflicht
programmiert ;-)
Ne also Joachim, mal ehrlich, deine Aussagen hier zeugen schon von
großer Unbedarftheit. In einem solchen Fall sollte man nicht von
Beweisen schwadronieren und irgendwelche Verzögerungen unterstellen.
Eigenen Code checken und den fixen wär angesagt. Und nicht so lange libs
austesten bis es zufällig mal geht.
Joachim B. schrieb:> Dann wollte ich die wordclock bauen, als ich die 117 LEDs fertig> bestückt hatte kam der erste Test, alle LEDs im Farbwechsel und ich sah> wie die Farben von der ersten zur letzten LED durchgereicht wurden und> habe sagenhafte 300ms gemessen was auch bei den lahmen 800kHz nicht sein> dürfte.
Klingt, als wenn Du ws2812_setleds in einer Schleife aufgerufen hast.
Das ist natürlich Unsinn, da der Aufruf das ganze Array auf einmal
beschreibt. Es wird kein Index, sondern die Länge übergeben. Es gibt
einfach keine Möglichkeit, die LEDS schnell oder langsam zu beschreiben.
Die Geschwindigkeit ist immer die gleiche.
Ich muss mich allerdings den Vorrednern anschließen. Du verunsicherst
mit solchen Kommentaren nur andere Anfänger. Wäre besser, wenn Du Dein
konkretes Problem beschreiben würdest (mit Code!), anstatt solche
Statements abzugeben.
Tim schrieb:> Klingt, als wenn Du ws2812_setleds in einer Schleife aufgerufen hast.> Das ist natürlich Unsinn,
hmmm, ist ja Schnee von vorgestern, ich hatte diese LIB und fastLED
beide auf dem Chip und konnte per #define beide probieren und beide
haben für 117 LEDs und einen Farbwechsel nicht einzeln aufgerufen 300ms
mit dem Oszi vermessen. Komischerweise hatte ich mit fastLED2 sofortigen
Erfolg, damit war bestätigt das die LEDs pro Farbset nur die geschätzten
30µs (1,5µs x24 bit) brauchen und 100 davon ca. 3ms.
Nun könnt ihr mich alle füür blöd halten, aber warum habe ich das denn
sofort mit fastLED2 geschafft?
Die einzige Erklärung die ich noch habe, falsche LIB erwischt, falsch
aufgerufen, was ich aber nicht glaube
ich wollte gerade noch mal nachsehen, aber der Link
Beitrag "Re: Lightweight WS2811/WS2812 Library"
führt zu:
https://github.com/cpldcpu/light_ws2812/tree/master/light_ws2812
page not found, in Schelm der Böses dabei denkt..... OK die Vorversionen
sind alle rausgeschmissen, kann ich verstehen
aber wo sollte mein Fehler sein wenn ich
#define MAXLEDS 117
for(i=0;i<MAXLEDS;i++)
{
value.b = 255; value.g = 0; value.r = 0; // RGB Value -> Blue
LED.set_crgb_at(i, value); // Set value at LED found at index 0
}
CONTRL_LED_ON; //macro eine single_LED am anderen Port einschalten
LED.sync(); // Sends the value to the LED
CONTRL_LED_OFF; //macro single_LED am anderen Port ausschalten
und die T on Time der CONTRL_LED mit dem Osi prüfe?
aber egal, ich hatte 2 LIBs versucht bei der 3ten Erfolg, es ist nun
müssig zu suchen woran es lag, könnte ich natürlich wiederholen, aber
mag ich grad nicht.
Vielleicht hatte ich auch nur eine vorvorfinal Version erwischt.
dann tut mir meine Kritik am TO leid.
Tim schrieb:> Du hast leider immer noch nicht> den tatsächlich von Dir benutzten Code gepostet.
mir wurde unterstellt
Tim schrieb:> Klingt, als wenn Du ws2812_setleds in einer Schleife aufgerufen hast.
und das hatte ich nicht, du kannst mich für blöd halten aber ich weiss
was ich getippt hatte:
Joachim B. schrieb:> for(i=0;i<MAXLEDS;i++)> {> value.b = 255; value.g = 0; value.r = 0; // RGB Value -> Blue> LED.set_crgb_at(i, value); // Set value at LED found at index 0> } // LED set in der Schleife>> CONTRL_LED_ON; //macro eine single_LED am anderen Port einschalten> LED.sync(); // Sends the value to the LED> CONTRL_LED_OFF; //macro single_LED am anderen Port ausschalten
// Messung ausserhalb der Schleife
komisch nur, das ich deine erste LIB die ich funktionierend an einem
puren Atmel auf eine Lochraster selbst gebaut mit einer Arduino LIB aus
anderer Quelle (ich nehme mal an nicht von dir) am nanoV3 verglichen
hatte und das beide 300ms für die 100 LEDs benötigten.
> Allerdings verstärkt sich mein Verdacht von oben...
nun ja bleibt dir unbenommen.
ist kein Problem, deine LIB ist ja hier nicht nicht für Arduino, ich
brenne das noch mal auf die pure AVR Musteplatte s.o.
welche Version ist jetzt aktuell? bitte Link.
Tim schrieb:> Klingt, als wenn Du ws2812_setleds in einer Schleife aufgerufen hast.
könnte glatt sein (sorry)
aber dann muss ich ein Verständnisfehler zwischen set_led und send_array
haben
im blinky.c wurde nirgends send_array aufgerufen und das war die
Vorlage.
Wie würde es denn in deiner LIB richtig laufen?
also set_led und send_array unabhängig? (dann könnte ich send ja
vermessen und meine Falschbehauptung selber widerlegen).
dann würde set led nicht einzeln erfolgen sondern wenn fertig mit
send_array?
tut mir echt leid wenn ich hier falsches geschrieben hatte, aber ohne
bessere Erklärung wie man das nutzt ist mein Fehler verständlich.
Joachim B. schrieb:> Tim schrieb:>> Klingt, als wenn Du ws2812_setleds in einer Schleife aufgerufen hast.>> könnte glatt sein (sorry)
Ok, danke fürs Nachforschen! Eine andere Erklärung hätte mich sehr
erstaunt.
> aber dann muss ich ein Verständnisfehler zwischen set_led und send_array> haben> im blinky.c wurde nirgends send_array aufgerufen und das war die> Vorlage.
Ja, und warum rufst Du es dann in Deinem Code auf? Weder im Readme, noch
in dem Beispiel wird diese Funktion erwähnt. Ich sehe aber, woher die
Verwechslung kam.
"send_array" ist eine interne Funktion, die im Wesentlichen aus
Kompatibilitätsgründen zur v1.0 vorhanden ist. Grund für das neue
Interface ist, dass viele die Anzahl der LEDs und Bytes verwechselt
haben und mit dem Drumherum (INT sperren, delay für reset) nicht zurecht
kamen.
> Wie würde es denn in deiner LIB richtig laufen?>> also set_led und send_array unabhängig? (dann könnte ich send ja> vermessen und meine Falschbehauptung selber widerlegen).
Die Funktion heisst "set_leds", weil sie mehrere LEDs beschreibt. Die
LEDS werden im Array übergeben. Es ist überhaupt nur dieser eine
Funktionsaufruf notwendig.
> tut mir echt leid wenn ich hier falsches geschrieben hatte, aber ohne> bessere Erklärung wie man das nutzt ist mein Fehler verständlich.
Mir fällt auf, dass ich vielleicht noch ein Beispiel zum Beschreiben
ganzer Strings hinzufügen sollte. Das sollte einige Missverständnisse
ausräumen.
Tim schrieb:> Die Funktion heisst "set_leds", weil sie mehrere LEDs beschreibt. Die> LEDS werden im Array übergeben. Es ist überhaupt nur dieser eine> Funktionsaufruf notwendig.>>> tut mir echt leid wenn ich hier falsches geschrieben hatte, aber ohne>> bessere Erklärung wie man das nutzt ist mein Fehler verständlich.>> Mir fällt auf, dass ich vielleicht noch ein Beispiel zum Beschreiben> ganzer Strings hinzufügen sollte. Das sollte einige Missverständnisse> ausräumen.
sorry das verstehe ich grad noch nicht, ich meinte wie setze ich die
Farben, Helligkeiten einzelner LEDs im Array bevor set_leds aufrufe?
Ich möchte ja für meine Wordclock nur die nötigen LEDs setzen und dann
komplett abschicken.
Joachim B. schrieb:> sorry das verstehe ich grad noch nicht, ich meinte wie setze ich die> Farben, Helligkeiten einzelner LEDs im Array bevor set_leds aufrufe?
Wie man halt Arrays in Ansi-C beschreibt:
1
structcRGBled[16];// array mit 16 leds reservieren
2
3
led[0].r=255;led[0].g=00;led[0].b=0;// Write red to led1
4
led[1].r=255;led[1].g=00;led[1].b=0;// Write red to led2
5
led[2].r=255;led[2].g=00;led[2].b=0;// Write red to led3
Alternativ kannst Du auch die ganze Struct (cRGB) gleichzeitig schreiben
und Dir vorher Farben definieren.
Tim schrieb:> Mir fällt auf, dass ich vielleicht noch ein Beispiel zum Beschreiben> ganzer Strings hinzufügen sollte. Das sollte einige Missverständnisse> ausräumen.
dazu fällt mir noch ein, ist denn set_led nicht ein "ungünstiger" Name
für eine Funktion die nur die LED im Array setzen soll?
ich fand
Tim schrieb:> "send_array" ist eine interne Funktion, die im Wesentlichen aus> Kompatibilitätsgründen zur v1.0 vorhanden ist.
doch irgendwie verständlicher,
also LED setzen im Array mit der Funktion set_led und abschicken mit
send_array.
Da wären alle Missverständnisse doch selbsterklärend ausgeräuumt.
Tim schrieb:> Ja, da hast Du vielleicht recht. Aber es macht wenig Sinn das jetzt zu> ändern, da es nur noch mehr Verwirrung stiften würde.
OK, wenigstens DANKE das du mich nicht für doof hältst
cyblord ---- schrieb:> Nutze auch die lib von Tim aber ich hab keine Ahnung was dein gelaber> von wegen fastLED dauernd soll.Di Pi schrieb:> Joachim B. schrieb:>> selbst an mir gezweifelt.>> Der erste Schritt in die richtige Richtung :)
Joachim B. schrieb:> Tim schrieb:>> Ja, da hast Du vielleicht recht. Aber es macht wenig Sinn das jetzt zu>> ändern, da es nur noch mehr Verwirrung stiften würde.>> OK, wenigstens DANKE das du mich nicht für doof hältst>> cyblord ---- schrieb:>> Nutze auch die lib von Tim aber ich hab keine Ahnung was dein gelaber>> von wegen fastLED dauernd soll.> Di Pi schrieb:>> Joachim B. schrieb:>>> selbst an mir gezweifelt.>>>> Der erste Schritt in die richtige Richtung :)
Du hast die lib, wie von uns vermutet, einfach nur falsch benutzt.
PUNKT.
Ob das nun an angeblich ungünstigen Funktionsnamen liegt, sei
dahingestellt. Nur lag das Problem eben nicht in der lib, sondern in
DEINEM Code der die lib nutzt. Trotzdem hast du auf die lib gehauen und
den Fehler dort hingeschoben.
Also verdreh das jetzt hier nicht.
cyblord ---- schrieb:> Du hast die lib, wie von uns vermutet, einfach nur falsch benutzt.> PUNKT.
ja und?
> Ob das nun an angeblich ungünstigen Funktionsnamen liegt, sei> dahingestellt.
woran denn sonst, schliesslich kann ich lesen, wenn es led_set gibt muss
das noch lange nicht led_sync sein, ich kann nämlich unterscheiden
zwischen setzen und syncen, aber egal, DU sollst RECHT behalten wenn es
dir dann besser geht.
> Nur lag das Problem eben nicht in der lib, sondern in DEINEM Code der die lib
nutzt. Trotzdem hast du auf die lib gehauen und
> den Fehler dort hingeschoben.
ich habe 2 verschiedene LIB genutzt und gleiche Ergebnisse bekommen,
worauf sollte ich es denn sonst schieben?
uns als ich die dritte LIB nutzte klappte es wie erwartet.
> Also verdreh das jetzt hier nicht.
und was motzt du hier rum?
ich verdrehe nix, aber du pöbelst.
ich wollte noch mal ne kleine Rückmeldung geben
ich habe ja einige Platinen hiervon bestellt und schon 2 aufgebaut:
https://github.com/JChristensen/mini1284
vorher arbeitete ich mit der Arduino FastLED Lib am m328p aber am m1284p
funktionierte die nicht, Timingproblem, alle Farbwerte 24 x 1,5µs = 30
µs wurden zu langsam übertragen, 33µs und die WS2812b spielten nicht
mit.
Erst dachte ich an einen Ausreisser, baute den m1284p 2x auf.
Dann wechselte ich dem mit 16 MHz programmierten m1284p den Quarz zu
18,432MHz und siehe da, Timing passt 30µs WS2812b läuft aber mit der
Verständigung zur Arduino IDE war es nun aus.
Dann erinnerte ich mich hieran und band die ws2812b LIB ein die es ja
nun auch vom Tim als Arduino LIB gibt und siehe da es läuft! auch auf
dem m1284p
Dafür schon mal ein Riesendanke...
nun noch meinen ganzen Code auf WS2812 Lib umstricken.....
mühsam.....
Hallo Tim,
Ich nutze Deine Lib auf dem Arduino Uno.
Klappt hervorragend im direkten Aufruf.
Da ich mehrere LED Streifen unterschiedliche Aufgabe, aber gleicher
Logik beabsichtige (Farbverteilung an Hand von Parametern, Löschen der
nicht genutzten LEDs), bietet es sich an, die Task in Subroutinen zu
verpacken und mit dem jeweiligen LED-Objekt und Parametersatz zu rufen.
Ich bin noch nicht ganz fertig damit, aber auch das scheint lässig und
ohne Verrenkungen möglich zu sein - Prima Design!
Vielen Dank,
Tarik
Hallo Tim,
gibt es eine Möglichkeit, die Leds zu Gruppieren, damit das struct/Array
entsprechend klein sein kann?
Ich habe 100 Leds. Wobei immer 10 Stück hintereinander den gleichen Wert
haben sollen.
Müsste halt eine externe Variable oder einen weiteren Parameter haben,
um die Anzahl an gleicher aufeinaderfolgender Leds
Wenn ich das richtig sehe, müsste ich nach dem Entritt in While schleife
dafür sorgen, dass sich jeweils nach 3 Durchläufen das Muster
wiederholt, komm da aber noch nicht mit klar. Bin noch recht neu dabei.
Könnte mir da evtl. jemand die Funktion kurz anpassen?
Das lässt sich recht einfach realisieren, indem man die Funktion
mehrmals hintereinander aufruft. Dass funktioniert nur mit dem alten
Interface, da die neue Funktion bereits den Reset-delay beinhaltet.
Es gibt ein Beispiel im Repository:
https://github.com/cpldcpu/light_ws2812/blob/master/light_ws2812_AVR/Examples/Chained_writes.c
Die Daten werden erst beim Reset (>10µs delay) in die LEDs übernommen.
So lange zwischen den Schreibzugriffen weniger als 5µs liegen, können
diese aneinander gereiht werden.
Hallo Tim, danke schon einmal für die schnelle Antwort
Habe einmal 8 Leds angeschlossen. Led 1 - 4 soll den gleichen Wert
zugewiesen bekommen. Genauso bekommt Led 5 - 8 den gleichen Wert.
Leider tut sich so noch nichts.
Hallo,
ich habe ein Problem bei deiner APA102C Lib.
Möchte das ganze mit dem Attiny841 und HW SPI betreiben.
in /*...*/ steht der orginal Inhalt, was mache ich hier bei der HW SPI
falsch, dass keine Daten gesendet werden?
1
inlinevoidSPI_init(void)
2
{
3
// MOSI | SCK
4
DDRA|=(1<<PORTA6)|(1<<PORTA4);
5
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0);
6
/*
7
apa102_DDRREG |= _BV(apa102_data);
8
apa102_DDRREG |= _BV(apa102_clk);
9
apa102_PORTREG &= ~_BV(apa102_clk); // initial state of clk is low
10
*/
11
}
12
13
// Assumed state before call: SCK- Low, MOSI- High
14
voidSPI_write(uint8_tc){
15
SPDR=c;
16
while(!(SPSR&(1<<SPIF)));
17
18
/*uint8_t i;
19
for (i=0; i<8 ;i++)
20
{
21
if (!(c&0x80)) {
22
apa102_PORTREG &= ~_BV(apa102_data); // set data low
23
} else {
24
apa102_PORTREG |= _BV(apa102_data); // set data high
25
}
26
27
apa102_PORTREG |= (1<< apa102_clk); // SCK hi , data sampled here
Hi, ich versuche auch gerade die Library zum Laufen zu bekommen. Leider
bisher erfolglos... Mein Attiny45 erzeugt zwar ein Signal, die Lows und
Highs sind aber ca. 10x länger als sie sein sollten. Der Attiny läuft
auf 8MHz, F_CPU ist entsprechend definiert, die Warteperiode wird auch
richtig erzeugt, aber mit dem WS2812-Code scheint irgendetwas nicht zu
stimmen.
Hier der Minimalcode:
1
1#defineF_CPU8000000UL
2
2#include<util/delay.h>
3
3#include"light_ws2812.h"
4
4
5
5structcRGBled[10];
6
6
7
7intmain(void)
8
8{
9
9
10
10intval=255;
11
11inti;
12
12
13
13/*CLKPR=_BV(CLKPCE);*/
14
14/*CLKPR=0;*/
15
15while(1)
16
16{
17
17for(i=0;i<10;i++)
18
18{
19
19
20
20led[i].r=255;
21
21led[i].g=0;
22
22led[i].b=0;
23
23}
24
24
25
25ws2812_setleds(led,10);
26
26
27
27/*val++;*/
28
28/*if (val == 256) val = 0;*/
29
29_delay_ms(5);
30
30}
31
31}
Hab auch spaßeshalber mal probiert, F_CPU um den Faktor 10 kleiner zu
machen, das ändert aber nix. Irgendeine Idee, was ich falsch mache?
Angehängt sind die Logic Analyzer-Screenshots von den erzeugten Takten
und den 5ms-Warteperioden
Icke ®. schrieb:> Auch das ist nicht möglich, weil die Farben in der gesamten Kette erst> nach dem Reset-Puls übernommen werden und zwar nahezu gleichzeitig.
Das stimmt leider schlicht nicht, bzw. erst dann, wenn mehr als ca. 256
LEDs angesteuert werden.
Man sieht das nur nicht, wenn man die Dinger mit einem einzelnen Burst
füttert und dann einen stabilen Pegel ausgibt (also z.B. Latch/Reset).
Nach "kurzer" Zeit übernehmen dann zwar alle LEDs den zuletzt an sie
gesandten Wert, aber eben nicht gleichzeitig, sondern nach einem
bestimmten Schema verzögert.
Wenn man den Kram nicht nach der Burst-Methode ansteuert, sonder sich
die Mühe macht, einen Treiber zu programmieren, der zyklisch mit Vmax
die Dinger füttert, dann kann man dieses Verhalten sehr schön sichtbar
machen.
Das habe ich (anfangs ungewollt) bei dem Versuch getan, die PWM der LEDs
um zusätzliche 3Bit in Software zu erweitern. Das Ergebnis sah einfach
mal Scheisse aus und garnicht so, wie eigentlich erwartet, es zeigten
sich nämlich "wabernde" Störungen statt gleichmäßig verringerter
Helligkeit.
Also die 3Bit-Erweiterung zunächst provisorisch auf nur ein Bit
zurückgebaut und die Sache mal genauer untersucht. Effektiv wird als
Testmuster also abwechselnd immer ein Frame komplett "weiss" und ein
Frame komplett "schwarz" rausgeschickt. Ein komplettes Frame meiner 1
Bit PWM-Erweiterung umfasst hier also 2 Frames des LED-Feeds.
Und obwohl die effektive Framerate (~285Hz bei 60 LEDs) eigentlich
locker für einen gleichmässigen Helligkeitseindruck reichen sollte,
zeigte sich ein waberndes Helligkeitsmuster und diesem Wabern sah man
sofort an, dass es irgendwie regulär ist.
Also, wenn's regular ist, dann sollte sich die Sache besser sichtbar
machen lassen, wenn man statt 1:1 Duty 1:n verwendet und n eine
Primzahl-1 sein lässt. Gedacht, getan: bei 1:6 ergab sich dann deutlich
sichtbar das ganze Ausmass dieser Scheisse.
Womit für's Erste meine Idee der PWM-Erweiterung gestorben ist. Bis zu
dem Zeitpunkt, wo ich die Gesetzmäßigkeiten der Sache vollständig
verstanden habe, was bis dato nicht der Fall ist. Nur einige Teilaspekte
konnte ich aufklären bzw. sind bereits aus dem 1:6-Versuch direkt
offensichtlich geworden.
Wer Lust hat, kann ja mitknobeln, am Wochenende werde ich mal meine
bisherigen Ergebnisse aufbereiten und hier posten. Ich werde dafür dann
einen neuen Thread namens "The secret of WS2812B" eröffnen.
Wer das nachvollziehen will, sollte sich irgendeinen AVR besorgen mit
SPI-fähiger UART und der Fähigkeit, mit einem 20MHz Quarz zu laufen. Ich
habe konkret einen Tiny4313 verwendet, es sollte aber auch jeder andere
gehen, der die genannten Anforderungen erfüllt.