esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
16.05k stars 13.33k forks source link

Add option to shift the phase of multiple PWM outputs #7850

Closed GagoX closed 3 years ago

GagoX commented 3 years ago

Basic Infos

Platform

Settings in IDE

Problem Description

In the current version of Tasmota, when using two PWM outputs to control a CCT light, both PWMs have 0° phase shift, i.e., both go up or down in sync at the start of a cycle. In some cases it would be better to spread out the PWM, so that at 100% brightness, the total power is distributed over the whole PWM cycle. This is relevant for tunable white COBs LEDs which usually are rated for a maximum combined constant current for both cold and warm channels.

E.g., For brightness slider at 100%, if the CCT slider is at 80%: Currently: PWM1 is high between 0 and 80% of the cycle, PWM2 is high between 0 and 20% of the cycle. The power profile over time is 120% during 0-20% of the cycle, 80% during 20-80% of the cycle and 0% during 80-100% of the cycle.

This effectively halves the max current that a tunable white LED can be driven with. As in the case where the CCT slider is 50%, the LED would get 200% of the driving current in half the cycle and zero on the other half.

Alternatively, an option could be implemented so that - for the same example (for brightness slider at 100%, if the CCT slider is at 80%): PWM1 is high between 0 and 80% of the cycle, the PWM2 should be high between 80 and 100% of the cycle. I this case the power profile is constantly 100% over the entire cycle.

GagoX commented 3 years ago

This was suggested briefly in #7057 by @s-hadinger as well

earlephilhower commented 3 years ago

Check the Phase-locked PWM generator described in the docs/headers. You can so manual startWaveform()s with shifted alignment to handle what you're talking about that way.

int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
  uint32_t runTimeCcys, int8_t alignPhase, uint32_t phaseOffsetCcys, bool autoPwm) 

Be sure to add the enablePhaseLockedWaveform(); call in your setup() (as in the FadePolledTimeout example) to enable the phase PWM, or else the phase alignment stuff will be ignored by the default generator.

devyte commented 3 years ago

The Arduino reference does not allow phase locking. One of our two implementations does, but as @earlephilhower says, you have to go below the "normal" Arduino api and implement things on your own according to what you need. Closing due to not an issue.

GagoX commented 3 years ago

thanks for your feedback, I will take a look and see if I can make it work. You are right, this is not an issue. However I think this would be a nice feature for a lot of people. Is there somewhere I can request it?

devyte commented 3 years ago

This is the place, but the point is that the feature is already implemented. All you have to do, as you said, is make it work to fit your needs, which should be trivial if you look at the implementation of the Arduino functions that wrap the lower level waveform generator, e. g. AnalogWrite(), AnalogFrequency(). I implemented a 4ch variable frequency pulse generator for stepper motors with the waveform gen by looking at that, and it took about 10 minutes to get the proof of concept working. To be clear, it doesn't make sense to add some parameter to the Arduino API calls, because the feature doesn't exist in the Arduino reference, and also because only the non-default waveform gen algorithm has the ability to shift phase. That said, if you have a proposal for exposing the phase shift param that doesn't involve changing the Arduino API function signatures and that has zero impact on the use case with the default waveform gen algorithm, then let's discuss it.

GagoX commented 3 years ago

Thanks for your replies. However I am overwhelmed. :( If I understand correctly you recommend that I complile a custom version of Tasmota, with a non default PWM. I am having problems to understand how to do that in the first place. earlephilhower suggest to look at the FadePolledTimeout example but I could not find it ( I googled it) But let's say I will be able to use the phase locked pwm...You suggest that I need to set the PWM shift from the setting of the color CCT slider? how can I do that? May I ask for a little more guidance? Thank you

s-hadinger commented 3 years ago

@GagoX You are just opening a big can of worms. You gave simple examples with 2 PWM that fit nicely. However what about 3,4,5 PWMs? What if the sum of duty cycle exceeds 100%? There are so many cases to consider that the code will become quickly bloated.

Did you actually see a problem with PWM being phase locked?

GagoX commented 3 years ago

Hi @s-hadinger,now that you mention it, I agree that the case of 2 channels is more straightforward to define.

My problem is only that I am a newbi and do not know how to proceed with the advice given by earlephilhower. I see that the function he mentioned is in https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_waveform.h.

cheers

GagoX commented 3 years ago

Hi, I have just learned how to compile a custom version of Tasmota using Gitpod. I found in the platformio_override.ini. In the [tasmota_stage] and [core_stage] sections There these lines: ; *** Use ONE of the two PWM variants. Tasmota default is Locked PWM -DWAVEFORM_LOCKED_PHASE ;-DWAVEFORM_LOCKED_PWM I have uncomment the locked phase pwm in both. I do not see a difference in the phase of the pwm channels just yet. I tried adding the call enablePhaseLockedWaveform() in the tasmota.ino in the section setup() but the compilation throws an error at me.

What am I missing?