Page 1 of 1

[SOLVED] My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 6:57 am
by filo_gr
Hello community,

I made a function that should be able to create a delay for a certain number of microseconds, here the code.

Code: delay_us.cpp Select all


void delay_us(uint64_t number_of_us){
// Initializing the variable with the time BEFORE the count.
uint64_t microseconds = esp_timer_get_time();
// Starting the count, it exits when it is greater than number_of_us.
while(number_of_us <= (esp_timer_get_time() - microseconds));
}
As you can see I measure the time between two instants using esp_timer_get_time() (this funcion returns an uint64_t with the number of microseconds starting from the power up).
I encountered the following problem when using it: if I use a value such as delay_us(20), it doesn't work!
Driving a pin (from high to low and vice versa) with a period of 40us I see, using an oscilloscope, that the time is not respected.
The period time is more or less 7us, very far from 40us (it is 3us low and 3us high!!!!).
That's not all! If I put delay_us(1000) the result doesn't change...

What am I doing wrong?

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 7:17 am
by WiFive

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 7:47 am
by filo_gr
Thank you @WiFive, however I also found my mistake (I think and I ask for a confirm).
Firstly, I didn't included esp_timer.h, I think the compiler didn't recognize esp_timer_get_time() and that's why it wasn't working (but no errors during compiling). Am I right?
Then, I tried your esp_rom_delay_us but it gives a possible problem (and here the second question): it stops the processor for a certain time, giving the impossibility of performing other tasks. It's true?

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 9:40 am
by filo_gr
I want to give a complete explanation of what I did.
1) Using esp_timer_get_time() I need to write an #include "esp_timer.h". The lines of code resulting from this choice are:

Code: Untitled.cpp Select all


void delay_us(uint64_t number_of_us){
uint64_t microseconds = (uint64_t)esp_timer_get_time();
if(number_of_us){
uint64_t total = (microseconds + number_of_us);
if(microseconds > total){
while((uint64_t)esp_timer_get_time() > total);
}
while((uint64_t)esp_timer_get_time() < total);
}
}
It works, however with a small value of number_of_us it could be imprecise.

2) On the other hand I can use esp_rom_delay_us and so I need #include "esp_rom_sys.h".

Code: Untitled.cpp Select all


void delay_us(uint64_t number_of_us){
esp_rom_delay_us((uint32_t)number_of_us);
}
Here the microprocessor waits util the time is passed.

What of these approaches is the best?

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 5:20 pm
by mbratch
When using unsigned values, if you do the math in the right place, the overflow takes care of itself. So I think your first option could look like this:

Code: Select all

void delay_us(uint64_t number_of_us) {
    uint64_t microseconds = (uint64_t)esp_timer_get_time();
    if (number_of_us) {
        while ((uint64_t)esp_timer_get_time() - microseconds < number_of_us) ;
    }
}
At first glance, this appears to be incorrect if `esp_timer_get_time()` overflows back to 0 before the difference reaches `number_of_us`. But this is not the case. The "unsigned math" works in your favor. :)

Actually, in your first post, you just about had it right. You just had the inequality reversed.

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 5:23 pm
by igrr
if `esp_timer_get_time()` overflows back to 0
Luckily, this shouldn't happen in a long long time :D

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 6:52 pm
by mbratch
if `esp_timer_get_time()` overflows back to 0
Luckily, this shouldn't happen in a long long time :D
Haha yep

Re: My function for microseconds delay doesn't work properly

Posted: Thu Sep 09, 2021 9:48 pm
by chegewara
Easier to use:

Code: Select all

ets_delay_us(); == esp_rom_delay_us();
no problem with header file.

Re: My function for microseconds delay doesn't work properly

Posted: Fri Sep 10, 2021 6:15 am
by filo_gr
Thank you for your replies!
@mbratch, with your message, now I understand why my first piece of code wasn't working, the condition was wrong! :lol:
Hence if I use the esp_rom_delay_us (instead of the while loop and esp_timer_get_time) it should not give any kind of problem.