#include #include #include #include // Utility macros #define adc_disable() (ADCSRA &= ~_BV(ADEN)) // disable ADC (before power-off) #define adc_enable() (ADCSRA |= _BV(ADEN)) // re-enable ADC #define enable_pin_interrupts() (GIMSK |= _BV(PCIE)) // Enable Pin Change Interrupts // Pins #define SWITCH 0 #define SENDER 2 #define CONTROLLER 4 #define SENSOR_ID 3 RCSwitch mySwitch = RCSwitch(); int counter = 0; void setup() { pinMode(SWITCH, INPUT_PULLUP); pinMode(CONTROLLER, OUTPUT); digitalWrite(CONTROLLER, HIGH); mySwitch.enableTransmit(SENDER); mySwitch.setProtocol(2); sendWindowState(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); enable_pin_interrupts(); enableWdt(); } void loop() { sleep(); } bool readState() { digitalWrite(CONTROLLER, LOW); bool state = digitalRead(SWITCH); digitalWrite(CONTROLLER, HIGH); return state; } void sendWindowState() { unsigned long value = 0x70000000; value |= readVcc() << 6; value |= !readState() << 5; value |= SENSOR_ID; mySwitch.send(value, 32); } void sleep() { PCMSK |= _BV(PCINT0); // Use PB0 as interrupt pin adc_disable(); sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) sei(); // Enable interrupts sleep_cpu(); // sleep cli(); // Disable interrupts PCMSK &= ~_BV(PCINT0); // Turn off PB0 as interrupt pin sleep_disable(); // Clear SE bit adc_enable(); sei(); // Enable interrupts } ISR(PCINT0_vect) { sendWindowState(); delay(5000); sendWindowState(); } ISR(WDT_vect) { counter++; if (counter % 220 == 0) { counter = 0; sendWindowState(); delay(10000); sendWindowState(); } } //enable the wdt for 8sec interrupt void enableWdt() { MCUSR = 0x00; WDTCR |= _BV(WDCE) | _BV(WDE); WDTCR = _BV(WDIE) | _BV(WDP3) | _BV(WDP0); //8192ms } long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }