Hi,
I am trying to use an ATtiny85 to transmit time data with an IR LED, but only every 10 seconds, which is more than the maximum time for the watchdog timer you can configure with the watchdog timer prescaler bits. The ATtiny also needs to be in ADC Noise Reduction mode to keep the internal clock running.
In the code at the bottom, I'm having trouble with the if statement calculating the time elapsed with the millis() function. The IR LED will blink if I just say something like if(current_time_ms) or if(last_transmit_time), but if I say if((current_time_ms-last_transmit_time)>0), the IR LED does not blink.
I took the watchdog timer code from an example online, and I don't really understand what each line is doing so I'm not sure how it's working. Is it possible the watchdog timer is interfering with the clock the millis() function uses? Ideally the watchdog timer triggers an interrupt and not a reset.
/*
The connections to the ATTiny are as follows:
ATTiny Arduino Info
Pin 1 - 5
Pin 2 - 3 / A3
Pin 3 - 4 / A2
Pin 4 - GND
Pin 5 - 0 IR LED (PWM)
Pin 6 - 1
Pin 7 - 2 / A1
Pin 8 - +Vcc
*/
// include IR library
#include <IRremote.hpp>
#include <avr/sleep.h>
// Routines to set and clear bits (used in the sleep code)
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// define pins
const int IR_LED_PIN = 0;
// declare variables
uint32_t time_command = 0; // variable to store time, sending as raw data
uint8_t sRepeats = 0;
unsigned long current_time_ms; // time in ms
unsigned long last_transmit_time;
int time_between_transmissions = 10; // time in seconds between transmissions
// sleep variables
volatile boolean f_wdt = 1;
void setup()
{
// Set up IO pins
pinMode(IR_LED_PIN, OUTPUT);
IrSender.begin(IR_LED_PIN, ENABLE_LED_FEEDBACK);
delay(100);
last_transmit_time = millis();
}
void loop() {
setup_watchdog(7); // sleep time defined in setup_watchdog
system_sleep(); // send the unit to sleep
if (f_wdt == 1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
// watchdog timer interrupt
f_wdt = 0; // reset flag
current_time_ms = millis();
if (( (current_time_ms - last_transmit_time) / 1000) > time_between_transmissions) {
time_command = 2678400; // test 31 days = 2678400 seconds
IrSender.sendNECRaw(time_command, sRepeats); // time is too big to send as address-command, send as raw data
last_transmit_time = millis();
}
}
}
void system_sleep() {
// set system into the sleep state
// system wakes up when watchdog is timed out
pinMode(IR_LED_PIN, INPUT); // set the ports to be inputs - saves more power
cbi(ADCSRA, ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_ADC); // sleep mode is set here
sleep_enable();
sleep_mode(); // System actually sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA, ADEN); // switch Analog to Digitalconverter ON
pinMode(IR_LED_PIN, OUTPUT); // set the ports to be output again
}
void setup_watchdog(int ii) {
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
byte bb;
int ww;
if (ii > 9 ) ii = 9;
bb = ii & 7;
if (ii > 7) bb |= (1 << 5);
bb |= (1 << WDCE);
ww = bb;
MCUSR &= ~(1 << WDRF);
// start timed sequence
WDTCR |= (1 << WDCE) | (1 << WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
ISR(WDT_vect) {
// Watchdog Interrupt Service / is executed when watchdog timed out
f_wdt = 1; // set global flag
}