Fri 06 March 2015 In intermediate. tags: delay leonardo

AVR-Ada provides basically two ways to delay the code execution.

One way is busy looping using Generic_Busy_Wait_Seconds and Generic_Wait_USecs procedures from the AVR.Wait package.

procedure My_Wait is new AVR.Wait.Generic_Busy_Wait_Seconds (Crystal_Hertz => 16_000_000); procedure Wait_1000ms is new AVR.Wait.Generic_Wait_USecs (Crystal_Hertz => 16_000_000, Micro_Seconds => (1_000_000));

Another way is to use AVR.Real_Time.Delays package and Delay_For or Delay_Until procedures. GNAT also automatically translates "delay X.Y;" and "delay until X;" statements into calls to the procedures of AVR.Real_Time.Delays. Only trick required is have "with AVR.Real_Time.Delays;" statement in your code, since AVR-GNAT is not clever enough to do that automatically.

delay 1.0;

Sometimes people have been wondering how accurate the various delay methods are.

I decided to test the delays on Arduino UNOr3 and Arduino Leonardo using following program:

with AVR.MCU; with AVR.Real_Time.Delays; with AVR.Interrupts; with AVR.Wait; with Interfaces; use AVR; procedure LED is use type Interfaces.Unsigned_32; procedure Wait_1000ms is new AVR.Wait.Generic_Wait_USecs (Crystal_Hertz => 16_000_000, Micro_Seconds => (1_000_000)); -- For Arduino Leonardo -- LED_Port : Boolean renames MCU.PINC_Bits (7); -- LED_DD : Boolean renames MCU.DDRC_Bits (7); -- For Arduino UNOr3 LED_Port : Boolean renames MCU.PINB_Bits (5); LED_DD : Boolean renames MCU.DDRB_Bits (5); begin AVR.Interrupts.Disable; -- AVR.MCU.PRR1_Bits(7) := True; -- uncomment for Leonardo LED_DD := DD_Output; LED_Port := False; AVR.Interrupts.Enable; Wait_1000ms; LED_Port := True; Wait_1000ms; LED_Port := True; Wait_1000ms; LED_Port := True; Wait_1000ms; LED_Port := True; delay 1.0; LED_Port := True; delay 1.0; LED_Port := True; delay 1.0; LED_Port := True; delay 1.0; LED_Port := True; loop LED_Port := True; delay 1.0; end loop; end LED;

I uploaded the program on Arduino and then connected Saleae Logic logic analyzer to the LED pin of Arduino to measure the LED blinking delay.

For Arduino UNOr3 I got follow capture:

And same for Arduino Leonardo:

On Arduino UNOr3 the Wait_1000ms call took 1.012_7 seconds and on Arduino Leonardo 1.012_9 seconds. So, on both boards, 1s delay using busy looping Wait_1000ms took about 1.3% more than what it should have.

On the other hand, "delay 1.0" call, which is implemented using timers, was quite accurate. On Arduino UNOr3 "delay 1.0" took 0.999_821 seconds and on Arduino Leonardo 1.000_037 seconds.

From this we can see that waiting one second using "delay 1.0" is probably accurate enough for most purposes. Error on Arduino UNOr3 is less than 200 microseconds and on Leonardo 37 microseconds.

However, to make Wait_1000ms call more accurate, I changed it to following on Arduino Leonardo:

procedure Wait_1000ms is new AVR.Wait.Generic_Wait_USecs (Crystal_Hertz => 16_000_000, Micro_Seconds => (1_000_000 - 12500));

Value 12500 was found by experimenting. Each invidual device is different and there is some error in the measurement also, so this value might not work on your devices.