Skip to content
  • 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. Troubleshooting
  3. Sleep() Caused Insomnia when assisted by interrupts
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store

Sleep() Caused Insomnia when assisted by interrupts

Scheduled Pinned Locked Moved Troubleshooting
7 Posts 5 Posters 2.1k Views 4 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.
  • ร Offline
    ร Offline
    รอเรือ
    wrote on last edited by
    #1

    Hi there!

    I feel I need to share this and I invite You to reflect upon this and share your ideas here.

    I've been working on a battery powered node with 2 push buttons. Normally it sleeps but it will wake up using two interrupts when one of the push buttons gets pressed.
    interruptReturn = sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, ONE_DAY_SLEEP_TIME);

    I've spent many hours trying to figure out how to make this script work. I had problem with that once a push button was pressed it was generating and endless loop of interrupts. It never slept.

    It sounds weird but using the following line

    sleep(50); // Short delay to allow switch to properly settle
    

    instead of

    delay(50); // Short delay to allow switch to properly settle
    

    caused the never ending interrupt loop.

    Below is my final script.

    #define MY_BAUD_RATE 9600
    #define MY_RADIO_NRF24
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Vcc.h>
    const float VccMin   = 1.8;           // Minimum expected Vcc level, in Volts.
    const float VccMax   = 3.2;           // Maximum expected Vcc level, in Volts.
    const float VccCorrection = 1.0/1.0;  // Measured Vcc by multimeter divided by reported Vcc
    Vcc vcc(VccCorrection);
    
    #define NODE_ID 17
    #define SKETCH_NAME "2x Binary Switch Sleep"
    #define SKETCH_VERSION "3.2"
    
    #define CHILD_ID_1 0
    #define CHILD_ID_2 1
    #define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch
    #define SECONDARY_BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch
    
    #define BATTERY_REPORT_DAY 2
    #define BATTERY_REPORT_BY_IRT_CYCLE 10 // Adjust this according to usage frequency.
    #define ONE_DAY_SLEEP_TIME 86400000 // No wakeup timer at all
    
    int oldValue1=-1;
    int oldValue2=-1;
    int dayCounter = BATTERY_REPORT_DAY;
    int irtCounter = 0;
    int interruptReturn = MY_WAKE_UP_BY_TIMER;
    
    MyMessage msg1(CHILD_ID_1,V_TRIPPED);
    MyMessage msg2(CHILD_ID_2,V_TRIPPED);
    
    void setup()	
    {	
    	pinMode(PRIMARY_BUTTON_PIN,INPUT);
    	pinMode(SECONDARY_BUTTON_PIN,INPUT);
    	// We use external and very weak pull ups to save power
    	//digitalWrite(PRIMARY_BUTTON_PIN, HIGH);    // Enable internal pull-up
    	//digitalWrite(SECONDARY_BUTTON_PIN, HIGH);    // Enable internal pull-up
    }
    
    void presentation() {
    	sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
    	present(CHILD_ID_1, S_DOOR);
    	present(CHILD_ID_2, S_DOOR);
    }
    
    void loop() 
    {
    	if (interruptReturn == MY_WAKE_UP_BY_TIMER) { // Woke up by timer (or first run)
    		dayCounter++;
    		#ifdef MY_DEBUG
    		Serial.println("Woke up by timer (or first run)");
    		#endif
    		if (dayCounter >= BATTERY_REPORT_DAY) {
    			dayCounter = 0;
    			sendBatteryReport();
    		}
    	} else {    // Woke up by pin change
    		irtCounter++;
    		#ifdef MY_DEBUG
    		Serial.print("Woke up by pin change on pin D");Serial.println(interruptReturn+2);
    		#endif
    		if (interruptReturn == 0) {
    			delay(50); // Short delay to allow switch to properly settle
    			int value1 = digitalRead(PRIMARY_BUTTON_PIN);
    			if (value1 != oldValue1) {
    				send(msg1.set(value1==HIGH ? 0 : 1));
    				oldValue1 = value1;
    				Serial.print("Sent value: '"); Serial.print(value1==HIGH ? 0 : 1); Serial.println("'.");
    			}
    		} else {
    			delay(50); // Short delay to allow switch to properly settle
    			int value2 = digitalRead(SECONDARY_BUTTON_PIN);
    			if (value2 != oldValue2) {
    				send(msg2.set(value2==HIGH ? 0 : 1));
    				oldValue2 = value2;
    				Serial.print("Sent value: '"); Serial.print(value2==HIGH ? 0 : 1); Serial.println("'.");
    			}
    		}
    	}
    	if (irtCounter>=BATTERY_REPORT_BY_IRT_CYCLE) {
    		irtCounter = 0;
    		sendBatteryReport();
    	}
    	#ifdef MY_DEBUG
    	Serial.println("Zzzzzz");
    	#endif
    	delay(500); //delay to allow serial to fully print before sleep
    	// Sleep until something happens with the sensor, or one sleep_time has passed since last awake.
    	interruptReturn = sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, ONE_DAY_SLEEP_TIME);
    }
    
    void sendBatteryReport() {
    	float v = vcc.Read_Volts();
    	float p = vcc.Read_Perc(VccMin, VccMax);
    	#ifdef MY_DEBUG
    	Serial.print("VCC = "); Serial.print(v); Serial.println(" Volts");
    	Serial.print("VCC = "); Serial.print(p); Serial.println(" %");
    	#endif
    	int batteryPcnt = static_cast<int>(p);
    	sendBatteryLevel(batteryPcnt);
    }
    

    The script above works now. (Arduino 1.6.13 and MySensors 2.1.0). It would be nice though to know why I can't use sleep(50) instead of delay(50) in my code. Any ideas?

    Cheers!

    mfalkviddM 1 Reply Last reply
    0
    • gohanG Offline
      gohanG Offline
      gohan
      Mod
      wrote on last edited by
      #2

      If I'm not mistaken, delay it's just a pause in execution, while sleep is an actual powersave mode. You would normally use sleep for longer times instead of 50 milliseconds

      1 Reply Last reply
      0
      • ร รอเรือ

        Hi there!

        I feel I need to share this and I invite You to reflect upon this and share your ideas here.

        I've been working on a battery powered node with 2 push buttons. Normally it sleeps but it will wake up using two interrupts when one of the push buttons gets pressed.
        interruptReturn = sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, ONE_DAY_SLEEP_TIME);

        I've spent many hours trying to figure out how to make this script work. I had problem with that once a push button was pressed it was generating and endless loop of interrupts. It never slept.

        It sounds weird but using the following line

        sleep(50); // Short delay to allow switch to properly settle
        

        instead of

        delay(50); // Short delay to allow switch to properly settle
        

        caused the never ending interrupt loop.

        Below is my final script.

        #define MY_BAUD_RATE 9600
        #define MY_RADIO_NRF24
        
        #include <SPI.h>
        #include <MySensors.h>
        #include <Vcc.h>
        const float VccMin   = 1.8;           // Minimum expected Vcc level, in Volts.
        const float VccMax   = 3.2;           // Maximum expected Vcc level, in Volts.
        const float VccCorrection = 1.0/1.0;  // Measured Vcc by multimeter divided by reported Vcc
        Vcc vcc(VccCorrection);
        
        #define NODE_ID 17
        #define SKETCH_NAME "2x Binary Switch Sleep"
        #define SKETCH_VERSION "3.2"
        
        #define CHILD_ID_1 0
        #define CHILD_ID_2 1
        #define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch
        #define SECONDARY_BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch
        
        #define BATTERY_REPORT_DAY 2
        #define BATTERY_REPORT_BY_IRT_CYCLE 10 // Adjust this according to usage frequency.
        #define ONE_DAY_SLEEP_TIME 86400000 // No wakeup timer at all
        
        int oldValue1=-1;
        int oldValue2=-1;
        int dayCounter = BATTERY_REPORT_DAY;
        int irtCounter = 0;
        int interruptReturn = MY_WAKE_UP_BY_TIMER;
        
        MyMessage msg1(CHILD_ID_1,V_TRIPPED);
        MyMessage msg2(CHILD_ID_2,V_TRIPPED);
        
        void setup()	
        {	
        	pinMode(PRIMARY_BUTTON_PIN,INPUT);
        	pinMode(SECONDARY_BUTTON_PIN,INPUT);
        	// We use external and very weak pull ups to save power
        	//digitalWrite(PRIMARY_BUTTON_PIN, HIGH);    // Enable internal pull-up
        	//digitalWrite(SECONDARY_BUTTON_PIN, HIGH);    // Enable internal pull-up
        }
        
        void presentation() {
        	sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
        	present(CHILD_ID_1, S_DOOR);
        	present(CHILD_ID_2, S_DOOR);
        }
        
        void loop() 
        {
        	if (interruptReturn == MY_WAKE_UP_BY_TIMER) { // Woke up by timer (or first run)
        		dayCounter++;
        		#ifdef MY_DEBUG
        		Serial.println("Woke up by timer (or first run)");
        		#endif
        		if (dayCounter >= BATTERY_REPORT_DAY) {
        			dayCounter = 0;
        			sendBatteryReport();
        		}
        	} else {    // Woke up by pin change
        		irtCounter++;
        		#ifdef MY_DEBUG
        		Serial.print("Woke up by pin change on pin D");Serial.println(interruptReturn+2);
        		#endif
        		if (interruptReturn == 0) {
        			delay(50); // Short delay to allow switch to properly settle
        			int value1 = digitalRead(PRIMARY_BUTTON_PIN);
        			if (value1 != oldValue1) {
        				send(msg1.set(value1==HIGH ? 0 : 1));
        				oldValue1 = value1;
        				Serial.print("Sent value: '"); Serial.print(value1==HIGH ? 0 : 1); Serial.println("'.");
        			}
        		} else {
        			delay(50); // Short delay to allow switch to properly settle
        			int value2 = digitalRead(SECONDARY_BUTTON_PIN);
        			if (value2 != oldValue2) {
        				send(msg2.set(value2==HIGH ? 0 : 1));
        				oldValue2 = value2;
        				Serial.print("Sent value: '"); Serial.print(value2==HIGH ? 0 : 1); Serial.println("'.");
        			}
        		}
        	}
        	if (irtCounter>=BATTERY_REPORT_BY_IRT_CYCLE) {
        		irtCounter = 0;
        		sendBatteryReport();
        	}
        	#ifdef MY_DEBUG
        	Serial.println("Zzzzzz");
        	#endif
        	delay(500); //delay to allow serial to fully print before sleep
        	// Sleep until something happens with the sensor, or one sleep_time has passed since last awake.
        	interruptReturn = sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, ONE_DAY_SLEEP_TIME);
        }
        
        void sendBatteryReport() {
        	float v = vcc.Read_Volts();
        	float p = vcc.Read_Perc(VccMin, VccMax);
        	#ifdef MY_DEBUG
        	Serial.print("VCC = "); Serial.print(v); Serial.println(" Volts");
        	Serial.print("VCC = "); Serial.print(p); Serial.println(" %");
        	#endif
        	int batteryPcnt = static_cast<int>(p);
        	sendBatteryLevel(batteryPcnt);
        }
        

        The script above works now. (Arduino 1.6.13 and MySensors 2.1.0). It would be nice though to know why I can't use sleep(50) instead of delay(50) in my code. Any ideas?

        Cheers!

        mfalkviddM Offline
        mfalkviddM Offline
        mfalkvidd
        Mod
        wrote on last edited by mfalkvidd
        #3

        @รอเรือ what Arduino are you using? Might is be an esp8266? If so, take a peek at the return value from sleep() :-(

        1 Reply Last reply
        0
        • mountainmanM Offline
          mountainmanM Offline
          mountainman
          wrote on last edited by
          #4

          I think I might be having a similar issue on the slim node. It seems to work fine when pulled down by the circuit but enters an endless loop between the time based interrupt and pin when the circuit is open and being pulled up.

          What value of resistor are using for you pull up and were you having the issue on both rising/falling edge?

          1 Reply Last reply
          0
          • ร Offline
            ร Offline
            รอเรือ
            wrote on last edited by
            #5

            Hi guys!

            In the example above, it would be more appropriate using millis() in a loop than using sleep(50). It's also kind of wrong to use delay(50) I believe since it's taking up 100% of the CPU.

            Never mind. I'm just interested to understand how the sleep(50) inside the main loop would cause the "endless loop of interrupts" in my example. Actually I suspect it's a bug so it might be worth digging into it a bit.

            I've been experimenting with both strong and weak external pull-ups and I've also tried internal pull ups but it made no difference actually. I'm currently using an external resistor of 4,7M Ohm and it's working great (unless using sleep(50) inside the main loop of course).

            Hardware used is a Slim Node I never tried using a "pull down" instead of a "pull up" resistor.

            1 Reply Last reply
            0
            • Nca78N Offline
              Nca78N Offline
              Nca78
              Hardware Contributor
              wrote on last edited by
              #6

              Probably a stupid question but ... can you confirm the interrupt pin of NRF24 is not connected to your board ?

              ร 1 Reply Last reply
              0
              • Nca78N Nca78

                Probably a stupid question but ... can you confirm the interrupt pin of NRF24 is not connected to your board ?

                ร Offline
                ร Offline
                รอเรือ
                wrote on last edited by
                #7

                @Nca78

                I checked the board. Pin 8 IRQ of the NRF24L01+ module is not connected.

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


                9

                Online

                11.7k

                Users

                11.2k

                Topics

                113.0k

                Posts


                Copyright 2019 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
                • OpenHardware.io
                • Categories
                • Recent
                • Tags
                • Popular