NRF51822 door sensor - help needed [Solved]



  • Hello

    After days of trying to figure out the Arduino sketch I have came up with the following sketch (followed sketch from @Omemanti from Openharware.io)

    #define MY_DEBUG 
    #define MY_RADIO_NRF5_ESB
    #define MY_NODE_ID 217 //change everytime
    
    #include <SPI.h>                                  // A communication backbone, the Serial Peripheral Interface.
    #include <MySensors.h>                            // The MySensors library. Hurray!
    #include <Wire.h>                                 // Enables the Wire communication protocol.
    
    // Timing etc //////////////////
    #define SHORT_WAIT 50
    #define LongSleep 30000    //(600.000 = 10 minutes) (-200 to counter shifting)
    long Interval_StartSleep;   // Sleeping interval check
    long Interval_Sleeptime;    // Sleeping interval check
    
    
    #define SKETCH_NAME "Two State Door Sensor"
    #define SKETCH_VERSION "v1"
    #define NC_PIN 0 //If door open, V_TRIPPED
    #define NO_PIN 1 //If door closed, V_ARMED
    
    #define DOOR_OPEN_CHILD_ID 0
    #define DOOR_CLOSE_CHILD_ID 1
    #define VOLT_CHILD_ID 10
    
    float batteryVoltage=0;
    MyMessage msgDoorOpen(DOOR_OPEN_CHILD_ID, V_TRIPPED); //TRIPPED --> Open, ARMED --> Closed
    MyMessage msgDoorClose(DOOR_CLOSE_CHILD_ID, V_ARMED); //AMRED --> Closed
    MyMessage msgVoltage(VOLT_CHILD_ID, V_VOLTAGE);
    
    void setup()
    {
      Serial.println("Door sensor, two state sensor");
      pinMode(NC_PIN, INPUT);
      pinMode(NO_PIN, INPUT);
      battery_report();
    }
    
    void presentation()
    {
      sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
      wait(SHORT_WAIT);
      present(DOOR_OPEN_CHILD_ID, S_DOOR);
      wait(SHORT_WAIT);
      present(DOOR_CLOSE_CHILD_ID, S_DOOR);
      wait(SHORT_WAIT);
      present(VOLT_CHILD_ID, S_MULTIMETER, "Battery Voltage");
    
      
    }
    
    
    void loop()
    {
      door_tripped();
      door_armed();
    }
    void battery_report()
    {
      batteryVoltage=((float)hwCPUVoltage())/1000.0;
      send(msgVoltage.set(batteryVoltage,2));
      sleep(3600000);
    }
    void door_tripped()
    {
      Interval_StartSleep = millis(); // Register where we started sleeping
     
     sleep(digitalPinToInterrupt(NC_PIN), CHANGE, LongSleep); // Here the waiting starts
     Interval_Sleeptime = millis()-Interval_StartSleep;
     //Serial.println("we are awake jeeh, party hard while i can!");   // DEBUG
    
     if (Interval_Sleeptime < LongSleep)
      {
      Serial.print("Door Opened at: ");Serial.println(millis()); // DEBUG 
      
      send(msgDoorOpen.set(millis));// Sending something
      battery_report();
      //Blinking because we can
      //digitalWrite(LED_GeneralPurpose, HIGH); wait(10);digitalWrite(LED_GeneralPurpose, LOW); //Blinking because we can
      
      Serial.print("Messge sent to HA, now going back to sleep at: ");Serial.print(Interval_Sleeptime);   // DEBUG
      
      Interval_Sleeptime = LongSleep- Interval_Sleeptime;
      if (Interval_Sleeptime <= 0 || Interval_Sleeptime >= LongSleep) // for the slim chance millis() gets confused or something, check if the remainder of sleep is still viable.
       {
       Serial.print(" Something went wrong with door sensor reporting : ");Serial.print(Interval_Sleeptime);
       Interval_Sleeptime = 150000; // just a time 
           
       }
       Serial.print("No more incidents to report by door sensor, now sleeping; at: ");Serial.println(Interval_Sleeptime); // DEBUG
       sleep(Interval_Sleeptime); // Sleep for the remainder of the 10 minutes
     
      }
    }
    void door_armed()
    {
      Interval_StartSleep = millis(); // Register where we started sleeping
     
     sleep(digitalPinToInterrupt(NO_PIN), CHANGE, LongSleep); // Here the waiting starts
     Interval_Sleeptime = millis()-Interval_StartSleep;
     //Serial.println("we are awake jeeh, party hard while i can!");   // DEBUG
    
     if (Interval_Sleeptime < LongSleep)
      {
      Serial.print("Door Closed at: ");Serial.println(millis()); // DEBUG 
      
      send(msgDoorClose.set(millis));// Sending something
      battery_report();
      //Blinking because we can
      //digitalWrite(LED_GeneralPurpose, HIGH); wait(10);digitalWrite(LED_GeneralPurpose, LOW); //Blinking because we can
      
      Serial.print("Messge sent to HA, now going back to sleep at: ");Serial.print(Interval_Sleeptime);   // DEBUG
      
      Interval_Sleeptime = LongSleep- Interval_Sleeptime;
      if (Interval_Sleeptime <= 0 || Interval_Sleeptime >= LongSleep) // for the slim chance millis() gets confused or something, check if the remainder of sleep is still viable.
       {
       Serial.print(" Something went wrong with door sensor reporting : ");Serial.print(Interval_Sleeptime);
       Interval_Sleeptime = 150000; // just a time 
           
       }
       Serial.print("No more incidents to report by door sensor, now sleeping; at: ");Serial.println(Interval_Sleeptime); // DEBUG
       sleep(Interval_Sleeptime); // Sleep for the remainder of the 10 minutes
     
      }
    }
    
    

    I am getting the following message on rpi gateway --

    Apr 09 20:54:57 INFO  Starting gateway...
    Apr 09 20:54:57 INFO  Protocol version - 2.3.2
    Apr 09 20:54:57 DEBUG MCO:BGN:INIT GW,CP=RNNGL-Q-,FQ=NA,REL=255,VER=2.3.2
    Apr 09 20:54:57 DEBUG TSF:LRT:OK
    Apr 09 20:54:57 DEBUG TSM:INIT
    Apr 09 20:54:57 DEBUG TSF:WUR:MS=0
    Apr 09 20:54:57 DEBUG TSM:INIT:TSP OK
    Apr 09 20:54:57 DEBUG TSM:INIT:GW MODE
    Apr 09 20:54:57 DEBUG TSM:READY:ID=0,PAR=0,DIS=0
    Apr 09 20:54:57 DEBUG MCO:REG:NOT NEEDED
    Apr 09 20:54:57 DEBUG MCO:BGN:STP
    Apr 09 20:54:57 DEBUG MCO:BGN:INIT OK,TSP=1
    Apr 09 20:54:57 DEBUG GWT:RMQ:CONNECTING...
    Apr 09 20:54:57 DEBUG connected to 192.168.1.17
    Apr 09 20:54:57 DEBUG GWT:RMQ:OK
    Apr 09 20:54:57 DEBUG GWT:TPS:TOPIC=mysensors-out/0/255/0/0/18,MSG SENT
    Apr 09 20:54:57 DEBUG TSM:READY:NWD REQ
    Apr 09 20:54:57 DEBUG ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
    Apr 09 20:54:57 DEBUG TSF:MSG:READ,217-217-0,s=255,c=3,t=21,pt=1,l=1,sg=0:0
    Apr 09 20:54:57 DEBUG GWT:TPS:TOPIC=mysensors-out/217/255/3/0/21,MSG SENT
    Apr 09 20:54:57 NOTICE RF24: Recovered from a bad interrupt trigger.
    Apr 09 20:54:57 DEBUG TSF:MSG:READ,217-217-0,s=255,c=3,t=6,pt=1,l=1,sg=0:0
    Apr 09 20:54:57 DEBUG GWT:TPS:TOPIC=mysensors-out/217/255/3/0/6,MSG SENT
    Apr 09 20:54:59 NOTICE RF24: Recovered from a bad interrupt trigger.
    Apr 09 20:54:59 DEBUG TSF:MSG:READ,217-217-0,s=255,c=3,t=12,pt=0,l=2,sg=0:v1
    Apr 09 20:54:59 DEBUG GWT:TPS:TOPIC=mysensors-out/217/255/3/0/12,MSG SENT
    Apr 09 20:54:59 NOTICE RF24: Recovered from a bad interrupt trigger.
    Apr 09 20:54:59 DEBUG TSF:MSG:READ,217-217-0,s=1,c=0,t=0,pt=0,l=0,sg=0:
    Apr 09 20:54:59 DEBUG GWT:TPS:TOPIC=mysensors-out/217/1/0/0/0,MSG SENT
    Apr 09 20:55:00 NOTICE RF24: Recovered from a bad interrupt trigger.
    Apr 09 20:55:00 DEBUG TSF:MSG:READ,217-217-0,s=255,c=3,t=26,pt=1,l=1,sg=0:2
    Apr 09 20:55:00 DEBUG TSF:MSG:SEND,0-0-217-217,s=255,c=3,t=27,pt=1,l=1,sg=0,ft=0,st=OK:1
    Apr 09 20:55:00 NOTICE RF24: Recovered from a bad interrupt trigger.
    Apr 09 20:55:24 DEBUG TSF:MSG:READ,217-217-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
    
    

    The code does not seem to report - the sensing of reed switch on pins P0.00 and P0.01 and also it does not report battery voltage. I seek help.
    Thanks.



  • @Puneit-Thukral It looks ot me that your sleep calls are the problem here.

    You sleep the mcu with no way of waking up when an interrupt happens. In my door node I have a sensor for the door open/closed and an anti-tamper which triggers if the unit is moved from the wall. Here is how I did the sleep and interrupt call.....

     sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, digitalPinToInterrupt(DIGITAL_INPUT_ANTITAMPER), CHANGE, SLEEP_TIME);
    

    This way the mcu will sleep, but awake when an interrupt changes.

    I hope this helps you get it working!



  • @skywatch said in NRF51822 door sensor - help needed:

    digitalPinToInterrupt

    Thanks for your earlier reply. If now I add debouncer and interrupt in the same function, the code does not seem to work

    
    void door_tripped()
    {
      bool tripped =  digitalRead(NO_PIN) == HIGH;
      debouncer.update();
      int value = debouncer.read();
      if (value != oldValue)
        {
          send(msgDoor.set(tripped?"1":"0"));
          oldValue = value;
        }
    
      sleep(digitalPinToInterrupt(NO_PIN), CHANGE, LongSleep);
    
    }
    

    Is this incorrect logic or bad syntax. This is what I want to achieve

    1. Wake up if the pin status changes (hence the interrupt)
    2. Do not spam the gateway (hence the debounce)
    3. Report the status
    4. Go back to sleep

    Thanks for the help



  • @Puneit-Thukral Please find below my full code for a node with debounce, sleep, anti-tamper and battery level reporting.
    Hopefully you will see the patterns in the coding and use the example to modify your code to work as you want.

    /*
    ******** FOR LOW POWER PRO-MINI 1MHz - 1,8V BOD ********
    * 
    * D2 - AntiTamper switch 
    * D3 - Sensor
    * A0 - Battery Sense Pin
    * 
     */
    
    // Enable debug prints
    // #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    #define MY_RF24_PA_LEVEL RF24_PA_HIGH  //Options are: MIN, LOW, HIGH or MAX
    #define MY_NODE_ID 4
    #define MY_RF24_CHANNEL (97)
    #define MY_PARENT_NODE_ID 0
    #define MY_PARENT_NODE_IS_STATIC
    #define DIGITAL_INPUT_ANTITAMPER 2   // Anti-Tamper switch connection.
    #define DIGITAL_INPUT_SENSOR 3       // The digital input you attached your Door/Window sensor.
    #define CHILD_ID_ANTITAMPER 0        // Id of the Anti-Tamper sensor child.
    #define CHILD_ID_SENSOR 1            // Id of the door/window sensor child.
    
    // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 2400 // check this as it might need reducing!!!!!
    #endif
    
    #include <MySensors.h>
    
    uint32_t SLEEP_TIME = 60000 * 30; // Sleep time between reports (in milliseconds).
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    int batteryPcnt = 0;
    int lastbatteryPcnt = 0;
    bool oldValueAT = -2;
    bool oldValueDoor = -1;
    
    // Initialize door/window message
    MyMessage msgANTITAMPER(CHILD_ID_ANTITAMPER, V_TRIPPED);  //Tamper.
    MyMessage msgSENSOR(CHILD_ID_SENSOR, V_TRIPPED); //Door/Window.
    
    void setup()
    {
      pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);      // sets the door/window sensor digital pin as input
      pinMode(DIGITAL_INPUT_ANTITAMPER, INPUT_PULLUP);      // sets the Anti-Tamper sensor digital pin as input
     }
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Patio Door", "4.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_ANTITAMPER, S_DOOR, "Patio Tamper",true);
      present(CHILD_ID_SENSOR, S_DOOR, "Patio Door",true);
    }
    
    void loop()
    {
      // Read digital anti-tamper.
      bool tripped = digitalRead(DIGITAL_INPUT_ANTITAMPER) == HIGH;
      if (tripped != oldValueAT)
      {
        send(msgANTITAMPER.set(tripped ? "1" : "0"), true); // Send anti-tamper tripped value to gw
        oldValueAT = tripped;
      }
    
      //Read digital door/window value.
      tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
      if (tripped != oldValueDoor)
      {
        send(msgSENSOR.set(tripped ? "1" : "0"), true); // Send door/window tripped value to gw
        oldValueDoor = tripped;
      }
    
      int sensorValue = analogRead(BATTERY_SENSE_PIN);
      batteryPcnt = sensorValue / 10;
      if (batteryPcnt != lastbatteryPcnt) {
        sendBatteryLevel(batteryPcnt);
        lastbatteryPcnt = batteryPcnt;
      }
      wait(100);
      sendHeartbeat();
      // Sleep until interrupt comes in on motion sensor. Send battery update every 15 minutes.  || (digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_3))
      sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, digitalPinToInterrupt(DIGITAL_INPUT_ANTITAMPER), CHANGE, SLEEP_TIME);
    }
    

    AS to your situation I would say the folowing......

    1. You only need ONE sleep call and that should be in the main void loop()
    2. If you want to detect the door change of state instantly you need to use interrupts if you sleep the node.
    3. You don't need separate 'open' and 'closed' variables and messages. One will do. IF the door is not open, then by default, it is closed. Makes sense?
    4. Node will not 'spam the gateway' unless you program it to do so. Use tests to detect change and then send the change status.


  • Thanks, it works 🙂



Suggested Topics

142
Online

9.5k
Users

10.2k
Topics

105.7k
Posts