Can I have multiple sleep/interrupt events in the one sketch?

  • I have a prototype battery relay node working, where using smart sleep I am able to turn on a relay (currently just a connected LED) and off from the controller, with a lag in actuation equal to the smart sleep duration.

    What I would now like to do is to introduce a secondary function where the node is able to turn the relay off after a preset period if no off command is received from the controller. Is this possible by introducing another sleep timer? If so how could I do this (as opposed to having a controller rule send the off command).

    Here's my quick and dirty test sketch - hacked from the relay node example.

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    #define MY_RF24_PA_LEVEL RF24_PA_LOW
    // Enable repeater functionality for this node
    // #define MY_REPEATER_FEATURE
    #include <MySensors.h>
    //#define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define LEDpin 5
    //#define NUMBER_OF_RELAYS 1 // Total number of attached relays
    //#define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define LED_ON 1
    //#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    #define LED_OFF 0
    #define VMIN 1.9 // Battery monitor lower level. Vmin_radio=1.9V
    #define VMAX 3.0 // " " " high level. Vmin<Vmax<=3.44
    int BATTERY_SENSE_PIN = A1;  // select the input pin for the battery sense point
    int oldBatteryPcnt = 0;
    // Sleep time between sensor updates (in milliseconds)
    static const uint64_t UPDATE_INTERVAL = 60000;
    #define child 1
    void before()
        //for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(LEDpin, OUTPUT);
        // Set relay to last known state (using eeprom storage)
        digitalWrite(LEDpin, loadState(LEDpin)?LED_ON:LED_OFF);
    void setup()
       analogReference(INTERNAL);     // use the 1.1 V internal reference for battery level measuring
    void presentation()
         // Send the sketch version information to the gateway and Controller
         sendSketchInfo("Relay", "1.0");
         //  for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
         // Register all sensors to gw (they will be created as child devices)
         present(child, S_BINARY);
    void loop()
    // get the battery Voltage
        int sensorValue = analogRead(BATTERY_SENSE_PIN);
    #ifdef MY_DEBUG
        // 1M, 470K divider across battery and using internal ADC ref of 1.1V
        // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
        // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
        // 3.44/1023 = Volts per bit = 0.003363075
        float batteryV  = sensorValue * 0.003347095;
        int batteryPcnt = static_cast<int>(((batteryV-VMIN)/(VMAX-VMIN))*100); 
    #ifdef MY_DEBUG
        Serial.print("Battery Voltage: ");
        Serial.println(" V");
        Serial.print("Battery percent: ");
        Serial.println(" %");
        if (oldBatteryPcnt != batteryPcnt) {
            // Power up radio after sleep
            oldBatteryPcnt = batteryPcnt;
      // Sleep for a while to save energy (using martsleep)
    void receive(const MyMessage &message)
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_STATUS) {
        // Change relay state
        digitalWrite(LEDpin, message.getBool()?LED_ON:LED_OFF);
        // Store state in eeprom
        saveState(LEDpin, message.getBool());
        // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.print(", New status: ");

  • Mod

    you could count how many times you have ran the loop, if your turn off time is a multiple of sleeptime, when you receive a switch on command you just reset the counter.

  • @gohan Lol you're absolutely right! I should have thought of that earlier - thanks!