NRF52 -> gateway Losing messages



  • I have quite an annoying problem keeping me from successfully deploying a bunch of NRF52 PIRs.
    For a little while it works and then the messages stop. I have serial logs from the NRF52 seemingly sending the messages but nothing on the gateway side. The two devices are about 6 feet apart. I've tried it at home with a completely different pi and a completely different radio (pa and non-pa version) and the results are the same. On my desk at work its a regular pi b with a non-pa radio. Again, six feet apart. I've tried the default channel. I've tried channel 10 and 125 as well. I've tried max power and low power. I send the message twice thinking maybe one gets lost and the second makes it through.

    Here's the sketch:

    // SUMMARY: This demo sketch runs on the AM612 PIR v607 PCBto transmit battery voltage (heartbeat) and motion detections to a MySensors gateway using MySensors protocols.
    
    // Note: because this is a passive node, node ID must be set manually to a unique sensor node ID:
    #define MY_NODE_ID 70  // Passive mode requires static node ID
    
    //#define MY_CORE_ONLY
    
    //#define MY_PASSIVE_NODE
    
    #define MY_RADIO_NRF5_ESB
    
    
    
    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2017 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - tekka
     *
     * DESCRIPTION
     * Passive node example: This is a passive & independent reporting node
     *
     */
    
    // This demo sketch also draws from the MySensor's example MotionSensor sketch.
    
    
    //#define IS_NRF51  //true iff the target is an nRF51.  If an nRF52, then comment this line out!
    
    
    #define PIR_DETECTION_PIN 2 
    #define SHORT_WAIT 100
    //#define MY_RF24_CHANNEL 125
    #define MY_NRF5_ESB_CHANNEL 125
    //#define MY_NRF5_ESB_PA_LEVEL NRF5_PA_MAX
    //#define MY_TRANSPORT_WAIT_READY_MS  3000
    //#define MY_TRANSPORT_MAX_TSM_FAILURES 2
    //#define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS 3000
    //#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
    //#define MY_PARENT_NODE_IS_STATIC
    //#define MY_PARENT_NODE_ID 0
    #define MY_DEBUG_VERBOSE_NRF5_ESB
    //#define MY_NRF5_ESB_REVERSE_ACK_RX
    //#define MY_NRF5_ESB_REVERSE_ACK_TX
    #define MY_DEBUG
    #define MY_DEBUG_VERBOSE_TRANSPORT
    
    #include <MySensors.h>
    
    
    // Enable debug prints
    
    
    
    volatile bool motion_change=false;
    
    void blinkityBlink(uint8_t pulses, uint8_t repetitions) {
      for (int x=0;x<repetitions;x++) {
        for (int i=0;i<pulses;i++) {
          digitalWrite(LED_BUILTIN,HIGH);
          wait(20);
          digitalWrite(LED_BUILTIN,LOW);
          wait(100);
        }    
          wait(500);
      }
    }
    
    void disableNfc() {  //only applied to nRF52
    
    #ifndef IS_NRF51
      //Make pins 9 and 10 usable as GPIO pins.
      NRF_NFCT->TASKS_DISABLE=1;  //disable NFC
      NRF_NVMC->CONFIG=1;  // Write enable the UICR
      NRF_UICR->NFCPINS=0; //Make pins 9 and 10 usable as GPIO pins.
      NRF_NVMC->CONFIG=0;  // Put the UICR back into read-only mode.
    #endif
    }
    
    
    void turnOffRadio() {
      NRF_RADIO->TASKS_DISABLE=1;
      while (!(NRF_RADIO->EVENTS_DISABLED)) {}  //until radio is confirmed disabled
    }
    
    void turnOffUarte0() {
    #ifndef IS_NRF51  
      NRF_UARTE0->TASKS_STOPRX = 1;
      NRF_UARTE0->TASKS_STOPTX = 1;
    //  NRF_UARTE0->TASKS_SUSPEND = 1;
      NRF_UARTE0->ENABLE=0;  //disable UART0
      while (NRF_UARTE0->ENABLE!=0) {};  //wait until UART0 is confirmed disabled.
    #endif
    
    #ifdef IS_NRF51
      NRF_UART0->TASKS_STOPRX = 1;
      NRF_UART0->TASKS_STOPTX = 1;
      NRF_UART0->TASKS_SUSPEND = 1;
      NRF_UART0->ENABLE=0;  //disable UART0
      while (NRF_UART0->ENABLE!=0) {};  //wait until UART0 is confirmed disabled.
    #endif
    }
    
    void turnOffAdc() {
    #ifndef IS_NRF51
      if (NRF_SAADC->ENABLE) { //if enabled, then disable the SAADC
        NRF_SAADC->TASKS_STOP=1;
        while (NRF_SAADC->EVENTS_STOPPED) {} //wait until stopping of SAADC is confirmed
        NRF_SAADC->ENABLE=0;  //disable the SAADC
        while (NRF_SAADC->ENABLE) {} //wait until the disable is confirmed
      }
    #endif
    }
    
    
    void turnOffHighFrequencyClock() {
        NRF_CLOCK->TASKS_HFCLKSTOP = 1;
        while ((NRF_CLOCK->HFCLKSTAT) & 0x0100) {}  //wait as long as HF clock is still running.
    }
    
    
    void mySleepPrepare() {  //turn-off energy drains prior to sleep
      turnOffHighFrequencyClock();
      turnOffRadio();
      //turnOffUarte0();
    }
     
    
    void activateLpComp() {
      NRF_LPCOMP->PSEL=0; // monitor AIN0 (i.e. pin P0.02 on nRF52832 PIR Motion Sensor v607).
      while (!(NRF_LPCOMP->PSEL==0)) {} //wait until confirmed
      NRF_LPCOMP->REFSEL=3;  // choose 1/2 VDD as the reference voltage
      while (!(NRF_LPCOMP->REFSEL==3)) {} //wait until confirmed
      NRF_LPCOMP->ANADETECT=0;  //detect CROSS events on PIR detection pin
      while (NRF_LPCOMP->ANADETECT!=0) {} //wait until confirmed
      NRF_LPCOMP->INTENSET=B1000;  //Enable interrupt for CROSS event
      while (!(((NRF_LPCOMP->INTENSET)&B1000)==B1000)) {} //wait until confirmed
      NRF_LPCOMP->ENABLE=1;  //Enable LPCOMP
      while (!(NRF_LPCOMP->ENABLE==1)) {} //wait until confirmed
      NRF_LPCOMP->TASKS_START=1;  //start the LPCOMP
      while (!(NRF_LPCOMP->EVENTS_READY)) {}  //wait until ready
      
      NVIC_SetPriority(LPCOMP_IRQn, 15);
      NVIC_ClearPendingIRQ(LPCOMP_IRQn);
      NVIC_EnableIRQ(LPCOMP_IRQn);
    }
    
    void suspendLpComp() { //suspend getting more interrupts from LPCOMP before the first interrupt can be handled
      if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {  //if LPCOMP is enabled
        NRF_LPCOMP->INTENCLR=B0100;  //disable interrupt from LPCOMP
        while (((NRF_LPCOMP->INTENCLR)&B0100)==B0100) {} //wait until confirmed
      }
    }
    
    void resumeLpComp() { //suspend getting interrupts from LPCOMP
      NRF_LPCOMP->INTENSET=B0100;  //Enable interrupt for UP event
      while (((NRF_LPCOMP->INTENSET)&B1000)!=B0100) {} //wait until confirmed
    }
    
    
    #define CHILD_ID 1   // Id of the motion sensor child
    #define ID_S_MULTIMETER        28
    
    // Initialize motion message
    
    MyMessage msg(CHILD_ID, V_TRIPPED);
    MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE);
    
    
    float batteryVoltage=0;  
    
    void blinkityBlink(uint8_t repetitions) {
      for (int x=0;x<repetitions;x++) {
        digitalWrite(LED_BUILTIN,HIGH);
        wait(20);
        digitalWrite(LED_BUILTIN,LOW);
        wait(100);
        digitalWrite(LED_BUILTIN,HIGH);
        wait(20);
        digitalWrite(LED_BUILTIN,LOW);    
        if (x<(repetitions-1)) {  //skip waiting at the end of the final repetition
          wait(500);
        }
      }
    }
    
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Motion Sensor", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID, S_MOTION);
    
      wait(SHORT_WAIT);
      
      present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Station");
      wait(SHORT_WAIT);
    }
    
    
    void setup()
    {
      hwInit();
      hwPinMode(LED_BUILTIN,OUTPUT_D0H1);
      hwPinMode(PIR_DETECTION_PIN,INPUT);
      blinkityBlink(2,1);  //Signify end of setup with two quick pulses.
      
      disableNfc();  //remove unnecessary energy drains
      turnOffAdc();  //remove unnecessary energy drains
      activateLpComp();
      motion_change=false;
    }
    
    
    
    void mySleep(uint32_t ms) {
       mySleepPrepare();  //Take steps to reduce drains on battery current prior to sleeping
       sleep(ms);
    }
    
    
    bool motionDetected=false;
    void loop() {
    
      mySleep(300000);  //sleep for 5 minutes
    
      if (motion_change) {
        motionDetected=!motionDetected;
        if (motionDetected) {
          digitalWrite(LED_BUILTIN,HIGH);  //turn-on LED to signify motion detected
          send(msg.set("1"));  // motion detected
          wait(SHORT_WAIT);
          send(msg.set("1"));
          delay(500);
          digitalWrite(LED_BUILTIN,LOW);
        }
        else {
          digitalWrite(LED_BUILTIN,LOW);  //turn-off LED to signify motion no longer detected
          send(msg.set("0"));  // send all-clear to prepare for future detections
          wait(SHORT_WAIT);
          send(msg.set("0"));
        }    
        
        NRF_LPCOMP->EVENTS_CROSS=0;
        motion_change=false;
      }
      else { //must be a scheduled wake-up.  Time to report voltage as a heartbeat.
        batteryVoltage=((float)hwCPUVoltage())/1000.0;  //take voltage measurement after transmission to hopefully measure lowest voltage that occurs. 
        send(msg_S_MULTIMETER_V_VOLTAGE.set(batteryVoltage,3));  //send battery voltage with 3 decimal places
      }
    }
    
    
    // * Reset events and read back on nRF52
    //* http://infocenter.nordicsemi.com/pdf/nRF52_Series_Migration_v1.0.pdf
     
    #if __CORTEX_M == 0x04
    #define NRF5_RESET_EVENT(event)                                                 \
            event = 0;                                                                   \
            (void)event
    #else
    #define NRF5_RESET_EVENT(event) event = 0
    #endif
    
    
    // This must be in one line
    extern "C" { void LPCOMP_IRQHandler(void) {motion_change=true; NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS); NRF_LPCOMP->EVENTS_CROSS=0; MY_HW_RTC->CC[0]=(MY_HW_RTC->COUNTER+2);}}
    

    The serial log from a wake up event:

    849294 MCO:SLP:WUP=-1
    849296 TSF:TRI:TPU
    849298 NRF5:INIT:ESB
    849300 NRF5:STL
    849301 NRF5:SND:TO=255,LEN=8,PID=1,NOACK=1
    849311 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=10
    849316 ?TSF:MSG:SEND,70-70-255-0,s=1,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:0
    849373 NRF5:SND:TO=255,LEN=8,PID=2,NOACK=1
    849383 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=9
    849388 ?TSF:MSG:SEND,70-70-255-0,s=1,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:0
    849394 NRF5:RX:LEN=8,NOACK=0,PID=1,RSSI=-63,RX=0
    849399 TSF:MSG:READ,0-0-70,s=1,c=1,t=16,pt=0,l=1,sg=0:0
    849404 TSF:MSG:ACK
    849406 MCO:SLP:MS=300000,SMS=0,I1=255,M1=255,I2=255,M2=255
    849411 TSF:TDI:TPD
    849413 NRF5:PD
    

    From the gateway at NRF5 power-on:

    May 07 14:07:49 DEBUG TSF:MSG:READ,70-70-0,s=255,c=3,t=6,pt=1,l=1,sg=0:255
    May 07 14:07:49 DEBUG GWT:TPS:TOPIC=mysensors-out/70/255/3/0/6,MSG SENT
    
    

    Sometimes it all makes it through, not this time.

    Here's the startup log from the NRF5 at the same time:

     __  __       ____
    |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
            |___/                      2.3.1
    
    23 MCO:BGN:INIT NODE,CP=RNNPN---,REL=255,VER=2.3.1
    28 TSM:INIT
    29 TSF:WUR:MS=0
    30 NRF5:INIT:ESB
    32 TSM:INIT:TSP OK
    34 TSM:INIT:TSP PSM
    35 TSM:INIT:STATID=70
    37 NRF5:STL
    39 TSF:SID:OK,ID=70
    40 TSM:FPAR
    41 TSM:FPAR:STATP=255
    43 TSM:ID
    44 TSM:ID:OK
    46 TSM:UPL:DISABLED
    47 TSM:READY:ID=70,PAR=255,DIS=1
    50 NRF5:SND:TO=255,LEN=9,PID=0,NOACK=0
    60 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=11
    65 ?TSF:MSG:SEND,70-70-255-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    72 NRF5:RX:LEN=9,NOACK=0,PID=1,RSSI=-71,RX=0
    76 TSF:MSG:READ,0-0-70,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    81 NRF5:SND:TO=255,LEN=12,PID=1,NOACK=1
    92 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=10
    96 ?TSF:MSG:SEND,70-70-255-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.3.1
    103 NRF5:SND:TO=255,LEN=8,PID=2,NOACK=1
    113 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=9
    118 ?TSF:MSG:SEND,70-70-255-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:255
    2124 NRF5:SND:TO=255,LEN=20,PID=3,NOACK=1
    2135 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=9
    2139 ?TSF:MSG:SEND,70-70-255-0,s=255,c=3,t=11,pt=0,l=13,sg=0,ft=0,st=OK:Motion Sensor
    2147 NRF5:SND:TO=255,LEN=10,PID=0,NOACK=1
    2158 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=9
    2162 ?TSF:MSG:SEND,70-70-255-0,s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=OK:1.0
    2169 NRF5:SND:TO=255,LEN=7,PID=1,NOACK=1
    2179 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=9
    2184 ?TSF:MSG:SEND,70-70-255-0,s=1,c=0,t=1,pt=0,l=0,sg=0,ft=0,st=OK:
    2240 NRF5:SND:TO=255,LEN=23,PID=2,NOACK=1
    2251 NRF5:SND:END=1,ACK=0,RTRY=4,RSSI=-61,WAKE=9
    2256 ?TSF:MSG:SEND,70-70-255-0,s=28,c=0,t=30,pt=0,l=16,sg=0,ft=0,st=OK:Electric Station
    2314 MCO:REG:NOT NEEDED
    2316 MCO:BGN:STP
    3057 MCO:BGN:INIT OK,TSP=1
    3059 MCO:SLP:MS=300000,SMS=0,I1=255,M1=255,I2=255,M2=255
    3064 TSF:TDI:TPD
    3066 NRF5:PD
    
    PORT CLOSED
    
    

    any hints would be more than welcome, please



  • Make sure you don't have two controllers running. That will split the messages between them randomly.


 

270
Online

8.4k
Users

9.3k
Topics

97.9k
Posts