Hi I am using Arduino Nano
to gamify my experience on Unity3D. I know that Update()
in Unity3D runs every frame per second but I because I'm not an electronics guy I don't know how loop()
function runs on Arduino.
Does it depends on number of CPU cycles(or micro processor chip in case of Arduino) or what? Please explain. I facing some lags in my game. I can fix them only if know how is loop() function running on Arduino
There ain't a lot of information about loop()
in arduino documentation
-
3"runs every frame per second" not sure you completely understand frames, or maybe just a typo. but in Unity3D each frame runs as fast as possible, they don't purposefully but a delay in the frameMCMastery– MCMastery2017年08月24日 18:19:53 +00:00Commented Aug 24, 2017 at 18:19
-
put a delay in the frame (can't edit it? thought i could)MCMastery– MCMastery2017年08月24日 19:18:08 +00:00Commented Aug 24, 2017 at 19:18
-
1Looks like the short answer is "as fast as possible".Stack Exchange Broke The Law– Stack Exchange Broke The Law2017年08月25日 01:56:19 +00:00Commented Aug 25, 2017 at 1:56
6 Answers 6
Loop runs as long as loop needs to run.
Instructions in a CPU run sequentially. The more instructions there are the longer it takes to run.
The more code you put in loop the longer loop will run.
There are two ways to know how long each iteration of loop will take:
- Profiling: Actively time each iteration of loop, though be warned, the act of timing will affect the amount of time taken.
- Cycle counting. Compile the source into assembly and total up the number of clock cycles needed for all the instructions (including calls to functions). Arduous for small loops, a gargantuan task for anything else.
Also note that many external factors can affect how long loop() takes to run - such as serial communication speed, etc.
-
Don't forget interruptions for example updating the millis value every 16000 clock cycles (for 16Mhz oscilator). They stop execution of program in regular intervals and prevent the arduino from being a good PWM source. (yes you can turn them off)Filip Franik– Filip Franik2017年08月24日 15:14:08 +00:00Commented Aug 24, 2017 at 15:14
-
5@FilipFranik: 1. The interrupt that updates the
millis()
value runs every 1024 µs, or 16384 CPU cycles at 16 MHz. 2. Interrupts affect the quality of software PWM output (e.g., the Servo library). They have no effect on hardware-generated PWM (e.g., withanalogWrite()
).Edgar Bonet– Edgar Bonet2017年08月24日 15:24:06 +00:00Commented Aug 24, 2017 at 15:24
the instructions between the end of loop() and the next run of it are a ret, jmp and a call.
You can consider the main function to be effectively:
void main(){
init();
while(1) loop();
}
Though in reality there is some setup done before init()
to make millis()
and such work.
-
2Also you have serial event code after loop.Majenko– Majenko2017年08月24日 11:19:55 +00:00Commented Aug 24, 2017 at 11:19
-
@Majenko isn't that done with interrupts?ratchet freak– ratchet freak2017年08月24日 11:20:36 +00:00Commented Aug 24, 2017 at 11:20
-
1No, it's not. It's just called at the end of loop. It's very crude and many people don't understand just how pointless it really is.Majenko– Majenko2017年08月24日 11:21:04 +00:00Commented Aug 24, 2017 at 11:21
-
I think the loop() is optimized by the compiler, so no actual jmp or ret occur. The code translates to: while (1) yourLoopCode; without function call. But I saw horrible dumb things with GCC...next-hack– next-hack2017年08月24日 11:22:35 +00:00Commented Aug 24, 2017 at 11:22
-
2The more I look at the standard runtime of an arduino the more I am dissapointed...ratchet freak– ratchet freak2017年08月24日 11:38:25 +00:00Commented Aug 24, 2017 at 11:38
A look at main.cpp (for avr code in my installation) in file:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\main.cpp
shows that the Arduino runs loop() alternately with serialEventRun() in an infinite loop:
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
Inspection of HardwareSerial.cpp shows that serialEventRun() simply calls serialEvent(), if you have defined it in your sketch.
This means that you can write your own infinite loop within loop() perfectly safely, unless you have written serialEvent() code and are expecting it to run regularly.
This begs the question: if serialEvent() is called sequentially with loop(), will serialEvent() be called if loop() never returns? In other words, is serialEvent() interrupt-driven as well as being called when loop() returns? A quick test -see below- shows that it is not interrupt-driven, so the previous paragraph is true.
/*
Serial Event Checker
A sketch to see if serialEvent() is interrupt-driven.
Will serialEvent() be called if loop() never returns?
This code is based on Tom Igoe's SerialEvent example.
On (at least) Arduino Uno we find that serialEvent() simply runs
sequentially with loop(). When loop() never returns serialEvent()
is never called.
NOTE: The serialEvent() feature is not available on the Leonardo, Micro, or
other ATmega32U4 based boards.
R Symonds-Tayler 2018年02月01日
This example code is in the public domain.
*/
String inputString = ""; // a String to hold incoming data
void setup() {
// initialize serial:
Serial.begin(115200);
// reserve 200 bytes for the inputString:
inputString.reserve(200);
}
// comment out this definition to allow loop() to return
#define INFINITE_LOOP
void loop() {
#ifdef INFINITE_LOOP
while(1);
#endif
}
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
// do something about it:
if (inChar == '\n') {
Serial.print("Got: '");
Serial.print(inputString);
Serial.println("'");
// clear the string:
inputString = "";
}
}
}
This means that serialEvent() code might just as well go into your main loop() within a:
if(serial.available()){
// your code here...
}
block.
It depends on what's in the loop. From a few clock cycles to infinite hang.
try looking up arduino functions micros() and delayMicroseconds() If you might need your loop to wait longer than 16000 microseconds then also look up the other delay() function which does milliseconds.
By the way, the internal clock is very slightly off and varies with room temperature, so don't rely on it staying synchronised to your other device without a handshake.
-
1
micros()
anddelayMicroseconds()
use 32-bit integers (unsigned long
) and can manage durations up to 2³² µs, or about 1.19 hours.Edgar Bonet– Edgar Bonet2017年08月24日 16:47:17 +00:00Commented Aug 24, 2017 at 16:47
In this article bri_huang made a nice experiment using an oscilloscope and simple write functions.
He calculated the speed of the loop to be 117 kHz even though the microcontroller has a 16 MHz clock.
-
3That link does not really say a lot about how "fast"
loop()
is (which I.M.O. Is meaningless), but only how fast the Arduino implementation ofdigitalWrite()
is (which is not exactly the fastest way to toggle a pin on the Arduino).StarCat– StarCat2021年05月10日 13:34:07 +00:00Commented May 10, 2021 at 13:34 -
So no satisfactory answer yet? Or can we assume it runs at the speed of the crystal oscillator?Arjuna Deva– Arjuna Deva2021年05月11日 12:51:06 +00:00Commented May 11, 2021 at 12:51
-
@Alejandro Camus It has a billion factors all the way from temperature of your room to how much load is the microprocessor is handling, we cannot even say that it runs at the speed of the oscillator as commands take time to doCoder9390– Coder93902021年05月12日 14:23:34 +00:00Commented May 12, 2021 at 14:23
-
That is a good test of how fast
digitalWrite()
works; not a good test of how fastloop()
loops. In that test, they're benchmarkingdigitalWrite()
, with no reasonable expectation that it's a single clock cycle or a single instruction.Edward Ned Harvey– Edward Ned Harvey2022年12月21日 15:13:22 +00:00Commented Dec 21, 2022 at 15:13 -
Yep, points takenArjuna Deva– Arjuna Deva2022年12月21日 16:16:02 +00:00Commented Dec 21, 2022 at 16:16