Delay from 1 to 2 microseconds

I have to generate a ramp with a fairly precise slope interspersed with a 1 second pause, and I got good results by connecting an old DAC (the DA1280), driven on the 8 most significant bits, connected to the L port of the arduino MEGA, and quickly writing the portL with the 256 values ​​in sequence. The sketch is the following:

void setup() {
 DDRL=B11111111; 
} 

void loop() { 
   for(int y=255;y>-1;y--){
       PORTL=y; 
       delayMicroseconds(1); //ritardo tra un campione ed il successivo del DAC, ovvero durata della rampa 
    }
    PORTL=255; 
    delay(1000); 
} 

The duration of this ramp is my problem, because with:
delayMicroseconds (1); the ramp lasts 100µsec delayMicroseconds (2); the ramp lasts 300µsec delayMicroseconds (3); the ramp lasts 520µsec delayMicroseconds (4); the ramp lasts 800µsec delayMicroseconds (5); the ramp lasts 1000µsec delayMicroseconds (6); the ramp lasts 1400µsec
(times measured with an oscilloscope).
I would also like to obtain intermediate values, such as 150, 200, 250, 300, 350 and so on, in steps of ABOUT 50µsec. What do you recommend?
I thought I was wasting some time with some "useless operation", like sums or other, to put after the delayMicroseconds (), but first I would like your opinion.
Many thanks

Short pulses can be produced using NOOPs.

You should remember other things are happening with interrupts that might give undesirable effects.

See the Arduino Reference guide for delayMicroseconds()

This function works very accurately in the range 3 microseconds and up to 16383

For accurate delays you need to turn off interrupts and can use avrlibc delays

_delay_loop_1 executes three CPU cycles per iteration, not including the overhead the compiler needs to setup the counter register. (187.5 ns/loop @ 16 MHz)

And, of course, take into account the precise instruction timing of the for loop.

The NOP instruction is a single instruction delay. You can put as many NOP instructions after each other to get a precise delay.

The compiler can do that for you with the function "__builtin_avr_delay_cycles()".
The compiler does not call a function, but replaces that with NOP instructions or any other combination of instructions and iterations to get to the exact number of clock cycle delay.

It is something specifically for the AVR boards: https://gcc.gnu.org/onlinedocs/gcc/AVR-Built-in-Functions.html

Since Arduino does not use the WatchDog, you can turn off the Arduino environment by disabling the interrupts. After that, you can no longer use Arduino functions, such as delay().

Did you know that the 'C' language uses 0b11111111 and that Arduino has defined B11111111 somewhere in a include file ?

The for-statement is too vague for precise timing, so I removed it. This is my experiment:

// For: https://forum.arduino.cc/t/delay-from-1-to-2-microseconds/1026312
//
// PortL is at pins 42 ... 49 (PORTL0 = 49, PORTL7 = 42)
//
// Starting this sketch actives the Logic Analyzer which wants to store the data.
//
// A clock cycle is 1/16MHz is 62.5ns
// 150µs for 256 steps is 586ns ? and is 9 cycles ?

#define DACCYCLES 7
#define DACVALUE(a) PORTL=a; __builtin_avr_delay_cycles(DACCYCLES)

void setup() 
{

#ifdef GENERATE_CODE
  Serial.begin(115200);
  for(int i=255; i>=0; i--)
  {
    Serial.print( "  DACVALUE(");
    Serial.print( i);
    Serial.print( ");\n");
  }
  Serial.flush();
#endif

  DDRL = 0xFF;
  noInterrupts();    // Bye bye Arduino
} 

