ich hab mit der STM32CubeIDE ein Projekt mit Timer und DMA geschrieben um WS2811 leds mithilfe eines Bluepill boards anzusteuern.
Nur leider flackern diese wie wild und ich kann mir nicht erklären woran es liegt. Ich hoffe jemand kann helfen.
Mir ist bewusst, dass ein delay in Kombination mim DMA nicht die beste Idee ist, allerdings flackern die LEDs ohne diesen delay ohne erkennbaren Ziel Zustand. Mit dem delay leuchten die LEDs grundsätzlich in der richtigen Farbe, allerdings nicht stabil.
Nach dem Datenblatt der WS2811er brauch er mindestens 280 us LOW pegel für den reset, was ich einfach umgesetzt habe, in dem ich das pwm data array entsprechend mit 230 LOW pegeln fülle (800kHz -> 1.25us pro takt). Gibt sicher schönere wege das zu lösen, aber Speicher ist ausreichend vorhanden. In erster Etappe muss der Spaß erstmal laufen.
400 kHz hab ich auch schonmal ausprobiert, funktioniert auch nicht besser, muss also irgendwas von mir creepy sein....woran ich auch schon gedacht hab wäre manglende Qualität des 8 mhz quarzes auf der bluepill.
Die SysClk ist auf 72Mhz konfiguriert, mit dem HSE Eingang (8 Mhz) und entsprechender Konfiguration in der PLLCLK.
(s. Bild clk-config)
Der Timer ist konfiguriert mit:
Prescaler: 0
ARR: 90-1 (72Mhz / 90 = 800 KHz)
(s. Bild tim-config)
DMA läuft in normal operation, memory to pheriphal
Memory mit Byte
Pheriphal mit Halfword
(s. Bild dma-config)
Nachfolgend der Code:
zunächst das header file:
1
#ifndef __ws281x
2
#define __ws281x
3
4
#include"../config.h"
5
#include"../../Core/Inc/main.h"
6
7
//#define NUM_LED NUM_LED defined in config.h
8
#define USE_BRIGHTNESS 0
9
#define WS2811_RESET_PERIOD 230
10
#define PWM_DATA_ARR_LENGTH ((24*NUM_LED)+WS2811_RESET_PERIOD) // 24Bits per LED + Reset bits
ich benutze eine LED Matrix mit WS2812 und schicke die Daten mit SPI / DMA raus.
Wenn ich SPI auf 4 MHz einstelle dann blinken alle LEDs weiss. Nehme ich 8 MHz dann funktioniert es super. Bei 16 MHz blinken einzelne LEDs wild durcheinander.
ich benutze eine LED Matrix mit WS2812 und schicke die Daten mit SPI /
DMA raus.
Wenn ich SPI auf 4 MHz einstelle dann blinken alle LEDs weiss. Nehme ich
8 MHz dann funktioniert es super. Bei 16 MHz blinken einzelne LEDs wild
durcheinander.
Ich mache das für eine Kette von WS2812B auch mit SPI und DMA, wobei ein Byte 2 WS2812-bits entspricht, 1000 für ein 0-bit, 1110 für ein 1-bit. Bittakt ist 3MHz. Dadurch komme ich auf eine Bit-Zeit von 1.33µs, was gut zu den im Datenblatt angegebenen Werten passt. Lediglich die T1H-Zeit ist mit 1µs etwas länger als die spezifizierten 950ns, was aber die Funktion nicht beinträchtigt. Die komplette Impulsfolge wird in einem Puffer abgelegt, mit 160 Null-Bits als Reset-Vorspann. Funktioniert mit 60 LEDs problemlos.
Bei WS2811 ist das Timing langsamer. Es sollte aber mit einer SPI-Frequenz von 1.5 MHz funktionieren, was einer Bitzeit von 0.667µs entspricht:
T0H: 1bit , Datenblatt sagt < 0.5+-0.15µs, also ganz knapp daneben, funzt aber vermutlich auch.
T0L: 3bits = 2.0µs, entspricht exakt der Spezifikation
T1L: 2bits = 1.33µs, Datenblatt sagt 1.3 +- 0.15µs
T1H: 2bits = 1.33µs, Spezifikation ist 1.2 +- 0.15µs
Alternativ wäre eine Bitdauer von 250µs möglich, was einem SPI-Takt von 4MHz entspricht. Dann wären allerdings 10 SPI-bits für ein WS2811-Bit nötig, was einen höheren RAM-Bedarf mit sich zieht.
T0 entspräche dann der Bitfolge 1100000000, T1 1111100000
ja an sich sieht die Logic passend aus (s. locig_detail.png) und es gibt auch keine Ausschläge die nicht in der Toleranz der LEDs liegen würden.
Beim rauszoomen fällt mir allerdings auf, dass da anscheinend eine unregelmäßigkeit in der Rate wie die Daten gesendet werden auftritt, bin mir aber nicht sicher ob das vlt auch nur durch die Darstellung oder die Auflösung des USB Logic Analyzers so aussieht. (s. long-time-view.png)
Hab im übrigen in Git ein Repo gefunden, in dem beschrieben ist, dass für WS2811 eine reset dauer von 270 us notwendig ist, und nicht wie im datenblatt von adafruit 50us. Damit kann ich den delay nun auch weglassen, das flimmern ist jedoch weiterhin beständig.
Passt die Spannung des Datensignals oder brauchst du noch einen
Levelshifter?
Gute Frage, an die ich bisher tatsächlich gar nicht gedacht hatte....
laut dem Datenblatt von Adafruit brauchen die LEDs VIH = 0.7VDD.
Ich hab an dem WS2811 direkt gemessen, was anliegt wenn der Strip mit 12V versporgt wird, und messe hier 5,4V
Demzufolge wären eigentlich 3,7V notwendig, meine Bluepill gibt natürlich nur 3V3 aus.
Ich hab parallel auch den Hersteller BFT-Lightning angeschrieben und dazu befragt.
Zitat:
"Es sollte funktionieren, wenn das Steuergerät (angeschlossen an eine 5-V-Stromversorgung) und der 12-V-Streifen (angeschlossen an eine 12-V-Stromversorgung) separat und getrennt voneinander mit Strom versorgt werden.
Aber wir haben nicht versucht zu sehen, ob es bei 3V funktioniert.
Vielleicht können Sie es versuchen."
So blöd wies klingt hat mich das auf einen andren Fehler meinerseits aufmerksam gemacht: Ich hab den GND des Strips und der Bluepill nicht miteinander verbunden.
Gesagt getan nun funktionierts einwandfrei, bissl widersprüchlich zu den Datenblatt aber ich werd mich nicht beklagen.
Abschließend war das Problem vermutlich die Kombination aus timing problem durch den Delay und die falsch angesetzte reset dauer und die fehlende GND Verbindung. Ich hatte beides beim testen und dem Versuch den Fehler zu finden bereits behoben, allerdings natürlich nicht beides gleichzeitig.