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.