Understanding Millis Behavior In Arduino's Low Power Mode

does millis work during arduino sleep

Arduino is a popular open-source platform used for building electronics projects. One of the key features of Arduino is its ability to enter a sleep mode, which helps conserve power. However, this raises the question of whether certain functions, such as millis(), continue to work during this low-power state. Millis() is a function in Arduino that returns the number of milliseconds that have passed since the Arduino board started up. This function is often used for timing and synchronization in Arduino projects. When an Arduino board enters sleep mode, some timers are disabled, including Timer0, causing the millis() function to stop counting. This has sparked discussions and workarounds in the Arduino community, as some projects require accurate timing even during sleep mode.

Characteristics and values of "does millis work during Arduino sleep"

Characteristics Values
Timer0 Disabled during sleep mode, causing millis to stop counting
SLEEP_MODE_IDLE The only sleep mode that allows millis() to continue running
Timer 2 Can run asynchronously during sleep, but not on Uno or Mega boards due to unavailable pins
Accuracy Millis() is inaccurate during sleep mode due to time drifting; external clock input or RTC modules may be used for better accuracy
Power Saving Sleeping for shorter durations multiple times can save a significant amount of power
Overflow Millis() overflow during light sleep mode may cause issues in exiting loops
ADC_sleep mode Millis() loses approximately 0.1 ms for every ADC conversion; corrections can be made to improve accuracy

shunsleep

Millis() stops counting during sleep mode

The Millis() function stops counting during sleep mode in Arduino. This is because Timer0 is disabled when the Arduino enters sleep mode, causing Millis() to stop counting. This can be an issue for applications that require accurate timekeeping, such as a stopwatch, timer, or alarm.

To address this, one solution is to use the SLEEP_MODE_IDLE sleep mode, which allows Millis() to continue running. However, this mode only saves a small amount of power, and there may be more efficient ways to achieve accurate timekeeping. Another possibility is to use an external clock input to Timer 1 or Timer 2 and run it asynchronously. This would require additional setup and may not be feasible on all boards due to the unavailability of certain pins.

Additionally, the accuracy of Millis() can be affected by clock drifting and overflow issues, especially when using the light sleep mode. This can cause unexpected behavior and side effects on timeout while loops or exit conditions. To compensate for clock drifting, the Arduino library includes code that adjusts the time, but it may not be sufficient for applications requiring high precision.

To maintain accurate timekeeping, it is recommended to use an external Real-Time Clock (RTC) module, which can provide more precise time measurements and synchronization across multiple boards. However, RTC modules can drift over time, and additional steps may be necessary to keep them synchronized, such as using WiFi and NTP to automatically update the time.

shunsleep

SLEEP_MODE_IDLE is required for millis() to run during sleep

SLEEP_MODE_IDLE is the only sleep mode that allows millis() to continue running. This is because all timers except the watchdog are stopped in other sleep modes. The watchdog is inaccurate and unreliable for timekeeping.

To keep track of the time an application has been running and use sleep modes simultaneously, one must ensure that Timer0 remains enabled, as millis() relies on it to function. However, Timer0 is disabled in most sleep modes, including the commonly used sleep modes such as light sleep mode and deep sleep mode. This results in millis() stopping counting, which can be problematic for applications with time-based processes such as stopwatches, timers, and alarms.

The SLEEP_MODE_IDLE, on the other hand, does not disable Timer0, allowing millis() to continue functioning during sleep. This makes it a valuable option for applications that require accurate timekeeping and need to track the duration of sleep periods.

It is worth noting that SLEEP_MODE_IDLE may not provide the same level of power savings as other sleep modes. Sleeping for 1 millisecond may not offer significant power savings, but when accumulated over multiple sleep periods, it can result in substantial power conservation. Therefore, the choice of SLEEP_MODE_IDLE should consider the specific requirements of the application, balancing the need for accurate timekeeping with power efficiency.

shunsleep

Light sleep mode causes time drifting and WiFi issues

The light sleep mode causes time drifting and WiFi issues. When an Arduino is put into light sleep mode, the clock is idle, and the millis() function cannot be used to measure the time anymore. This time drifting can cause side effects on the timeout while loops or exit conditions used in the library.

