////////////////////////////////////////////////////////////////////////////////////////
// OVERVIEW
////////////////////////////////////////////////////////////////////////////////////////
/*
DESCRIPTION: Watchdog Timer Demo 1.
AUTHOR: Andre' LaMothe
COMMENTS:
VT100 commands can be found here:
http://www.braun-home.net/michael/info/misc/VT100_commands.htm
HISTORY:
*/
////////////////////////////////////////////////////////////////////////////////////////
// INCLUDES
////////////////////////////////////////////////////////////////////////////////////////
#include <Arduino.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <avr/wdt.h> // this includes the watchdog timer functionality, constants, etc.
using namespace std;
////////////////////////////////////////////////////////////////////////////////////////
// PROTOTYPES
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// DEFINES AND MACROS
////////////////////////////////////////////////////////////////////////////////////////
const uint8_t button_pin = 7; // PD7, D7, AIN[1],PCINT[23]
const uint8_t LED_pin = 8; // PB0
////////////////////////////////////////////////////////////////////////////////////////
// GLOBALS
////////////////////////////////////////////////////////////////////////////////////////
// buffer for messages, etc.
char gStringBuffer[ 80 ];
////////////////////////////////////////////////////////////////////////////////////////
// ISRs - INTERRUPT SERVICE ROUTINES
////////////////////////////////////////////////////////////////////////////////////////
ISR( WDT_vect )
{
// do whatever you wish in here, but do it FAST!
// turn on LED to indicate interrupt occured
digitalWrite( LED_pin, HIGH );
} // end ISR( WDT_vect )
////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
// the setup function runs once when you press reset or power the board
// initialize serial port
Serial.begin(115200);
Serial.write( "\n\rSystem Reset: Watchdog Timer Demo 1 Initializing...\n\r" );
// setup GPIO pins
pinMode( button_pin, INPUT_PULLUP );
digitalWrite( LED_pin, LOW );
pinMode( LED_pin, OUTPUT );
// before anything, temporarily disable interrupts, create a "critical section", so we know we can't be interrupted
// as well as we don't trigger the interrupt we are setting up, we don't HAVE to do this, but it's a nice safety measure
cli();
// reset the WDT timer just in case its about to trigger
wdt_reset();
// WDTCSR - Watchdog timer control register (0x60)
// Step 1: set WDIE (watchdog interrupt enable) and WDE (watchdog change enable) both to 1 in the WDTCSR,
// this is required by the 328p as a "safety" precaution to indicate that
// you really want to play with the WDT, after this instruction executes, you must set the WDT settings within
// 4 clock cycles, see 328p datasheet for more detail.
WDTCSR |= ( 1 << WDCE ) | ( 1 << WDE );
// Step 2: now, we have 4 clocks to get on with manipulating the setting bits, as usual, you can always save the
// bit field and restore, OR only set/clear bits of interest, but since we are the only app running, we will simply
// over write the register as desired. The WDTCSR controls the interrupt enable, watchdog reset enable, and the prescaler
// values for timeout of the watchdog from 16ms to 8s, refer to datasheet for more detail.
// in our case we are going to enable the watchdog interrupt, the watchdog reset, and set the time out for 4 seconds
// NOTE: Be carefull not to set the time out for too small a value, if so, the WDT will timeout before the 328P boots and
// has time for the bootloader to accept new code. So, 2 seconds is the recommended minimum with Arduino tech, you can
// change this if you know what you are doing, if you brick your arduino, you may need an ISP programmer to reset it.
// these settings enable both interrupt, and reset, and set timeout to 2.0s
//
// Typical Time-out at VCC = 5.0V
// WDP3 WDP2 WDP1 WDP0 Timeout
// 0 0 0 0 16ms
// 0 0 0 1 32ms
// 0 0 1 0 64ms
// 0 0 1 1 0.125s
// 0 1 0 0 0.25s
// 0 1 0 1 0.5s
// 0 1 1 0 1.0s
// 0 1 1 1 2.0s --------- safe time outs 2,4,8
// 1 0 0 0 4.0s
// 1 0 0 1 8.0s
WDTCSR = ( 1 << WDIE ) | ( 1 << WDE ) | ( 0 << WDP3 ) | ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDP0 );
// finally, be sure that you have defined the interrupt service routine for the WDT_vect, since we enabled it with
// the above bit settings
// Step 3: re-enable interrupts
// nothing will happen until the I flag is set in the SREG, so enable interrupts
sei();
Serial.write( "\n\rWatchdog Timer now running with 2.0s timeout...\n\r" );
} // end setup
////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
static int loopCounter = 0;
// waiting for external event to reset the watchdog
// build up message string and print
sprintf( gStringBuffer, "\n\r(%d):Waiting for push button to reset...", loopCounter++);
Serial.write( gStringBuffer );
// test if user has pressed the WDT button, LOW means pressed
if ( digitalRead( button_pin ) == 0 )
{
// user has pressed the button, so we will reset the WDT
wdt_reset();
// echo button press
Serial.write( "\n\r---------- User pressed button resetting WDT! ----------\n\r" );
} // end if
// pause a moment
delay( 100 );
// clear interrupt LED always
digitalWrite( LED_pin, LOW );
} // end loop
////////////////////////////////////////////////////////////////////////////////////////