DS_CAP_TIMERS_SOLAR - denis-stepanov/esp-ds-system Wiki

DS_CAP_TIMERS_SOLAR — Support for Timer on Solar Events


This capability adds support for timers based on solar events — sunrise or sunset. Because timing of these events changes every day, it is not easy to make a timer event for them. This type of timer offers standard timer interface for such events.

The timer is implemented as a variant of an absolute timer, hence, it requires that a notion of time is enabled in controller.

The following methods, complementary to the generic timer methods, are available:

TimerSolar::TimerSolar(const String action = "undefined", const timer_type_t type = TIMER_SUNRISE,
  const int8_t offset = 0, const uint8_t dow = TIMER_DOW_ANY, const bool armed = true,
  const bool recurrent = true, const bool transient = false, const int id = -1);  // Constructor
int8_t TimerSolar::getOffset() const;                  // Return offset in minutes from event
void TimerSolar::setOffset(const int8_t offset );      // Set offset in minutes from event
void TimerSolar::adjust();                             // Recalculate alignment to solar times

One can also compare solar timers among themselves and with a struct tm value containing absolute time.

Timer type can be one of TIMER_SUNRISE (default) or TIMER_SUNSET. offset defines optional offset in minutes within one hour from the solar event (e.g., "5 minutes before sunset"). Methods getOffset() and setOffset() allow changing the offset at run-time. If timer is modified at run-time, a function adjust() should be called. It should also be called if system time jumps significantly (e.g., another date is set, which will affect effective times of solar events). The library will automatically recalculate solar events every night at 3:30 am, or as soon as 24 hours from the previous calculation have elapsed.

The rest of the timer methods are the same as for an absolute timer.

Solar event time calculation is assured by an external library, Dusk2Dawn. This is a mathematical calculation based on controller's geographical location; no external database is consulted. Accuracy of calculation is pretty decent and differs from an actual sunrise or sunset by no more than few minutes. In order to enable calculation, the following information must be provided in MySystem.h:

#define DS_TIMEZONE TZ_Europe_Paris       // Controller timezone
#define DS_LATITUDE 48.85863              // Controller latitude (in decimal notation)
#define DS_LONGITUDE 2.29443              // Controller longitude (in decimal notation)

If these are not defined, the library will issue a warning and default time zone to UTC and geographical location to Greenwich. You can obtain your coordinates from any navigation software, such as Google Maps. For details of time zone definition refer to time capability.

Even though time resolution of an absolute timer is one second, time resolution of a solar timer is one minute. This is linked to a relatively low accuracy needed in defining of solar events. The getSecond() method of a solar timer would typically return 0.

Since a solar timer is also an absolute timer, its registration and processing is made in the same way; consult the absolute timer page for more details.

When solar timer capability is enabled, the following additional ds::System methods are made available:

uint16_t System::getSunrise();       // Return sunrise time (in minutes from midnight)
uint16_t System::getSunset();        // Return sunset time (in minutes from midnight)


Cooperates With

Conflicts With




#define DS_CAP_SYS_TIME     // Enable system time
#define DS_CAP_TIMERS_SOLAR // Enable timers from solar events

#define DS_TIMEZONE TZ_Europe_Paris       // My timezone
#define DS_LATITUDE 48.85863              // My latitude
#define DS_LONGITUDE 2.29443              // My longitude

#include "System.h"         // System global definitions


#include "MySystem.h"

using namespace ds;

// Timer handler
void myTimerHandler(const TimerAbsolute* timer) {
  if (timer->getAction() == "lamp on") {

    // Turn the lamp on here ...
void (*System::timerHandler)(const TimerAbsolute*) = myTimerHandler;  // Install the handler

void setup() {

  // Turn on the lamp every day five minutes before sunset
  System::timers.push_front(new TimerSolar("lamp on", TIMER_SUNSET, -5));  

void loop() {

Mandatory Calls




Version 1.1 or later.

See Also