void loop() 
{ 
  DACVALUE(255);
  DACVALUE(254);
  DACVALUE(253);
  DACVALUE(252);
  DACVALUE(251);
  DACVALUE(250);
  DACVALUE(249);
  DACVALUE(248);
  DACVALUE(247);
  DACVALUE(246);
  DACVALUE(245);
  DACVALUE(244);
  DACVALUE(243);
  DACVALUE(242);
  DACVALUE(241);
  DACVALUE(240);
  DACVALUE(239);
  DACVALUE(238);
  DACVALUE(237);
  DACVALUE(236);
  DACVALUE(235);
  DACVALUE(234);
  DACVALUE(233);
  DACVALUE(232);
  DACVALUE(231);
  DACVALUE(230);
  DACVALUE(229);
  DACVALUE(228);
  DACVALUE(227);
  DACVALUE(226);
  DACVALUE(225);
  DACVALUE(224);
  DACVALUE(223);
  DACVALUE(222);
  DACVALUE(221);
  DACVALUE(220);
  DACVALUE(219);
  DACVALUE(218);
  DACVALUE(217);
  DACVALUE(216);
  DACVALUE(215);
  DACVALUE(214);
  DACVALUE(213);
  DACVALUE(212);
  DACVALUE(211);
  DACVALUE(210);
  DACVALUE(209);
  DACVALUE(208);
  DACVALUE(207);
  DACVALUE(206);
  DACVALUE(205);
  DACVALUE(204);
  DACVALUE(203);
  DACVALUE(202);
  DACVALUE(201);
  DACVALUE(200);
  DACVALUE(199);
  DACVALUE(198);
  DACVALUE(197);
  DACVALUE(196);
  DACVALUE(195);
  DACVALUE(194);
  DACVALUE(193);
  DACVALUE(192);
  DACVALUE(191);
  DACVALUE(190);
  DACVALUE(189);
  DACVALUE(188);
  DACVALUE(187);
  DACVALUE(186);
  DACVALUE(185);
  DACVALUE(184);
  DACVALUE(183);
  DACVALUE(182);
  DACVALUE(181);
  DACVALUE(180);
  DACVALUE(179);
  DACVALUE(178);
  DACVALUE(177);
  DACVALUE(176);
  DACVALUE(175);
  DACVALUE(174);
  DACVALUE(173);
  DACVALUE(172);
  DACVALUE(171);
  DACVALUE(170);
  DACVALUE(169);
  DACVALUE(168);
  DACVALUE(167);
  DACVALUE(166);
  DACVALUE(165);
  DACVALUE(164);
  DACVALUE(163);
  DACVALUE(162);
  DACVALUE(161);
  DACVALUE(160);
  DACVALUE(159);
  DACVALUE(158);
  DACVALUE(157);
  DACVALUE(156);
  DACVALUE(155);
  DACVALUE(154);
  DACVALUE(153);
  DACVALUE(152);
  DACVALUE(151);
  DACVALUE(150);
  DACVALUE(149);
  DACVALUE(148);
  DACVALUE(147);
  DACVALUE(146);
  DACVALUE(145);
  DACVALUE(144);
  DACVALUE(143);
  DACVALUE(142);
  DACVALUE(141);
  DACVALUE(140);
  DACVALUE(139);
  DACVALUE(138);
  DACVALUE(137);
  DACVALUE(136);
  DACVALUE(135);
  DACVALUE(134);
  DACVALUE(133);
  DACVALUE(132);
  DACVALUE(131);
  DACVALUE(130);
  DACVALUE(129);
  DACVALUE(128);
  DACVALUE(127);
  DACVALUE(126);
  DACVALUE(125);
  DACVALUE(124);
  DACVALUE(123);
  DACVALUE(122);
  DACVALUE(121);
  DACVALUE(120);
  DACVALUE(119);
  DACVALUE(118);
  DACVALUE(117);
  DACVALUE(116);
  DACVALUE(115);
  DACVALUE(114);
  DACVALUE(113);
  DACVALUE(112);
  DACVALUE(111);
  DACVALUE(110);
  DACVALUE(109);
  DACVALUE(108);
  DACVALUE(107);
  DACVALUE(106);
  DACVALUE(105);
  DACVALUE(104);
  DACVALUE(103);
  DACVALUE(102);
  DACVALUE(101);
  DACVALUE(100);
  DACVALUE(99);
  DACVALUE(98);
  DACVALUE(97);
  DACVALUE(96);
  DACVALUE(95);
  DACVALUE(94);
  DACVALUE(93);
  DACVALUE(92);
  DACVALUE(91);
  DACVALUE(90);
  DACVALUE(89);
  DACVALUE(88);
  DACVALUE(87);
  DACVALUE(86);
  DACVALUE(85);
  DACVALUE(84);
  DACVALUE(83);
  DACVALUE(82);
  DACVALUE(81);
  DACVALUE(80);
  DACVALUE(79);
  DACVALUE(78);
  DACVALUE(77);
  DACVALUE(76);
  DACVALUE(75);
  DACVALUE(74);
  DACVALUE(73);
  DACVALUE(72);
  DACVALUE(71);
  DACVALUE(70);
  DACVALUE(69);
  DACVALUE(68);
  DACVALUE(67);
  DACVALUE(66);
  DACVALUE(65);
  DACVALUE(64);
  DACVALUE(63);
  DACVALUE(62);
  DACVALUE(61);
  DACVALUE(60);
  DACVALUE(59);
  DACVALUE(58);
  DACVALUE(57);
  DACVALUE(56);
  DACVALUE(55);
  DACVALUE(54);
  DACVALUE(53);
  DACVALUE(52);
  DACVALUE(51);
  DACVALUE(50);
  DACVALUE(49);
  DACVALUE(48);
  DACVALUE(47);
  DACVALUE(46);
  DACVALUE(45);
  DACVALUE(44);
  DACVALUE(43);
  DACVALUE(42);
  DACVALUE(41);
  DACVALUE(40);
  DACVALUE(39);
  DACVALUE(38);
  DACVALUE(37);
  DACVALUE(36);
  DACVALUE(35);
  DACVALUE(34);
  DACVALUE(33);
  DACVALUE(32);
  DACVALUE(31);
  DACVALUE(30);
  DACVALUE(29);
  DACVALUE(28);
  DACVALUE(27);
  DACVALUE(26);
  DACVALUE(25);
  DACVALUE(24);
  DACVALUE(23);
  DACVALUE(22);
  DACVALUE(21);
  DACVALUE(20);
  DACVALUE(19);
  DACVALUE(18);
  DACVALUE(17);
  DACVALUE(16);
  DACVALUE(15);
  DACVALUE(14);
  DACVALUE(13);
  DACVALUE(12);
  DACVALUE(11);
  DACVALUE(10);
  DACVALUE(9);
  DACVALUE(8);
  DACVALUE(7);
  DACVALUE(6);
  DACVALUE(5);
  DACVALUE(4);
  DACVALUE(3);
  DACVALUE(2);
  DACVALUE(1);
  DACVALUE(0);

  DACVALUE(255);         // end of ramp
   
  __builtin_avr_delay_cycles(16000000UL - ((DACCYCLES * (256 + 1)) - 4)); // PROBABLY WRONG !
}

Try this sketch in Wokwi:

The Wokwi Logic Analyzer tries to store the data when the simulation is stopped. Click on the Logic Analyzer and delete it to remove it.

All that is needed, is someone who can calculate the cycles from the number of microseconds and compensate that in the 1 second delay.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.