Forum: Mikrocontroller und Digitale Elektronik SK6812 schwanken in Helligkeit - bekanntes Problem?


von SK6812 (Gast)


Angehängte Dateien:

Lesenswert?

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.

von SK6812 (Gast)


Lesenswert?

Lösung gefunden: Ich musste Timer und DMA stoppen und dann zuerst DMA 
und dann den Timer starten.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.