The millis() function is used to keep track of the time an application has been running and is often used in processes based on time, such as a stopwatch, timer, and alarm. However, when the Arduino enters sleep mode, Timer0 is disabled, and the millis() stop counting. This can cause issues with time-sensitive applications.

Additionally, the light sleep mode can cause WiFi issues. Some users have reported that their WiFi stops working after a few hours when using the light sleep mode. It is suspected that the WiFi API does not renew and negotiate WiFi tokens in a timely manner because millis() is not a good time indicator when using the light sleep mode.

To resolve the WiFi issue, some users have suggested using esp_wifi_stop() before entering light sleep and then esp_wifi_start() after waking up. Others have suggested trying to configure the WiFi peripheral with the esp-idf functions and avoiding reconfiguring the WiFi.mode() every time.

Overall, while the light sleep mode can help reduce power consumption, it can also cause time drifting and WiFi issues that need to be addressed.

shunsleep

Millis() loses 0.1ms for every ADC conversion in ADC_sleep mode

When using sleep modes in an Arduino application, Timer0 is disabled, and the millis stop counting. This can be a problem when the application has many time-based processes, such as a stopwatch, timer, and alarm.

One solution to this problem is to use the SLEEP_MODE_IDLE, which keeps Timer0 running. However, this means that an interrupt wakes up the device every millisecond, which may not be advantageous in terms of power saving. Another option is to use an external Real-Time Clock (RTC) module, which can provide time in 100ths of a second.

When using the ADC_sleep mode specifically, the millis() function loses about 0.1ms for every ADC conversion performed. This is due to the standard number of CPU cycles needed for the ADC conversion and the standard prescaler for Timer0. To compensate for this loss, one suggestion is to update the Timer0 register (TCNT0) manually by increasing it by 14. However, this approach still has a drift of 0.5 ticks and misses the overflow event used by Arduino for time tracking.

Another possible solution is to use Timer2 for the Arduino millis-ISR. This approach involves some trade-offs, and the accuracy of the crystal oscillator should also be considered.

shunsleep

RTC modules are useful for time synchronisation

Real-time clock (RTC) modules are useful for time synchronisation as they can keep track of the current time and date, even when a device is turned off or not connected to a network. They are commonly used in embedded systems, servers, and other devices that require accurate timekeeping. This makes them ideal for time synchronisation.

RTC modules offer various interfaces to connect to microcontrollers and development boards, with the most common types being I2C, SPI, and UART. They come in a range of sizes, from 0.5 inches square to larger modules that include additional features like alarms, interrupts, or non-volatile memory for data storage.

When choosing an RTC module, it's important to consider the power source. Self-powered RTC modules contain a built-in battery that maintains timekeeping when external power is removed, ensuring the clock keeps time during a power failure. On the other hand, RTC modules without a built-in battery, known as supercapacitor modules, require an uninterrupted power source to maintain timekeeping and settings.

The accuracy of an RTC module is another important factor. Most modules offer accuracy within 1 minute per month to 10 minutes per year, with higher accuracy modules being more expensive. For projects that require higher precision, a chip with temperature compensation can be chosen.

RTC modules, such as the DS3231 and DS1307, are popular choices for microcontrollers. They come with a battery holder to connect a battery, ensuring they keep working even if the microcontroller resets or loses power. The DS3231 is known for its accuracy as it includes a temperature sensor and provides temperature-compensated results.

In summary, RTC modules are useful for time synchronisation as they provide accurate timekeeping, even during power interruptions. They offer flexibility in terms of interfaces and sizes, and there are various options available depending on the specific requirements of a project.

Why You Shouldn't Sleep With Him Yet

You may want to see also

Frequently asked questions

No, millis do not work during Arduino sleep. When using sleep modes, Timer0 is disabled, and therefore millis stop counting.

One way to keep track of millis during sleep mode is to use SLEEP_MODE_IDLE. This is the only sleep mode in which millis will continue to run.

To keep track of time when using ADC_sleep mode, you can use Timer2 for the Arduino millis-ISR. Alternatively, you can put an external clock input into Timer 1 and run it asynchronously.

To reset millis after waking up from deep sleep mode, you can store millis() at boot, and if (resetCause == "Deep-Sleep Wake") zero out the stored copy of millis().

Written by
Reviewed by

Explore related products

Share this post
Print
Did this article help you?

Leave a comment