Exact number of clock cycles for a particular piece of code?

The main loop of my program is quite short, and it isn't important for it to take any specific amount of time to complete, as long as it always takes the EXACT SAME amount of time to complete EVERY time, and if I know EXACTLY how many clock cycles it will take.

My code is as follows:

void loop()
{ 
  Udp.beginPacket(broadcastIP, 8890);  

  voltage = analogRead(A0);
  data[0] = lowByte(voltage);
  data[1] = highByte(voltage);
  Udp.write(data, 2);
  Udp.endPacket();

  delay(3);
}

Can anyone tell me how many clock cycles the above loop will take, or direct me to how I can find out? I'm assuming delay(3) will take 48 thousand (16 MHz clock), but is it exact? I know that I can look up in the ATMega328 datasheet to figure out how long the assembly instructions take, and I know that the compiler turns the C++ into assembly at some point, but I don't know where I can find the assembly that gets made.

in case it matters, data is a byte array, and voltage is an int, both global.

Thanks for your help!

Hi

I’m assuming delay(3) will take 48 million (16 MHz clock),

delay(3) will pause the program for 3 milliseconds, not 3 seconds.

If you want loop() to repeat exactly every 3 seconds, use millis() and the “BlinkWithoutDelay” approach - there is an example program which demonstrates it.

A video about the approach: Arduino State Management Explained (BlinkWithoutDelay) - YouTube

How accurate do you need the timing to be for each iteration?

Regards

Ray

Oops, that was a typo, I meant 48 thousand.

I don't need the timing to be specific to any number in particular, I'd just like to know exactly how long it is, down to the microsecond if possible. I know that the other instructions in the loop take a non-negligible amount of time, so I'd really just like to know how many microseconds the loop takes.

Something else I could possibly do is run the program with wireshark running on the computer that will be receiving the udp packets, and try to time how fast I get packets, but I'd rather not go that route because there would be too much human error with using a stopwatch

The

  Udp.beginPacket(broadcastIP, 8890);

is a function call to some code. It is likely that it will interact with the shield and that interaction will wait for some responce from the hardware / network. Therefore you can not say how long it is going to take. It will be different every time.

There is a micros() function, similar to millis(), with a resolution of 4us on a Uno.

How frequently do you need the loop to execute?

In my implementation, the Arduino is functioning as a remote unit that is communicating with a main program on a PC, and the rate at which data gets sent is very important. This rate can be anything, but it needs to be an exact number.

I'd like the loop to execute approximately every 3 milliseconds, but I'd REALLY like to know the EXACT amount of time the loop takes, so I can account for any drift on the other end.

I would approach it in two (maybe three) steps.

  1. Add some debug code to measure and print the time in us for each pass through your code. Analyse the results to address Grumpy_Mike’s point about variability in function execution times. Choose a target loop repeat frequency that allows “headroom” above the maximum measured duration. Allow for the fact that the added code (e.g. store micros() in a variable, compare variable with micros()) will add to loop time.

  2. Use “BlinkWithoutDelay” and the micros() function to repeat your code at the “headroom” frequency.

  3. If you have an accurate, high resolution frequency counter, confirm the loop execution frequency by adding code to set / reset a pin on each iteration and measure the frequency of the pulses on this pin.

That sounds like a great place to get started!

Thanks for your help!

the rate at which data gets sent is very important. This rate can be anything, but it needs to be an exact number.

Is it the rate that has to be exact, or would it be enough to know the time at which each analogRead() measurement is taken? Could the PC adjust for a variable rate by doing an interval calculation on the time of the readings?

If so, you could time stamp each packet with a reading from micros().

and the rate at which data gets sent is very important.

Rubbish. If it was, you wouldn't be using UDP.

The time that udp.write() takes is totally unpredictable. Dependent on what is going on, on the network, there are packet collisions to avoid, and you also have to rely on everything else on the network giving YOUR packets priority over everything else they may be doing at the time.

You need to have a good look at what you are attempting to achieve and somehow remove that dependency on a regular time interval. It'll NEVER be reliable with ANY network protocol involved.

Which is why using ancient IEEE488 (GPIB) is so much better than TCP/IP for instruments that need to be triggered. (Sorry, did I say that out loud?)

You should read micros() at the beginning of the loop, and use a while loop at the end until the micros() reaches some amount. That way, while the network traffic may take a variable amount of time, the aggregate loop time will be the same.

KeithRB:
Which is why using ancient IEEE488 (GPIB) is so much better than TCP/IP for instruments that need to be triggered.

CANBUS is a good choice (typically with a separate line for "trigger").

There are also interrupts happening that you don't have total control over. Their frequency and duration could vary. You could turn them off if you don't care about system timing or other hardware interrupts. Except maybe the Ethernet receive code...

If you just want total control over your code, there is a _delay_us() call that is accurate to the exact clock cycle. It's pretty cool.

Another way to be very accurate would be to use the 1 second signal from a GPS card or other such external hardware signal.

Probably the most accurate way I can think of to accomplish what you want is to put wait code at the bottom of your loop() routine that is triggered by the timer. That way, you don't really care how long the other stuff takes, as long as it is less than your timer setting. You will be guaranteed the same amount of time for each packet. It will also eliminate drift.

awilder1015:
I don't need the timing to be specific to any number in particular, I'd just like to know exactly how long it is, down to the microsecond if possible. I know that the other instructions in the loop take a non-negligible amount of time, so I'd really just like to know how many microseconds the loop takes.

As others have said, network transmissions are likely to be somewhat unpredictable. If, for example, the router is busy doing something else that microsecond, it will introduce a delay. I don't see how knowing to the microsecond how long the loop takes will achieve anything.

network transmissions are likely to be somewhat unpredictable.

UDP isn't even guaranteed. At least TCP will try again if the packet isn't delivered. UDP doesn't care.

If timing is critical, put the time in the packet, and don't use UDP.

Perhaps it's time to quit whining and explain WHY you think you need to send packets on a regular schedule. What are you sending them to?

A better approach would be to build the recipient application with a buffer. Maybe even return some signaling to let your arduino know when it has recieved packets and when it is ready for more.

Nothing is more time critical than video feeds, YET (at least in some instances) this has been achieved across networks seemlessly. The way it works is by the recipient application allocating a large buffer to store many frames ahead. It still gets delivered to the front end at a steady predictable rate, but the data collection is done as and when circumstances permit.

That is because each "frame" is time stamped, which is what the OP needs to do.