Hallo,
ich habe mir nach eigenen Plänen eine W***uhr gebaut. Diese funktioniert
auch soweit, jedoch schwanken meine LEDs periodisch in der Helligkeit.
Ich vermute entweder ein Timingfehler oder einen Softwarefehler.
Vielleicht kennt jemand aber direkt die Ursache, kann mir einen Tipp
geben und ich kann mir eine stundenlange Suche ersparen.
Ich setze in einem Test alle 200mS den Speicher für die Farben mit einer
immer gleichen, relativ niedrig hellen Farbe und übertrage diese.
Egal ob ich rot, grün, blau oder weiß nehme, die Helligkeit schwankt
manchmal um ein paar Prozentpunkte und es blitzt auf.
An der Frequenz und den Zeitabständen habe ich auch schon herumgespielt,
das hat aber absolut keine Auswirkung, lediglich, dass es ab bestimmten
Werten gar nicht mehr funktioniert.
Ich verwende einen STM32WB55CEU6 und nutze zur Übertragung eine PWM +
DMA. Der Ausgangspin ist ein Opendrain mit Pullup nach 5V.
Kann der Pullup zu niedrig/hoch sein?
Dies ist meine Datensruktur:
1 | struct s_Data{
|
2 | struct{
|
3 | uint8_t green[8];
|
4 | uint8_t red[8];
|
5 | uint8_t blue[8];
|
6 | uint8_t white[8];
|
7 | } LEDs[N_LEDS];
|
8 |
|
9 | uint8_t u8Void[70];
|
10 | };
|
Und dies die Funktion mit der ich übertrage:
1 | void Wordclock::transmit(bool bVal){
|
2 | while(!(DMA1->ISR & DMA_ISR_TCIF1) && (DMA1_Channel1->CCR & DMA_CCR_EN));
|
3 | DMA1_Channel1->CCR = 0;
|
4 | DMA1_Channel1->CPAR = (uint32_t) &TIM1->CCR4;
|
5 | DMA1_Channel1->CMAR = (uint32_t) &oData;
|
6 | DMA1_Channel1->CNDTR = sizeof(s_Data);
|
7 | DMA1_Channel1->CCR = DMA_CCR_MINC | (0b00 << 10)| (0b01 << 8) | DMA_CCR_DIR;
|
8 | DMA1->IFCR = DMA_IFCR_CTCIF1;
|
9 | DMAMUX1_Channel0->CCR = 25;
|
10 | if(bVal){
|
11 | DMA1_Channel1->CCR |= DMA_CCR_EN;
|
12 | }
|
13 | }
|
Mit folgender Funktion setze ich die Farbe einer LED:
1 | void Wordclock::setLED(uint8_t u8N, s_Colors & oColors){
|
2 | if(u8N >= N_LEDS){
|
3 | return;
|
4 | }
|
5 |
|
6 | uint8_t u8Pos = Wordclock::au8Mapping[u8N];
|
7 |
|
8 | setByte(&oData.LEDs[u8Pos].red[0], oColors.red);
|
9 | setByte(&oData.LEDs[u8Pos].green[0], oColors.green);
|
10 | setByte(&oData.LEDs[u8Pos].blue[0], oColors.blue);
|
11 | setByte(&oData.LEDs[u8Pos].white[0], oColors.white);
|
12 | }
|
13 |
|
14 | void Wordclock::setByte(uint8_t * p, uint8_t u8Val){
|
15 | constexpr uint8_t u8High = (uint32_t)((CLK_TIMER / CLK_SK6812) - 1) * 50 / 100;
|
16 | constexpr uint8_t u8Low = (uint32_t)((CLK_TIMER / CLK_SK6812) - 1) * 25 / 100;
|
17 |
|
18 | for(uint8_t i = 0; i < 8; i++){
|
19 | if(u8Val & (1<<i)){
|
20 | p[7-i] = u8High;
|
21 | }
|
22 | else{
|
23 | p[7-i] = u8Low;
|
24 | }
|
25 | }
|
26 | }
|
Danke für eure Ideen. Wenn weitere Codeabschnitte benötigt werden, zeige
ich sie hier.