Notifications
Clear all

[Solved] ESP 32 Timer Interrupts – ‘Unlimited’ Programmatic User Definable Timers

54 Posts
7 Users
37 Likes
2,476 Views
ron bentley
(@ronbentley1)
Honorable Member
Joined: 12 months ago
Posts: 386
Topic starter  

@zander 

Hi Ron,

thanks, I've had a quick look and nothing springs out from this snippet.

How many timer interrupts are you using/defining? Your comments/code suggest more than timer 0, especially, as you say, the wrong timer is being triggered?

As a way of moving this forward, have you pared everything back to say just one appliance and then building things back in?

Ron B

PS

Just a thought but your snippet code does not validate that you have successfully created a semaphore:

...
timerSemaphoreK = xSemaphoreCreateBinary(); // Create semaphore to inform us when the timer has fired
...

Try adding a validation check, eg:

  ...
  timerSemaphoreK = xSemaphoreCreateBinary(); // Create semaphore to inform us when the timer has fired
  if( timerSemaphoreK == NULL )
    {
        // There was insufficient FreeRTOS heap available for the semaphore to
        be created successfully.
        ...
    }
    else
    {
        // The semaphore can now be used. Its handle is stored in the xSemahore variable.  Calling xSemaphoreTake() on the semaphore here will fail until the semaphore has first been given. 
       ...
    }
  ...

 

 

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
ReplyQuote
ron bentley
(@ronbentley1)
Honorable Member
Joined: 12 months ago
Posts: 386
Topic starter  

@zander 

Hi Ron,

your example uses the Boolean pdTRUE which is okay for the one ISR you have suggested in the above snippet, but if you have more than one timer ISR running, each executing xSemaphoreGiveFromISR(timerSemaphore?, NULL), how do you differentiate your ISRs by using a 'common' Boolean flag, ie pdTRUE?

Is such a construct a point of conflict?

Regards

Ron B

 

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
frogandtoad reacted
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@zander 

 if (TimerWasherOn | TimerBathroomOn | TimerKitchenOn) digitalWrite(SSR_Pin, HIGH);  

Without understanding of what your code is actually doing, this is a just an observation that I'd like to point out.

Did you want a "bitwise or (|) there", OR... did you want a "logical or (||) instead" ?

Cheers


   
ron bentley reacted
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

@ronbentley1 Those are both good ideas Ron I will do both, thanks.

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ron bentley reacted
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

@ronbentley1 I have no idea, I am commiting the sin of copying code that I don't fully understand. The thing is though, I can simplify this to just setting a volatile bool and it works, most of the time without all the extra fancy stuff.

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ron bentley reacted
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

@frogandtoad What I meant was if any of the bool's is true then digitalwrite. In this case I think the net result is the same, but the || logical operator is more correct.

The bug has nothing to do with this section of code unfortunatly, it's related to when the timer fires the wrong ISR is being executed.

To restate, timer0/alarm is set for 30 mins, timer1/alarm is not set timer2/alarm is not set. When the 30 minutes expire it's the ISR attached to  timer1/alarm that executes.

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ron bentley reacted
ReplyQuote
ron bentley
(@ronbentley1)
Honorable Member
Joined: 12 months ago
Posts: 386
Topic starter  

@frogandtoad @zander

Hi, either construct should yield the same results, albeit '||' is perhaps what is intended.

If the variables are all Bool, then a | b | c |....| n will deliver TRUE if any one is true, otherwise FALSE (0), as would a || b || c || ....|| n

Ron B

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
frogandtoad and Ron reacted
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

@ronbentley1 @frogandtoad I did a complete rewrite using simple millis() loops and NO timer. The first two buttons work fine but when I add in the 3rd it fires right away repeatedly. Today I will move wires and see if the problem follows the physical button or the pin. I am a little worried the board I select in the IDE has no direct match with mine, I have a ESP-WROOM-32 but the closest match in the IDE is ESP32-WROOM-DA.

Even if this is a bad solder joint, loose pin, bad/wrong pin it does NOT explain the problem I had with the timer approach where the symptom was start alarm 0 but alarm 1 fires.

 

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ReplyQuote
ron bentley
(@ronbentley1)
Honorable Member
Joined: 12 months ago
Posts: 386
Topic starter  

@zander 

Ron,

Looks like things are starting to move in the right direction. Button switches are notoriously flaky, I've had some doing what your 3rd one is doing and I presume you have swapped it out,?

These switches are only reliable if debounce is implemented otherwise you will get multiple spurious firings.

I have a 30 pin ESP32 WROOM board and I select the "DOIT ESP32 DEVKIT V1" from the IDE board menu. I've never had any issues this far.

Your post has spurred to look at freertos semaphores more deeply, so thanks for the awakening.

Ron B

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

