Forum: Mikrocontroller und Digitale Elektronik ESP8266 PWM flackert bei nidrigen Frequenzen


von Kolja L. (kolja82)


Lesenswert?

Moin

Ich hatte es gestern schon mal hier gepostet,
jetzt kann ich das Problem aber wohl auf den ESP8266 schieben.

Aufbau: ESP steuert über 4 Pins mittels PWM 4 KSQ (TP4115) an denen je 9 
3W LED hängen.
Funktion: Die LED sollen langsam bis zur vollen Helligkeit hochgefahren 
werden
Problem: gerade bei geringen Frequenzen gibt es ein helles Aufblitzen 
der LED

Das Problem scheint bekannt:
https://www.bountysource.com/issues/27026077-pwm-flickering-with-small-analogwrite-values
Und zwei der Lösungsvorschläge habe ich auch schon getestet:

Die PWM Frequenz auf 200Hz verringern, default sind 1kHz.
 analogWriteFreq(200);

Die Taktfrequenz des ESP (in der ArduinoIDE) von 80 auf 160MHz erhöhen.

Beide Maßnahmen brachten eine eindeutige Verbesserung,
aber leider keine vollständige.

Dann gibt es noch diese Möglichkeit:
https://github.com/StefanBruens/ESP8266_new_pwm
aber leider verstehe ich aber nicht was ich machen soll.

Kann mir damit jemand helfen?
oder habt ihr eine andere Lösung für das Problem?

Danke und Gruß

Kolja

: Bearbeitet durch User
von Sascha W. (sascha-w)


Lesenswert?

Kolja L. schrieb:
> Problem: gerade bei geringen Frequenzen gibt es ein helles Aufblitzen
> der LED

> Die PWM Frequenz auf 200Hz verringern, default sind 1kHz.
>  analogWriteFreq(200);

Die Aussagen wiedersprechen sich!

Was macht denn dein ESP sonst noch so?
Ich habe hier auch gerade einen RGB-Controller zusammengebaut 3x PWM, 
IR, WLAN.

Zuvor hab ich mal getestet mit 3xPWM, I2C-OLED-Laufschrift alle 15ms 
aktualisiert und per UDP neuen Text fürs Display gesendet.
Mit dem Logikanalysator ist auf der PWM auch dabei nur ein minimaler 
Jitter festzustellen.

Sascha

von Kolja L. (kolja82)


Lesenswert?

Hallo Sascha

Sascha W. schrieb:
> Die Aussagen wiedersprechen sich!

Wegen dem Wort Frequenz?
Wenn ja, dann verstehe ich was du meinst.

Mit "geringe Frequenzen" meinte ich den geringen Tastgrad.
Also n etwa so:     analogWrite(PIN1, 100);

Sascha W. schrieb:
> Was macht denn dein ESP sonst noch so?

Nix, das ist der ganze Sketch:
1
int brightness = 0;    // how bright the LED is
2
int fadeAmount = 2;    // how many points to fade the LED by
3
unsigned long currentTime;
4
unsigned long loopTime;
5
6
void setup()
7
{
8
  Serial.begin(115200);
9
  pinMode(14, OUTPUT);
10
  pinMode(12, OUTPUT);
11
  pinMode(4, OUTPUT);
12
  currentTime = millis();
13
  loopTime = currentTime;
14
 //  analogWriteFreq(200);
15
}
16
17
void loop()  {
18
  currentTime = millis();
19
  if (currentTime >= (loopTime + 1000))
20
  {
21
    analogWrite(14, brightness);
22
    analogWrite(12, brightness);
23
    analogWrite(4, brightness);
24
    Serial.println(brightness);
25
26
    brightness = brightness + fadeAmount;
27
28
    if (brightness == 0 || brightness == 1000)
29
    {
30
      fadeAmount = -fadeAmount ;
31
    }
32
    loopTime = currentTime;  // Updates loopTime
33
  }
34
35
}

Gruß und Danke schon einmal

Kolja

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Tritt das Flackern ca. alle Sekunde auf?
Ja -> dann verschluckt sich der PWM für die analoge Spannung, da Dieser 
jede Sekunde neu gestartet wird.

Gibt's im Arduino eine Möglichkeit, nur das Tastverhältnis des PWM 
anzupassen?
Also NICHT wie hier, durch den neuen Befehl den PWM immer wieder neu 
anzustoßen.

MfG

von Kolja L. (kolja82)


Lesenswert?

Patrick J. schrieb:
> Tritt das Flackern ca. alle Sekunde auf?

Nein, ehr bei bestimmten Werten.
Habe gerade einen Wert zwischen 450 und 500 in Verdacht.

Patrick J. schrieb:
> Gibt's im Arduino eine Möglichkeit, nur das Tastverhältnis des PWM
> anzupassen?

Nicht dass ich wüsste.
Zumindest habe ich es noch nirgendwo gesehen.

Im Gegensatz zu den ArduinoBoards kann der ESP eine PWM mit 10 Bit,
nur falls es jemand wundert, dass die Werte über 254 gehen.

