Skip to content

delay() function doesn't work for less than 10ms #2981

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
ducalex opened this issue Jul 11, 2019 · 15 comments
Closed

delay() function doesn't work for less than 10ms #2981

ducalex opened this issue Jul 11, 2019 · 15 comments
Labels
Status: Stale Issue is stale stage (outdated/stuck)

Comments

@ducalex
Copy link
Contributor

ducalex commented Jul 11, 2019

Hardware:

Board: Lolin32
Core Installation version: d5fdd71
IDE name: IDF component
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 115200
Computer OS: Windows 8.1

Description:

delay() doesn't work for periods smaller than one tick(10ms) (it is also rounded down if not divisible by 1 tick).

It is a small change but I can create a pull request if it is the proper way to do things also, just tell me.

Sketch: (leave the backquotes for code formatting)

Current code is:
void delay(uint32_t ms)
{
    vTaskDelay(ms / portTICK_PERIOD_MS);
}



//  My suggestion is:
void delay(uint32_t ms)
{
    uint32_t delay_end = millis() + ms;
    vTaskDelay(ms / portTICK_PERIOD_MS);
    while (delay_end > millis()) {
        NOP();
    }
}
@stickbreaker
Copy link
Contributor

@ducalex
Why do you think portTICK_PERIOD_MS is 10?

Chuck.

@stickbreaker
Copy link
Contributor

@ducalex if you are worried the portTICK_PERIOD_MS will change in the future, then you could change delay() current Delay coding
to:

void delay(uint32_t ms)
{
    vTaskDelay(ms / portTICK_PERIOD_MS);
    uint32_t remainderUS = (ms % portTICK_PERIOD_MS)*1000;
    if(remainderUS) delayMicroseconds(remainderUS);
}

@ducalex
Copy link
Contributor Author

ducalex commented Jul 11, 2019

@ducalex
Why do you think portTICK_PERIOD_MS is 10?

Chuck.

#define CONFIG_FREERTOS_HZ 100
#define configTICK_RATE_HZ				( CONFIG_FREERTOS_HZ )
#define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ )\

vTaskDelay's argument is a tick number. Therefore it works correctly only on multiples of portTICK_PERIOD_MS which is 10.

Your code would also resolve the problem indeed.

@ducalex
Copy link
Contributor Author

ducalex commented Jul 11, 2019

You can see the problem with this code:

void setup()
{
    for (int i = 0; i < 20; i++) {
        int start = millis();
        delay(i);
        printf("i = %d, actual sleep = %dms\n", i, (int)(millis() - start));
    }
}

Output:

i = 0, actual sleep = 0ms
i = 1, actual sleep = 0ms
i = 2, actual sleep = 0ms
i = 3, actual sleep = 0ms
i = 4, actual sleep = 0ms
i = 5, actual sleep = 0ms
i = 6, actual sleep = 0ms
i = 7, actual sleep = 0ms
i = 8, actual sleep = 0ms
i = 9, actual sleep = 0ms
i = 10, actual sleep = 7ms
i = 11, actual sleep = 10ms
i = 12, actual sleep = 10ms
i = 13, actual sleep = 10ms
i = 14, actual sleep = 10ms
i = 15, actual sleep = 10ms
i = 16, actual sleep = 10ms
i = 17, actual sleep = 10ms
i = 18, actual sleep = 10ms
i = 19, actual sleep = 10ms

@negativekelvin
Copy link

negativekelvin commented Jul 12, 2019

#define CONFIG_FREERTOS_HZ 1000

So I assume you are using arduino-esp32 as a component with your own sdkconfig settings?

Let's say portTICK_PERIOD_MS = 10 and you call delay(9). Do you really want to block and spin for 9ms?

@stickbreaker
Copy link
Contributor

@ducalex with current core 7dbda4

to console i = 0, actual sleep = 0ms
to console i = 1, actual sleep = 1ms
to console i = 2, actual sleep = 2ms
to console i = 3, actual sleep = 3ms
to console i = 4, actual sleep = 4ms
to console i = 5, actual sleep = 5ms
to console i = 6, actual sleep = 6ms
to console i = 7, actual sleep = 7ms
to console i = 8, actual sleep = 8ms
to console i = 9, actual sleep = 9ms
to console i = 10, actual sleep = 10ms
to console i = 11, actual sleep = 11ms
to console i = 12, actual sleep = 12ms
to console i = 13, actual sleep = 13ms
to console i = 14, actual sleep = 14ms
to console i = 15, actual sleep = 15ms
to console i = 16, actual sleep = 16ms
to console i = 17, actual sleep = 17ms
to console i = 18, actual sleep = 18ms
to console i = 19, actual sleep = 19ms

Chuck.

@ducalex
Copy link
Contributor Author

ducalex commented Jul 12, 2019

So I assume you are using arduino-esp32 as a component with your own sdkconfig settings?

Correct, the default esp-idf settings.

Let's say portTICK_PERIOD_MS = 10 and you call delay(9). Do you really want to block and spin for 9ms?

I do. That is how other arduino boards work and a lot of code and libraries expect delay to work as per the documentation.

That is also how esp-idf's own usleep() works.

As you pointed out delay works fine in Arduino IDE, if you consider Arduino as component to be unsupported then please close this issue!

Thanks

@ducalex
Copy link
Contributor Author

ducalex commented Jul 12, 2019

@stickbreaker Yes, I can see it works fine in Arduino IDE now. As pointed out by @negativekelvin, it is only a problem when using arduino-esp32 as a component because freertos frequency is 100hz (by default).

@stickbreaker
Copy link
Contributor

I missed you were using arduino as a component. I don't know all the rules when using arduino as a component. I do know, I2C is not shared between Wire() and idf.

Chuck.

@negativekelvin
Copy link

I do. That is how other arduino boards work and a lot of code and libraries expect delay to work as per the documentation.
That is also how esp-idf's own usleep() works.

Yes usleep, emphasis on the u. It is not good design to use it for ms delays. Is there a reason you don't want to set tick hz to 1000?

@ducalex
Copy link
Contributor Author

ducalex commented Jul 12, 2019

Is there a reason you don't want to set tick hz to 1000?

None, I didn't know that Arduino-esp32 IDE version wasn't using the default 100Hz.

I will change my project to 1000 but perhaps it could be worth mentioning this necessary step in the setup guide here https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md.

Thanks

@romansavrulin
Copy link
Contributor

@ducalex Please fix that doc to and make a PR

@ducalex
Copy link
Contributor Author

ducalex commented Jul 19, 2019

Done. #3014

@stale
Copy link

stale bot commented Sep 17, 2019

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 17, 2019
@stale
Copy link

stale bot commented Oct 1, 2019

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Stale Issue is stale stage (outdated/stuck)
Projects
None yet
Development

No branches or pull requests

4 participants