Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. General Discussion
  3. Interrupt, Perform a specific function, not the loop

Interrupt, Perform a specific function, not the loop

Scheduled Pinned Locked Moved General Discussion
14 Posts 7 Posters 5.5k Views 5 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    vickey
    wrote on last edited by
    #1

    Hi. I have a node which sleeps most of the time and It has interrupt function enabled. But I want to perform a specific function when Node awake from sleep through interrupt pin 2, not the loop and again it should go to sleep using gw.sleep command. Is it possible to perform that specific function on an interrupt?

    https://www.arduino.cc/en/Reference/AttachInterrupt describes what I need but I want to implement sleep function of mysensors also.

    May someone please help me?

    martinhjelmareM 1 Reply Last reply
    0
    • scalzS Offline
      scalzS Offline
      scalz
      Hardware Contributor
      wrote on last edited by
      #2

      hi.
      it is not recommended, and not good practice to do stuff in your interrupt routine. you must keep it short. one idea and there are others : you could set a boolean to true in your interrupt routine for this. and use this flag like you want in your loop for example. do things if your boolean=true or not...

      1 Reply Last reply
      0
      • V vickey

        Hi. I have a node which sleeps most of the time and It has interrupt function enabled. But I want to perform a specific function when Node awake from sleep through interrupt pin 2, not the loop and again it should go to sleep using gw.sleep command. Is it possible to perform that specific function on an interrupt?

        https://www.arduino.cc/en/Reference/AttachInterrupt describes what I need but I want to implement sleep function of mysensors also.

        May someone please help me?

        martinhjelmareM Offline
        martinhjelmareM Offline
        martinhjelmare
        Plugin Developer
        wrote on last edited by martinhjelmare
        #3

        @vickey

        The sleep function with single interrupt returns true if woken by the interrupt and false if woken by the timer. Sleeping with two interrupts returns the number of the interrupt pin that wakes it or negative if timer wakes. See the API.

        I would check the return value of the sleep function and divide the loop into at least two functions. One is run if interrupt wakes it, the other is run after timer wake up.

        edit

        Note that it's the interrupt number and not the pin number of the interrupt, that is returned for the two pin interrupt sleep function, according to the API.
        http://www.mysensors.org/download/sensor_api_15#the-full-api

        1 Reply Last reply
        2
        • n3roN Offline
          n3roN Offline
          n3ro
          wrote on last edited by
          #4

          This sounds great!

          Do you have a code example?

          pimatic + MySensors + Homeduino + z-way
          https://github.com/n3roGit/MySensors_n3ro

          martinhjelmareM 1 Reply Last reply
          0
          • n3roN n3ro

            This sounds great!

            Do you have a code example?

            martinhjelmareM Offline
            martinhjelmareM Offline
            martinhjelmare
            Plugin Developer
            wrote on last edited by
            #5

            @n3ro

            It's untested, but here you go. It's a modified version of the sketch by @Anticimex for a binary switch with two interrupts.

            https://codebender.cc/sketch:171302

            1 Reply Last reply
            1
            • AnticimexA Offline
              AnticimexA Offline
              Anticimex
              Contest Winner
              wrote on last edited by
              #6

              I tested it when I submitted it so I can vouch for the functionality. At least for the time of submission. But the library might have changed since then of course.

              Do you feel secure today? No? Start requiring some signatures and feel better tomorrow ;)

              1 Reply Last reply
              0
              • V Offline
                V Offline
                vickey
                wrote on last edited by
                #7

                @martinhjelmare Thank you so much buddy for the help. I have not tested it yet. Can I use it with mysensors 1.4 version? Because I am using easyiot as controller and it uses 1.4 version.

                martinhjelmareM 1 Reply Last reply
                0
                • V vickey

                  @martinhjelmare Thank you so much buddy for the help. I have not tested it yet. Can I use it with mysensors 1.4 version? Because I am using easyiot as controller and it uses 1.4 version.

                  martinhjelmareM Offline
                  martinhjelmareM Offline
                  martinhjelmare
                  Plugin Developer
                  wrote on last edited by
                  #8

                  @vickey

                  Yes, I don't see why it shouldn't work with version 1.4, but as I said, I haven't even tested this myself yet. Try it, and post back if you encounter problems. It'll be interesting to see what your final version will be.

                  Btw, @hek, I noticed that the API says that the sleep function with two interrupts returns a bool, but looking at github it should be int8_t, which also makes sense.

                  int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0);
                  
                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    vickey
                    wrote on last edited by vickey
                    #9

                    I have tried it with single interrupt and It is working good so far on my mysensors 1.4 version. In case of interrupt

                    wake = gw.sleep(INTERRUPT,FALLING, SLEEP_TIME);
                    

                    I use wake value (wake == 1) for function related to interrupt and use else condition for function related to timer wake up.

                    1 Reply Last reply
                    1
                    • V Offline
                      V Offline
                      vickey
                      wrote on last edited by vickey
                      #10

                      Here is my sketch if someone finds it useful. It uses LDR to set night mode in low light conditions and vice versa, door reed switch and PIR sensor to turn ac or dc lights with the help of two channel relay and EasyIOT as server. Interrupts perform the functions of turning lights on and off while timer wake up decides the night mode implementation. Moreover, sensor node sleeps most of its time to conserve the battery.

                      #include <SPI.h>
                      #include <MySensor.h>
                      
                      #define CHILD_ID_LIGHT 0
                      #define CHILD_ID_DOOR 1
                      #define CHILD_ID_PIR 2
                      #define CHILD_ID_LED 3
                      #define CHILD_ID_SAVER 4
                      
                      #define LDR_PIN A0
                      #define DOOR_PIN 2
                      #define PIR_PIN 3
                      #define LED_PIN 4 // Relay 1 is attached
                      #define SAVER_PIN 5 // Relay 2 is attached
                      
                      #define INTERRUPT DOOR_PIN-2
                      
                      unsigned long SLEEP_TIME = 1200000; // Sleep time 1200000 i.e. 20 minutes (in milliseconds)
                      
                      MySensor gw;
                      
                      boolean activity = false;
                      boolean LEDSwitch = false;
                      boolean SaverSwitch = false;
                      boolean nightSwitch = false;
                      
                      MyMessage msgLDR(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
                      MyMessage msgDoor(CHILD_ID_DOOR, V_TRIPPED);
                      MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
                      
                      void setup()  
                      { 
                        gw.begin(NULL, AUTO, false, 1);
                        gw.sendSketchInfo("BedRoom", "1.2");
                        
                        pinMode(DOOR_PIN,INPUT);
                        pinMode(PIR_PIN,INPUT);
                        pinMode(LED_PIN, OUTPUT);
                        pinMode(SAVER_PIN, OUTPUT);
                        
                        digitalWrite(DOOR_PIN, HIGH);
                        digitalWrite(PIR_PIN, HIGH);
                        digitalWrite(LED_PIN, HIGH);
                        digitalWrite(SAVER_PIN, HIGH);
                        
                        gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
                        gw.present(CHILD_ID_DOOR, S_DOOR);
                        gw.present(CHILD_ID_PIR, S_MOTION);
                        
                        int LightLevel;
                        for(int i = millis(); i < (millis() + 5000); i++){
                          LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                        }
                        if(LightLevel < 20){
                          gw.send(msgLDR.set(LightLevel));
                          nightSwitch = true;
                        }
                        else {
                          gw.send(msgLDR.set(LightLevel));
                          nightSwitch = false;
                        }
                      }
                      
                      void loop()      
                      {
                        if(nightSwitch){ //When night switch is on
                          int wake;
                          wake = gw.sleep(INTERRUPT,FALLING, SLEEP_TIME);
                          if(wake == 1){
                            if(!activity){
                              gw.send(msgDoor.set("1"));
                              gw.send(msgDoor.set("0"));
                              activity = true;
                              if((!LEDSwitch) && (!SaverSwitch)){
                                pirswitch();
                              }
                              else{ //activity finished
                              activityoff();
                              }
                            }
                          }
                          else{ //Timer wake up
                            int LightLevel;
                            if((!LEDSwitch) && (!SaverSwitch)){
                              for(int i = millis(); i < (millis() + 5000); i++){
                                LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                              }
                            }
                            else{
                              for(int i = millis(); i < (millis() + 1000); i++){
                                LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                              }
                            }
                              
                            if((LightLevel < 10) && ((!LEDSwitch) && (SaverSwitch))){
                              Serial.println("Light level is less than 50%, Turning LED on");
                              digitalWrite(LED_PIN, LOW);
                              LEDSwitch = true;
                              SLEEP_TIME = 7200000; // Sleep time changed to 2 hours
                            }
                            else if((LightLevel > 20) && ((!LEDSwitch) && (!SaverSwitch))){
                              gw.send(msgLDR.set(LightLevel));
                              nightSwitch = false;
                              SLEEP_TIME = 7200000; // Sleep time changed to 2 hours
                              gw.sleep(SLEEP_TIME);
                            }
                            else if((LightLevel > 5) && (nightSwitch) && ((!LEDSwitch) && (!SaverSwitch))){
                              gw.send(msgLDR.set(LightLevel));
                              SLEEP_TIME = 600000; // Sleep time changed to 10 minutes
                            }
                          }
                        }
                        else { //When night switch is off
                          int LightLevel;
                          for(int i = millis(); i < (millis() + 5000); i++){
                            LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                          }
                          if(LightLevel < 20){
                            gw.send(msgLDR.set(LightLevel));
                            nightSwitch = true;
                            SLEEP_TIME = 7200000; // Sleep time changed to 2 hours
                            gw.sleep(INTERRUPT,FALLING, SLEEP_TIME);
                          }
                          else if((LightLevel < 30) && (!nightSwitch)){
                            SLEEP_TIME = 600000; // Sleep time changed to 10 minutes
                            gw.sleep(SLEEP_TIME);
                          }
                          else if((LightLevel < 50) && (!nightSwitch)){
                            SLEEP_TIME = 1800000; // Sleep time changed to 30 minutes
                            gw.sleep(SLEEP_TIME);
                          }
                        }
                      }
                      
                      void pirswitch()
                      {
                        for(int i = millis(); i < (millis() + 5000); i++){ //Check PIR for activity 10 times with delay of half second
                          boolean tripped = digitalRead(PIR_PIN) == HIGH;
                          Serial.println(i);
                          if(tripped){
                            gw.send(msgPir.set(tripped?"1":"0"));
                            Serial.println("Motion detected");
                            //activity on function
                            activityon();
                            Serial.println("Loop terminated");
                            break;
                          }
                        }
                        delay(3000);
                        activity = false;
                      }
                             
                      void activityon()
                      {
                        //turn saver on
                        digitalWrite(SAVER_PIN, LOW);
                        SaverSwitch = true;
                        Serial.println("Energy saver turned on");
                        int LightLevel;
                        for(int i = millis(); i < (millis() + 1000); i++){ //Check if energy saver is on
                          LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                        }
                        if(LightLevel < 10){
                          Serial.println("Light level is less than 50%, Turning LED on");
                          digitalWrite(LED_PIN, LOW);
                          LEDSwitch = true;
                        }
                        else{
                          SLEEP_TIME = 1000;
                          Serial.println("Sleep time changed to second");
                        }
                      }
                        
                      void activityoff()
                      {
                        delay(3000);
                        //turn off saver or LED
                        digitalWrite(SAVER_PIN, HIGH);
                        digitalWrite(LED_PIN, HIGH);
                        Serial.println("Activity finished");
                        SaverSwitch = false;
                        LEDSwitch = false;
                        activity = false;
                        SLEEP_TIME = 7200000;
                        Serial.println("Sleep time changed to 2 hours");
                      }
                      
                      AWIA 1 Reply Last reply
                      2
                      • V vickey

                        Here is my sketch if someone finds it useful. It uses LDR to set night mode in low light conditions and vice versa, door reed switch and PIR sensor to turn ac or dc lights with the help of two channel relay and EasyIOT as server. Interrupts perform the functions of turning lights on and off while timer wake up decides the night mode implementation. Moreover, sensor node sleeps most of its time to conserve the battery.

                        #include <SPI.h>
                        #include <MySensor.h>
                        
                        #define CHILD_ID_LIGHT 0
                        #define CHILD_ID_DOOR 1
                        #define CHILD_ID_PIR 2
                        #define CHILD_ID_LED 3
                        #define CHILD_ID_SAVER 4
                        
                        #define LDR_PIN A0
                        #define DOOR_PIN 2
                        #define PIR_PIN 3
                        #define LED_PIN 4 // Relay 1 is attached
                        #define SAVER_PIN 5 // Relay 2 is attached
                        
                        #define INTERRUPT DOOR_PIN-2
                        
                        unsigned long SLEEP_TIME = 1200000; // Sleep time 1200000 i.e. 20 minutes (in milliseconds)
                        
                        MySensor gw;
                        
                        boolean activity = false;
                        boolean LEDSwitch = false;
                        boolean SaverSwitch = false;
                        boolean nightSwitch = false;
                        
                        MyMessage msgLDR(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
                        MyMessage msgDoor(CHILD_ID_DOOR, V_TRIPPED);
                        MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
                        
                        void setup()  
                        { 
                          gw.begin(NULL, AUTO, false, 1);
                          gw.sendSketchInfo("BedRoom", "1.2");
                          
                          pinMode(DOOR_PIN,INPUT);
                          pinMode(PIR_PIN,INPUT);
                          pinMode(LED_PIN, OUTPUT);
                          pinMode(SAVER_PIN, OUTPUT);
                          
                          digitalWrite(DOOR_PIN, HIGH);
                          digitalWrite(PIR_PIN, HIGH);
                          digitalWrite(LED_PIN, HIGH);
                          digitalWrite(SAVER_PIN, HIGH);
                          
                          gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
                          gw.present(CHILD_ID_DOOR, S_DOOR);
                          gw.present(CHILD_ID_PIR, S_MOTION);
                          
                          int LightLevel;
                          for(int i = millis(); i < (millis() + 5000); i++){
                            LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                          }
                          if(LightLevel < 20){
                            gw.send(msgLDR.set(LightLevel));
                            nightSwitch = true;
                          }
                          else {
                            gw.send(msgLDR.set(LightLevel));
                            nightSwitch = false;
                          }
                        }
                        
                        void loop()      
                        {
                          if(nightSwitch){ //When night switch is on
                            int wake;
                            wake = gw.sleep(INTERRUPT,FALLING, SLEEP_TIME);
                            if(wake == 1){
                              if(!activity){
                                gw.send(msgDoor.set("1"));
                                gw.send(msgDoor.set("0"));
                                activity = true;
                                if((!LEDSwitch) && (!SaverSwitch)){
                                  pirswitch();
                                }
                                else{ //activity finished
                                activityoff();
                                }
                              }
                            }
                            else{ //Timer wake up
                              int LightLevel;
                              if((!LEDSwitch) && (!SaverSwitch)){
                                for(int i = millis(); i < (millis() + 5000); i++){
                                  LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                                }
                              }
                              else{
                                for(int i = millis(); i < (millis() + 1000); i++){
                                  LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                                }
                              }
                                
                              if((LightLevel < 10) && ((!LEDSwitch) && (SaverSwitch))){
                                Serial.println("Light level is less than 50%, Turning LED on");
                                digitalWrite(LED_PIN, LOW);
                                LEDSwitch = true;
                                SLEEP_TIME = 7200000; // Sleep time changed to 2 hours
                              }
                              else if((LightLevel > 20) && ((!LEDSwitch) && (!SaverSwitch))){
                                gw.send(msgLDR.set(LightLevel));
                                nightSwitch = false;
                                SLEEP_TIME = 7200000; // Sleep time changed to 2 hours
                                gw.sleep(SLEEP_TIME);
                              }
                              else if((LightLevel > 5) && (nightSwitch) && ((!LEDSwitch) && (!SaverSwitch))){
                                gw.send(msgLDR.set(LightLevel));
                                SLEEP_TIME = 600000; // Sleep time changed to 10 minutes
                              }
                            }
                          }
                          else { //When night switch is off
                            int LightLevel;
                            for(int i = millis(); i < (millis() + 5000); i++){
                              LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                            }
                            if(LightLevel < 20){
                              gw.send(msgLDR.set(LightLevel));
                              nightSwitch = true;
                              SLEEP_TIME = 7200000; // Sleep time changed to 2 hours
                              gw.sleep(INTERRUPT,FALLING, SLEEP_TIME);
                            }
                            else if((LightLevel < 30) && (!nightSwitch)){
                              SLEEP_TIME = 600000; // Sleep time changed to 10 minutes
                              gw.sleep(SLEEP_TIME);
                            }
                            else if((LightLevel < 50) && (!nightSwitch)){
                              SLEEP_TIME = 1800000; // Sleep time changed to 30 minutes
                              gw.sleep(SLEEP_TIME);
                            }
                          }
                        }
                        
                        void pirswitch()
                        {
                          for(int i = millis(); i < (millis() + 5000); i++){ //Check PIR for activity 10 times with delay of half second
                            boolean tripped = digitalRead(PIR_PIN) == HIGH;
                            Serial.println(i);
                            if(tripped){
                              gw.send(msgPir.set(tripped?"1":"0"));
                              Serial.println("Motion detected");
                              //activity on function
                              activityon();
                              Serial.println("Loop terminated");
                              break;
                            }
                          }
                          delay(3000);
                          activity = false;
                        }
                               
                        void activityon()
                        {
                          //turn saver on
                          digitalWrite(SAVER_PIN, LOW);
                          SaverSwitch = true;
                          Serial.println("Energy saver turned on");
                          int LightLevel;
                          for(int i = millis(); i < (millis() + 1000); i++){ //Check if energy saver is on
                            LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                          }
                          if(LightLevel < 10){
                            Serial.println("Light level is less than 50%, Turning LED on");
                            digitalWrite(LED_PIN, LOW);
                            LEDSwitch = true;
                          }
                          else{
                            SLEEP_TIME = 1000;
                            Serial.println("Sleep time changed to second");
                          }
                        }
                          
                        void activityoff()
                        {
                          delay(3000);
                          //turn off saver or LED
                          digitalWrite(SAVER_PIN, HIGH);
                          digitalWrite(LED_PIN, HIGH);
                          Serial.println("Activity finished");
                          SaverSwitch = false;
                          LEDSwitch = false;
                          activity = false;
                          SLEEP_TIME = 7200000;
                          Serial.println("Sleep time changed to 2 hours");
                        }
                        
                        AWIA Offline
                        AWIA Offline
                        AWI
                        Hero Member
                        wrote on last edited by
                        #11

                        @vickey Just curious, what is the purpose of this piece of code?

                         for(int i = millis(); i < (millis() + 5000); i++){
                             LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                           }
                        
                        V 1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          MikeF
                          wrote on last edited by
                          #12

                          @martinhjelmare In your code example, the sleep function needs a non-zero last parameter, in order to wake on timer.

                          So line 104 should read:

                          wake_cause = sensor_node.sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, SLEEP_TIME);
                          

                          where SLEEP_TIME is in milliseconds, e.g.,

                          unsigned long SLEEP_TIME = 60000;  	//  60 sec sleep time between reads (seconds * 1000 milliseconds)
                          

                          Just tested this on the binary switch sketch.

                          martinhjelmareM 1 Reply Last reply
                          0
                          • M MikeF

                            @martinhjelmare In your code example, the sleep function needs a non-zero last parameter, in order to wake on timer.

                            So line 104 should read:

                            wake_cause = sensor_node.sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, SLEEP_TIME);
                            

                            where SLEEP_TIME is in milliseconds, e.g.,

                            unsigned long SLEEP_TIME = 60000;  	//  60 sec sleep time between reads (seconds * 1000 milliseconds)
                            

                            Just tested this on the binary switch sketch.

                            martinhjelmareM Offline
                            martinhjelmareM Offline
                            martinhjelmare
                            Plugin Developer
                            wrote on last edited by
                            #13

                            @MikeF

                            Thanks! Good to hear that the sketch works after that correction.

                            1 Reply Last reply
                            0
                            • AWIA AWI

                              @vickey Just curious, what is the purpose of this piece of code?

                               for(int i = millis(); i < (millis() + 5000); i++){
                                   LightLevel = (100 - ((1023-analogRead(LDR_PIN))/10.23));
                                 }
                              
                              V Offline
                              V Offline
                              vickey
                              wrote on last edited by
                              #14

                              @AWI This code runs continuously for 5 seconds in order to get a stable reading of light using LDR, which is used to set night mode on and off.

                              1 Reply Last reply
                              0
                              Reply
                              • Reply as topic
                              Log in to reply
                              • Oldest to Newest
                              • Newest to Oldest
                              • Most Votes


                              24

                              Online

                              11.7k

                              Users

                              11.2k

                              Topics

                              113.1k

                              Posts


                              Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                              • Login

                              • Don't have an account? Register

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • MySensors
                              • OpenHardware.io
                              • Categories
                              • Recent
                              • Tags
                              • Popular