Best emtpy loop()

Sometimes a little knowledge is a dangerous thing.

1 Like

On ESP8266, that will cause the Soft WatchDog Timer to reboot after a few seconds.

As shown with AVR above, main is more generally

int main() {
  setup();
  for (;;) {
    loop();
    boardSpecificHouseKeeping();
  }
  return 0;
}

Best not to get in the way of that house-keeping. Just leave an empty loop

1 Like

@geistesschatten - See Post #13 for how Arduino's minimum sketch:

void setup(){}
void loop() {}

is encapsulated in the "real" program, so no need to write all that other code. Pretty neat.

If this is a battery powered project then it is worth looking at sleep or standby modes for the ATmega328P chip (if that is what it is on your cheap copy board) to reduce power consumption or using a hardware latch on the power supply, which the MCU breaks when a one- time activity has completed.
Otherwise it is difficult to see what you want to achieve by disabling the loop function.

1 Like

Put all your setup code in a do while true loop and just put the processor to sleep at the end. loop will never be executed.

Some boards have "background functions" (networking, USB, RTOS scheduling etc) in the loop in main that calls loop(), so never allowing setup() to finish might not be the best idea...

1 Like

I'm wondering what some of you are reading in my post...

Minimal Example? It is worth after describing? OK..

Setup() {
  // Initialize timer
  // Initialize HW
}

void loop() {
  // What do write here if we don't need this function?
}

ISR (TIMER0_COMPA_vect) {
  // Timer function handling everything..
}

Because of this I'm asking,.. FYI: I'm hiding my light under a bushel. I'm more than "a bit" experienced. But this is my first time with Arduino

Thank you. A good hint. I'll search for this in the next days.

.

As I asked before.

Why does it matter? Even with the standard, empty loop(), interrupts still interrupt. You seem intent on saving processor cycles; but since you've written your code to use interrupts, the timing is going to be pretty much defined.

You're no newbie, so I know you know it doesn't matter much, so why? If it's to avoid having the millis() timer running, for example, because it's interrupts are disturbing your tight interrupt timing requirements, then yeah, that's a good cause; start by stripping everything to the minimum, but tell us why, to give us something to work with.

Hi, @geistesschatten

What is the aim of your code, what are you trying to accomplish?

Tom.... :smiley: :+1: :coffee: :australia:

Start here

a7

1 Like

In that case, there's nothing you can do to make a "Best" loop() function that will reduce power dissipation anymore. As suggested above, you need to explore the various sleep modes of the processor. You need to pick one that can be woken by the timer interrupt. You also need to ensure that any of the processor's infrastructure / peripherals that you need are ready to go upon wake-up. Otherwise, they might need to be re-initialized.

1 Like

This compiles and runs on an Uno

int main(void)
{
  init();
  pinMode(13, OUTPUT);
  while (true)
  {
    digitalWrite(13, HIGH);
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
  }
  return true;
}

No setup()
No loop()

But it doesn't achieve @geistesschatten's stated goal of reducing power dissipation. This thread got off in the wrong direction because it started with the X-Y Problem of thinking that could be achieved by writing the "Best" loop() function or getting rid of it entirely.

1 Like

It isn't supposed to if indeed that is his/her goal.
It disproves @geistesschatten statement that the compiler requires loop().

Inferred from Post #1:

1 Like

Again I repeat my sketch is to show that loop is NOT required.
Has nothing to do with sleeping.

Yea. This is why i'm a beginner in Arduino. I don't know about this ominous main. Yes, I can remove the Loop with it - at which costs (what is also done in standard main?) and for which advantage?

So: Good to know about this, but this is not helping.

Nevertheless thanks for everybody for this thread. I've learned things I did not find at other places.

Hello.

Thank you so far for your help. But I only managed to save zero point something milli Ampere. I've readed a lot of tutorials, but I did not manage to find a API reference (What is sleep_enable() / sleep_disable() doing?).

ATM this is my power saving code:

void setup() {
  [..]
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // choose power down mode
  sleep_enable();
  power_usart0_disable();
  power_spi_disable();
  power_timer0_disable();
  power_timer2_disable();
  power_twi_disable();
  power_adc_disable();
  sleep_bod_disable();
  //sleep_disable();
  SPCR = 0;
}

And the call (last action in timer):

  //sleep_enable();
  sleep_mode(); // sleep now!
  // sleep_disable();

(out commeted code to show my last testing)

The timer only runs every few ms. The function is so fast that my oscilloscope (yea, not an expensive one) barely can see it (I put an output to HIGH during run in the timer).

Ahh.. And for the curious people: This is what I'm doing: Youtube: Lord Vetinari's Clock. But ATM the battery is empty after a week.

If you are using a board with the ATMEGA328P processor then see the data sheet chapter: "Power Management and Sleep Modes".
The macros like sleep_enable() are documented here: avr-libc: Modules

The clock looks good but for any useful comments on the power consumption you have to show the schematic diagram and the complete code.

Thank you for your answer.

Schematic is not interesting. Of course I detached all of the other devices before testing. Just the Arduino is powered.

The rest of the code also isn't interesting. In the meantime I've commented every other code out - except timer and power handling. The code is as minimal as it could be for testing.

void setup() {
  TCCR2A = (1 << WGM21); //Set the CTC mode
  TCCR2B = 7;
  OCR2A = 230;// 15 ms

  TIMSK2 |= (1 << OCIE2A); //Set the interrupt request
  sei(); //Enable interrupt

  pinMode(LED_BUILTIN, OUTPUT); // Debug
  // GPIO PIN
  pinMode(PINTICK, OUTPUT);
  pinMode(PINTACK, OUTPUT);
  pinMode(PINDEBUG, OUTPUT);

  set_sleep_mode(SLEEP_MODE_PWR_SAVE); // choose power down mode
  sleep_enable();
  power_usart0_disable();
  power_spi_disable();
  //power_timer0_disable(); // need for debug delay in timer
  power_timer1_disable();
  power_twi_disable();
  power_adc_disable();
  sleep_bod_disable();
  sleep_disable();
  SPCR = 0;
}

// Not needed
void loop() {
  //
}

ISR (TIMER2_COMPA_vect) {
  digitalWrite(PINDEBUG, HIGH);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1); // To get a reading in the oszi
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(PINDEBUG, LOW);
  ActivateSleep();
}

void ActivateSleep() {
 //sleep_enable();
  sleep_mode(); // sleep now!
  //sleep_disable();
}

Normal reading: ~ 11mA. In power save ~8mA as above. Without Timer0: ~6mA. I see an effect, but not as good as I expect. I expect <1mA, because the timer callback is just a a few cycles active. And how much did the power LED consume? As far as I see (i've googled a bit): ~ 0.5mA.

Edit:
I forgot to mention: I'm using three AA Batteries for testing. So the Board has to reduce the voltage from 4.5V to 3.3V. Now I measured the power consuming when the programmer is attached: 3.5mA. Again a bit less (2.5 mA loss? Is this normal?) but still far away of what should possible.