I'm building a SHT21 based sensor which runs off a CR2032 battery, so I need it to sleep most of the time.
With that in mind, I found a way of sleeping the 'tiny and waking every x seconds using the built in watchdog timer. Perfect.... or so I thought.
I'm using a SRF radio which uses serial. Because I didn't think through the design of my PCB well enough, I've managed to tie the receive pin from the SRF to the external interrupt pin on the 'tiny. As a result, when there is any traffic on the SRF, it sets the pin low and wakes up the MCU. I haven't defined any external interrupts, and this functionality is unwanted.
Is there any way to disabled external interrupts completely, while still allowing the watchdog interrupt to work?
Normally the SRF will be disabled and so it won't be receiving data, but I wanted to know whether its possible to disable this functionality anyway
This is my current testing code:
// Software serial
#include <SoftwareSerial.h>
#define RXPIN 3
#define TXPIN 2
SoftwareSerial mySerial (RXPIN, TXPIN);
// Low power
#include <avr/sleep.h> //Needed for sleep_mode
#include <avr/wdt.h> //Needed to enable/disable watch dog timer
// Sleep variables
volatile boolean f_wdt = 1;
volatile int watch_dog_counter = 0;
int sleep_loops = 0;
int awake_loops = 0;
// Missing for ATtiny44, 84
#ifndef WDTCR
#define WDTCR _SFR_IO8(0x21)
#endif
ISR(WDT_vect) {
watch_dog_counter++;
f_wdt = 1;
}
void setup() {
// Setup serial
mySerial.begin(9600);
mySerial.println("STARTING");
// Setup sleep watchdog
setup_watchdog(6);
}
void loop() {
if (f_wdt == 1) {
f_wdt = 0;
sleep_loops++;
}
awake_loops++;
mySerial.print("watchdog: ");
mySerial.print(watch_dog_counter);
mySerial.print(" sleep: ");
mySerial.print(sleep_loops);
mySerial.print(" wake: ");
mySerial.println(awake_loops);
steve_sleep();
}
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int timerPrescaler) {
if (timerPrescaler > 9 ) {
timerPrescaler = 9; //Correct incoming amount if need be
}
byte bb = timerPrescaler & 7;
if (timerPrescaler > 7) {
bb |= (1<<5); //Set the special 5th bit if necessary
}
//This order of commands is important and cannot be combined
MCUSR &= ~(1<<WDRF); //Clear the watch dog reset
WDTCR |= (1<<WDCE) | (1<<WDE); //Set WD_change enable, set WD enable
WDTCR = bb; //Set new watchdog timeout value
WDTCR |= _BV(WDIE); //Set the interrupt enable, this will keep unit from resetting after each int
}
void steve_sleep() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_enable();
sei();
sleep_cpu();
sleep_disable();
}
Output:
STARTING
watchdog: 0 sleep: 1 wake: 1
watchdog: 1 sleep: 2 wake: 2
watchdog: 2 sleep: 3 wake: 3
watchdog: 3 sleep: 4 wake: 4
watchdog: 4 sleep: 5 wake: 5
watchdog: 5 sleep: 6 wake: 6
watchdog: 6 sleep: 7 wake: 7
watchdog: 7 sleep: 8 wake: 8
then when I simulate incoming serial:
watchdog: 42 sleep: 43 wake: 46
watchdog: 42 sleep: 43 wake: 47
watchdog: 42 sleep: 43 wake: 48
watchdog: 43 sleep: 44 wake: 49
watchdog: 43 sleep: 44 wake: 50
watchdog: 43 sleep: 44 wake: 51
watchdog: 43 sleep: 44 wake: 52
watchdog: 43 sleep: 44 wake: 53
watchdog: 43 sleep: 44 wake: 54
watchdog: 43 sleep: 44 wake: 55
watchdog: 44 sleep: 45 wake: 56
watchdog: 45 sleep: 46 wake: 57
watchdog: 46 sleep: 47 wake: 58
watchdog: 47 sleep: 48 wake: 59
watchdog: 48 sleep: 49 wake: 60