@ronbentley1 I swapped the button leads and the problem stayed with the same pin. That means either a bad pin or wrong type of pin. I desoldered GPIO25 and attached the misbehaving button to GPIO26. It is now working and I can watch what is happening on my Pi4 because I threw in MQTT. Easy peasy, one procedure to do the WiFi with WiFiManager, one to set up MQTT then just change my Serial to Log and voila, magic. Over the net noticeably slow, but on my local net hardly any effect. I need to check if 802.11/ax offers any benefit over 802.11/ac. It shouldn't, but nice to know.

Thanks to all those that offered advice, this was a difficult one, @ronbentley1, @frogandtoad, @Inq, and especially to @will who wrote code for me to try and helped keep me focused (a REAL challenge at times)

Now I want to go back to the original hardware timer based sketch and see if it now works, but I doubt it since the ISR was firing for the wrong  timer. How a flaky pin affects that I am not sure, but maybe.

I will leave this unsolved until some time has passed and I also try with the older ISR code.

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ron bentley reacted
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

I have finished the testing of the original HW_Timer code and simple ISR (one bool = true) no semaphores or crit sections, it's about as small a piece of code possible.

The main problem was the pin. Either that pin is not supposed to be used for input although the doc says it is, or I have a problem on the perf board. I moved the offending button to a different pin and all was well!

The other problem is terrible documentation. I spent a few hours today running several tests and finally realized this API is a 2 for. The timer is seperate from the alarm. As soon as I did a restart on the timer followed by an alarm enable when the button was pressed it worked every time. 

Marking this solved now, again, thanks to all that helped, I learned a lot.

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ron bentley and DaveE reacted
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@zander

Posted by: @zander

@frogandtoad What I meant was if any of the bool's is true then digitalwrite. In this case I think the net result is the same, but the || logical operator is more correct.

The bug has nothing to do with this section of code unfortunatly, it's related to when the timer fires the wrong ISR is being executed.

To restate, timer0/alarm is set for 30 mins, timer1/alarm is not set timer2/alarm is not set. When the 30 minutes expire it's the ISR attached to  timer1/alarm that executes.

I can only assume and provide assumptions without seeing the code.  If I had a $ for "it ain't the code..."!

Btw... you're always telling newbies to show their code... pot kettle black?

Please help us to help you - You know the drill very well 😉


   
ron bentley reacted
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@ronbentley1

Posted by: @ronbentley1

@frogandtoad @zander

Hi, either construct should yield the same results, albeit '||' is perhaps what is intended.

If the variables are all Bool, then a | b | c |....| n will deliver TRUE if any one is true, otherwise FALSE (0), as would a || b || c || ....|| n

Ron B

Good pickup Ron 🙂

Perhaps @zander can confirm if he was working with boolean data types or something else.

Cheers


   
ron bentley reacted
ReplyQuote
ron bentley
(@ronbentley1)
Honorable Member
Joined: 12 months ago
Posts: 386
Topic starter  

Hi,

I am currently working through FreeRTOS as an operating system alternative and just covered its software timers. I was very happy to find that this capability provides the same/similar functionality as my ETA Framework!!!

As far as I can see, though, it operates on 'ticks" rather than milliseconds. On Arduino UNO and MEGA 1 tick is about 25 milliseconds, so does not get close to the 1 millisecond resolution required by the ETA Framework. There is a solution and that is to use a hardware timer like the Framework.

I suspect that 1 tick on an ESP 32 will be closer to 1 millisecond because of it's much higher clock speed, but I cannot confirm this - does anyone know?

Anyway, just an observation. I am cracking on getting further into FreeRTOS and quite enjoying it.  The quality of the documentation from the FreeRTOS group is excellent, see my post signposting this if you have an interest in FreeRTOS (FreeRTOS Documentation LINK).

Cheers

Ron B

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


   
frogandtoad and DaveE reacted
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 4017
 

@ronbentley1 I forget exactly which board, but pretty sure its an esp32 and it is 80000000 ticks per second IIRC. I would go look for it but since you are rooting around in there already I am surprised you haven't noticed it.

I just googled up the following

 

Regarding the prescaler, we have said in the introductory section that typically the frequency of the base signal used by the ESP32 counters is 80 MHz (this is true for the FireBeetle board). This value is equal to 80 000 000 Hz, which means means the signal would make the timer counter increment 80 000 000 times per second.

Although we could make the calculations with this value to set the counter number for generating the interrupt, we will take advantage of the prescaler to simplify it. Thus, if we divide this value by 80 (using 80 as the prescaler value), we will get a signal with a 1 MHz frequency that will increment the timer counter 1 000 000 times per second.

From the previous value, if we invert it, we know that the counter will be incremented at each microsecond. And thus, using a prescaler of 80, when we call the function to set the counter value for generating the interrupt, we will be specifying that value in microseconds.

I was using a factor of 40000 and I have no idea why now. I do NOT have a firm grasp of this concept, so would really appreciate you doing a deep dive then creating a summary that us mere mortals can understand and use.

 

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ron bentley reacted
ReplyQuote
Page 3 / 4