Arduino lag problem

I'm trying to convert my Arduino into a square wave generator to test various flybacks. The problem is the functions seem to lag the process down, I've separated the generator() sequence from the rest of the program to isolate it from lags, but executing the analogread() the while() and digitalWrite() seem to be enough to limit the whole thing to 6kHz when set to 20kHz (50 uS period).

void generator(){

while(analogRead(0)>1000){         //when a button is pressed it returns to settings mode

digitalWrite(out, HIGH);
digitalWrite(out, LOW);


Removing analogread() and putting a silly constant like (n==0) it goes up to 16kHz, it's quite remarkable, but doing that there's no way of using the buttons to adjust the settings while running. I don't know if I can substiitute analogRead since all the buttons of the display have different analog values and are connected to A0.

Is there a way to remove this lags? I know there's a lot of optimization to be done even at a very basic level, but I don't know how or where to start.
Ideally I just want it to work from 1 to 50kHz.

Here's the complete program, as far as I know, all the lags occur inside the generator() function.

Thanks for your time!!

Picture of Arduino lag problem
sort by: active | newest | oldest
seandogue2 years ago

Your problem stems from the fact that the commands and query (analog read) take finite time themselves, causing the expected wave to stretch in time (effectively reducing the output frequency)

AFAIK, many (?most? ?all;?) Arduinos have some sort of PWM channel that can be configured to output a continuous square wave at fixed duty cycle. This will all but eliminate the delays associated with the DIO on, DIO off, delay, and the loop itself.

You can also use an interrupt instead of a loop to detect an event. Using an analog threshold *may require the use of an external comparator (essentially, a very high gain amp) as the input to the interupt I/O port.

You'll have to wait for an Arduino "expert" to provide detailed programming assistance for this family of uCs, as I use them infrequently and am not intimate.

Victor805 (author)  seandogue2 years ago

Got it, external comparator to convert to digital so I don't have to use the analogRead() which I think is heavier. I'll look into interrupts, they seem interesting and I haven't worked with them too much...

Again, regardless of the lopp vs interrupts, PWM will set the frequency to a constant value,independent of a check loop... So although interrupts are "better" for certain triggers, it's probably unnecessary in this case, as long as you use PWM instead of essentially "manually" toggling the DIO.

If, however, you need the function to shut off ~immediately upon hitting some threshold, interrupts will suit the purpose far better than a loop.

PS> I first encountered this behavior back in the early 80s when I started programming loops, so it's not a completely uncommon . "learning experience".

good luck

iceng2 years ago

C has overhead executable code.

Try writing the generator as a call to machine code

Victor805 (author)  iceng2 years ago

I didn't understand the slang, but I guess you mean to avoid the "fool proof" arduino functions and learn how to program from the root.

iceng Victor8052 years ago

delayMicroseconds(period) say 3us

delay: Take the period value and in binary place it into a down counter [3steps]

DD: call FRACount down another value and return on zero [7steps]

decrement the period down counter [1step]

compare and exit on zero [2steps]


Just guessing

Each binary value decrement is comprised of [10 machine time steps]

for a total of 30 plus the preload of 3 for a grand total of 33 machine steps

for a simple 3us delay.