StefanBruens / ESP8266_new_pwm

This is a drop-in replacement for the ESP8266 SDK PWM
GNU General Public License v2.0
196 stars 46 forks source link

flicker at 50% :-( #9

Open gorec2005 opened 7 years ago

gorec2005 commented 7 years ago

i have flicker at 50% pwm! if range=10000 than pwm from 4998 to 4999 ok but from 4999 to 5000 flicker :-(

kaeferfreund commented 7 years ago

same here

StefanBruens commented 7 years ago
gorec2005 commented 7 years ago
StefanBruens commented 7 years ago

Can you please clarify the second answer?

gorec2005 commented 7 years ago

i test it again: flicker appear only when pwm intersects 5000 (for 10000 range)! from 4999 to 5000 i don't know how i can clarify... - sorry... 4990..4995...4999.flicker..5000...5005...

StefanBruens commented 7 years ago

no videos, please.

Just describe, step by step, what you are doing, and what results you have, e.g.:

  1. I set PWM to 4999 -> ~50% output
  2. set to 5000 -> flickering
  3. set to 5001 -> ~50% output, no flickering ...
gorec2005 commented 7 years ago

yes! - your's describe is correct i just make slow soft-on and slow soft-off led lamp via table for equal change bright speed in both low and high ends... and when it from full bright (100% = 10000) go to the (0% = 0) at the 50% all time flicker have appear... and from 0 to 10000 also the same

gorec2005 commented 7 years ago

i think it's because at the 50% pwm you just invert signal... but this inverse have destroy smoth regulation... :-(

StefanBruens commented 7 years ago

What do you mean by flicker? A single flash? Or constant flickering? Are you using the compat mode? If yes, then lower your PWM period to ~2500, 100 Hz is flickering anyway.

gorec2005 commented 7 years ago

sorry - single flash only no - i did not use compat mode:

ifndef SDK_PWM_PERIOD_COMPAT_MODE

define SDK_PWM_PERIOD_COMPAT_MODE 0

endif

ifndef PWM_MAX_CHANNELS

define PWM_MAX_CHANNELS 4

endif

define PWM_DEBUG 0

define PWM_USE_NMI 0

UweHeinritz commented 7 years ago

Hi, I have the problem with a single flash when passing the 50% also. I have 5 PWM channels and use NMI mode. Period ist set to 20000 (should be 250Hz). Each time a channel pass the 50% it generate a single flash. Channels which do not pass the 50% mark at the same time do not flash.

Example with 2 channels: Ch1 9500 / CH2 9991 -> smooth Output of both channels Ch1 9700 / CH2 9993 -> smooth Output of both channels Ch1 9900 / CH2 9995 -> smooth Output of both channels Ch1 10200 / CH2 9997 -> Ch1 have a single flash Ch1 10500 / CH2 9999 -> smooth Output of both channels Ch1 10500 / CH2 10001 -> Ch2 have a single flash Ch1 10700 / CH2 10003 -> smooth Output of both channels Ch1 9950 / CH2 9950 -> CH1 and Ch2 have a single flash (passed both the 50% at same time) Ch1 9940 / CH2 9940 -> smooth Output of both channels

Kind regards, Uwe.

StefanBruens commented 7 years ago

Do you use a selfbuilt board or something from the shelf? Can you please provide schematics/part numbers of the MOSFETs/board photos?

I can not reproduce it, and am suspecting a hardware specific issue.

UweHeinritz commented 7 years ago

Hello Stefan, I do not think that this is a hardware issue. Because I also have random flickering when cossfade all channels, I tried 2 things to exclude issues create from my remaining source code (use 3 timers and do some calculation/display stuff). First I disabled pwm_start and let all functions in my source active. There were no flickering -> I have no CPU limitation issue Then I enabled pwm_start, but disabled changes to duty cycles (use fix values for test). There were also no flickering -> The calculation in pwm_start + my functions does also have no CPU limitation issue So the flickering must be generated by the pwm phases calculated in pwm_start. I looked in your source code and also did a simple test with enabled pwm_debug. I found out that the source code force flickering in 2 conditions. Condition 1 - pass the 50% duty cycle value: I let pwm_start calculate the pwm phases for following 2 duty sets (period of 20000). Set 1: 6000/6000/9995/6000/6000, Set 2: 6000/6000/10005/6000/6000 The calculated phases are (duration / on mask / off mask): Set 1: 5999 / 0,1,2,3,4 / - 3994 / - / 0,1,3,4 10004 / - / 2 Set 2: 5999 / 0,1,3,4 / 2 3994 / - / 0,1,3,4 10004 / 2 / -

Both sets are OK and create exact the duty cycles which are defined. But if we have a look at channel 2 when switching pwm sets (finish cylce after pwm_start) we see this (duration/output state): Last set 9995 on 10005 off Switch set 9995 off 10005 on Restart set 9995 off 10005 on.... When switching to the new set, the output of channel 2 is a complete period (nearly 20000 ticks) off. This will create a single flicker. When switching direction (from high to low) this will create a 20000 ticks on signal which is seen as a single flash.

Condition 2 - 2 channels have nearly the same duty cycle which is > 16: I let pwm_start calculate the pwm phases for following 2 duty sets (period of 20000). Set 1: 6000/6000/6500/6480/6000, Set 2: 6000/6000/6500/6485/6000 The calculated phases are (duration / on mask / off mask): Set 1: 5999 / 0,1,2,3,4 / - 479 / - / 0,1,4 19 / - / 3 13499 / - / 2 Set 2: 484 / - / 0,1,4 13499 / - / 2,3 14 / 2 / - 5999 / 0,1,3,4 / -

Both sets are OK and create exact the duty cycles which are defined. But if we have a look at channels 0,1,4 when switching pwm sets we see this: Last set 5999 on 13997 off Switch set 13998 off 5999 on Restart set 13998 off 5999 on When switching to the new set, the outputs of these 3 channels (where we did not change the duty cylce) are longer then a complete period (nearly 28000 ticks) off. This will create a single flicker on these 3 channels. With duty cycles in the upper half we get a single flash.

Following changes are necessary to get rid of these flickering/flashes:

Positive effects:

Unfortunately this will have negative side effects:

I wonder why you could not reproduce these problems when they are clearly visible in debug outputs and also on the LEDs (also in source code).

Kind regards, Uwe.

StefanBruens commented 7 years ago

Hi Uwe,

I am completely aware of the calculations, and also the fact that the phase mirroring extends the pulse length when crossing the 50% setting.

At a PWM frequency of 250Hz, the pulse scheme is changed from 2ms low/2ms high/2ms low/2ms high to 2ms low/4ms high/2ms low. From a human vision standpoint, double the luminous flux does not equal double the perceived brightness. There is a tradeoff between the the length of a flash and its intensity to be noticeable.

If you can notice a brightness increase, either the pulse is longer than 4ms, or the brightness increase is more than intended.

Depending on the MOSFET and the driver strength, you may not be switching the MOSFET fully on with a 2ms pulse, but do with a 4ms pulse, increasing the power from e.g. 20% to 100%, instead of the expected 50% to 100%.

None of you proposed changes is applyable in general:

  1. the maximum interrupt rate is limited to about 4us
  2. due to the interrupt rate limiting, fine adjustments have to be done with a busy loop
  3. if you have a busy loop, you have to reserve some time for the busy loop.

The term "inversion" is also not good to describe the effects, you better used "phase shifting". The maximum phase shifting happening for any duty cycle below 50% is 3us, less than 1% of the cycle of a 250Hz PWM, which is completely irrelevant. When crossing 50% duty, there is a one-time phase shift by 2ms between consecutive pulses which might be relevant.

Feel free to come up with a pulse scheme under the following constraints:

UweHeinritz commented 7 years ago

Hi, you say that the maximum Phase shifting für duty cycles below 50% is 3us. But in my example of the second condition I get a 28000tick = 1,4 PWM cycle = 5,6ms pause between 2 pulses (250Hz, 20000 ticks period). The human eye recognize the differences in phases when invert/shift phases (in my examples this generate a 2-4ms longer pause at this time) as short brightness changes. I could not see that the LEDs are full off or full on at this time, but I recognize a slight flicker.

I use IRLML2502 MOSFET which is a very fast switching Ultra low On-Resistance MOSFET. I added a 180Ohm resistor in the signal line to limit the gate current. This Setup should work well.

I removed the 50% Phase switching, the "shift left to align right edge" and the cyclic shift if last phase is short. Then I added the check for restart PWM cycle to the while cycle (only executed if current PWM phase is shorter then 16 ticks). With this modifications a get a smooth Fading between 0 and 100% and also when randomly cross fade all 5 channels (which produced flickering when diff between duty cycles are < 16). The PWM is not affected by my main application (include httpd, oled Display, color calculation).

The execution time of the pwm_intr_handler is only longer (if Statement with 2 expressions) if we have a PWM phase which is shorter than 16 ticks.

Kind regards, Uwe Heinritz.

StefanBruens commented 7 years ago

Now set your 5 channels to 12, 24, 36, 48, 60 ticks duty, and measure the duty of the fifth channel, it will be well beyond 60 ticks ...

steveh80 commented 4 years ago

As there are no new posts and the problem still exists, @UweHeinritz I would like to try your changes in my project, maybe it'd solve the flickering. Can you fork this repo and publish your changes? That would be awesome.

UweHeinritz commented 4 years ago

Hello Stephan, I uploaded my source to https://github.com/UweHeinritz/ESP8266_new_pwm

steveh80 commented 4 years ago

Thanks Uwe, it works and looks good at first glance. 🥇