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 MY_SMART_SLEEP_WAIT_DURATION_MS 1000
    
    
    //#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
        Serial.println(sensorValue);
    #endif
    
        // 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.print(batteryV);
        Serial.println(" V");
    
        Serial.print("Battery percent: ");
        Serial.print(batteryPcnt);
        Serial.println(" %");
    #endif
    
        if (oldBatteryPcnt != batteryPcnt) {
            // Power up radio after sleep
            sendBatteryLevel(batteryPcnt);
            oldBatteryPcnt = batteryPcnt;
        }
    
      // Sleep for a while to save energy (using martsleep)
    smartSleep(UPDATE_INTERVAL); 
      }
    
    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(message.sensor);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }
    

  • 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!


 

326
Online

7.9k
Users

8.7k
Topics

93.7k
Posts