I want RF 434MHz RF transmitter (via virtualwire) to transmit a message whenever an interrupt pin's state is changed. Rest of the time it is expected to sleep.
Interrupt works fine when I am attaching interrupt to "LOW" but it doesn't work on "CHANGE". What is the timing criteria for the CHANGE interrupt??? What am I doing wrong... Please help! (FYI... I am using this code on ATMega8 if it makes any difference)
#include <VirtualWire.h> //load virtual wire library for RF communication
#include <avr/sleep.h> //load sleep library to allow the Ardunio to go to sleep
const int TxPin = 10;
const int Tx_en_pin = 11;
const int ReedSwitch = 2; //Reed switch
char msgopen[] = "O\n";
char msgclose[] = "C\n";
int DoorState = 0; //current state of the Door
int count = 3; //timer
void setup()
{
//ADCSRA |= (0 << ADEN); //Disabling ADC
vw_set_tx_pin(TxPin);
vw_set_ptt_pin(Tx_en_pin);
vw_setup(2000); //Virtual wire bits per sec
pinMode(ReedSwitch, INPUT_PULLUP);
attachInterrupt(0, wakeUpNow, CHANGE); //either 0 or 1 for interrupts on pin 2 or 3.
}
void loop()
{
DoorState = digitalRead(ReedSwitch); //read Door State
if (DoorState == LOW) //if door is close the reed switch goes low
{
count--; //count down
if (count == 0) //when counter is 0 send analog value then go to sleep
{
vw_send((uint8_t *)msgclose, strlen(msgclose));
vw_wait_tx(); // Wait until the whole message is gone
count = 3;
sleepNow(); // sleep function called here
}
}
else
{
count = 3; //reset counter to 3
vw_send((uint8_t *)msgopen, strlen(msgopen));
vw_wait_tx(); // Wait until the whole message is gone
sleepNow();
}
}
void sleepNow() // here we put the Ardunio to sleep
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0, wakeUpNow, CHANGE);
sleep_mode();
sleep_disable();
detachInterrupt(0);
}
void wakeUpNow() // here the interrupt is handled after wakeup
{
}
I updated the code to moving functions sleep_disable() and detachInterrupt(0) to the ISR.
So, once you go to sleep, there should be some kind of external interrupt to wake you up. When that happens, you want to disable the interrupt permanently. So, next time you go to sleep, you can't be awakened.
I'm failing to understand that. Must be a weekend thing. Set the alarm. Wake up when it goes off. Smash the alarm into bits. Go back to sleep. Forever.
So, once you go to sleep, there should be some kind of external interrupt to wake you up. When that happens, you want to disable the interrupt permanently. So, next time you go to sleep, you can't be awakened.
This is not right... If you look at the code carefully... When I call the sleepNow() function, the interrupt gets attached again. I disabled sleep in ISR (wakeUpNow() function) , detachInterrupt() in loop. After doing whatever activity in the loop, I attach interrupts again before entering sleep.
void sleepNow() // here we put the Ardunio to sleep
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0, wakeUpNow, CHANGE);
sleep_mode();
}
void wakeUpNow() // here the interrupt is handled after wakeup
{
sleep_disable();
}
void loop()
{
detachInterrupt(0);
//do whatever else you want...
sleepNow();
}
This scheme works perfectly for when the interrupt goes LOW. I checked that it goes to sleep by current consumption measurement and wakes up every time the interrupt goes LOW and does the job in the loop goes back to sleep. It wakes up every single time!
I believe the problem is with not having an external pull up resistor at the interrupt to detect "CHANGE". ( I am currently use internal pull-up by defining the pin as INPUT_PULLUP)