Ok I might shorten my Question!
I can brake the problem down to a not correct wake by Serial Rx (PCI on Pin 0, on Mega PCINT8 on PCI1).
I took this Code on Sleep a ATtiny85 with WDT and Serial wake of Nick Gammon as a start and modified it to my ideas/needs to:
/*
* Original from Nick Gammon at http://gammon.com.au/forum/?id=11497&reply=6#reply6
* Changed by Jim Beam on 05/09/15 to work with Meag2560, changed toSleep Function
* Thanks to the guys of the Arduino Forum and Nick Gammon!
* To-DO: add Wake by Serial Rx (D0) by PCI, simplify more PCI Pins, disable more Hardware,
* set sleepMode for toSleep Function, Auomatic detect WDT Periodes and bytes,
* add setable ext-Hardware-FCN and setable int. Hwardware FCN
*/
#include <avr/sleep.h> // Sleep Modes
#include <avr/power.h> // Power management
#include <avr/wdt.h> // Watchdog timer
const byte LED = 12; // pin 13
const byte LEDWAKE = 13; // pin 13
const byte SWITCH = 10; // pin 10 / PCINT4
volatile bool sleep_enable = 1; // 0= stop sleeping, go back to loop, set 0 by any ISR
volatile bool serial_isr = 0; // Serial Rx isr was activ
ISR (PCINT0_vect) // Wake Pin 10
{
// do something interesting here
sleep_disable (); // precaution
wdt_disable();
sleep_enable = 0;
} // end of PCINT0_vect
ISR (PCINT1_vect) // Serial
{
// do something interesting here
sleep_disable (); // precaution
wdt_disable();
sleep_enable = 0;
serial_isr = 1;
} // end of PCINT0_vect
// watchdog interrupt
ISR (WDT_vect)
{
//wdt_disable(); // disable watchdog
} // end of WDT_vect
void setup ()
{
resetWatchdog (0b100001); // do this first in case WDT fires
pinMode (LED, OUTPUT);
pinMode (LEDWAKE, OUTPUT);
digitalWrite (LEDWAKE, HIGH);
Serial.begin(115200);
Serial.print(F("\n\nStarting...\n File: " __FILE__ "\n Date: " __DATE__ "\n Time: " __TIME__ "\n IDE : "));
Serial.println(ARDUINO);
Serial.println();
pinMode (SWITCH, INPUT);
digitalWrite (SWITCH, HIGH); // internal pull-up
//set PCI for Pin 0, Provide PCI ISR!!
// pin change interrupt (example for D0) Mega 2560! to Waik by Serial if wanted!
PCMSK1 |= bit (PCINT8); // want pin 0
PCIFR |= bit (PCIF1); // clear any outstanding interrupts
PCICR |= bit (PCIE1); // enable pin change interrupts for D0 to D7
PCMSK0 |= bit (PCINT4); // want pin 10
PCIFR |= bit (PCIF0); // clear any outstanding interrupts
PCICR |= bit (PCIE0); // enable pin change interrupts for D0 to D7
} // end of setup
void loop ()
{
Serial.print(F("\n Loop"));
checkSerial();
for(byte i=0;i<15;i++){
digitalWrite (LED, HIGH);
delay (100);
digitalWrite (LED, LOW);
delay (100);
}
doSerial();
Serial.flush();
goToSleep (15999L);
} // end of loop
void goToSleep (long msToSleep)
{
noInterrupts (); // timed sequence coming up
sleep_enable = 1;
byte old_ADCSRA = ADCSRA;
// disable ADC
ADCSRA = 0;
PCMSK1 |= bit (PCINT8); // want pin 0
PCIFR |= bit (PCIF1); // clear any outstanding interrupts
PCICR |= bit (PCIE1); // enable pin change interrupts for D0 to D7
interrupts (); // interrupts are required now
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
UCSR0B &= ~bit (RXEN0); // disable receiver
UCSR0B &= ~bit (TXEN0); // disable transmitter
wdtWhileLoop(msToSleep, 8000UL, 0b100001); //8Sec //Change: just give msToSleep, max WDT Periode and byte will be
//determined in FCN by switch case
wdtWhileLoop(msToSleep, 1000UL, 0b000110); //1Sec
wdtWhileLoop(msToSleep, 128UL, 0b000011); //128ms
wdtWhileLoop(msToSleep, 16UL, 0b000000); //16ms
// now disable wdt once ( not in wdt isr) is that ok so?
wdt_disable();
power_all_enable (); // power everything back on
ADCSRA = old_ADCSRA;
PCICR &= ~bit (PCIE1); // disable pin change interrupts for Serial D0 Pin0 (Mega)
UCSR0B |= bit (RXEN0); // enable receiver
UCSR0B |= bit (TXEN0); // enable transmitter
} // end of goToSleep
void wdtWhileLoop(long &msToSleep, int wdtPeriodeMs, byte wdtPeriodeByte){
//Change: just give msToSleep, max WDT Periode and byte will be
//determined in FCN by switch case
noInterrupts (); // timed sequence coming up
resetWatchdog (wdtPeriodeByte); // get watchdog ready
bool sleep_enable_c = sleep_enable;
interrupts (); // interrupts are required now
while((msToSleep >= wdtPeriodeMs) && sleep_enable_c){
msToSleep -= wdtPeriodeMs;
noInterrupts (); // timed sequence coming up
digitalWrite (LEDWAKE, LOW);
sleep_enable (); // ready to sleep
interrupts (); // interrupts are required now
sleep_cpu (); //
sleep_disable (); // precaution
digitalWrite (LEDWAKE, HIGH);
noInterrupts (); // timed sequence coming up
sleep_enable_c = sleep_enable;
interrupts (); // interrupts are required now
}//while
}
void resetWatchdog (byte interval)
{
//byte interval = 0b100001; //8sec
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = bit (WDCE) | bit (WDE);
// set interrupt mode and an interval
WDTCSR = bit (WDIE) | interval; // set WDIE, and requested delay
wdt_reset(); // pat the dog, only 1.st time needed? is it possible to let it running while in
//sleep-loops??
} // end of resetWatchdog
void doSerial(){
Serial.println();
Serial.print(F("Echo: "));
while(Serial.available()){
Serial.print(Serial.read());
}
Serial.println();
}
void checkSerial(){
noInterrupts ();
bool serial_isr_c = serial_isr;
interrupts ();
if(serial_isr_c){
noInterrupts ();
serial_isr = 0;;
interrupts ();
Serial.println(F("\nWoke by Serial. pls. reenter Command now within 3 sec."));
}
}
But now it seems to just skip one WDT-Sleep period if receiving Serial, but not stopping entire sleep period. But with the PCI from switch it does skip recent entire sleep periode and goes back to loop. What is the Error?
Thanks a lot! 