decimal microseconds

hi
what do you do when you want to a delay of 1.5 microseconds for example?
or 0.5 microseconds?

I've seen arduino only accepts delayMicroseconds( a ), where a is an integer and a>=1

You can substitute and fractional seconds by adding in dummy instructions. @16Mhz, there are 16 instructions per microsecond. So you would need 8 dummy instructions to delay half a microsecond.

Generally you would insert NOP (No OPeration) instructions:

asm("nop\n\t");

asm("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); \ gang them up like this

Each NOP instruction take one machine cycle. On a 16 MHz Arduino that will be 1/16th of a microsecond.

I would recommend using a delay routine that takes into consideration the cpu clock
rate so that it "just works" even if the code is run on AVR running at a different speed.

You could call call the AVR libC delay code.

#include <util/delay.h>

Then you can call the delay functions.

_delay_us(XXX);

Where XXX is a constant value an can be less than 1.
What is too bad and makes this options not really viable
is that the avr libC that Arduino ships with Arduino is old/out-of-date,
and the older <util/delay.h> doesn't have very good resolution so if you start
to get into low values like you are talking about you won't get a delay that is
as close to the delay that is possible at the given CPU clock rate.

With the newer <util/delay.h> you will get a delay that is withing 1 clock cycle of
what you want and can specify if you want the delay to rounded up or down to the
nearest clock cycle.

With the older code (which is what ships with Arduino) you get a delay that is a multiple
of 3 clock cycles and can not be lower than 3 clock cycles.

This kind of in-accuracy can be REALLY bad if your clock rate is slow say on a 1Mhz AVR
or if you are trying to get say sub 1us delays.

I argued with the AVR libC maintainers about this for more than a year before it was finally
updated.

Rather than have to worry or be limited by the Arduino code and their development
schedule, or worry about which version of the compiler or AVR libC is installed,
the easiest thing to do (which I would highly recommend), would be to go
get Hans Heinrich's delay_x project from the AVR freaks site:
http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=665&item_type=project
zip image download: http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=1992

Just grab the delay_x.h header file from the zip image. (it is the only file you need)
Copy it to your sketch area and include it in your sketch.
Then you can call _delay_ns(xxx) and specify the number of nano-seconds to delay.
Hans' code will then calculate the closest delay possible while rounding up to the nearest AVR clock cycle.
note: xxx must be constant (not a variable)

These delays are very accurate.
The glcd library uses this to provided the needed h/w setup timing that is much less than 1us.

--- bill

I see the last 2 guys told stuff more difficult than I was expecting,
can it be something like

i=1;

and it is equivalent in time to 62.5 ns ?

If you want to delay 62.5 nS do this, as johnwasser said:

__asm__("nop\n\t");

What's complicated about it?

That assumes you are running a clock at 16 MHz.

Why do you want to do this? Interrupts are going to make such fine-grained delays not totally reliable.

softuino:
I see the last 2 guys told stuff more difficult than I was expecting,
can it be something like

i=1;

and it is equivalent in time to 62.5 ns ?

Probably. You have to be careful though. One line of code isn't necessarily 1 instruction. In this case, it should be but I would also be weary of the compiler optimizing the code and possibly removing one or more of your statements. I don't know enough about either scenario to tell you with certainty, so I think the NOP is your best bet.

Just a note, the asm as it is fine (though I would omit the trailing "\n\t").

However, if you ever move to the extended form of asm where you pass in values and/or use the results, you probably want to use asm volatile, so that the optimizer does not move the asm around. Asm's that are just a string, are assumed to be volatile.

__asm__ volatile ("foo" : "=r" (out) : "r" (in));

Johns suggestion was kind of doing what you are now talking about.
Each NOP is 1 AVR clock cycle. If you are running at 16Mhz then each NOP is 62.5ns.

The problem is, you asked a very generic question in the original post.
The way I read the post, it seemed to be asking for doing some kind of delay that
specified in wall clock time vs AVR clock cycles.
Without knowing what you really want/need and what clock rate your AVR is running at
it is impossible to suggest a "simple" solution.

If you use Hans' delay_x.h header file, you can call _delay_ns(xx) and specify the delays
in nano seconds that get rounded to AVR clock cycles.

So, if you want accurate CPU speed independent delays specified in terms of wall clock time,
I'd still recommend using Han's delay_x.h delay routines.

If you want to specify your own delays in AVR clock cycles,
use NOPs as others have suggested.
Just keep in mind that since NOPs are AVR clock cycle delays, that
when the frequency of the AVR changes the delay will change as well.

Han's routines will adjust the clock cycles to match the new clock frequency when the code
is rebuilt for the new clock frequency.

--- bill

Nick,
It is possible that Arch, may be the same issue I was dealing with in the glcd library.
You need a minimum delay that is as short as possible. Longer is ok but in the case of the glcd library
when the delay gets longer it dramatically affects rendering performance.

I am intrigued by this and would like to try it out on an arduino uno, but I am a newbie so I'm running into some challenges. I tried placing the header file in the folder with the sketch, and am including it with #include "delay_x.h" but I am getting issues when compiling.

Do other variables need to be set? (I set F_CPU = 16000000 in my sketch)

Maybe someone knows a simple example of "_delay_ns" being used? Seeing a working (potentially extremely simple, yet complete) sketch would be extremely helpful. It's hard for me to sort out what is necessary to include in the test file included.

Or maybe is there a knowledge-base or readme with more step by step instructions?

Thanks

WOW, this is a old thread coming back to life.

Assuming you are using an AVR based arduino,
To use it all you need to do is add the include to your sketch:

#include <util/delay.h>

The IDE automatically sets the F_CPU value for you based on the board you selected.

Then you can use the _delay_us() function.
It is just that simple.

_delay_us(0.5);

would be asking for a delay of 0.5us or 500ns
Just keep in mind that the delay you actually get is based on the cpu clock and can't always be exactly what you ask for.
The delay you get will be the closet delay time that can be done that is at least as long as you asked. i.e. it can and often will be longer.

See the AVR libC manual for more details and additional options:
http://nongnu.org/avr-libc/user-manual/group__util__delay.html

--- bill

Dear Bill,

thank you very much. Worked like a charm.