Skip to content

timerRestart does not restart timer #2944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Javerre opened this issue Jun 30, 2019 · 10 comments
Closed

timerRestart does not restart timer #2944

Javerre opened this issue Jun 30, 2019 · 10 comments

Comments

@Javerre
Copy link

Javerre commented Jun 30, 2019

The implementation of timerRestart in esp32-hal-timers.c is as follows:

void timerRestart(hw_timer_t *timer) {
    timer->dev->config.enable = 0;
    timer->dev->config.enable = 1;
}

However, according to the ESP32 reference manual it appears this will have no net effect:

Counting can be enabled and disabled by setting and clearing TIMGn_Tx_EN. Clearing this bit essentially freezes the counter, causing it to neither count up nor count down; instead, it retains its value until TIMGn_Tx_EN is set again.

Clearing and resetting the timer enable bit as implemented above will have the effect of pausing the timer for a few cycles. This might be what is intended but I suspect not! My expectation was that calling timerRestart would cause the timer to restart, i.e. to start counting from the beginning. It appears from the reference manual that this is accomplished by reloading the timer instead:

To trigger a software instant reload, any value can be written to the register TIMGn_Tx_LOAD_REG; this will cause the counter value to change instantly

Which would imply the following code for timerRestart might be more appropriate:

void timerRestart(hw_timer_t *timer) {
    timer->dev->reload = 1;
    timer->dev->config.enable = 1;
}

Am I missing something here, or is this a bug? I need this functionality to implement a timeout.

@lbernstone
Copy link
Contributor

It is not a heavily used piece of the code. If it works for you, it can be submitted as a PR. @me-no-dev is the only one that really knows what the author was thinking...

@atanisoft
Copy link
Collaborator

atanisoft commented Jun 30, 2019

In my usage of the timer hal I always used it as:

hw_timer_t *timer;
void setup() {
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, alarmHandler, true);
  timerAlarmWrite(timer, 100, true);
  timerWrite(timer, 0);
  timerAlarmEnable(timer);
}

In the ISR code I would call timerAlarmWrite(), timerWrite() and timerAlarmEnable() to reset the timer period.

I agree the timerRestart doesn't look correctly implemented, I'd suggest a slight adjustment to your proposal:

void timerRestart(hw_timer_t *timer) {
    timer->dev->config.enable = 0;
    timer->dev->reload = 1;
    timer->dev->config.enable = 1;
}

@notdodgy
Copy link

Really pleased to find this discussion as I was getting very frustrated with things not working.

  • I have tried the timerRestart modification above and it appears to work fine.

My original plan was to have a timer that runs once, that can be re-triggered by an event.
E.g. push a button and a door is unlocked for 6 seconds.

I thought I could use
timerAlarmWrite(timer1, 6000000 , false); // Using false means it runs once.
and
timerRestart(timer1);
to trigger it again, but this does not work.
Currently I have the timer running continuously, but reset when pressing the button as a work around.

Any suggestions?

@beegee-tokyo
Copy link
Contributor

Did you try the Ticker library that comes with the ESP32-Arduino framework? Works for me.

It has a .once() function to start a timer once and can be restarted any time.

I use it to quite often. Here is an example with retriggering for a blinking LED that blinks every 500ms for 10ms

#include <Ticker.h>

// Ticker called every 500ms
Ticker statusLED;

// Ticker called to switch off the green LED after 10ms
Ticker greenOff;
// Ticker called to switch off the redLED after 10ms
Ticker redOff;

// Forward declaration of function
void blinkLED(void);

// Called by Ticker greenOff 
void switchGreenOff(void)
{
    digitalWrite(STAT_BLUE, LED_OFF);
}

// Called by Ticker redOff 
void switchRedOff(void)
{
    digitalWrite(STAT_RED, LED_OFF);
}

// Initialize the blinking and GPIOs
void initLED(void)
{
    pinMode(STAT_RED, OUTPUT);
    pinMode(STAT_BLUE, OUTPUT);
    digitalWrite(STAT_RED, LED_ON);
    digitalWrite(STAT_BLUE, LED_ON);
    statusLED.attach_ms(500, blinkLED);
}

// Called every 500ms by Ticker statusLED
void blinkLED(void)
{
        digitalWrite(STAT_RED, LED_ON);
        digitalWrite(STAT_BLUE, LED_ON);
        redOff.once_ms(10, switchRedOff);
        greenOff.once_ms(10, switchGreenOff);
}

@notdodgy
Copy link

Thanks beegee-tokyo

Ticker looks like a simpler way to do it.
I had started from using timer to solve my problem, and hit the challenges above.
It looks like ticker is a front end for timer which makes it much simpler to implement .

I am using a card reader - when read successfully (matched with a known card) it triggers a relay output for 6 seconds.
At the same time a status led flashes rapidly (normally off for 30 second on for .3 seconds).
This sequence can also be triggered by a push button.
Some specific cards can also enable / disable it, with a different LED sequence used.

My existing code ran using millis(), with 4 separate procedures called, 3 of these kept track of timing.
This was on an arduino pro mini. With the list of access cards hard coded.

My intention is to have the list of cards configurable using a web interface which the ESP32 is ideally suited for.

As I want to vary the LED on and off periods independently, I will need to experiment, to see if I can do it with a single timer called once, which then gets called again repeatedly with alternating durations.

The challenge may be that I will need to change to a shorter delay, while it is part way through a long time period...

@stale
Copy link

stale bot commented Sep 22, 2019

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Sep 22, 2019
@willemlj
Copy link

willemlj commented Sep 24, 2019

I use the timer as a watchdog. So the timer needs to be reset every time the 'watched' function is called.

Replacing timerReset(timer); with timerWrite(timer, 0); is a workaround for the bug in timerReset(); No need to call any other function (assumed the timer is created to restart automatically)

Tnx for fix! :)

@stale
Copy link

stale bot commented Sep 24, 2019

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

@stale stale bot removed the Status: Stale Issue is stale stage (outdated/stuck) label Sep 24, 2019
@buccaneer-jak
Copy link

I am just using timerAlarmWrite(timer, 100, true) when I need to reset the timer.
I played with using timerAlarmDisable(timer); etc but found only using Write seems to restart the timer just fine. I have not tested this very thoroughly so far but using it in the 'seconds' range (ie 2000000) seems to be working.

@mehrdad987
Copy link

I am just using timerAlarmWrite(timer, 100, true) when I need to reset the timer.
I played with using timerAlarmDisable(timer); etc but found only using Write seems to restart the timer just fine. I have not tested this very thoroughly so far but using it in the 'seconds' range (ie 2000000) seems to be working.

Thankyou
its working--->timerAlarmDisable(timer);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants