Hi Gurus,
Here is my code for low-power device, atTiny 25/45/85.
It sleeps until wakes up with PCINT. I use PB3 and PB4 INTs,
pins 2 and 3 on chip. When it wakes, it moves to WDT-mode,
causing LED blink every 8 sec.
Power consumption before wake-up is round 0,1uA, and in
WDT-mode round 6uA: quite good, I assume.
BUT: I would like do different things if wake-up signal (grounding
PB3 or PB4) occurs. Only thing seems to be, that both INTs are
triggering function ISR (PCINT0_vect). I have tried ISR(PCINT...younameit)
but grounding PB3 or PB4 allways goes to ISR(PCINT0_vect).
It would be very nice to have own ISR-handlers for PB3 and PB4
caused interrupts. This is the core of my question. I have googled
around and tested some codes without success - so please don't send me
links (which I already have tested).
Any ideas to split functionality? In my application PB4 is the
trigger for certain action, PB3 should be battery monitor (I use
NCP301-series voltage monitor there).
Following code is mostly adapted/stolen/modified from
Nick Gammon's great site. AND: I only use AtTiny25 for
this project, so don't advise me on 328 or AtMega.
I need help with AtTiny25 now. Thanks in advance, -kari
#include <avr/sleep.h> // Sleep Modes
#include <avr/power.h> // Power management
#include <avr/wdt.h> // Watchdog timer
#include <avr/interrupt.h>
#include<avr/io.h>
const byte LED = PB0; // pin 5
const byte POWER = PB3; // pin2 /
const byte SWITCH = PB4; // pin 3 /
static int battLow=0, water=0;
void ledBlink()
{
detachInterrupt(0);
do
{
digitalWrite (LED, HIGH);
delay (100);
digitalWrite (LED, LOW);
delay (100);
goToSleep();
} while (true);
}
ISR (PCINT0_vect)
{
ledBlink();
} // end of PCINT0_vect
// watchdog interrupt
ISR (WDT_vect)
{
wdt_disable(); // disable watchdog
} // end of WDT_vect
void setup ()
{
resetWatchdog (); // do this first in case WDT fires
wdt_disable(); // disable watchdog
pinMode (LED, OUTPUT);
pinMode (SWITCH, INPUT);
pinMode (POWER, INPUT);
digitalWrite (SWITCH, HIGH); // internal pull-up
digitalWrite (POWER, HIGH); // internal pull-up
GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
PCMSK |= _BV(PCINT4); // Use PB4 as interrupt pin
GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
PCMSK |= _BV(PCINT3); // Use PB3 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
goToSleep();
} // end of setup
void resetWatchdog ()
{
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset, clear existing interrupt
WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
// set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay
// pat the dog
wdt_reset();
} // end of resetWatchdog
void loop ()
{
} // end of loop
void goToSleep ()
{
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
ADCSRA = 0; // turn off ADC
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
noInterrupts (); // timed sequence coming up
resetWatchdog (); // get watchdog ready
sleep_enable (); // ready to sleep
interrupts (); // interrupts are required now
sleep_cpu (); // sleep
sleep_disable (); // precaution
power_all_enable (); // power everything back on
} // end of goToSleep