[SOLVED] Development branch: st=fails after node sleep



  • I decided to start with the development branch because of the improved support for the RFM69. I have one outside weather node running without problems for over a month now. My gateway is on 1.5 and my controller is Pimatic.

    My next node will be a wall switch with extra's. I want to make it super versatile and configurable in the same way as the MySensors settings in the 2.0 branch (that will show in the code I have so far...). It consists of 2 boards: one withe the radio and buttons mounted on a standard (in DE and NL) pulse switch, and one with the relays and a power supply. If you only use the mcu board it will be powered by a CR2032.

    That's my project in short, now the challenge:
    Slowly building up the sketch I now come to the sleeping part for when the node is battery powered. I used the code from a LowPowerLab forum user (bottom post on page 2) because at first I was unable to get the PCInt function working. Later I found I used a outdated version of the lib (2.19 in stead of 2.42).
    Without sleep the code loops through the updateChan() function. Works perfectly. ChanA is a momentary button and ChanB toggles. All the changes are sent to the controller like I want them to. Now enter "sleep": when I use sleep(0, FALLING, 0) , all I get after the node sleeps are st=fail:x. The node sleeps only after 5 seconds. In the time before sleeping it registers all changes well.

    Starting sensor (RRNNA-, 2.0.0-beta)
    Radio init successful.
    
    Reading config...
    
    Starting up...
    Start radio and sensors
    Send node info.
    send: 117-117-0-0 s=255,c=3,t=15,pt=0,l=2,sg=0,st=ok:
    send: 117-117-0-0 s=255,c=0,t=17,pt=0,l=10,sg=0,st=ok:2.0.0-beta
    send: 117-117-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0
    read: 0-0-117 s=255,c=3,t=6,pt=0,l=1,sg=0:M
    send: 117-117-0-0 s=255,c=3,t=11,pt=0,l=19,sg=0,st=ok:switchNode(battery)
    send: 117-117-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,st=ok:0.9
    send: 117-117-0-0 s=0,c=0,t=3,pt=0,l=0,sg=0,st=ok:
    send: 117-117-0-0 s=1,c=0,t=3,pt=0,l=0,sg=0,st=ok:
    Init complete, id=117, parent=0, distance=1
    Function 1
    Pressed
    send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:1
    Function 1
    Released
    send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:0
    Function 1
    Pressed
    send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:1
    Function 1
    Released
    send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:0
    Sleeping
    Function 1
    Pressed
    send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=fail:1
    Function 1
    Released
    send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=fail:0
    Sleeping
    

    If I use sleep(ms) the code fails to register the first button press while sleeping. Not exactly what you want in a light switch.

    Do I do something wrong? I also tried the LowPower.h library but that will not compile because of double declarations of enum period_t

    And finally: the code...

    /***************************************************************************
    **
    ** Light switch v1.0 with additional relay/power supply daughter board
    **
    ** Designed by D Hille. MySensors library by Henrik Ekblad. 
    **    Interrupt and debounce by 
    **
    ***************************************************************************/
    // Enable debug prints
    #define MY_DEBUG
    
    // Set serial baudrate
    #define MY_BAUD_RATE 57600
    
    // Enable and select radio type attached
    #define MY_RADIO_RFM69
    
    #define MY_NODE_ID 117
    
    /**************************************************************************/
    
    #define LED_FUNCTION 0
    // LED functions:
    // 0.: no LED present
    // 1.: ACK				(LED will flash briefly when ACk is received)
    // 2.: Notification			(LED wil diplay a function of the controller)
    
    #define NODE_CHAN_A_FUNCTION 1
    
    #define NODE_CHAN_B_FUNCTION 2
    
    // Node functions:
    // 0.: channel off
    // 1.: button only momentary  ("ON" while button pushed, "OFF" when released)
    // 2.: button only toggle     (every button push toggles state)
    
    /**************************************************************************/
    
    
    #include <SPI.h>
    #include <MySensor.h>
    #include <PinChangeInt.h>
    //#include "LowPower.h"
    
    #define buttApin  4  // Arduino Digital I/O pin number for buttons
    #define buttBpin  5
    #define LEDpin 9
    
    #define pulseMinimal 200
    #define bounceTime 10
    #define awakeTime 5000
    
    #define sketchName "switchNode(battery)"
    #define sketchVer "0.9" 
    
    #define ChanA 0
    #define ChanB 1
    #define ChanC 2
    #define ChanD 3
    
    int pinChanged = 255;
    bool loopRead;
    bool reqAck = false;
    bool stateLED = 0;
    
    unsigned long pulseTime = 0;
    static unsigned long lastInterruptTime = 0;
    
    int inputPin[4] = {0, 0, 0, 0};
    int function[4] = {0, 0, 0, 0};
    bool currLvl[4] = {1, 1, 1, 1};
    bool lastLvl[4] = {1, 1, 1, 1};
    bool debouncer[4] = {1, 1, 1, 1};
    bool outState[4] = {0, 0, 0, 0};
    unsigned long lastButtonPressed[4] = {0, 0, 0, 0};
    
    bool setDebug = false;
    bool startUp = true;
    
    bool noRFchanB = false;
    
    MyMessage msgButton(0, V_TRIPPED);
    MyMessage msgToggle(0, V_STATUS);
    MyMessage msgLED(LEDpin, V_LIGHT);
    
    #if (NODE_CHAN_A_FUNCTION == 0)
    #error Channel A cannot be turned off. For single channel use turn off channel B.
    #endif
    
    
    void setup()  
    {  
      #ifdef MY_DEBUG                //Differentiate between global debug including radio and local debug 
        setDebug = true;             //for the sketch alone.
      #endif
      
      if (setDebug){
        Serial.println("\nReading config...");
      }
      
      if (NODE_CHAN_B_FUNCTION == 0) {
        noRFchanB = true;
      }
      if (LED_FUNCTION == 1) {
        reqAck = true;
      }
      inputPin[ChanA] = buttApin;
      inputPin[ChanB] = buttBpin;
      
      function[ChanA] = NODE_CHAN_A_FUNCTION;
      function[ChanB] = NODE_CHAN_B_FUNCTION;
      
      if (setDebug) {
        Serial.println("\nStarting up...");
        Serial.println("Start radio and sensors");  
        Serial.println("Send node info.");
      }
      
      pinMode(inputPin[ChanA],INPUT_PULLUP);
      pinMode(inputPin[ChanB],INPUT_PULLUP);
      pinMode(LEDpin, OUTPUT);
      
      attachPinChangeInterrupt(inputPin[ChanA], ChanA_ISR, FALLING);
      attachPinChangeInterrupt(inputPin[ChanB], ChanB_ISR, FALLING);
    }
    
    
    void presentation()  
    {
      sendSketchInfo(sketchName, sketchVer);
    
      present(ChanA, S_BINARY);
    
      if (!noRFchanB) {
        present(ChanB, S_LIGHT);
      }
      
      if (LED_FUNCTION == 2) {
        present(LEDpin, S_LIGHT);
      }
      lastInterruptTime = millis();
    }
    
    
    void loop() 
    { 
      updateChan(pinChanged);
      sleepNow();
    }
    
    
    void sleepNow(void)
    {
     if (millis()-lastInterruptTime > awakeTime) {
       //delay (50);  
       Serial.println ("Sleeping");
       lastInterruptTime = millis();
       //delay (100);
       sleep(0, RISING, 0); 
     }
    }
    
     
    void receive(const MyMessage &message) 
    {
      if (message.isAck()) {
        flashLED();
      }
      
      if (message.type == V_LIGHT) 
      {
        if (message.sensor == LEDpin) {
          stateLED = message.getBool();
          changeNotification();
        }
      } 
    }
    
    
    void flashLED()
    {
      digitalWrite(LEDpin, HIGH);
      wait(50);
      digitalWrite(LEDpin, LOW);
    }
    
    
    void changeNotification()
    {
      
    }
    
    
    void ChanA_ISR()
    {
      pinChanged = ChanA;
      lastInterruptTime = millis();
    }
    
    
    void ChanB_ISR()
    {
      pinChanged = ChanB;
      lastInterruptTime = millis();
    }
    
      
    void updateChan(byte bttnNo)
    {
      currLvl[bttnNo] = digitalRead(inputPin[bttnNo]);
      unsigned long currTme = millis();
      if (currLvl[bttnNo] != lastLvl[bttnNo]) {
        lastButtonPressed[bttnNo] = currTme;
      }
      if (currTme - lastButtonPressed[bttnNo] > bounceTime) {
        if (currLvl[bttnNo] != debouncer[bttnNo]) {
          debouncer[bttnNo] = currLvl[bttnNo];
          if (function[bttnNo] == 1) {
            Serial.println("Function 1");
            if (currLvl[bttnNo] == LOW) {
              Serial.println("Pressed");
              send(msgButton.setSensor(bttnNo).set(true));      
            }
            else {
              Serial.println("Released");
              send(msgButton.setSensor(bttnNo).set(false));
            }
          }  
          if (function[bttnNo] >= 2)  {
            Serial.println("Function 2");
            if (currLvl[bttnNo] == LOW) {
              Serial.println("Toggle");
              outState[bttnNo] = !outState[bttnNo];
              send(msgToggle.setSensor(bttnNo).set(outState[bttnNo]), reqAck);
            }
          }
        }
      }
      lastLvl[bttnNo] = currLvl[bttnNo];
    }
    


  • Well, I DID do it wrong!
    Thanks to @Dirk_H in another topic I changed my call to sleep to sleep(0xff, 0x00, 0xff, 0x00, 0);, and presto, goin'....

    SOLVED!


  • Contest Winner

    Glad it helped David. I just thought about it again, maybe sleep(0xff, 0x00, 0) does work too. I did not test it but I think it calls the same function anyway.

    However the method of direct calling sleep(0xff, 0x00, 0xff, 0x00, 0) should save some clocks because one less jmp is required 馃檪


Log in to reply
 

Suggested Topics

  • 15
  • 9
  • 9
  • 4
  • 30
  • 14
  • 35
  • 2

271
Online

9.4k
Users

10.0k
Topics

104.5k
Posts