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