von Sascha W. (sascha-w)


Lesenswert?

Kolja L. schrieb:
> Im Gegensatz zu den ArduinoBoards kann der ESP eine PWM mit 10 Bit,
> nur falls es jemand wundert, dass die Werte über 254 gehen.

und wo hast du den PWM-Range gesetzt? Ich sehe nichts in deinem Code.

Sascha

: Bearbeitet durch User
von Kolja L. (kolja82)


Lesenswert?

Sascha W. schrieb:
> und wo hast du den PWM-Range gesetzt?

Wenn ich es richtig verstanden habe,
ist die per default fest auf 1kHz.
Ich hatte sie mal testweise auf 200Hz runtergesetzt:
 //  analogWriteFreq(200);

von Kolja L. (kolja82)


Lesenswert?

Sascha W. schrieb:
> und wo hast du den PWM-Range gesetzt?

Meinst du diese Zeile
    if (brightness == 0 || brightness == 1000) ?

von Sascha W. (sascha-w)


Lesenswert?

Kolja L. schrieb:
> Sascha W. schrieb:
>> und wo hast du den PWM-Range gesetzt?
>
> Meinst du diese Zeile
>     if (brightness == 0 || brightness == 1000) ?

Nein - beim ESP gibts da AnalogWriteRange() um die Auflösung der PWM 
einzustellen.

Sascha

von Kolja L. (kolja82)


Lesenswert?

Ist auch auf default:

Analog output

analogWrite(pin, value) enables software PWM on the given pin. PWM may 
be used on pins 0 to 16. Call analogWrite(pin, 0) to disable PWM on the 
pin. value may be in range from 0 to PWMRANGE, which is equal to 1023 by 
default. PWM range may be changed by calling 
analogWriteRange(new_range).

PWM frequency is 1kHz by default. Call analogWriteFreq(new_frequency) to 
change the frequency.

Quelle:http://esp8266.github.io/Arduino/versions/2.0.0-rc2/doc/reference.html#analog-output

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

konnte das Problem jetzt nachvollziehen! Tritt beim langsamen ändern der 
PWM-Werte bei mehreren aktivierten Kanälen auf.

Problem ist ein Fehler in der core-Bibliothek 
"core_esp8266_wiring_pwm.c" die mit Version 2.3.0 noch als aktuell 
eingebunden wird, obwohl die lib in  auf Github schon überarbeitet 
wurde.
1
void ICACHE_RAM_ATTR pwm_timer_isr(){
2
  static uint8_t current_step = 0;
3
  static uint8_t stepcount = 0;
4
  static uint16_t steps[17];
5
  static uint32_t masks[17];
6
  if(current_step < stepcount){
7
//    T1L = (pwm_steps[current_step+1] * pwm_multiplier); //<-Fehler
8
    T1L = (steps[current_step+1] * pwm_multiplier); //<-richtig
9
    TEIE |= TEIE1;
10
    if(masks[current_step] & 0xFFFF) GPOC = masks[current_step] & 0xFFFF;
11
    if(masks[current_step] & 0x10000) GP16O = 0;
12
    current_step++;
13
  } else {
14
    current_step = 0;
15
    stepcount = 0;
16
    if(pwm_mask == 0) return;
17
    T1L = (pwm_steps[current_step] * pwm_multiplier);
18
    TEIE |= TEIE1;
19
    if(pwm_mask & 0xFFFF) GPOS = pwm_mask & 0xFFFF;
20
    if(pwm_mask & 0x10000) GP16O = 1;
21
    stepcount = pwm_steps_len;
22
    memcpy(steps, pwm_steps, (stepcount + 1) * 2);
23
    memcpy(masks, pwm_steps_mask, stepcount * 4);
24
  }
25
}
Obwohl die Tabelle der Timerschritte doppelt gepuffert ist und nur beim 
Nulldurchgang aktualisiert wird, wird beim Durchlauf der ISR auf die 
ungepufferten Daten zugegriffen die durch zwischenzeitliches verändern 
der PWM-Werte nicht mehr mit der Maske für die Ausgänge übereinstimmt.
Kleine Korrekur - siehe oben - und schon ist der Fehler weg.

Sascha

von Sven P. (bastelnoob)


Lesenswert?

Sascha W. schrieb:

> Kleine Korrekur - siehe oben - und schon ist der Fehler weg.

Das kann ich leider nicht bestätigen. Bei mir flackert es trozdem.
Ich habe alles auf default.

Bei meinem Sketch ist allerdings noch ein AMS2301 dran und er sendet 
jede Minute seine Temp Daten an eine Datenbank. Der Status wird an eine 
Website (wenn er abgefragt wird) gesendet (ca. jede Minute). Da wird was 
mit dem Interupt nicht stimmen, denke ich.

Evtl. kann man das ja umgehen wenn man einen Arduino dazwischen 
schaltet, aber das ist ja wie mit Kanonen auf Spatzen schiessen.

Sven P.

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.