mikrocontroller.net

Forum: Projekte & Code WS2812 Ansteuerung per Bitbanging für AVR und ARM von 4 Mhz-60 Mhz


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Tim  . (cpldcpu)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Da ich bisher hier noch keinen Beitrag geschrieben hatte, möchte ich 
noch einmal auf meine light-weight WS2812 Library hinweisen. Die Library 
nutzt Zyklengenaues CPU-Timing ("bitbanging"), um WS2812 
RGB-Leuchtdioden anzusteuern.

Der Code wird durch bedingte compilierung automatisch für die gewünschte 
Taktgeschwindigkeit der CPU ausgelegt. Für AVR gibt es implementierungen 
ab 4 Mhz, für ARM ab 8 Mhz.

Der Code kann auf Github heruntergeladen werden:

https://github.com/cpldcpu/light_ws2812

Die Implementierung über Bitbanging hat auf AVR gegenüber Ansätzen mit 
SPI und PWM den Vorteil, dass sie weniger Ressourcen benötigen und 
kleiner sind. Die CPU-Belastung ist identisch.


This is a small Ansi-C library to control WS2811/WS2812 based RGB Leds and strings. Only the 800kHz high-speed mode is supported. This library uses a bit-banging approach with cycle optimized assembler innerloops. Some advantages of this approach compared to existing solutions are:

    *Compatible to all AVR MCUs since it does not rely on special periphery.
    *Low hardware footprint: Does not rely on any timer or the USI
    *Much smaller program code: Size optimized assembler without unrolled loops (<50 bytes in most cases)
    *No initialization required
    *Carefully optimized to use instructions which are available on all AVR cores and have the same instruction timing across all devices.
    *Supports standard AVR, reduced core AVR (Attiny 4/5/9/10/20/40) and XMEGA (untested) without special case handling.
    *New:Supports Cortex ARM cores.
    *Arduino or C++ not required
    *Clock speeds down to 4Mhz supported.

Release History
===============

    v0.3 2013/05/06
        *Initial release. Thanks to "Matthias H." for testing with a longer led chain.
    v0.4 2013/05/07
        *General clean up
        *Some code size optimizations. Thanks to "Fallobst" for suggestions
        *Disabled interrupts in the critical sections.
    v0.5 2013/05/20
        *Fixed timing bug from size optimization
    v0.6 2013/05/27
        *Major update: Changed all port accesses from SBI/CBI to OUT. This
        *removes a timing inconsistency between reduced core AVR and
        *standard AVR, avoiding separate implementations for different            
        *cores. A disadvantage is increase register usage.
        *Added the "ws2812_sendarray_mask" function which allows to pass 
         a bitmask for the selected port. This allows controlling up to 
         8 independent LED strips.
        *Removed functions for interrupt handling. Avoiding interference
         with interrupts is now up to the user.
        *4 MHz clock speed is now also supported for standard core AVRs.
    v0.7 2013/05/28
        *Optimized timing and size of 8 and 12 Mhz routines. All routines
         are within datasheet specs now, except of 9.6 Mhz which is
        *marginally off but works under all test conditions
    v0.8 2013/06/03
        *9.6 Mhz implementation now within specifications.
        *brvs->brcs. Loops terminate correctly (thanks to Mario Pieschel).
    v0.9 2013/07/29
        *Added first version of ARM Cortex library
        *20 MHz AVR Version contributed by http://github.com/denimjeans

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier übrigens noch eine Interessante Diskussion zur ARM-Version.

http://www.lpcware.com/content/forum/controlling-ws2812-led-strips-lpc810

Auf dem LPC 810 ist es möglich, die CPU durch geschickte Nutzung der 
Peripherie zu entlasten.

