Skip to content

delayMicroseconds(): added support for 1Mhz, 12Mhz and 24Mhz #1678

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
wants to merge 2 commits into from

Conversation

cano64
Copy link

@cano64 cano64 commented Nov 13, 2013

1Mhz is a default clock speed on Atmega328, many users run stand alone microcontroller on the
internal 1Mhz clock to save battery power. Up until now delayMicroseconds() function wasn't taking this frequencies into an account defaulting to 8Mhz resulting incorrect timing. Patch includes support for 12 and 24 Mhz clock as well

1Mhz is a default clock speed on Atmega328, many users run it on the
internal 1Mhz clock to save battery power. Up until now
delayMicroseconds() function wasn't taking this frequencies into an
account.
@Lauszus
Copy link
Contributor

Lauszus commented Nov 13, 2013

Could you perhaps add support for 10MHz as well?

@niesteszeck
Copy link

Nativelly arduino has support for 20Mhz? 'cause I use 20Mhz clock and it will be great to have supported that hz to.

Thanks for your work

@cano64
Copy link
Author

cano64 commented Nov 14, 2013

The branch I edited already had 20Mhz support, I can add 10Mhz support later, right now 10Mhz will default to 8Mhz, with 20% error, close enough :)

@Lauszus
Copy link
Contributor

Lauszus commented Nov 15, 2013

Thanks. I would really appreciate that :)

@niesteszeck
Copy link

Thanks

@RobTillaart
Copy link

The proposed code has the bug reported in #1121 - "bug in delayMicroseconds() when called with 0"
cause
if (--us == 0)
return;

Q: is the code tested ? especially small values (0..10).
what are the results?
Cmaglie has posted some testcode in #1121 (mid of page)

@cano64
Copy link
Author

cano64 commented Feb 3, 2014

I fixed the problem with zero delay, I also fixed the problem with ADC prescaler. I tested the microdelay with an oscilloscope, everything works fine now.

@ArduinoBot
Copy link
Contributor

Can I build this pull request?

@cano64
Copy link
Author

cano64 commented Aug 22, 2014

Yes, please.

@ffissore
Copy link
Contributor

@cano64 sorry for the arduinobot comment. we are setting up automatic build of pull requests

@cmaglie cmaglie added feature request A request to make an enhancement (not a bug fix) Architecture: AVR Applies only to the AVR microcontrollers (Uno, etc.) labels Apr 15, 2015
@cano64
Copy link
Author

cano64 commented May 20, 2015

Can we please merge it already? It's been open for a year and half. I spent a lot of time writing and fine tuning it and it has been working fine over the past year and half.

@cmaglie cmaglie added this to the Release 1.6.5 milestone May 22, 2015
@cmaglie
Copy link
Member

cmaglie commented May 22, 2015

Rebased and merged the fix.
Thank you, and sorry for the long delay!

@RobTillaart
Copy link

Just checked the 1.6.4 (AVR) code and you still cannot call delayMicroSeconds(0) as the --us statement wraps around. Apparently nobody tested it ...

The patch was in already in my issue of 18 nov 2012
see #1121

The code below is FAULTY!

void delayMicroseconds(unsigned int us)
{
    // calling avrlib's delay_us() function with low values (e.g. 1 or
    // 2 microseconds) gives delays longer than desired.
    //delay_us(us);
#if F_CPU >= 20000000L
    // for the 20 MHz clock on rare Arduino boards

    // for a one-microsecond delay, simply wait 2 cycle and return. The overhead
    // of the function call yields a delay of exactly a one microsecond.
    __asm__ __volatile__ (
        "nop" "\n\t"
        "nop"); //just waiting 2 cycle
    if (--us == 0)
        return;

    // the following loop takes a 1/5 of a microsecond (4 cycles)
    // per iteration, so execute it five times for each microsecond of
    // delay requested.
    us = (us<<2) + us; // x5 us

    // account for the time taken in the preceeding commands.
    us -= 2;

#elif F_CPU >= 16000000L
    // for the 16 MHz clock on most Arduino boards

    // for a one-microsecond delay, simply return.  the overhead
    // of the function call yields a delay of approximately 1 1/8 us.
    if (--us == 0)
        return;

    // the following loop takes a quarter of a microsecond (4 cycles)
    // per iteration, so execute it four times for each microsecond of
    // delay requested.
    us <<= 2;

    // account for the time taken in the preceeding commands.
    us -= 2;
#else
    // for the 8 MHz internal clock on the ATmega168

    // for a one- or two-microsecond delay, simply return.  the overhead of
    // the function calls takes more than two microseconds.  can't just
    // subtract two, since us is unsigned; we'd overflow.
    if (--us == 0)
        return;
    if (--us == 0)
        return;

    // the following loop takes half of a microsecond (4 cycles)
    // per iteration, so execute it twice for each microsecond of
    // delay requested.
    us <<= 1;

    // partially compensate for the time taken by the preceeding commands.
    // we can't subtract any more than this or we'd overflow w/ small delays.
    us--;
#endif

    // busy wait
    __asm__ __volatile__ (
        "1: sbiw %0,1" "\n\t" // 2 cycles
        "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
    );
}

@cmaglie
Copy link
Member

cmaglie commented Jul 4, 2015

@RobTillaart
the code you quoted is not the one shipped on 1.6.4.
I'm pretty sure that delayMicroseconds(0) works as expected, I've tested it personally.

https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c#L131

@RobTillaart
Copy link

@cmaglie
(the github link seems right)
I just downloaded - https://www.arduino.cc/en/Main/OldSoftwareReleases#previous -
the - Windows ZIP file for non admin install - option

Please check the wiring.c in that zip

(1.6.4 of course)

@cmaglie
Copy link
Member

cmaglie commented Jul 5, 2015

Right, the patch has been merged after IDE 1.6.4.

BTW IDE 1.6.5 should ship the latest or, alternatively, you can update the AVR core through Cores Manager.

@RobTillaart
Copy link

Thanks, I'll check the 1.6.5. instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Architecture: AVR Applies only to the AVR microcontrollers (Uno, etc.) Component: Core Related to the code for the standard Arduino API feature request A request to make an enhancement (not a bug fix)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants