An Arduino Nano is set up to perform A/D conversions and send results out over Serial
. Currently the code structure is like
loop() {
delayUntilNextTargetTime();
measure();
sendMeasurementsToSerial();
}
Though I make already sure that delayUntilNextTargetTime
does not blindly delay(MILLIS)
but rather subtracts the computation time from the time to sleep to prevent drift, I would rather get the timing from the host computer.
The idea is that the host computer sends a command string over the serial when it wants data, so the loop could look like
loop() {
if (!Serial.available()) return;
measure();
sendMeasurementsToSerial();
}
Now I wonder if there is a way to do this without idle polling, something along the lines of
loop() {
if(Serial.available()) {
measure();
sendMeasurementsToSerial();
}
sleepUntilSerialPotentiallyHasData();
}
I read that saving power is hard and likely not worth the effort, in particular when having a USB power supply. It is pure curiosity to see
- what it takes to bring the system into, say, IDLE mode, possibly stopping the timers too, because they are not used (I guess)
- and what it takes to get out of IDLE mode correctly again such that A/D conversion in
measure()
works without flaws.
1 Answer 1
On a Nano you can #include <avr/sleep.h>
, then simply call
sleep_mode()
from loop()
. This will put the device to sleep, by
default in IDLE mode, until the next interrupt fires. The Nano will wake
up at least once every 1,024 μs, to service the timer interrupt
that is used to implement the Arduino timing function(millis()
,
delay()
, etc.). Most of the time this loop()
will do nothing more
than testing Serial.available()
, so the MCU will be awake only for a
couple of microseconds every 1,024 μs, which is not much.
If you disable the timer interrupt, all the timing functions will be off, but the MCU will still be waken by the serial port interrupt as soon as data is available.