Interrupt and sleep
-
I checked the used versions - as I already wrote the used arduino-IDE is 1.6.8. But due to the case that I used 1.8.0 before and downgraded the board definition by "Board manager" the board definition is 1.6.11 (if you down/upgrade by BoardManager you can find the files in dir "C:\Users...\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.11"
I added my own definitions to board.txt (because I use 2AA Battery node -> https://www.openhardware.io/view/10/My-Slim-2AA-Battery-Node)here my quick and dirty source - have to clean up if it works as expected:
// --------------------------------------------------------- // based on 2AA Battery Node // ATMEGA328P (@ internal OSC 1MHz) // device ID = 0x07D5 (2005d ) // --------------------------------------------------------- // 0 - Input 0 -> S_DOOR / V_TRIPPED // 1 - Input 1 -> S_DOOR / V_TRIPPED // 2 - temperature (HTU) // 3 - humidity (HTU) // --------------------------------------------------------- // --------------------------------------------------------- // includes // --------------------------------------------------------- #include <Wire.h> #include "Adafruit_HTU21DF.h" #include <Vcc.h> #include <avr/wdt.h> // --------------------------------------------------------- // MySensors // --------------------------------------------------------- #define MY_RADIO_NRF24 #define MY_RF24_PA_LEVEL RF24_PA_MAX #include <MySensors.h> #include <SPI.h> // --------------------------------------------------------- // MySensor // --------------------------------------------------------- #define SN "AA - Windows / Temperature" #define SV "1.1" #define ms_input_0 0 #define ms_input_1 1 #define ms_temperature 2 #define ms_humidity 3 // --------------------------------------------------------- // used PINs // --------------------------------------------------------- #define PIN_INPUT_0 2 #define PIN_INPUT_1 3 // --------------------------------------------------------- // Sleep // --------------------------------------------------------- #define SLEEP_TIME 300000 // ms => 5 min #define VALUE_MIN_COUNT 12 // send min every 12th measurement one value (once per hour) // --------------------------------------------------------- // Vcc // --------------------------------------------------------- #define VCC_MIN 1.9 #define VCC_MAX 3.3 #define BATTERY_COUNT 288 // 288 * 5 min = 1 day // --------------------------------------------------------- // global vars // --------------------------------------------------------- MyMessage msg(0,0); Adafruit_HTU21DF htu = Adafruit_HTU21DF(); boolean htu_available = false; float htu_temperature = 1000; float htu_humidity = 1000; int batteryCnt = 0; int temperatureCnt = 0; int humidityCnt = 0;; Vcc vcc; // ######################################################### // setup // ######################################################### void setup() { // --------- // PINs // --------- pinMode(PIN_INPUT_0, INPUT_PULLUP); pinMode(PIN_INPUT_1, INPUT_PULLUP); // --------- // HTU21 // --------- if (htu.begin()) htu_available = true; } // ######################################################### // presentation // ######################################################### void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo(SN, SV); // Send sensor information present(ms_input_0, S_DOOR); present(ms_input_1, S_DOOR); if(htu_available) { present(ms_temperature, S_TEMP); present(ms_humidity, S_HUM); } } // ######################################################### // loop // ######################################################### void loop() { // enable watchdog wdt_enable(WDTO_8S); // ------------- // inputs // ------------- sendInput0(); sendInput1(); // ------------- // check battery // ------------- if(batteryCnt == 0) sendBatteryReport(); batteryCnt++; if(batteryCnt > BATTERY_COUNT) batteryCnt = 0; // ------------- // temperature // ------------- if(htu_available) { sendTemperature(); sendHumidity(); } // ------------- // sleep // ------------- delay(500); wdt_disable(); sleep(digitalPinToInterrupt(PIN_INPUT_0), CHANGE, digitalPinToInterrupt(PIN_INPUT_1), CHANGE, SLEEP_TIME); } // ######################################################### // helper functions // ######################################################### float rfloat(float val, unsigned int num) { if(num) { float f = 10.0 * num; return round(val*f)/f; } else return round(val); } void sendTemperature() { wdt_reset(); float tmp = htu.readTemperature(); if(tmp < 900){ // check errors tmp = rfloat(tmp, 1); if((tmp != htu_temperature) || (temperatureCnt >= VALUE_MIN_COUNT)){ htu_temperature = tmp; send(msg.setSensor(ms_temperature).setType(V_TEMP).set(htu_temperature,1)); temperatureCnt = 0; } else temperatureCnt++; } } void sendHumidity() { wdt_reset(); float tmp = htu.readHumidity(); if(tmp < 900){ // check errors tmp = rfloat(tmp, 0); if((tmp != htu_humidity) || (humidityCnt >= VALUE_MIN_COUNT)){ htu_humidity = tmp; send(msg.setSensor(ms_humidity).setType(V_HUM).set(htu_humidity,0)); humidityCnt = 0; } else humidityCnt++; } } void sendBatteryReport() { wdt_reset(); delay(500); float p = vcc.Read_Perc(VCC_MIN, VCC_MAX, true); int batteryPcnt = static_cast<int>(p); sendBatteryLevel(batteryPcnt); } void sendInput0() { wdt_reset(); if(digitalRead(PIN_INPUT_0) == HIGH) send(msg.setSensor(ms_input_0).setType(V_TRIPPED).set(0)); else send(msg.setSensor(ms_input_0).setType(V_TRIPPED).set(1)); } void sendInput1() { wdt_reset(); if(digitalRead(PIN_INPUT_1) == HIGH) send(msg.setSensor(ms_input_1).setType(V_TRIPPED).set(0)); else send(msg.setSensor(ms_input_1).setType(V_TRIPPED).set(1)); }``` -
I checked the used versions - as I already wrote the used arduino-IDE is 1.6.8. But due to the case that I used 1.8.0 before and downgraded the board definition by "Board manager" the board definition is 1.6.11 (if you down/upgrade by BoardManager you can find the files in dir "C:\Users...\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.11"
I added my own definitions to board.txt (because I use 2AA Battery node -> https://www.openhardware.io/view/10/My-Slim-2AA-Battery-Node)here my quick and dirty source - have to clean up if it works as expected:
// --------------------------------------------------------- // based on 2AA Battery Node // ATMEGA328P (@ internal OSC 1MHz) // device ID = 0x07D5 (2005d ) // --------------------------------------------------------- // 0 - Input 0 -> S_DOOR / V_TRIPPED // 1 - Input 1 -> S_DOOR / V_TRIPPED // 2 - temperature (HTU) // 3 - humidity (HTU) // --------------------------------------------------------- // --------------------------------------------------------- // includes // --------------------------------------------------------- #include <Wire.h> #include "Adafruit_HTU21DF.h" #include <Vcc.h> #include <avr/wdt.h> // --------------------------------------------------------- // MySensors // --------------------------------------------------------- #define MY_RADIO_NRF24 #define MY_RF24_PA_LEVEL RF24_PA_MAX #include <MySensors.h> #include <SPI.h> // --------------------------------------------------------- // MySensor // --------------------------------------------------------- #define SN "AA - Windows / Temperature" #define SV "1.1" #define ms_input_0 0 #define ms_input_1 1 #define ms_temperature 2 #define ms_humidity 3 // --------------------------------------------------------- // used PINs // --------------------------------------------------------- #define PIN_INPUT_0 2 #define PIN_INPUT_1 3 // --------------------------------------------------------- // Sleep // --------------------------------------------------------- #define SLEEP_TIME 300000 // ms => 5 min #define VALUE_MIN_COUNT 12 // send min every 12th measurement one value (once per hour) // --------------------------------------------------------- // Vcc // --------------------------------------------------------- #define VCC_MIN 1.9 #define VCC_MAX 3.3 #define BATTERY_COUNT 288 // 288 * 5 min = 1 day // --------------------------------------------------------- // global vars // --------------------------------------------------------- MyMessage msg(0,0); Adafruit_HTU21DF htu = Adafruit_HTU21DF(); boolean htu_available = false; float htu_temperature = 1000; float htu_humidity = 1000; int batteryCnt = 0; int temperatureCnt = 0; int humidityCnt = 0;; Vcc vcc; // ######################################################### // setup // ######################################################### void setup() { // --------- // PINs // --------- pinMode(PIN_INPUT_0, INPUT_PULLUP); pinMode(PIN_INPUT_1, INPUT_PULLUP); // --------- // HTU21 // --------- if (htu.begin()) htu_available = true; } // ######################################################### // presentation // ######################################################### void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo(SN, SV); // Send sensor information present(ms_input_0, S_DOOR); present(ms_input_1, S_DOOR); if(htu_available) { present(ms_temperature, S_TEMP); present(ms_humidity, S_HUM); } } // ######################################################### // loop // ######################################################### void loop() { // enable watchdog wdt_enable(WDTO_8S); // ------------- // inputs // ------------- sendInput0(); sendInput1(); // ------------- // check battery // ------------- if(batteryCnt == 0) sendBatteryReport(); batteryCnt++; if(batteryCnt > BATTERY_COUNT) batteryCnt = 0; // ------------- // temperature // ------------- if(htu_available) { sendTemperature(); sendHumidity(); } // ------------- // sleep // ------------- delay(500); wdt_disable(); sleep(digitalPinToInterrupt(PIN_INPUT_0), CHANGE, digitalPinToInterrupt(PIN_INPUT_1), CHANGE, SLEEP_TIME); } // ######################################################### // helper functions // ######################################################### float rfloat(float val, unsigned int num) { if(num) { float f = 10.0 * num; return round(val*f)/f; } else return round(val); } void sendTemperature() { wdt_reset(); float tmp = htu.readTemperature(); if(tmp < 900){ // check errors tmp = rfloat(tmp, 1); if((tmp != htu_temperature) || (temperatureCnt >= VALUE_MIN_COUNT)){ htu_temperature = tmp; send(msg.setSensor(ms_temperature).setType(V_TEMP).set(htu_temperature,1)); temperatureCnt = 0; } else temperatureCnt++; } } void sendHumidity() { wdt_reset(); float tmp = htu.readHumidity(); if(tmp < 900){ // check errors tmp = rfloat(tmp, 0); if((tmp != htu_humidity) || (humidityCnt >= VALUE_MIN_COUNT)){ htu_humidity = tmp; send(msg.setSensor(ms_humidity).setType(V_HUM).set(htu_humidity,0)); humidityCnt = 0; } else humidityCnt++; } } void sendBatteryReport() { wdt_reset(); delay(500); float p = vcc.Read_Perc(VCC_MIN, VCC_MAX, true); int batteryPcnt = static_cast<int>(p); sendBatteryLevel(batteryPcnt); } void sendInput0() { wdt_reset(); if(digitalRead(PIN_INPUT_0) == HIGH) send(msg.setSensor(ms_input_0).setType(V_TRIPPED).set(0)); else send(msg.setSensor(ms_input_0).setType(V_TRIPPED).set(1)); } void sendInput1() { wdt_reset(); if(digitalRead(PIN_INPUT_1) == HIGH) send(msg.setSensor(ms_input_1).setType(V_TRIPPED).set(0)); else send(msg.setSensor(ms_input_1).setType(V_TRIPPED).set(1)); }``` -
@JoergP ans others, I have tried versions 1.6.8 and the board definitions 1.6.11 and interrupt seems to work but in the case of using a PIR the sensor somehow seems to be triggered when going out of sleep due to time...
-
@Efflon I'm not sure what exactly you mean - do you refer to my code? In that case this is a quick and dirty try - I'll send at every pin change and at timeout the input values ...
@JoergP Sorry, what I meant was regarding the versions you were using to get your sensor to work. I've been fighting to get interrupts to work for a day and your suggestion helped.
Now it's just that going out of sleep triggers the PIR, then it goes for sleep and wakes up immediately and then finally goes to sleep ... gahhTripped: 0 13207 MCO:SLP:MS=30000,SMS=0,I1=1,M1=3,I2=255,M2=255 13213 MCO:SLP:TPD 13217 MCO:SLP:WUP=-1 interrupt: -1 Tripped: 0 Tripped: 1 Tripped: 1 Tripped: 1 Tripped: 1 interrupt: -1 Tripped: 1 Tripped: 0 Tripped: 0 Tripped: 0 Tripped: 0 14024 MCO:SLP:MS=30000,SMS=0,I1=1,M1=3,I2=255,M2=255 14032 MCO:SLP:TPD 14034 MCO:SLP:WUP=1 interrupt: 1 Tripped: 0 Tripped: 0 Tripped: 0 Tripped: 0 Tripped: 0 14440 MCO:SLP:MS=30000,SMS=0,I1=1,M1=3,I2=255,M2=255 14446 MCO:SLP:TPD``` -
hmmmm .... I'm not so familiar with the arduino build process - I guess that Interrupt Request registers are not reset correctly, but never did that manual with Arduino
I use following board setting
AAnode1.name=AA sensor node (1MHz int) AAnode1.upload.tool=avrdude AAnode1.upload.protocol=arduino AAnode1.upload.maximum_size=32256 AAnode1.upload.speed=9600 AAnode1.bootloader.tool=avrdude AAnode1.bootloader.low_fuses=0x62 AAnode1.bootloader.high_fuses=0xde AAnode1.bootloader.extended_fuses=0x07 AAnode1.bootloader.path=optiboot_v50 AAnode1.bootloader.unlock_bits=0x3F AAnode1.bootloader.lock_bits=0x2F AAnode1.build.mcu=atmega328p AAnode1.build.f_cpu=1000000L AAnode1.build.core=arduino AAnode1.build.variant=standard AAnode1.build.board=AVR_AANODE_1MHzI guess the xxx.build.xxx settings are of interest - do you use the same or do you have different?
-
hmmmm .... I'm not so familiar with the arduino build process - I guess that Interrupt Request registers are not reset correctly, but never did that manual with Arduino
I use following board setting
AAnode1.name=AA sensor node (1MHz int) AAnode1.upload.tool=avrdude AAnode1.upload.protocol=arduino AAnode1.upload.maximum_size=32256 AAnode1.upload.speed=9600 AAnode1.bootloader.tool=avrdude AAnode1.bootloader.low_fuses=0x62 AAnode1.bootloader.high_fuses=0xde AAnode1.bootloader.extended_fuses=0x07 AAnode1.bootloader.path=optiboot_v50 AAnode1.bootloader.unlock_bits=0x3F AAnode1.bootloader.lock_bits=0x2F AAnode1.build.mcu=atmega328p AAnode1.build.f_cpu=1000000L AAnode1.build.core=arduino AAnode1.build.variant=standard AAnode1.build.board=AVR_AANODE_1MHzI guess the xxx.build.xxx settings are of interest - do you use the same or do you have different?
-
my 2 cents :
Why are you doing a sleep into setup method?
why not using wait method instead?I understand that you'd like switch in sleep mode after a loop, but this doesnt sounds natural to do this during "initializing" step.
if you remove sleep from setup, do you still have your issues?
moreover, i've read somewhere that smartsleep methode gives messages time to be sent before sleeping (i'm not absolutly sure about this, i cannot find anymore the place where i've read that).
bool smartSleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0)
@params:
• interrupt: Pin that should trigger the wakeup
• mode: RISING, FALLING, CHANGE
• ms: Number of milliseconds to sleep or 0 to sleep forever
@return: True if wake up was triggered by pin change and false means timer woke it up.at last : you can wait for an aknownledge, it'll be slower but you'll be sure that message is sent before going to the next line of code...
i did not test it yet, but it would be something like this :
bool ack = true; send(myMsg.set(avalue), ack ); if(!wait(2000,V_TEMP , mymsg.getType());) Serial.println("timeout after 2 secs"); -
my 2 cents :
Why are you doing a sleep into setup method?
why not using wait method instead?I understand that you'd like switch in sleep mode after a loop, but this doesnt sounds natural to do this during "initializing" step.
if you remove sleep from setup, do you still have your issues?
moreover, i've read somewhere that smartsleep methode gives messages time to be sent before sleeping (i'm not absolutly sure about this, i cannot find anymore the place where i've read that).
bool smartSleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0)
@params:
• interrupt: Pin that should trigger the wakeup
• mode: RISING, FALLING, CHANGE
• ms: Number of milliseconds to sleep or 0 to sleep forever
@return: True if wake up was triggered by pin change and false means timer woke it up.at last : you can wait for an aknownledge, it'll be slower but you'll be sure that message is sent before going to the next line of code...
i did not test it yet, but it would be something like this :
bool ack = true; send(myMsg.set(avalue), ack ); if(!wait(2000,V_TEMP , mymsg.getType());) Serial.println("timeout after 2 secs");