[SOLVED] Development branch: st=fails after node sleep
-
I decided to start with the development branch because of the improved support for the RFM69. I have one outside weather node running without problems for over a month now. My gateway is on 1.5 and my controller is Pimatic.
My next node will be a wall switch with extra's. I want to make it super versatile and configurable in the same way as the MySensors settings in the 2.0 branch (that will show in the code I have so far...). It consists of 2 boards: one withe the radio and buttons mounted on a standard (in DE and NL) pulse switch, and one with the relays and a power supply. If you only use the mcu board it will be powered by a CR2032.
That's my project in short, now the challenge:
Slowly building up the sketch I now come to the sleeping part for when the node is battery powered. I used the code from a LowPowerLab forum user (bottom post on page 2) because at first I was unable to get the PCInt function working. Later I found I used a outdated version of the lib (2.19 in stead of 2.42).
Without sleep the code loops through theupdateChan()
function. Works perfectly. ChanA is a momentary button and ChanB toggles. All the changes are sent to the controller like I want them to. Now enter "sleep": when I usesleep(0, FALLING, 0)
, all I get after the node sleeps arest=fail:x
. The node sleeps only after 5 seconds. In the time before sleeping it registers all changes well.Starting sensor (RRNNA-, 2.0.0-beta) Radio init successful. Reading config... Starting up... Start radio and sensors Send node info. send: 117-117-0-0 s=255,c=3,t=15,pt=0,l=2,sg=0,st=ok: send: 117-117-0-0 s=255,c=0,t=17,pt=0,l=10,sg=0,st=ok:2.0.0-beta send: 117-117-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0 read: 0-0-117 s=255,c=3,t=6,pt=0,l=1,sg=0:M send: 117-117-0-0 s=255,c=3,t=11,pt=0,l=19,sg=0,st=ok:switchNode(battery) send: 117-117-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,st=ok:0.9 send: 117-117-0-0 s=0,c=0,t=3,pt=0,l=0,sg=0,st=ok: send: 117-117-0-0 s=1,c=0,t=3,pt=0,l=0,sg=0,st=ok: Init complete, id=117, parent=0, distance=1 Function 1 Pressed send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:1 Function 1 Released send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:0 Function 1 Pressed send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:1 Function 1 Released send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=ok:0 Sleeping Function 1 Pressed send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=fail:1 Function 1 Released send: 117-117-0-0 s=0,c=1,t=16,pt=1,l=1,sg=0,st=fail:0 Sleeping
If I use
sleep(ms)
the code fails to register the first button press while sleeping. Not exactly what you want in a light switch.Do I do something wrong? I also tried the LowPower.h library but that will not compile because of double declarations of
enum period_t
And finally: the code...
/*************************************************************************** ** ** Light switch v1.0 with additional relay/power supply daughter board ** ** Designed by D Hille. MySensors library by Henrik Ekblad. ** Interrupt and debounce by ** ***************************************************************************/ // Enable debug prints #define MY_DEBUG // Set serial baudrate #define MY_BAUD_RATE 57600 // Enable and select radio type attached #define MY_RADIO_RFM69 #define MY_NODE_ID 117 /**************************************************************************/ #define LED_FUNCTION 0 // LED functions: // 0.: no LED present // 1.: ACK (LED will flash briefly when ACk is received) // 2.: Notification (LED wil diplay a function of the controller) #define NODE_CHAN_A_FUNCTION 1 #define NODE_CHAN_B_FUNCTION 2 // Node functions: // 0.: channel off // 1.: button only momentary ("ON" while button pushed, "OFF" when released) // 2.: button only toggle (every button push toggles state) /**************************************************************************/ #include <SPI.h> #include <MySensor.h> #include <PinChangeInt.h> //#include "LowPower.h" #define buttApin 4 // Arduino Digital I/O pin number for buttons #define buttBpin 5 #define LEDpin 9 #define pulseMinimal 200 #define bounceTime 10 #define awakeTime 5000 #define sketchName "switchNode(battery)" #define sketchVer "0.9" #define ChanA 0 #define ChanB 1 #define ChanC 2 #define ChanD 3 int pinChanged = 255; bool loopRead; bool reqAck = false; bool stateLED = 0; unsigned long pulseTime = 0; static unsigned long lastInterruptTime = 0; int inputPin[4] = {0, 0, 0, 0}; int function[4] = {0, 0, 0, 0}; bool currLvl[4] = {1, 1, 1, 1}; bool lastLvl[4] = {1, 1, 1, 1}; bool debouncer[4] = {1, 1, 1, 1}; bool outState[4] = {0, 0, 0, 0}; unsigned long lastButtonPressed[4] = {0, 0, 0, 0}; bool setDebug = false; bool startUp = true; bool noRFchanB = false; MyMessage msgButton(0, V_TRIPPED); MyMessage msgToggle(0, V_STATUS); MyMessage msgLED(LEDpin, V_LIGHT); #if (NODE_CHAN_A_FUNCTION == 0) #error Channel A cannot be turned off. For single channel use turn off channel B. #endif void setup() { #ifdef MY_DEBUG //Differentiate between global debug including radio and local debug setDebug = true; //for the sketch alone. #endif if (setDebug){ Serial.println("\nReading config..."); } if (NODE_CHAN_B_FUNCTION == 0) { noRFchanB = true; } if (LED_FUNCTION == 1) { reqAck = true; } inputPin[ChanA] = buttApin; inputPin[ChanB] = buttBpin; function[ChanA] = NODE_CHAN_A_FUNCTION; function[ChanB] = NODE_CHAN_B_FUNCTION; if (setDebug) { Serial.println("\nStarting up..."); Serial.println("Start radio and sensors"); Serial.println("Send node info."); } pinMode(inputPin[ChanA],INPUT_PULLUP); pinMode(inputPin[ChanB],INPUT_PULLUP); pinMode(LEDpin, OUTPUT); attachPinChangeInterrupt(inputPin[ChanA], ChanA_ISR, FALLING); attachPinChangeInterrupt(inputPin[ChanB], ChanB_ISR, FALLING); } void presentation() { sendSketchInfo(sketchName, sketchVer); present(ChanA, S_BINARY); if (!noRFchanB) { present(ChanB, S_LIGHT); } if (LED_FUNCTION == 2) { present(LEDpin, S_LIGHT); } lastInterruptTime = millis(); } void loop() { updateChan(pinChanged); sleepNow(); } void sleepNow(void) { if (millis()-lastInterruptTime > awakeTime) { //delay (50); Serial.println ("Sleeping"); lastInterruptTime = millis(); //delay (100); sleep(0, RISING, 0); } } void receive(const MyMessage &message) { if (message.isAck()) { flashLED(); } if (message.type == V_LIGHT) { if (message.sensor == LEDpin) { stateLED = message.getBool(); changeNotification(); } } } void flashLED() { digitalWrite(LEDpin, HIGH); wait(50); digitalWrite(LEDpin, LOW); } void changeNotification() { } void ChanA_ISR() { pinChanged = ChanA; lastInterruptTime = millis(); } void ChanB_ISR() { pinChanged = ChanB; lastInterruptTime = millis(); } void updateChan(byte bttnNo) { currLvl[bttnNo] = digitalRead(inputPin[bttnNo]); unsigned long currTme = millis(); if (currLvl[bttnNo] != lastLvl[bttnNo]) { lastButtonPressed[bttnNo] = currTme; } if (currTme - lastButtonPressed[bttnNo] > bounceTime) { if (currLvl[bttnNo] != debouncer[bttnNo]) { debouncer[bttnNo] = currLvl[bttnNo]; if (function[bttnNo] == 1) { Serial.println("Function 1"); if (currLvl[bttnNo] == LOW) { Serial.println("Pressed"); send(msgButton.setSensor(bttnNo).set(true)); } else { Serial.println("Released"); send(msgButton.setSensor(bttnNo).set(false)); } } if (function[bttnNo] >= 2) { Serial.println("Function 2"); if (currLvl[bttnNo] == LOW) { Serial.println("Toggle"); outState[bttnNo] = !outState[bttnNo]; send(msgToggle.setSensor(bttnNo).set(outState[bttnNo]), reqAck); } } } } lastLvl[bttnNo] = currLvl[bttnNo]; }
-
Well, I DID do it wrong!
Thanks to @Dirk_H in another topic I changed my call to sleep tosleep(0xff, 0x00, 0xff, 0x00, 0);
, and presto, goin'....SOLVED!
-
Glad it helped David. I just thought about it again, maybe sleep(0xff, 0x00, 0) does work too. I did not test it but I think it calls the same function anyway.
However the method of direct calling sleep(0xff, 0x00, 0xff, 0x00, 0) should save some clocks because one less jmp is required