Hi,
I've been researching and struggling to get PCINT to wake ATmega328p from Sleep without resetting. Could really use some assistance in figuring this out. THANKS ahead of time!
Summary of Setup
- Two buttons (INT0, INT1)
- One Analog Input (In this example PCINT8)
(Final project will use PCINT13 so could use help in understanding specific addressing.)
Summary of Process
- After powerup, a voltage is checked via Analog Input.
- When no voltage to input, Atmeg is put to sleep after short delay
- Atmeg to be woken up by either of the three occurrences
-INT0 (Pin 2) WORKS!!
-INT1 (Pin 3) WORKS!!
-Voltage applied to Analog Input (PCINT) DOESN't WORK - When woken, want code to continue where left off WITHOUT resetting
ISSUE:
The PCINT8 (pin14) Resets whenever voltage is applied/removed regardless of Wake or Sleep status of ATmega
I know I'm messing this up, but just can't figure out where it's bugger'd.
Please, if anyone can help, sure would appreciate it!
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <RBD_Timer.h>
#include <RBD_Button.h>
RBD::Button LTsw(2); //Left Button
RBD::Button RTsw(3); //Right Button
const byte LED = 13;
static const int RTPos = 6; //V
static const int LTPos = 7; //PK
static const int IGN = A0; //R/Y (Analog input sensing when Ignition is on/off)
boolean IGNOFF = 0; //Ignition power status
boolean PwrDwn = 0; //Power Down pending status (0=Not powering down, 1=powering down)
boolean Status = 0;
unsigned long PWROFFtime; //time to initiate Power Down Mode
unsigned long PWROFFint = 3000; //Interval to stay awake
int INT0_interrupt_flag;
int INT1_interrupt_flag;
// turn off interrupts until we are ready
ISR (PCINT8_vect)
{
PCICR = 0; // cancel pin change interrupts
}
void setup () {
Serial.begin(19200); while (!Serial);
pinMode(RTPos, OUTPUT); //Right LED
pinMode(LTPos, OUTPUT); //Left LED
RTsw.setDebounceTimeout(40);
LTsw.setDebounceTimeout(40);
PWROFFtime = millis() + PWROFFint; //Set Power Down Time
PCMSK1 |= bit (PCINT8); // pin change interrupt mask A0 (ProMini Pin 14)
detachInterrupt (0);
detachInterrupt (1);
Startup (); //flashes LEDs
}
void wake (){
sleep_disable(); // cancel sleep as a precaution
// Not sure which to use to disable ALL PCInt Interrupts
// PCMSK = 0x00; // Is this how to Disable all PCInt Interrupts ???
// PCMSK &= ~(1<<PCINT8); // Is this how to Disable PCInt8 Interrupt ???
detachInterrupt (0);
detachInterrupt (1);
power_all_enable();
ADCSRA |= (1 << 7); // enable ADC
// precautionary while we do other stuff
PCICR = 0; // cancel pin change interrupts
}
void sleep(){
ADCSRA &= ~(1 << 7); // disable ADC
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
noInterrupts (); // Do not interrupt before we go to sleep, or the
// ISR will detach interrupts and we won't wake.
attachInterrupt (0, INT0_isr, FALLING); //will be called when pin INT0 goes low - WORKS FINE
attachInterrupt (1, INT1_isr, FALLING); //will be called when pin INT0 goes low - WORKS FINE
PCIFR |= bit (PCIF1); // clear any outstanding interrupts
PCICR |= bit (PCIE1); // enable pin change interrupts
EIFR = bit (INTF0); // clear flag for interrupt 0
EIFR = bit (INTF1); // clear flag for interrupt 0
MCUCR = bit (BODS) | bit (BODSE); // turn off brown-out enable in software
MCUCR = bit (BODS);
interrupts ();
sleep_cpu ();
}
void loop (){
if (analogRead(IGN) <= 400){ //Check if Ignition voltage is off
IGNOFF = 1; //Set Ignition Status OFF
if (Status == 0){ //Check if Routine is running
if (PwrDwn == 0){ //Check if Powering Down Status already set
PWROFFtime = millis() + PWROFFint; //Set Power Down Time
PwrDwn = 1; //Set Powering Down Status YES
} else {
SerPrint();
digitalWrite (LED, HIGH); delay (400);
digitalWrite (LED, LOW); delay (100);
if (millis() >= PWROFFtime){ //Check Power Down Time
sleep(); //Go to sleep!
wake (); //Waking up!
Serial.println("I'M AWAKE");
IGNOFF = 0; //Set Ignition Status ON
PwrDwn = 0; //Powering Down Status NO
SerPrint();
} //End PWROFFtime
} //end of PwrDwn check
} else { //Routine is ON, don't sleep, keep flashing with IGN off
digitalWrite (LED, HIGH); delay (100);
digitalWrite (LED, LOW); delay (50);
} //end of Status check
} else {
SerPrint();
IGNOFF = 0; //Set Ignition Status ON
PwrDwn = 0; //Powering Down Status NO
digitalWrite (LED, HIGH); delay (100); //Slower Flashing to indicate Powering Down
digitalWrite (LED, LOW); delay (50);
} //end IGN check
switch (Status) {
case 0:
break;
case 1: //LED Flashing Routine
digitalWrite (RTPos, HIGH); delay (100);
digitalWrite (RTPos, LOW); delay (50);
digitalWrite (RTPos, HIGH); delay (100);
digitalWrite (RTPos, LOW); delay (50);
}
SerPrint();
// Button Selection Routines
if (LTsw.onPressed()) {
Status = 1; //Turns LED Routine on
digitalWrite (RTPos, HIGH); delay (100);
digitalWrite (RTPos, LOW); delay (50);
}
if (RTsw.onPressed()) {
Status = 0; //Turns LED Routine off
digitalWrite (LTPos, HIGH); delay (100);
digitalWrite (LTPos, LOW); delay (50);;
}
} //end of main loop
void INT0_isr(){
detachInterrupt(0);
INT0_interrupt_flag = 1;
}
void INT1_isr(){
detachInterrupt(0);
INT1_interrupt_flag = 1;
}
void Startup (){ //LED Flashing sequence at Startup
digitalWrite (RTPos, HIGH); digitalWrite (LTPos, HIGH); delay (50);
digitalWrite (RTPos, LOW); digitalWrite (LTPos, LOW); delay (50);
digitalWrite (RTPos, HIGH); digitalWrite (LTPos, HIGH); delay (50);
digitalWrite (RTPos, LOW); digitalWrite (LTPos, LOW); delay (200);
digitalWrite (RTPos, HIGH); digitalWrite (LTPos, HIGH); delay (50);
digitalWrite (RTPos, LOW); digitalWrite (LTPos, LOW); delay (50);
digitalWrite (RTPos, HIGH); digitalWrite (LTPos, HIGH); delay (50);
digitalWrite (RTPos, LOW); digitalWrite (LTPos, LOW); delay (50);
}
void SerPrint()
{
Serial.print(Status); Serial.print('\t');
Serial.print(IGNOFF); Serial.print('\t');
Serial.print(PwrDwn); Serial.print('\t');
Serial.print(analogRead(IGN)); Serial.println('\r');
} //End of SerPrint