[SOLVED] A2 interrupt doesn't wake node from sleep
-
Hello first off here is my code (not all ofcourse):
//**************// //* INTERRUPTS *// //**************// // Install Pin change interrupt for a pin, can be called multiple times void pciSetup(byte pin) { *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group } // Use one Routine to handle each group ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here { tripped = true; GetDigital(); // digitalWrite(13, digitalRead(8)); } ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here { //Only on fall interrupt of TSL2561 if (!digitalRead(A2)) { lightInterrupt = true; Serial.println("falling trigger"); } } ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here { tripped = true; GetDigital(); // digitalWrite(13, digitalRead(2) and digitalRead(3) and digitalRead(5) and digitalRead(6) and digitalRead(7)); }
void loop() { //*****************// //* BATTERY LEVEL *// //*****************// //processBattLevel(); //********************// //* DHT: TEMPERATURE *// //********************// //processTemperature(); //*****************// //* DHT: HUMIDITY *// //*****************// //processHumidity(); //*******************// //* TSL: LIGHTLEVEL *// //*******************// //processLightLevel(); if (lightInterrupt == true) { Serial.println("A2 low!!!!!!!!!!!!!!!!!"); processLightLevel(); light.clearInterrupt(); lightInterrupt = false; } //*******************// //* DI: DOOR/WINDOW *// //*******************// //UpdateCurrentState(); //*********// //* SLEEP *// //*********// // Sleep for a while to save energy sleep(PCINT1_vect, CHANGE, PCINT2_vect, CHANGE, UPDATE_INTERVAL); }
I have the problem that a change in PCINT1_vect doesn't wake up my node. The interrupt gets triggered but it doesn't seem to run all of the code in the ISR and doesn't exit the sleep. I get the following in the output:
data0: 1343 data1: 219 TSL2561 interrupts thresholds set successfully lux: 34.25 mlux: 36 lastLux: 36 gain: 1 10764 TSF:MSG:SEND,59-59-0-0,s=3,c=1,t=0,pt=2,l=2,sg=0,ft=0,st=OK:34 LightLevel: 34 lux 10774 MCO:SLP:MS=30000,SMS=0,I1=186,M1=1,I2=59,M2=1 10780 MCO:SLP:TPD 10782 MCO:SLP:WUP=-1 10784 MCO:SLP:MS=30000,SMS=0,I1=186,M1=1,I2=59,M2=1 10790 MCO:SLP:TPD 10792 MCO:SLP:WUP=-1 10795 MCO:SLP:MS=30000,SMS=0,I1=186,M1=1,I2=59,M2=1 10801 MCO:SLP:TPD 10803 MCO:SLP:WUP=-1 10805 MCO:SLP:MS=30000,SMS=0,I1=186,M1=1,I2=59,M2=1 10811 MCO:SLP:TPD faโธฎ
Last line is supposed to be "falling triggr". This Serial.println is located in the ISR PCINT0_vect, but it seems it doesn't get fully executed. after the node wakes up (on timer), it seems like 'lightInterrupt' has been set in the ISR since the lightlevel is processed and updated.
A2 low!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! data0: 1440 data1: 245 TSL2561 interrupts thresholds set successfully lux: 36.30 mlux: 35 lastLux: 35 gain: 1 8491 TSF:MSG:SEND,59-59-0-0,s=3,c=1,t=0,pt=2,l=2,sg=0,ft=0,st=OK:36 LightLevel: 36 lux 8503 MCO:SLP:MS=30000,SMS=0,I1=186,M1=1,I2=210,M2=1 8507 MCO:SLP:TPD 8509 MCO:SLP:WUP=-1 8511 MCO:SLP:MS=30000,SMS=0,I1=186,M1=1,I2=210,M2=1 8517 MCO:SLP:TPD
Stranger even still, PCINT2_vect does work as expected. In this case the node does wake up on interrupt on D2-D7 (if these DI's are enabled in the code). If anyone can help it would be much appreciated. I really don't see the reason PCINT1_vect doesn't wake up the node. If more code is needed tell me, I will happely post the entire code if you want.
-
Using Serial from within an ISR is not recommended. See TL;DR at http://gammon.com.au/interrupts
What does GetDigital() do? ISRs need to be executed quickly, and a lot of things must be avoided (see above link).
10782 MCO:SLP:WUP=-1
shows that the wake up reason is -1 which is MY_WAKE_UP_BY_TIMER so the wake up reason was timer, not interrupt.
What is PCINT1_vect and PCINT2_vect ? (they are not defined in the code you've posted).
Maybe these variables are not what the MySensors sleep function expects? Documentation: https://www.mysensors.org/download/sensor_api_20#sleeping
-
@mfalkvidd Hi, first off thanks for taking a look at my problem.
I know I'm not supposed to use Serial.print inside an ISR, this was just for debugging purposses to see if this part of the code even was run. I tried without the Serial.print but same result.
GetDigital looks wich interruptpin was triggered
boolean GetDigital(void) { noInterrupts(); if (tripped) { for (char i = 0; i < NR_OF_SWITCH; i++) { currState[i] = digitalRead(intPin[i]); if (lastState[i] != currState[i]) { lastState[i] = currState[i]; Serial.print("Pin "); Serial.print(intPin[i]); Serial.print(" triggered: "); Serial.println(currState[i]); switch (i) { case 0: send(msgSwitch1.set(currState[i])); break; case 1: send(msgSwitch2.set(currState[i])); break; case 2: send(msgSwitch3.set(currState[i])); break; case 3: send(msgSwitch4.set(currState[i])); break; case 4: send(msgSwitch5.set(currState[i])); break; case 5: send(msgSwitch6.set(currState[i])); break; default: Serial.println("Not an interrupt pin"); } } } tripped = false; //Clear processed triggers interrupts(); return true; } interrupts(); return false; }
Again Serial.print for debugging (but seems to run fine even with Serial.print, granted it takes the ISR alot longer)
I know the node woke up because the timer expired, this is kind of the problem
PCINT0_vect, PCINT1_vect and PCINT2_vect are interruptvectors used in pinchange interrupt on all pins (D8-D13, A1-A5 & D0-D7) see this link: https://playground.arduino.cc/Main/PinChangeInterrupt.
These variables are probably not what the MySensors Sleep function expects, but it seems to work fine for PCINT0_vect and PCINT2_vect, where the digital pins are connected to. When any of the digital pins change the node wakes up immediatly and sends an update about the pin that changed. Should work the same for the interrupt on the analog pin, but something goes wrong
I even tried using absolute pinnumbers for analog pins (A0=14,A1=15,A2=16,...) but still same result. see:
http://forum.arduino.cc/index.php?topic=41238.0I will include the entire sketch in next post, so you can follow all of the code if needed. Its devided into several files and i cant upload a zip appearently so get ready for some serious code blocks
I have these nodes on every door & window in my house for about a year now and they work great. Just wanted to add interrupt functionality to my light measurement now.
-
This is the entire code:
Setup & loop (.ino)
/** 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-2015 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: Henrik EKblad Version 1.1 - 2016-07-20: Converted to MySensors v2.0 and added various improvements - Torben Woltjen (mozzbozz) DESCRIPTION Mysensors battery node. With temperature, relative humidity, lightintensity and battery level measurements For more information, please visit: http://www.mysensors.org/build/ */ //** Includes #include "Defines.h" #include "Globals.h" #include <SPI.h> #include <Wire.h> //**************// //* INTERRUPTS *// //**************// // Install Pin change interrupt for a pin, can be called multiple times void pciSetup(byte pin) { *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group } // Use one Routine to handle each group ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here { tripped = true; GetDigital(); } ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here { //Only on fall interrupt of TSL2561 if (!digitalRead(16)) { lightInterrupt = true; Serial.println("falling trigger"); } } ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here { tripped = true; GetDigital(); } void setup() { Serial.begin(115200); //***********************// //* SETUP BATTERY LEVEL *// //***********************// setupBattery(); //*************// //* SETUP DHT *// //*************// setupDHT(); //*****************// //* SETUP TSL2561 *// //*****************// setupTSL(); //**************// //* SETUP DI's *// //**************// setupDI(); } void loop() { //*****************// //* BATTERY LEVEL *// //*****************// processBattLevel(); //********************// //* DHT: TEMPERATURE *// //********************// processTemperature(); //*****************// //* DHT: HUMIDITY *// //*****************// processHumidity(); //*******************// //* TSL: LIGHTLEVEL *// //*******************// // processLightLevel(); if (lightInterrupt == true) { Serial.println("A2 low!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); processLightLevel(); light.clearInterrupt(); lightInterrupt = false; } //*******************// //* DI: DOOR/WINDOW *// //*******************// UpdateCurrentState(); //*********// //* SLEEP *// //*********// // Sleep for a while to save energy sleep(PCINT1_vect, CHANGE, PCINT2_vect, CHANGE, UPDATE_INTERVAL); }
Battery (.ino)
void setupBattery(void) { // Define internal reference for battry level measurement #if defined(__AVR_ATmega2560__) analogReference(INTERNAL1V1); #else analogReference(INTERNAL); #endif } void processBattLevel(void) { noInterrupts(); int sensorValue = analogRead(batterySensePin); interrupts(); #ifdef MY_DEBUG Serial.print("Battery sensorValue : ");Serial.println(sensorValue); #endif //1M, 470K divider across battery and using ADC ref of 1.1V //Sense point is bypassed with 0.1ยตF cap to reduce noise at that point //((1e6+470e3) / 470e3) * 1.1 = Vmax = 3.44V //3.44 / 1023 = Volt per bit = 0.003363075 int batteryPcnt = sensorValue / 10; #ifdef MY_DEBUG float batteryV = sensorValue * 0.003363075; Serial.print("Battery Voltage: "); Serial.print(batteryV); Serial.println(" V"); Serial.print("Battery Percent: "); Serial.print(batteryPcnt); Serial.println(" %"); #endif if (oldBatteryPcnt != batteryPcnt || nNoUpdatesBatt == FORCE_UPDATE_N_READS_B) { // Only send battery message when value has changed //Power up radio after sleep send(msgBatt.set(batteryPcnt)); //sendBatteryLevel(batteryPcnt); oldBatteryPcnt = batteryPcnt; nNoUpdatesBatt = 0; } else { // Increase no update counter if the battery level stayed the same nNoUpdatesBatt++; } }
DHT (.ino)
void setupDHT(void){ dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) { Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!"); } // Sleep for the time of the minimum sampling period to give the sensor time to power up // (otherwise, timeout errors might occure for the first reading) sleep(dht.getMinimumSamplingPeriod()); } void processTemperature(void){ noInterrupts(); // Force reading sensor, so it works also after sleep() dht.readSensor(true); // Get temperature from DHT library float temperature = dht.getTemperature(); interrupts(); Serial.print("temperature (float): ");Serial.println(temperature); if (isnan(temperature)) { Serial.println("Failed reading temperature from DHT!"); } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS_T) { // Only send temperature if it changed since the last measurement or if we didn't send an update for n times lastTemp = temperature; if (!metric) { temperature = dht.toFahrenheit(temperature); } // Reset no updates counter nNoUpdatesTemp = 0; temperature += SENSOR_TEMP_OFFSET; send(msgTemp.set(temperature, 1)); #ifdef MY_DEBUG Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" ยฐC"); #endif } else { // Increase no update counter if the temperature stayed the same nNoUpdatesTemp++; } } void processHumidity(void){ noInterrupts(); // Get humidity from DHT library float humidity = dht.getHumidity(); interrupts(); if (isnan(humidity)) { Serial.println("Failed reading humidity from DHT"); } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS_H) { // Only send humidity if it changed since the last measurement or if we didn't send an update for n times lastHum = humidity; // Reset no updates counter nNoUpdatesHum = 0; send(msgHum.set(humidity, 1)); #ifdef MY_DEBUG Serial.print("Humidity: "); Serial.print(humidity); Serial.println(" %"); #endif } else { // Increase no update counter if the humidity stayed the same nNoUpdatesHum++; } }
Digital (.ino)
void setupDI(void) { #ifdef PULL_UP_EN // set pullups, if necessary for (int i = 2; i <= 8; i++) { digitalWrite(i, HIGH); } Serial.println("pullup"); #endif // enable interrupt for pin... for (int i = 0; i < NR_OF_SWITCH; i++) { pciSetup(intPin[i]); #ifdef MY_DEBUG Serial.print("Int pin "); Serial.print(i); Serial.print(": "); Serial.println(intPin[i]); #endif } } void UpdateCurrentState(void) { noInterrupts(); for (char i = 0; i < NR_OF_SWITCH; i++) { currState[i] = digitalRead(intPin[i]); Serial.print("Pin "); Serial.print(intPin[i]); Serial.println(" updated: "); Serial.println(currState[i]); switch (i) { case 0: send(msgSwitch1.set(currState[i])); break; case 1: send(msgSwitch2.set(currState[i])); break; case 2: send(msgSwitch3.set(currState[i])); break; case 3: send(msgSwitch4.set(currState[i])); break; case 4: send(msgSwitch5.set(currState[i])); break; case 5: send(msgSwitch6.set(currState[i])); break; default: Serial.println("Not an interrupt pin"); } } interrupts(); } boolean GetDigital(void) { noInterrupts(); if (tripped) { for (char i = 0; i < NR_OF_SWITCH; i++) { currState[i] = digitalRead(intPin[i]); if (lastState[i] != currState[i]) { lastState[i] = currState[i]; Serial.print("Pin "); Serial.print(intPin[i]); Serial.print(" triggered: "); Serial.println(currState[i]); switch (i) { case 0: send(msgSwitch1.set(currState[i])); break; case 1: send(msgSwitch2.set(currState[i])); break; case 2: send(msgSwitch3.set(currState[i])); break; case 3: send(msgSwitch4.set(currState[i])); break; case 4: send(msgSwitch5.set(currState[i])); break; case 5: send(msgSwitch6.set(currState[i])); break; default: Serial.println("Not an interrupt pin"); } } } tripped = false; //Clear processed triggers interrupts(); return true; } interrupts(); return false; }
Presentation (.ino)
void presentation() { noInterrupts(); // Send the sketch version information to the gateway sendSketchInfo(SKETCH_NAME, Sketch_VERSION); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID_BATT, I_BATTERY_LEVEL); present(CHILD_ID_HUM, S_HUM); present(CHILD_ID_TEMP, S_TEMP); present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); if (NR_OF_SWITCH >= 1) { present(CHILD_ID_SWITCH1, S_DOOR); if (NR_OF_SWITCH >= 2) { present(CHILD_ID_SWITCH2, S_DOOR); if (NR_OF_SWITCH >= 3) { present(CHILD_ID_SWITCH3, S_DOOR); if (NR_OF_SWITCH >= 4) { present(CHILD_ID_SWITCH4, S_DOOR); if (NR_OF_SWITCH >= 5) { present(CHILD_ID_SWITCH5, S_DOOR); if (NR_OF_SWITCH >= 6) { present(CHILD_ID_SWITCH6, S_DOOR); } } } } } } metric = getControllerConfig().isMetric; interrupts(); }
TSL (.ino)
void setupTSL(void) { pinMode(16,INPUT_PULLUP);//16 = A2 pciSetup(16); // Initialize the SFE_TSL2561 library // You can pass nothing to light.begin() for the default I2C address (0x39), // or use one of the following presets if you have changed // the ADDR jumper on the board: // TSL2561_ADDR_0 address with '0' shorted on board (0x29) // TSL2561_ADDR default address (0x39) // TSL2561_ADDR_1 address with '1' shorted on board (0x49) // For more information see the hookup guide at: https://learn.sparkfun.com/tutorials/getting-started-with-the-tsl2561-luminosity-sensor light.begin(); // The light sensor has a default integration time of 402ms, // and a default gain of low (1X). // If you would like to change either of these, you can // do so using the setTiming() command. // If gain = false (0), device is set to low gain (1X) // If gain = high (1), device is set to high gain (16X) gain = 1; // If time = 0, integration will be 13.7ms // If time = 1, integration will be 101ms // If time = 2, integration will be 402ms // If time = 3, use manual start / stop to perform your own integration time = 2; // setTiming() will set the third parameter (ms) to the // requested integration time in ms (this will be useful later): light.setTiming(gain, time, ms); if (light.setInterruptControl(1,2)) { Serial.println("TSL2561 interrupts set successfully"); } if (light.setInterruptThreshold(500, 1800)) { Serial.println("TSL2561 interrupts thresholds set successfully"); } // To start taking measurements, power up the sensor: light.setPowerUp(); // The sensor will now gather light during the integration time. // After the specified time, you can retrieve the result from the sensor. // Once a measurement occurs, another integration period will start. } void processLightLevel(void) { // Wait between measurements before retrieving the result // (You can also configure the sensor to issue an interrupt // when measurements are complete) // This sketch uses the TSL2561's built-in integration timer. // You can also perform your own manual integration timing // by setting "time" to 3 (manual) in setTiming(), // then performing a manualStart() and a manualStop() as in the below // commented statements: // ms = 1000; // light.manualStart(); //delay(ms); // light.manualStop(); // Once integration is complete, we'll retrieve the data. // There are two light sensors on the device, one for visible light // and one for infrared. Both sensors are needed for lux calculations. // Retrieve the data from the device: unsigned int data0, data1; if (light.getData(data0, data1)) { // getData() returned true, communication was successful #ifdef MY_DEBUGX Serial.print("data0: "); Serial.println(data0); Serial.print(" data1: "); Serial.println(data1); #endif if(data0>65000){ gain=0; light.setTiming(gain, time, ms); } if(data0<500){ gain=1; light.setTiming(gain, time, ms); } if (light.setInterruptThreshold(data0-(data0/100*10),data0+(data0/100*10))) { //light.setInterruptThreshold(data0-50,data0+50) Serial.println("TSL2561 interrupts thresholds set successfully"); } double lux; // Resulting lux value boolean good; // True if neither sensor is saturated // Perform lux calculation: good = light.getLux(gain, ms, data0, data1, lux); if (good) { #ifdef MY_DEBUGX Serial.print("lux: "); Serial.println(lux); Serial.print("mlux: "); Serial.println(mlux); Serial.print("lastLux: "); Serial.println(lastLux); Serial.print("gain: "); Serial.println(gain); #endif mlux = int(lux); // Lux value to be transmitted as integer if (isnan(mlux)) { Serial.println("Failed reading lightintensity from TSL2561!"); } else if (mlux != lastLux || nNoUpdatesTemp == FORCE_UPDATE_N_READS_L) { send(msgLight.set(mlux)); lastLux = mlux; #ifdef MY_DEBUG Serial.print("LightLevel: "); Serial.print(mlux); Serial.println(" lux"); #endif } else { // Increase no update counter if the humidity stayed the same nNoUpdatesLight++; } } } }
Defines (.h)
//** Define scetch name and version #define SKETCH_NAME "ID59_Kitchen_1(2*window)" #define Sketch_VERSION "V1.1" //** Enable debug prints #define MY_DEBUG #define MY_DEBUGX //** Define node ID #define MY_NODE_ID 59 //** Define child ID's #define CHILD_ID_BATT 0 #define CHILD_ID_HUM 1 #define CHILD_ID_TEMP 2 #define CHILD_ID_LIGHT 3 #define CHILD_ID_SWITCH1 4 #define CHILD_ID_SWITCH2 5 #define CHILD_ID_SWITCH3 6 #define CHILD_ID_SWITCH4 7 #define CHILD_ID_SWITCH5 8 #define CHILD_ID_SWITCH6 9 #define NR_OF_SWITCH 6 //Window_1+2 //** Define interrupt pins (doors & windows) #define INT_PIN1 2 #define INT_PIN2 3 #define INT_PIN3 5 #define INT_PIN4 6 #define INT_PIN5 7 #define INT_PIN6 8 #define PULL_UP_EN true //** Enable and select radio type attached #define MY_RADIO_NRF24 #define MY_RF24_CE_PIN 9 #define MY_RF24_CS_PIN 10 #define MY_RF24_PA_LEVEL RF24_PA_HIGH //** DHT defines // Set this to the pin you connected the DHT's data pin to #define DHT_DATA_PIN 4 // Set this offset if the sensor has a permanent small offset to the real temperatures #define SENSOR_TEMP_OFFSET 0
Globals (.h)
#include <DHT.h> #include <SparkFunTSL2561.h> #include <MySensors.h> enum { ON, OFF }; //** Define sleep time // Sleep time between sensor updates (in milliseconds) // Must be >1000ms for DHT22 and >2000ms for DHT11 static const uint64_t UPDATE_INTERVAL = 30000; //** Define force values // Force sending an update of the temperature after n sensor reads, so a controller showing the // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that // the value didn't change since; // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms] static const uint8_t FORCE_UPDATE_N_READS_T = 10; //Temperature force value static const uint8_t FORCE_UPDATE_N_READS_H = 10; //Humidity force value static const uint8_t FORCE_UPDATE_N_READS_L = 10; //LightLevel force value static const uint8_t FORCE_UPDATE_N_READS_B = 50; //Binairy force value // Vars for battery level measurement int batterySensePin = A0; int oldBatteryPcnt = 0; uint8_t nNoUpdatesBatt; // Vars for DHT sensor DHT dht; float lastTemp; float lastHum; uint8_t nNoUpdatesTemp; uint8_t nNoUpdatesHum; bool metric = true; //Vars for TSL2461 SFE_TSL2561 light; int lastLux; double lux; // Resulting lux value int mlux; boolean gain; // Gain setting, 0 = X1, 1 = X16; unsigned char time; unsigned int ms; // Integration ("shutter") time in milliseconds uint8_t nNoUpdatesLight; volatile boolean lightInterrupt=true; //Vars for DI's volatile byte tripped = 0; int intPin[] = {2, 3, 5, 6, 7, 8}; boolean currState[] = {OFF, OFF, OFF, OFF, OFF, OFF}; volatile boolean lastState[] = {OFF, OFF, OFF, OFF, OFF, OFF}; // Prepare messages for gateway MyMessage msgBatt(CHILD_ID_BATT, I_BATTERY_LEVEL); // Battery message MyMessage msgHum(CHILD_ID_HUM, V_HUM); // Humidity message MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); // Temperature message MyMessage msgLight(CHILD_ID_LIGHT, V_TEMP); // Lightlevel message MyMessage msgSwitch1(CHILD_ID_SWITCH1, V_TRIPPED); MyMessage msgSwitch2(CHILD_ID_SWITCH2, V_TRIPPED); MyMessage msgSwitch3(CHILD_ID_SWITCH3, V_TRIPPED); MyMessage msgSwitch4(CHILD_ID_SWITCH4, V_TRIPPED); MyMessage msgSwitch5(CHILD_ID_SWITCH5, V_TRIPPED); MyMessage msgSwitch6(CHILD_ID_SWITCH6, V_TRIPPED);
-
@jimmy-loyens I haven't analyzed everyhing you posted, but calling send from within an ISR will not work. Send will need to communicate over SPI which will be problematic when clocks and interrupts are disabled.
So you'll need to refactor the code. That doesn't explain why sleep isn't woken up by the interrupts though.
-
@jimmy-loyens Oh I see now, ....
the node isn't waking up by any of my interrupt vectors. GetDigital does more then just getting the interrupt pin, it allso sends a message inside the ISR. Thats why status changes on digital pins are sent immediatly. the node never wakes up to send them its handeled by the interrupt!!!
This is not possible for my lightsensor (evaluate & send mssg in ISR) because this uses functions (i think). Is the sleep function expecting interrupt pins on the 'interrupt1' & 'interrupt2' parameters? Does anyone have an idea for a workaround? I have about 50 of these pcb's so its a little late for a re-design
-
@mfalkvidd For the digital pins send seems to work just fine, as long as i don't use any functions inside the ISR
-
These mssges where all sent from within ISR:
Pin 2 triggered: 0 8417 !TSF:MSG:SEND,59-59-0-0,s=4,c=1,t=16,pt=1,l=1,sg=0,ft=0,st=NACK:0 Pin 2 triggered: 1 8419 !TSF:MSG:SEND,59-59-0-0,s=4,c=1,t=16,pt=1,l=1,sg=0,ft=1,st=NACK:1 Pin 3 triggered: 0 8421 TSF:MSG:SEND,59-59-0-0,s=5,c=1,t=16,pt=1,l=1,sg=0,ft=2,st=OK:0 Pin 3 triggered: 1 8423 !TSF:MSG:SEND,59-59-0-0,s=5,c=1,t=16,pt=1,l=1,sg=0,ft=0,st=NACK:1 8425 MCO:SLP:WUP=-1 8427 MCO:SLP:MS=30000,SMS=0,I1=114,M1=2,I2=75,M2=1 8433 MCO:SLP:TPD Pin 5 triggered: 0 8435 !TSF:MSG:SEND,59-59-0-0,s=6,c=1,t=16,pt=1,l=1,sg=0,ft=1,st=NACK:0 Pin 5 triggered: 1 8437 !TSF:MSG:SEND,59-59-0-0,s=6,c=1,t=16,pt=1,l=1,sg=0,ft=2,st=NACK:1 Pin 6 triggered: 0 8439 !TSF:MSG:SEND,59-59-0-0,s=7,c=1,t=16,pt=1,l=1,sg=0,ft=3,st=NACK:0 Pin 6 triggered: 1 8441 !TSF:MSG:SEND,59-59-0-0,s=7,c=1,t=16,pt=1,l=1,sg=0,ft=4,st=NACK:1 8443 MCO:SLP:WUP=-1 8445 MCO:SLP:MS=30000,SMS=0,I1=114,M1=2,I2=75,M2=1 8452 MCO:SLP:TPD Pin 7 triggered: 0 8454 !TSF:MSG:SEND,59-59-0-0,s=8,c=1,t=16,pt=1,l=1,sg=0,ft=5,st=NACK:0 Pin 7 triggered: 1 8456 !TSF:MSG:SEND,59-59-0-0,s=8,c=1,t=16,pt=1,l=1,sg=0,ft=6,st=NACK:1 8458 MCO:SLP:WUP=-1 8460 !TSM:READY:UPL FAIL,SNP
i think the NACK comes from triggering pins in fast tempo
-
The whole problem seems to originate from the node not waking up by the interruptvectors. If i can get the node to wake up by PCINT0_vect/PCINT1_vect/PCINT2_vect i can process data and send messages outside the ISR. I gues thats why i resorted to sending messages in ISR a year ago. Does anyone know how to wake the node by these interrupt vectors? maybe i can re-write the sleep function to do this?
-
I just found this post on the forum: https://forum.mysensors.org/topic/6352/pin-change-interrupt-on-any-pin/11
It adds "_wokeUpByInterrupt = 0xFE; // Dirty hack to get out of MySensors sleep loop" at the end of every ISR
and
"// Unset value from dirty hack to get out of sleep loop (set in interrupt)
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;" at the beginning of loop.I tried it, not knowing at all what i'm doing by adding these lines. But i do know it works!!! Even if it is a dirty hack, IT WORKS!!!!
Now i can rewrite my code to do the processing/messaging in loop outside of the ISR. If anyone can explane what these lines do exactly please let me know.
It would be even nicer if somewhere in the future there could be a sleep function in the MySensors library that supports these pinchange interrupt vectors, but this hack makes it work for now.
Thanks for all the help!