letscontrolit/ESPEasy

ESP32 LittleFS build PWM GPIO : port#2 is out of range

TommoT1 opened this issue · 20 comments

In preparation to move to the LittleFS builds on ESP32 just flashed an ESP32 with with the ESP_Easy_mega_20240202_normal_ESP32_4M316k_LittleFS.factory.bin build.
Then I restored the rules wich only PWM fade the blue GPIO2 led.
On the non LittleFS build this worked fine, now I got the Logmessage:

521118: ACT : PWM,2,40,1500
521129: GPIO : port#2 is out of range

522609: ACT : PWM,2,300,1500
522619: GPIO : port#2 is out of range

524118: ACT : PWM,2,40,1500
524128: GPIO : port#2 is out of range

And the led stays dark.
When I use GPIO,2,0 or GPIO,2,1 instead of PWM it works and the led blinks.....
Is this a bug or what did change regarding PWM?

Hmm I will have a look at it, looks like a bug

Hmm looks like this recent change may have broken the PWM functionality:
https://github.com/espressif/arduino-esp32/pull/9031/files

When this build has finished, you can test if it is also fixed on your node:
https://github.com/letscontrolit/ESPEasy/actions/runs/7775190734

Incredible fast you are......
Sadly this build stalls my node, I can see it via serial for some seconds, looks as it does PWM again (two PWM Commands without errors) but then it stops talking (about 5 to 6 seconds after reboot)

Hmm I did see a potential bug in the Arduino code for reserving PWM channels.
I did do a quick fix on my end and later tried to revert it to see if it actually is a problem.
However with the original Arduino code I was not able to reproduce the bug as I thought would happen.
But I will try to make a pull request for it to the Arduino repo and try to let Jason2866 make a build for the platform code so we have a fix before it was even merged by the Arduino team.

OK, just in case you need it, this ist the rule what stalls my node:

on System#Boot do LoopTimerSet_ms,1,1500

on Rules#Timer=1 do
if [int#1] = 0
PWM,2,0,1500
let,1,1
else
PWM,2,40,1500
let,1,0
endif
endon

Not 100% sure this will be done correctly, so maybe best to change this first rules line to this:

on System#Boot do 
  LoopTimerSet_ms,1,1500
endon

Anyway, the rest is I think asking for trouble as you try to constantly fade were it may try to update a running fade as the rules are triggered at the same offset (thus no drift) while the execution of the rules may sometimes be slightly delayed.

So in this specific use case, you might be better of not using the loop timer, but rather restart the timer at the end of the rules block:

on System#Boot do 
  TimerSet_ms,1,1500
endon


on Rules#Timer=1 do
  if [int#1] = 0
    PWM,2,0,1500
    let,1,1
  else
    PWM,2,40,1500
    let,1,0
  endif
  timerset_ms,1,2000
endon

And maybe a good idea to not let the fade during be exactly the same as the timer interval.

By the way, on older builds this was completely blocking as the fade command only ended when it was done.
So by running rules like you have, the ESP would not be able to do anything else.

So may be I was just lucky it worked before, was only a fade test...
I'll change it like you showed me.
Thx

Since ESP-IDF5 there is a fade command which is not blocking and it allows to add a callback function.

So a fade loop like this could be done as a background running call, which we could trigger using a command like fadeloop in ESPEasy.

Would that be a desired command?

I use those "breathing" fades sometimes to indicate "normal" operation. So I don't know how much work that is for just am gimmick in my case...
btw. with todays build it also stalls with your changes... :-(

Just to be sure, what is 'stall' ?
What no longer works?

From what I can observe it stops completely.
WebUi not reachable anymore, the time when the other nodes saw it counts up till it gets removed from the list and serial logging stops. No serial commands are taken anymore.

changed the rules, after the 40s timer 2 (to have the chance to get access and stop it from PWM) the node hangs completely
Build: ESP_Easy_mega_20240204_normal_ESP32_4M316k_LittleFS

on System#Boot do
 TimerSet,2,40
 Let,1,0
endon

on Rules#Timer=2 do 
   TimerSet,1,3
endon

on Rules#Timer=1 do 
 if [int#1] = 0
  PWM,2,300,2000
  let,1,1
 else 
  PWM,2,40,2000
  let,1,0
 endif 
 TimerSet,1,3
endon

OK, will check your rules later today as I'm not near a computer right now.

I ran it on an ESP32-C2 and it was running fine for a while.
Now I finally got time to run it on ESP32-classic and indeed it seems to stall completely.
No idea what is happening here.

Found the cause... and made an issue for it: espressif/arduino-esp32#9212

I also have got a work-around and will make a commit for it.

Thank you!

There is still another potential bug in the Arduino code: espressif/arduino-esp32#9213
I tested with the suggested fix of that bug, but the test build doesn't have this.
So please let me know if you do experience issues with it.

Here is the test build (still running) https://github.com/letscontrolit/ESPEasy/actions/runs/7790177773

Hmm it looks like this problem will also cause issues for other use cases, so I will append those to the same pull request.

For example

  • servo functionality will cause issues if you start/stop a servo several times.
  • Switching PWM on the same pin can also cause these deadlocks.

Good morning Gijs!
For me it's working again with your latest fix, the node is "breathing" again.
I'll keep you posted if I find anything.
Thank you!