Autor: Ben W. (ben_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit DMA kann man die CPU bei der Übertragung praktisch komplett 
entlasten.
Hab das ganze mal auf einem STM32F4 ausprobiert.
(https://github.com/benwilliam/equinox_clock/tree/master/WS2811)

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt ein Miniupdate mit einem neuen Beispiel, in dem verkettete 
Aufrufe verwendet werden, um das LED-Muster in Echtzeit zu erzeugen.

https://github.com/cpldcpu/light_ws2812
v0.9b 2013/08/30
    Added new example for chained writes.

Autor: Clemens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, danke für den code.
Könnte jemand den assembler code so anpassen das es auch für mehr als 
256 LED-Adressen funktioniert? momentan wird der blauwert bei mir nicht 
bei der korrekten LED angezeigt wenn ich die Variablendeklaration des 
Zeigers einfach auf uint16_t ändere.

Ich nehme an das bei dem assembler teil irgendwas mit dem Überschlag 
nicht klappt.. aber da sehe ich leider nicht durch

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hallo, danke für den code.
> Könnte jemand den assembler code so anpassen das es auch für mehr als
> 256 LED-Adressen funktioniert? momentan wird der blauwert bei mir nicht
> bei der korrekten LED angezeigt wenn ich die Variablendeklaration des
> Zeigers einfach auf uint16_t ändere.


Hallo Clemens,

- Bei welcher Routine taucht das Problem genau auf? CPU? MHz?
- Warum willst Du den Zeiger auf einen 16bit Typen verändern? Die LEDs 
benötigen nur 3 bytes pro LED.
- Außer der 4 Mhz implementierung unterstützen alle Routeinen mehr als 
256 LEDs. Dazu musst Du im Code nichts ändern.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Nachhinein fällt mir auf, dass Du evtl. etwas in der C-Syntax 
verwechselst: (uint8_t*) beschreibt einen Zeiger auf ein Byte, 
(uint16_t*) auf ein Word. Beide Zeiger sind auf AVR immer 16 Bit groß.

Autor: Clemens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahh, ja, das habe ich wohl verwechselt. Danke für die Klarstellung. Ich 
begebe mich erstmal auf Fehlersuche in meinem Code.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kleines Update: In den Beispielen werden Interrupts während des 
Library-calls unterdrückt.

v0.9c 2013/09/08
    Updated examples to disable interrupts.

Autor: Jürgen E. (sid)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

das sieht echt sehr gut aus. Kurze Frage bevor ich es teste:
Funktioniert das ganze auch ohne externes Quarz?
Also z.B. mit einem Attiny85@8Mhz(intern)? Ich will nicht viel LEDs 
damit betreiben. Vielleicht 4 oder 8.

Gruss
Juergen

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen Eckert schrieb:
> Funktioniert das ganze auch ohne externes Quarz?

Ja, da das Protokoll asynchron ist, ist es ziemlich tolerant gegenüber 
abweichendem Timing. +-2% sollten eigentlich kein Problem sein.

: Bearbeitet durch User
Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
V1.0!
 v1.0 2013/12/11  
 - Moved IRQ disabling to library again.


Troubleshooting

Only a part of the string is lighting up / all the colours are wrong

    Please check whether the correct array length was passed to the call. The value to by passed is the array-length in bytes. Therefore you have to pass the number of LEDs multiplied by three.

The LEDs are flickering and not showing the intended colour

    Are you using a bypass capacitor for each LEDs as indicated in the datasheet? Not using a bypass capacitor will lead to erroneous behaviour.
    Is your power supply able to supply the required current-level? If set to white at maximum brightness, each LED will require 60mA. A single USB-Port is barely able to supply 10 LEDs.
    Did you choose the correct CPU frequency setting? Maybe you multiplier setting is wrong?
    Is anything interrupting correct executing of the write-calls? Interrupts? Watch-dog?

Autor: Hans Ulli K. (elektroman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nett ...

Ich würde mal in deinem Repo mal irgendeine Lizenz angeben.
Es reicht nicht das du dieses per Anmeldung auf Github machst.

Ich kenne mich jetzt nicht mit den Mikrocontrollern aus (eher Linux 
Kernel)
Kann das denn noch irgendwie erweitert werden, das diese Sache per 
serieller Schnittstelle der USB gesteuert werden kann ?

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans Ulli Kroll schrieb:
> Ich würde mal in deinem Repo mal irgendeine Lizenz angeben.
> Es reicht nicht das du dieses per Anmeldung auf Github machst.

Was hat das Eine mit dem Anderen zu tun? Ich kann natürlich eine LGPL, 
GPL o.Ä. ins Repository klatschen, aber ehrlich gesagt erscheint mir so 
etwas im µC Bereich doch eher unüblich zu sein.

> Ich kenne mich jetzt nicht mit den Mikrocontrollern aus (eher Linux
> Kernel)
> Kann das denn noch irgendwie erweitert werden, das diese Sache per
> serieller Schnittstelle der USB gesteuert werden kann ?

Wie auch unter Linux, kann man mehrere Libraries kombinieren um Software 
mit der gewünschten Funktion zu entwickeln. Für AVR gibt es z.B. V-USB, 
welches eine USB Schnittstelle zur Verfügung stellt.

Autor: Hans Ulli K. (elektroman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim    schrieb:
> Hans Ulli Kroll schrieb:
>> Ich würde mal in deinem Repo mal irgendeine Lizenz angeben.
>> Es reicht nicht das du dieses per Anmeldung auf Github machst.
>
> Was hat das Eine mit dem Anderen zu tun? Ich kann natürlich eine LGPL,
> GPL o.Ä. ins Repository klatschen, aber ehrlich gesagt erscheint mir so
> etwas im µC Bereich doch eher unüblich zu sein.
>

Was du damit machst ist mir ehrlich egal ...

Als großes Bespiel fällt mir sofort ContikiOS. Das soll auf verschiedene 
µC laufen.
Dieses wird für Internet of Things benutzt. Zigbee, 6lowpan usw.

>> Ich kenne mich jetzt nicht mit den Mikrocontrollern aus (eher Linux
>> Kernel)
>> Kann das denn noch irgendwie erweitert werden, das diese Sache per
>> serieller Schnittstelle der USB gesteuert werden kann ?
>
> Wie auch unter Linux, kann man mehrere Libraries kombinieren um Software
> mit der gewünschten Funktion zu entwickeln. Für AVR gibt es z.B. V-USB,
> welches eine USB Schnittstelle zur Verfügung stellt.

Danke habe ich mir gerade ansehen. USB 1.1 reicht hier dicke.

Das könnte ein Projekt für Winterabende werden

Autor: grindguakn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo


ich verwende deine lib für den atmega1284p mit 16mhz quarz!
gut die portpins wackeln vor sich hin allerdings funktionieren tuts 
leider nicht so wie ich das will .. es leuchtet genau gar nichts. 
Leider!

Ist die Lib für den ws2811 gemacht oder nur für den ws2812???

habe mal im datenblatt ws2811 und ws2812 verglichen. Bis auf die Timings 
arbeiten die beiden genau gleich.
Das heißt ich müsste in die Funktion:

void ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
{
        irq_disable
        uint8_t curbyte,ctr,masklo;
        masklo        =~maskhi&ws2812_port;
        maskhi |=ws2812_port;
        
        while (datlen--) {
                curbyte=*data++;
                
                asm volatile(
                
                "                ldi        %0,8                \n\t"                // 0
                "loop%=:out        %2,        %3                \n\t"                // 1
                "                lsl        %1                        \n\t"                // 2
                "                dec        %0                        \n\t"                // 3

                "                rjmp .+0                \n\t"                // 5
                
                "                brcs .+2                \n\t"                // 6l / 7h
                "                out        %2,        %4                \n\t"                // 7l / -

                "                rjmp .+0                \n\t"                // 9
                
                "                nop                                \n\t"                // 10
                "                out        %2,        %4                \n\t"                // 11
                "                breq end%=                \n\t"                // 12 nt. 13 taken

                "                rjmp .+0                \n\t"                // 14
                "                rjmp .+0                \n\t"                // 16
                "                rjmp .+0                \n\t"                // 18
                "                rjmp loop%=                \n\t"                // 20
                "end%=:                                        \n\t"
                :        "=&d" (ctr)
                :        "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_port)), "r" (maskhi), "r" (masklo)
                );
        }
        irq_restore
}

wenn ich hier ein paar "nops" dazwischen reinpacke sollte es hinhauen??
kann mir hier jemand weiterhelfen? kenn mich mit assembler absolut 
nussbrot aus!
Wäre nett wenn hier jemand fix drüber sehen könnte :)

Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
grindguakn schrieb:
> ich verwende deine lib für den atmega1284p mit 16mhz quarz!
> gut die portpins wackeln vor sich hin allerdings funktionieren tuts
> leider nicht so wie ich das will .. es leuchtet genau gar nichts.
> Leider!

Hast du denn die Anweisungen unter "Usage" auf 
https://github.com/cpldcpu/light_ws2812 beachtet?

Ich weise mal gezielt auf den Punkt "Wait for at least 50 us before the 
next LED update to reset the chain" hin.

Autor: Carsten M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist das eigentlich mit der Leitungslänge und so. Hat da mal jemand 
ein bisschen Probiert. 20 oder 30 LEDs sind ja nun wahrlich kein Test... 
Was passiert nach 180 LEDs usw ? .... any problems ?

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
grindguakn schrieb:
> ich verwende deine lib für den atmega1284p mit 16mhz quarz!

Und was für LEDs versuchst Du anzusteuern? Beschreibe Deinen Aufbau am 
besten genau und poste auch Deinen Source. WS2811 hat m.W. bisher 
tatsächlich noch niemand getestet.

Bisher lag es jedes mal an etwas anderen als dem Timing.

: Bearbeitet durch User
Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carsten M. schrieb:
> 20 oder 30 LEDs sind ja nun wahrlich kein Test...
> Was passiert nach 180 LEDs usw ? .... any problems ?

Da das signal in den LEDs regeniert wird, ist die Länge für die 
Ansteuerung egal. Ein ganzer Streifen (240 LEDs) ist kein Problem. 
Allerdings kann es sein, dass man bei langen Strings an meherren Stellen 
Strom einspeisen muss.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir vorgenommen, das Interface zur Library zu überarbeiten, da 
sich Missverständnisse in gewissen Bereichen zu häufen scheinen. Bisher 
habe ich nur ein "Bare-Bones" Interface definiert, da ich persönlich die 
volle Kontrolle über eine Lib bevorzuge.

Das bisherige Interface besteht nur aus zwei Funktionen:
void ws2812_sendarray(uint8_t *ledarray,uint16_t length);
void ws2812_sendarray_mask(uint8_t *ledarray,uint16_t length, uint8_t mask);

Zusätzliche wird per Define manuell die zur Taktgeschwindigkeit der CPU 
passende Routine ausgewählt.

Mir schweben folgende Änderungen vor:

- Wenn keine Routine per Define ausgewählt wurde, wird versucht 
automatisch aus F_CPU eine abzuleiten.
- Es wird im Headerfile die struct cRGB definiert und als Datentyp für 
den Aufruf verwendet.

Über das bisherige Interface wird folgendes gestülpt:
// Führt Reset durch
void ws2812_setleds(cRGB *ledarray, uint16_t number_of_leds);
void ws2812_setleds(cRGB *ledarray, uint16_t number_of_leds,uint8_t pin);

// Führt keinen Reset durch
void ws2812_setleds_noreset(cRGB *ledarray, uint16_t number_of_leds);
void ws2812_setleds_noreset(cRGB *ledarray, uint16_t number_of_leds,uint8_t pin);

// Wartet 100 us
void ws2812_reset();

Denkbar wäre es auch, den Port zur Laufzeit zu übergeben. Das wäre aber 
erst ab 12MHz umsetzbar.

Eine weitere Änderung könnte sein, dass man per Define das Timing ändern 
kann, wie es in der ARM-Version jetzt möglich ist. Allerdings erscheint 
mir dieses gefährlich, da bisher jeder impulsiv etwas an den TImings 
ändern will, die wirklich Fehlerquellen bisher aber wirklich immer 
woanders zu suchen waren.

Ist das Interface soweit verständlich? Gibt es Vorschläge zur Änderung 
der Namen?

: Bearbeitet durch User
Autor: Grindguakn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
Also ich verwende diese 
Ebay-Artikel Nr. 310772659909 LED Pixel! Habe 
zurzeit testweise 1 Stück probiert!

Zur Schaltung ich habe ein Atmega1284p Board und die Pixel werden mit 
einem stabilisierten Netzteil versorgt also Spannungseinbrüche etc. Kann 
ich ausschließen.

Zur Software: ich habe das testbsp von github verwendet, demnach sollte 
es auch keine Probleme mit reset Zeiten geben .. (Software kann ich bei 
Bedarf posten! Bin aber nur am Handy)

Pb0 habe ich mir oszi nachgemessen und ja es toggelt! Allerdings reicht 
die Bandbreite meines oszis ansxheinend nicht da ich nur mehr Impulse 
erkennen kann..

Kann es eventuell sein dass ich einen pull up oder so benötige?
Oder muss ich den Portpin irgendwie initialisieren??

MfG und danke schon mal für die Hinweise!

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grindguakn schrieb:
> Pb0 habe ich mir oszi nachgemessen und ja es toggelt! Allerdings reicht
> die Bandbreite meines oszis ansxheinend nicht da ich nur mehr Impulse
> erkennen kann..

Das sind gerade mal 1Mhz, mit einem 20MHz Osci sollte man etwas sehen 
können. Du kannst ja die Warteschleife einmal entfernen, dann sollte man 
auch vernünftig triggern können.

Grindguakn schrieb:
> Also ich verwende diese
> Ebay-Artikel Nr. 310772659909 LED Pixel! Habe
> zurzeit testweise 1 Stück probiert!

Wie gesagt, mit dem WS2811 habe ich keine Erfahrung. Es kann sein, dass 
das Timing wirklich anders ist. Du solltest auf jeden Fall zunächst 
überprüfen, ob Deine Clock Settings wirklich auf 16MHz sind. Ist der 
Divider richtig konfiguriert, oder läuft dein MCU vielleicht doch mit 
8MHz? Ist der WS2811 auch im high-speed Mode konfiguriert? Hast Du evtl. 
eine echte WS2812 LED, um zu testen ob alles funktioniert?

Anonsten könntest Du tatsächlich versuchen, dass Timing zu verändern und 
zu sehen ob es dann besser wird. Als erstes würde ich versuchen das 
Timing für die "1" zu verlängern. Dazu kannst Du an der markierten 
Stelle ein oder mehrere NOPS einfügen.
          "                dec        %0                        \n\t"

                "                rjmp .+0                \n\t"
                
                "                brcs .+2                \n\t" 
                "                out        %2,        %4                \n\t"

                "                rjmp .+0                \n\t" 
<<<------------ hier nops einfügen ------------ >>>
                
                "                nop                                \n\t"

: Bearbeitet durch User
Autor: grindguakn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja da Uart funktioniert habe ich mal stark angenommen dass die quarz 
einstellungen passen. habe deinen Vorschlag befolgt und gemessen und ich 
hatte immer 0,6µS..

allerdings ist mir aufgefallen, dass auf meinem Board an PB0 eine 
DebugLED war ^^ Die hat den Fehler verursacht anscheinend... LED weg, 
prima funktioniert!


Jedenfalls in diesem Sinne Vielen Dank für deine Hilfe und natürlich 
auch für die Lib! vielleicht kommen am Ende von meinem Projekt ein paar 
nützliche Funktionen für eine API zu deinem Projekt.


mfg

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
grindguakn schrieb:
> allerdings ist mir aufgefallen, dass auf meinem Board an PB0 eine
> DebugLED war ^^ Die hat den Fehler verursacht anscheinend... LED weg,
> prima funktioniert!

Gratulation!  Womit wieder einmal gezeigt wurde, dass es nie am Timing 
liegt :)

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es vielleicht noch Feedback zum Vorschlag von oben?
Beitrag "Re: WS2812 Ansteuerung per Bitbanging für AVR und ARM von 4 Mhz-60 Mhz"

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe soeben den ersten Release der V2 fertiggestellt. Im Vorfeld 
habe ich das Timing der WS2812 noch einmal genau untersucht, um die 
korrekte Ansteuerung von allen Devices sicherzustellen:

http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/

Die Vorteile der neuen Version gegenüber der alten:

-Vereinfachtes Interface zur Ansteuerung.
-Es werden beliebige CPU Taktfrequenzen ab 4 MHz unterstützt. Das Timing 
wird währed der Compilierung automatisch aus "F_CPU"  bestimmt.

Download: https://github.com/cpldcpu/light_ws2812


Description
===========

This is a small Ansi-C library to control WS2811/WS2812 based RGB Leds and strings. 
Only the 800kHz high-speed mode is supported. This library uses a bit-banging approach with cycle optimized assembler innerloops. 

Some advantages of this approach compared to other solutions are:

    Compatible to all AVR MCUs since it does not rely on special periphery.
    The code timing is automatically adjusted for CPU clock speeds from 4 Mhz up to the maximum on AVR.
    Much smaller program code: Size optimized assembler without unrolled loops (<50 bytes in most cases)
    Supports standard AVR, reduced core AVR (Attiny 4/5/9/10/20/40) and XMEGA (untested) without special case handling.
    Arduino or C++ not required
    New: Experimental Cortex-M0 ARM core.

The timing values used in the library were adjusted to work on all devices. Look here for details

Usage
=====

    Add "light_ws2812.c", "light_ws2812.h" and "ws2812_config.h" to your project.
    Update "ws2812_config.h" according to your I/O pin.
    Make sure F_CPU is correctly defined in your makefile or the project.
   (For AtmelStudio: Project->Properties->Toolchain->AVR/GNU C Compiler->Symbols. Add symbol F_CPU=xxxxx)
    Call "ws2812_setleds" with a pointer to the LED array and the number LEDs.
    Alternatively you can use "ws2812_setleds_pin" to control up to 8 LED strips on the same Port.

Examples are provided in the Examples folder. You can build them with the supplied makefile.

Troubleshooting
===============

Please note that incorrect timing is rarely the source of problems. If you want to save some time, go through the items below before altering the library.

None or only a part of the string is lighting up.

    Did you pass the correct array size in the function call?
    Is the pin configuration correct?
    Is anything else connected to the output pin you are using? Some development boards have LEDs connected to various pins.
    Did you choose the correct CPU frequency setting? Did you initialize the clock correctly?

The LEDs are flickering and not showing the intended colour.

    This is usually a problem with insufficient current sourcing capability.
    Are you using a bypass capacitor for each LEDs as indicated in the datasheet? Not using a bypass capacitor will lead to erroneous behaviour.
    You may have to add an additional electrolytic capacitor at the input of your LED strip if you use long power supply lines.
    Is your power supply able to supply the required current-level? If set to white at maximum brightness, each LED will draw 60mA. 
    A single USB-Port is barely able to supply 10 LEDs.


Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim    schrieb:
> Im  Vorfeld habe ich das Timing der WS2812 noch einmal genau
> untersucht, um die korrekte Ansteuerung von allen Devices
> sicherzustellen:
>
> http://cpldcpu.wordpress.com/2014/01/14/light_ws28...

Hi Tim,

super Arbeit! Ich habe aber einen kleinen "Schönheitsfehler" entdeckt.

Am Ende deines Artikels schreibst du

"•A “1″ can be encoded with pulses of almost arbitrary length as long as 
they are not shorter than ~625 ns (minimum on WS2812B)."

Die beliebig lange High-Time einer "1" lässt sich nur für die erste LED 
"sinnvoll" einsetzen, da die "1" am Ausgang auf jeden Fall wieder nur 
ein Puls von 4 Cycles sein wird und somit automatisch ein Lowpegel 
ausgegeben wird, welcher bei der folgenden LED zum Reset führt.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Magnus,

danke für den Hinweis, das wir wirlich etwas missverständlich 
formuliert. Ich habe es geändert.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt dank Matthias (https://github.com/xvzf) jetzt Arduno-Support:

https://github.com/cpldcpu/light_ws2812

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
V2.2 ist jetzt fertig.

    v2.1 2014/03/08
        Added Arduino and C++ support courtesy of Matthias Riegler 
(@xvzf)
    v2.2 2014/11/30
        Improved Ardunio version with variable color order, courtesy of 
Windell Oskay (@oskay)
        Fixed a bug where the other bits of the port were trashed in 
Arduino version.

Download hier:
https://github.com/cpldcpu/light_ws2812

Zusätzlich gibt es jetzt eine Library zur Ansteuerung der APA RGB-LEDs:
https://github.com/cpldcpu/light_ws2812/tree/master/light_apa102_AVR

Hintergrund zu den APA102:
https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
https://cpldcpu.wordpress.com/2014/08/27/apa102/

Autor: Frank M. (frank_41)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es mit Pro Mini AtMega328P und z.Zt. nur 8 LEDs ausprobiert
und hat auf Anhieb funktioniert. (WS2812 für AVR)
Gute Arbeit !!

Autor: Spawnsen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

komischer Weise kann ich nur einmal die Funktion 
"ws2812_setleds(led,1);" aufrufen und danach nicht mehr. Ich habe das 
Beispiel Programm Blinky benutzt und die LED bleibt dauerhaft in der 
ersten eingestellten Farbe eingeschaltet.

Hier der Code aus der main.c
#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "light_ws2812.h"

struct cRGB led[11];

int main(void)
{
  while(1)
  {
    led[0].r=255;led[0].g=255;led[0].b=255;    // Write red to array
    ws2812_setleds(led,1);
    _delay_ms(500);                         // wait for 500ms.

    led[0].r=0;led[0].g=255;led[0].b=0;      // green
    ws2812_setleds(led,1);
    _delay_ms(500);

  }
}

Habe ich etwas falsch verstanden?

Gruß Spawnsen

Autor: Spawnsen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun geht es.
War mal wieder eine Sache der Einstellung.
Habe den Test mit nem atmega8 gemacht und eingestellt war ein 32er.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach langer Zeit wieder ein Update:

v2.3 2015/11/29
    Added support for SK6812RGBW LEDs. Please see example folder for 
usage.

https://github.com/cpldcpu/light_ws2812

SK6812RGBW Support gibt es bisher leider nur für die Ansi-C Version. Die 
Arduino Lib unterstützt diese noch nicht.

: Bearbeitet durch User
Autor: Axel L. (ligonap)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen.

Ich bekommen die Lib (https://github.com/cpldcpu/light_ws2812) nicht ans 
laufen.
Zum Test habe ich fünf ws2812b an ein ATMega328p (an PC0) angeschlossen.
Als Testcode soll mir Rainbow.c aus der lib dienen.

Mein AVRSudio4 schreibt mir folgenden Fehler:
- In function 'main':
- warning: large fixed-point constant implicitly truncated to 
fixed-point type
- sorry, unimplemented: GCC cannot support operators with integer types 
and fixed-point types that have too many integral and fractional bits 
together
- confused by earlier errors, bailing out
        //fade red
        if(led[0].r<colors[j].r)
            led[0].r+=FADE;
->      if(led[0].r>255.r)
            led[0].r=255; 

Da der Macher der Lib nicht antorten kann oder will, versuche ich es mal 
hier.

Als Ausweg bleibt mir nur eine andere, nicht in cpp geschriebene, Lib zu 
nehmen oder eine eigene zu entwickeln.

Danke
Axel

Autor: Axel L. (ligonap)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin zu Testzwecken auf einen anderen Test-Code mit der selben Lib 
gewechselt:
http://gotronik.com/2015/09/07/obsluga-diod-z-kontrolerem-pwm-ws2812b-za-pomoca-atmega32/

Dieser geht. Hurra.

Ich vermute einen Fehler in der Rainbow.c, die der Lib beiliegt.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
rainbow.c hatte tatsächlich ein paar Bugs - es war ein externer Beitrag. 
Das Beispiel sollte jetzt funktionieren. Die anderen Beispiele 
funktionierten allerdings auch schon vorher

Freut mich, dass es mit dem anderen Beispiel funktioniert hat.

Autor: Axel L. (ligonap)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Mein nächster Schritt von der Testphase weg, ist es mittels Array die 
LED zu steuern.

Was bei der Audioausgabe ohne Probelme ging, will bei den LEDs nicht 
gelingen. Ich habe den sehr einfachen Code als Datei hinterlegt.

Nach dem Start werden die fünf LED orange, wie es die zweite Zeile im 
Array auch definiert. Dann gehen die LEDs aus, was auch OK ist. Aber 
anschließend werden die LEDs nach der ersten Zeile definiert und nicht 
nach der dritten Zeile im Array, als ob irgendwo sample=0 stehen würde.

Weiß jemand rat oder hat einen Tipp für mich?

Autor: Josef D. (jogedua)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
5 Leds?
Die for-Schleifen werden aber 6 Mal durchlaufen.
Auch sollte samples nicht unbegrenzt hochgezählt werden.

Autor: Axel L. (ligonap)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Josef D. schrieb:
> 5 Leds?
> Die for-Schleifen werden aber 6 Mal durchlaufen.
> Auch sollte samples nicht unbegrenzt hochgezählt werden.

Wenn ich für die Schleife
for (i=0; i<5; i++){ 
schreibe, leuchtet die fünfte LED nicht.

Bei
for (i=1; i<6; i++){ 
leuchtet die erste LED nicht.

Daher ist wohl die Schreibweise
for (i=0; i<6; i++){ 
richtig, da alle fünf LED angesprochen werden.

Warum sollte ich samples nicht hochzählen?

Wie ich schon schrieb, es ist irgendwo ein Wurm drin.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ws2812_setleds(led,i); 

Gibt das Array "led" von der Länge "i" auf dem Datenpin aus. Dadurch 
werden "i" LEDs angesteuert.

Ersetze den Aufruf mal durch
  ws2812_setleds(led,6); 
für 6 LEDs. Dann sollte es funktionieren.

Leider scheint das Missverständnis häufiger aufzutreten. Ich muss wohl 
mal ein paar zusätzliche Beispiele hinzufügen.

: Bearbeitet durch User
Autor: Axel L. (ligonap)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Tim  . schrieb:
>
> ws2812_setleds(led,i);
> 
>
> Gibt das Array "led" von der Länge "i" auf dem Datenpin aus. Dadurch
> werden "i" LEDs angesteuert.
>
> Ersetze den Aufruf mal durch
>
>   ws2812_setleds(led,6);
> 
> für 6 LEDs. Dann sollte es funktionieren.
>
> Leider scheint das Missverständnis häufiger aufzutreten. Ich muss wohl
> mal ein paar zusätzliche Beispiele hinzufügen.

Dies ist die Lösung. Danke.

Durch
#define MAXPIX 5
und
ws2812_setleds(led,MAXPIX);

läuft die Schleife
for (i=0; i<=4; ++i)
fünf mal durch und macht genau das, was sie soll.

Übrigens mit
ws2812_setleds(led,i+1);
ging es auch. Keine Ahnung wieso. ;-)

Autor: Julian B. (julinho)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim  . schrieb:
> Für AVR gibt es implementierungen
> ab 4 Mhz,

Habe den Code gerade auf einem Atmega88 mit 8 Mhz internen Takt getestet 
und es hat nicht funktioniert, die Farben ändern sich, aber nicht 
reproduzierbar.
Gleicher Code auf Atmega328 mit 16Mhz Quarz lief alles super.
Auf dem Oszi sieht man bei 8Mhz, dass die High-Impulse nur 1/8 Mhz also 
125ns lang, und damit zu kurz sind.

Hat jemand die Bibliothek schon mal jemand mit 8MHz auf einem Atmega 
getestet?
Muß ich den Optimizer irgendwie einstellen?

Ich verwende Version 2.3.

Autor: Julian B. (julinho)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die High-Impulse haben die richtige Länge, ca. 900ns bzw. 330ns, 
allerdings ist die Periodendauer mit 5us viel zu lang. Hat irdend jemand 
eine Idee?

Autor: Julian B. (julinho)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Bibliothek funktioniert nicht für 8Mhz, Grund ist das ein 
Delay-Parameter, der bei 8MHz negativ wird. Es handelt sich um w3.

#define w3 (w_totalcycles-w_fixedtotal-w1-w2)

Der folgende Code interpretiert diese Zahl aber als positiv und knallt 
alle möglichen Delays rein, dadurch kommt eine Periode von 5 us 
zustande.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian B. schrieb:
> Die Bibliothek funktioniert nicht für 8Mhz, Grund ist das ein
> Delay-Parameter, der bei 8MHz negativ wird. Es handelt sich um w3.
>
> #define w3 (w_totalcycles-w_fixedtotal-w1-w2)
>
> Der folgende Code interpretiert diese Zahl aber als positiv und knallt
> alle möglichen Delays rein, dadurch kommt eine Periode von 5 us
> zustande.

Nö. Dafür kommt ein paar Zeilen später
#if w3>0
#define w3_nops w3
#else
#define w3_nops  0
#endif

Zum Problem generell: Ist die CPU wirklich mit 8Mhz getaktet, oder ist 
ein Multiplier falsch? Ist das F_CPU define korrekt?

Hast Du Dir schon einmal das Listing-File angeschaut? (*.lss)

Autor: Julian B. (julinho)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tim  . schrieb:
> Zum Problem generell: Ist die CPU wirklich mit 8Mhz getaktet, oder ist
> ein Multiplier falsch? Ist das F_CPU define korrekt?

Das passt schon alles.

Ich denke es liegt wirklich daran,dass w3 negativ ist, aber als positive 
Zahl interpretiert wird, eventuell fehlt ein cast.

Damit sind alle Vergleiche wahr:

#if (w3_nops&1)
w_nop1
#endif
#if (w3_nops&2)
w_nop2
#endif
#if (w3_nops&4)
w_nop4
#endif
#if (w3_nops&8)
w_nop8
#endif
#if (w3_nops&16)
w_nop16
#endif

man hat also 16+8+4+2+1=31 nops, was die hohe Periodendauer erklärt.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich denke es liegt wirklich daran,dass w3 negativ ist, aber als positive
> Zahl interpretiert wird, eventuell fehlt ein cast.

Nein, w3_nop wird nie negativ.

Unten der Code, der mit F_CPU=8000000 generiert wird. Passt alles. Das 
Makefile der Beispiele legt um Unterverzeichnis \objects die *.lss Files 
ab. Am besten mal hier nachschauen, ob etwas schief läuft.

  dc:  e6 17         cp  r30, r22
  de:  f7 07         cpc  r31, r23
  e0:  61 f0         breq  .+24       ; 0xfa <loop42+0x14>
    curbyte=*data++;
  e2:  81 91         ld  r24, Z+
    
    asm volatile(
  e4:  98 e0         ldi  r25, 0x08  ; 8

000000e6 <loop42>:
  e6:  28 bb         out  0x18, r18  ; 24
  e8:  87 ff         sbrs  r24, 7
  ea:  38 bb         out  0x18, r19  ; 24
  ec:  88 0f         add  r24, r24
  ee:  00 00         nop
  f0:  00 c0         rjmp  .+0        ; 0xf2 <loop42+0xc>
  f2:  38 bb         out  0x18, r19  ; 24
  f4:  9a 95         dec  r25
  f6:  b9 f7         brne  .-18       ; 0xe6 <loop42>
  f8:  f1 cf         rjmp  .-30       ; 0xdc <ws2812_sendarray_mask+0x1c>

: Bearbeitet durch User
Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein paar kleine Updates:

1) WS2813 support

v2.4 2016/11/27
    * Increased waittime to support WS2813 LEDs

https://github.com/cpldcpu/light_ws2812

2) SK9822 support für die APA102 library

v1.1 2016/11/27
    * Added reset frame to fix SK9822 update issue. Changed reset frame to 0x000000.
    * Added apa102_setleds_brightness function which allows to set global brightness as well.

https://github.com/cpldcpu/light_ws2812/tree/master/light_apa102_AVR

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Neuerdings tauchen auf den China-Seiten clones der APA102 auf, die 
SK9822. Ich habe beide Devices verglichen:

https://cpldcpu.com/2016/12/13/sk9822-a-clone-of-the-apa102/

Die SK9822 gefallen mir recht gut. Sie haben eine programmierbare 
Konstantstromquelle zum Einstellen der globalen Helligkeit. Damit können 
die Devices auch gut zur Statusanzeige genutzt werden. Dafür sind die 
anderen programmierbaren LEDs generell zu hell oder Flackern zu viele.

Autor: Dennis X. (debegr92)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
in der letzten Version von light_ws2812 ist im Readme immer noch zu 
lesen:
- Supports standard AVR, reduced core AVR (Attiny 4/5/9/10/20/40) and 
XMEGA (untested) without special case handling.

Ich hatte das gerade mal gezogen und kompiliert und den selben Fehler 
wie MichaelS98 Mitte 2014 hatte:
Beitrag "Re: Lightweight WS2811/WS2812 Library"

Zwei Beiträge später schreibt er, er habe das Problem gelöst. Weiß da 
einer mehr? Kein Eintrag im Git? Kein Update?

Vielleicht hat da ja jemand mehr Infos dazu. Ich wäre sehr dankbar.

: Bearbeitet durch User
Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Antwort kommt etwas spät, aber evtl. hilft es ja anderen.

Dennis X. schrieb:
> Hallo,
> in der letzten Version von light_ws2812 ist im Readme immer noch zu
> lesen:
> - Supports standard AVR, reduced core AVR (Attiny 4/5/9/10/20/40) and
> XMEGA (untested) without special case handling.
>
> Ich hatte das gerade mal gezogen und kompiliert und den selben Fehler
> wie MichaelS98 Mitte 2014 hatte:
> Beitrag "Re: Lightweight WS2811/WS2812 Library"
>
> Zwei Beiträge später schreibt er, er habe das Problem gelöst. Weiß da
> einer mehr? Kein Eintrag im Git? Kein Update

Das ist kein Problem mit der Library per se, sondern hat damit zu tun, 
dass der PORTD auf dem XMEGA nicht mit "out" angesprochen werden kann.

Mögliche Optionen:
 - Anderen PORT verwenden
 - PORTD auf einen der virtuellen I/O Ports mappen, damit er
mit dem Befehl "Out" beschrieben werden kann. Steht ab s. 145 im 
XMEGA-Manual.
 - Die Arduino-Version der Library nutzt indizierte Adressierung, um die 
Ports anzusprechen. Diese erlaubt Zugriff auf I/O ports außerhalb des 
I/O Bereichs und sollte auch mit dem nicht gemappeten PORTD 
funktionieren.

: Bearbeitet durch User

Antwort schreiben

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

Wichtige Regeln - erst lesen, dann posten!

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

Formatierung (mehr Informationen...)

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




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

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