diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index 55b15ee..e7002d5 100755 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -465,43 +465,49 @@ int MySensor::getInternalTemp(void) return result/10000; } -int continueTimer = true; +int8_t pinIntTrigger = 0; void wakeUp() //place to send the interrupts { - continueTimer = false; + pinIntTrigger = 1; +} +void wakeUp2() //place to send the second interrupts +{ + pinIntTrigger = 2; } void MySensor::internalSleep(unsigned long ms) { - while (continueTimer && ms >= 8000) { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); ms -= 8000; } - if (continueTimer && ms >= 4000) { LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); ms -= 4000; } - if (continueTimer && ms >= 2000) { LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF); ms -= 2000; } - if (continueTimer && ms >= 1000) { LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); ms -= 1000; } - if (continueTimer && ms >= 500) { LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); ms -= 500; } - if (continueTimer && ms >= 250) { LowPower.powerDown(SLEEP_250MS, ADC_OFF, BOD_OFF); ms -= 250; } - if (continueTimer && ms >= 125) { LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF); ms -= 120; } - if (continueTimer && ms >= 64) { LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); ms -= 60; } - if (continueTimer && ms >= 32) { LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_OFF); ms -= 30; } - if (continueTimer && ms >= 16) { LowPower.powerDown(SLEEP_15Ms, ADC_OFF, BOD_OFF); ms -= 15; } + while (!pinIntTrigger && ms >= 8000) { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); ms -= 8000; } + if (!pinIntTrigger && ms >= 4000) { LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); ms -= 4000; } + if (!pinIntTrigger && ms >= 2000) { LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF); ms -= 2000; } + if (!pinIntTrigger && ms >= 1000) { LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); ms -= 1000; } + if (!pinIntTrigger && ms >= 500) { LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); ms -= 500; } + if (!pinIntTrigger && ms >= 250) { LowPower.powerDown(SLEEP_250MS, ADC_OFF, BOD_OFF); ms -= 250; } + if (!pinIntTrigger && ms >= 125) { LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF); ms -= 120; } + if (!pinIntTrigger && ms >= 64) { LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); ms -= 60; } + if (!pinIntTrigger && ms >= 32) { LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_OFF); ms -= 30; } + if (!pinIntTrigger && ms >= 16) { LowPower.powerDown(SLEEP_15Ms, ADC_OFF, BOD_OFF); ms -= 15; } } void MySensor::sleep(unsigned long ms) { // Let serial prints finish (debug, log etc) Serial.flush(); RF24::powerDown(); - continueTimer = true; + pinIntTrigger = 0; internalSleep(ms); } -bool MySensor::sleep(int interrupt, int mode, unsigned long ms) { +bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { // Let serial prints finish (debug, log etc) bool pinTriggeredWakeup = true; Serial.flush(); RF24::powerDown(); - attachInterrupt(interrupt, wakeUp, mode); //Interrupt on pin 3 for any change in solar power + attachInterrupt(interrupt, wakeUp, mode); if (ms>0) { - continueTimer = true; + pinIntTrigger = 0; sleep(ms); - pinTriggeredWakeup = !continueTimer; + if (0 == pinIntTrigger) { + pinTriggeredWakeup = false; + } } else { Serial.flush(); LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); @@ -510,7 +516,32 @@ bool MySensor::sleep(int interrupt, int mode, unsigned long ms) { return pinTriggeredWakeup; } +int8_t MySensor::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { + int8_t retVal = 1; + Serial.flush(); // Let serial prints finish (debug, log etc) + RF24::powerDown(); + attachInterrupt(interrupt1, wakeUp, mode1); + attachInterrupt(interrupt2, wakeUp2, mode2); + if (ms>0) { + pinIntTrigger = 0; + sleep(ms); + if (0 == pinIntTrigger) { + retVal = -1; + } + } else { + Serial.flush(); + LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); + } + detachInterrupt(interrupt1); + detachInterrupt(interrupt2); + if (1 == pinIntTrigger) { + retVal = (int8_t)interrupt1; + } else if (2 == pinIntTrigger) { + retVal = (int8_t)interrupt2; + } + return retVal; +} #ifdef DEBUG void MySensor::debugPrint(const char *fmt, ... ) { diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index f6dbba1..a69e48c 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -219,7 +219,20 @@ class MySensor : public RF24 * @param 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. */ - bool sleep(int interrupt, int mode, unsigned long ms=0); + bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); + + /** + * Sleep (PowerDownMode) the Arduino and radio. Wake up on timer or pin change for two separate interrupts. + * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin + * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 + * @param interrupt1 First interrupt that should trigger the wakeup + * @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) + * @param interrupt2 Second interrupt that should trigger the wakeup + * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) + * @param ms Number of milliseconds to sleep or 0 to sleep forever + * @return Interrupt number wake up was triggered by pin change and negative if timer woke it up. + */ + int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); /** * getInternalTemp diff --git a/libraries/MySensors/examples/BinarySwitchSensorInt/BinarySwitchSensorInt.ino b/libraries/MySensors/examples/BinarySwitchSensorInt/BinarySwitchSensorInt.ino index 033b2f0..ff8637a 100644 --- a/libraries/MySensors/examples/BinarySwitchSensorInt/BinarySwitchSensorInt.ino +++ b/libraries/MySensors/examples/BinarySwitchSensorInt/BinarySwitchSensorInt.ino @@ -1,60 +1,90 @@ -// Interrupt driven binary switch example +// Interrupt driven binary switch example with dual interrupts // Author: Patrick 'Anticimex' Fallberg -// Connect button or door/window reed switch between -// digitial I/O pin 3 (BUTTON_PIN below) and GND. +// Connect one button or door/window reed switch between +// digitial I/O pin 3 (BUTTON_PIN below) and GND and the other +// one in similar fashion on digital I/O pin 2. // This example is designed to fit Arduino Nano/Pro Mini #include #include -#define CHILD_ID 3 -#define BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch +#define SKETCH_NAME "Binary Sensor" +#define SKETCH_MAJOR_VER "1" +#define SKETCH_MINOR_VER "0" -#if (BUTTON_PIN < 2 || BUTTON_PIN > 3) -#error BUTTON_PIN must be either 2 or 3 for interrupts to work +#define PRIMARY_CHILD_ID 3 +#define SECONDARY_CHILD_ID 4 + +#define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch +#define SECONDARY_BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch + +#if (PRIMARY_BUTTON_PIN < 2 || PRIMARY_BUTTON_PIN > 3) +#error PRIMARY_BUTTON_PIN must be either 2 or 3 for interrupts to work #endif - -MySensor gw; +#if (SECONDARY_BUTTON_PIN < 2 || SECONDARY_BUTTON_PIN > 3) +#error SECONDARY_BUTTON_PIN must be either 2 or 3 for interrupts to work +#endif +#if (PRIMARY_BUTTON_PIN == SECONDARY_BUTTON_PIN) +#error PRIMARY_BUTTON_PIN and BUTTON_PIN2 cannot be the same +#endif +#if (PRIMARY_CHILD_ID == SECONDARY_CHILD_ID) +#error PRIMARY_CHILD_ID and SECONDARY_CHILD_ID cannot be the same +#endif + +MySensor sensor_node; // Change to V_LIGHT if you use S_LIGHT in presentation below -MyMessage msg(CHILD_ID,V_TRIPPED); +MyMessage msg(PRIMARY_CHILD_ID, V_TRIPPED); +MyMessage msg2(SECONDARY_CHILD_ID, V_TRIPPED); void setup() { - gw.begin(); + sensor_node.begin(); - // Setup the button - pinMode(BUTTON_PIN,INPUT); - // Activate internal pull-up - digitalWrite(BUTTON_PIN,HIGH); + // Setup the buttons + pinMode(PRIMARY_BUTTON_PIN, INPUT); + pinMode(SECONDARY_BUTTON_PIN, INPUT); + + // Activate internal pull-ups + digitalWrite(PRIMARY_BUTTON_PIN, HIGH); + digitalWrite(SECONDARY_BUTTON_PIN, HIGH); // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Binary Sensor", "1.0"); + sensor_node.sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER); - // Register binary input sensor to gw (they will be created as child devices) + // Register binary input sensor to sensor_node (they will be created as child devices) // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. - gw.present(CHILD_ID, S_DOOR); + sensor_node.present(PRIMARY_CHILD_ID, S_DOOR); + sensor_node.present(SECONDARY_CHILD_ID, S_DOOR); } -// Loop will iterate on changes on the BUTTON_PIN +// Loop will iterate on changes on the BUTTON_PINs void loop() { uint8_t value; static uint8_t sentValue=2; + static uint8_t sentValue2=2; - // Short delay to allow button to properly settle - gw.sleep(5); + // Short delay to allow buttons to properly settle + sensor_node.sleep(5); - value = digitalRead(BUTTON_PIN); + value = digitalRead(PRIMARY_BUTTON_PIN); if (value != sentValue) { // Value has changed from last transmission, send the updated value - gw.send(msg.set(value==HIGH ? 1 : 0)); + sensor_node.send(msg.set(value==HIGH ? 1 : 0)); sentValue = value; } - // Sleep until something happens with the sensor - gw.sleep(BUTTON_PIN-2, CHANGE, 0); -} + value = digitalRead(SECONDARY_BUTTON_PIN); + + if (value != sentValue2) { + // Value has changed from last transmission, send the updated value + sensor_node.send(msg2.set(value==HIGH ? 1 : 0)); + sentValue2 = value; + } + // Sleep until something happens with the sensor + sensor_node.sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, 0); +}