Coming from a C background, I was taught that tight loops that just burn CPU aren't desirable.

Is there any programming style guides on Arduino? Is it common practice to just let loop iterate as a tight loop forever?

  • Is your project powered by batteries or by mains? May 4 '20 at 18:03
  • @EdgarBonet mains, I'm just wondering if the loop section can be made more elegant or if its always just a tight loop, feels a little like while(1).
    – Woodstock
    May 4 '20 at 18:03

A microcontroller's execution path is a tight loop whether you like it or not.

If you take a CPU and connect it to empty memory the CPU will execute each empty cell in turn and loop back to the beginning of memory when it reaches the end (assuming empty memory cells equate to NOP and covers the whole memory space).

With no operating system, no scheduler, nothing except your specific code running, the CPU is always executing something.

The only time the CPU stops executing is when you manually send it to sleep to be woken by some external source (such as a timer, or a sensor sending an interrupt signal). You'd only do that, normally, to reduce power consumption.

On Arduino the loop() function is in fact executed from within a while(1) loop.

On microcontrollers when main() exits, or you call exit() it just disables interrupts and drops out to a while(1) loop.


On a multiprocess system, like your typical desktop, you usually have way more processes than logical CPUs. When programming such systems you therefore have to avoid burning more CPU cycles than needed. Instead, when your program has nothing to do, it should just sleep, and leave the CPU available for other processes.

On an Arduino, you only have one single program running at a time. It is then not that useful to keep the CPU idle. Also, the power dissipation is so low that you will not notice the microcontroller getting even slightly warm. The extra complexity of getting into and out of sleep mode is therefore not that useful. Only when running on batteries do you care about saving every possible milliamp: then learning about sleep modes starts getting useful.

  • Furthermore, with cooperative multitasking on a real mode system like an Arduino you WANT the main app loop to run as fast as possible (The tightest possible loop.) That way it checks for & responds to inputs as fast as possible. If you write interrupt code, you want THAT to finish as quickly as possible in order to get back to that tight main loop.
    – Duncan C
    May 4 '20 at 19:01

That is a difference between embedded systems programming and (many but not all) other types of programming. An embedded system is usually a controller of some kind and needs to be responsive to one or more kinds of events. Three typical ways of accomplishing this are

  • to use some kind of operating system to coordinate events and the code that manages each of them;
  • to write interrupt service routines (ISRs) to manage events and dispatch to code that manages them;
  • to poll for events frequently and dispatch to the code to manage them.

On processors as small as the AVRs, data memory and sometimes instruction memory, are scarce resources and an operating system is usually too expensive (in terms of memory needs) for most of them. On the ATtinys, forget it. On Uno, maybe kinda sorta, but memory will be a pretty severe limitation. On Megas, you might manage it.

ISR programming can be complex to write and is definitely more complex to debug(!). It's not out of the question, and it may be justified in a system that must be highly responsive - think automotive ABS braking, traction control, and fly-by-wire systems. On the other hand, systems like these have to be right.

Polling is the easiest to write and debug. You call each subsystem (code) in a tight loop (and there's your answer: "yes, let it iterate") that gives each one an opportunity to assess whether or not it needs to act and to do so. This is a case where burning cycles is inconsequential, while making a more responsive system.

In my hobbyists' classes, this is what I teach; it's also what use most. I call it "maybe-do" (and wrote about it here in answer to another question). In loop() I do nothing but call a number of functions in turn, each of which does:

      if I dont need to act now,
      else {
         do what needs to be done -- quickly!;
  • thank you JRobert!
    – Woodstock
    May 4 '20 at 19:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.