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


  • Plugin Developer

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


Log in to reply
 

Suggested Topics

10
Online

11.4k
Users

11.1k
Topics

112.7k
Posts