I am using arduino duemilanove w/atmega328.
I have some code i am writing that responds to a GSM module by sending the AT command to send the text message "hello" to a certain number, using the PDU format.
I also have some code that puts the atmega328 to sleep for about 8 seconds using the watchdog timer and is woken up by an externally triggered interrupt.
Both worked fine in many many tests in isolation, but when i tried to combine the the two, so that my arduino tells the GSM to send a text if it receives one, even if it was asleep at the time is when the trouble happens.
When i upload the following will happen, the LED attached to D13 will start flashing very rapidly, i can no longer load any new programs onto the board, not even blink, i get the following error if i try:
avrdude: stk500_getsync(): not in sync: resp=0x15
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x78
This has happened on three different atmega328 chips, it will occur either as soon as i upload my dodgy program, or the program will run and work, successively sending sms to a phone but if i cut power to the arduino by removing the USB cable to the computer, the problem occurs.
I can reburn the bootloader to fix the chips i've been told but this isn't what is important, what i really need to know is what is so wrong with my code that it ruins every chip that it touches? What programming crime have i commited here? I really have no idea...
#include <avr/sleep.h>
#include <avr/wdt.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int sms_ready = 0; //change to 0 when not testing!!!
int de_holder = 0;
int octets_send = 18; //for now leave at 18 for test code "hello"
int pin_wake = 2;
volatile boolean watchdog_expired = 1; //see "Example of MMIO In C" on the page http://en.wikipedia.org/wiki/Volatile_variable for volatile to make sense
void setup(void)
{
Serial.begin(9600);
attachInterrupt(0,sms_received,LOW); //the GSM will send a pin low for 120ms when a sms is received, it will b connected to interupt pin0 (Dpin2)
pinMode(pin_wake,INPUT);
cbi(SMCR,SE); // sleep enable, power down mode
cbi(SMCR,SM0); // power down mode
sbi(SMCR,SM1); // power down mode
cbi(SMCR,SM2); // power down mode
setup_watchdog(9);
//instruction set here(?)
//0000, read tank
}
void loop(void)
{
if(watchdog_expired == 1)
{
watchdog_expired = 0;
//---actual program in here---//
check_sms();
//----------------------------//
int i;
for(i = 2; i <= 13 ; i++)
{
pinMode(i,INPUT); // set all ports to input to save power
}
system_sleep();
}
}
//------------------------------------------------------------------------------------------------//
//tank end specific functions //
//------------------------------------------------------------------------------------------------//
//AT+CMGL=<stat>[,<mode>]
//<stat>: 0, received unread
// 1, received read
// 2, stored unsent
// 3, stored sent
// 4, all
//
//<mode>: 0, normal
// 1, do not change status of specified sms record (i think this means it will leave an unread message as unread despite having just read it)
void check_sms(void)
{
if(sms_ready == 1)
{
Serial.print("\r"); //so that any noise that might have reaching the GSM Rx is removed
delay(1000);
octets_send = 18/*chungs code*/; //for now leave at 18 for test code "hello"
Serial.print("AT+CMGS=");
Serial.print(octets_send,DEC);
Serial.print("\r");
delay(1000); //waiting for OK response from modem
Serial.print("0001000B811634527505F8000005E8329BFD06"); //ugly re-encoded HEX for the GSM to send back to server/phone //for now its code to send a text to specific person
delay(1000);
Serial.print(0x1A,BYTE); //ctrl+Z
delay(4000);
sms_ready = 0;
}
}
//interrupt handler: when an sms is received
void sms_received(void)
{
if(de_holder == 0)
{
//don't forget to timer based functions in here like serial.print, delay etc can be put in the interrupt function
sms_ready = 1;
watchdog_expired = 1;
de_holder = 1;
}
}
//friends phone numbers in PDU format:
//i ommited this in this forum post for obvious reasons
//
//sample texts:
//E8329BFD06 hello
//int cnt;
//------------------------------------------------------------------------------------------------//
//sleep/watchdog functions //
//------------------------------------------------------------------------------------------------//
// set system into the sleep state
// system wakes up when watchdog is timed out
void system_sleep(void)
{
/*
The 5 different modes are:
SLEEP_MODE_IDLE -the least power savings
SLEEP_MODE_ADC
SLEEP_MODE_PWR_SAVE
SLEEP_MODE_STANDBY
SLEEP_MODE_PWR_DOWN -the most power savings
*/
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
/*
In the function call attachInterrupt(A, B, C)
A can be either 0 or 1 for interrupts on pin 2 or 3.
B Name of a function you want to execute at interrupt for A.
C Trigger mode of the interrupt pin. can be:
LOW a low level triggers
CHANGE a change in level triggers
RISING a rising edge of a level triggers
FALLING a falling edge of a level triggers
In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt(0,sms_received,LOW); // use interrupt 0 (pin 2) and run function
// go_to_loop when pin 2 gets LOW
de_holder = 0;
sleep_mode(); // System sleeps here }THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
sleep_disable(); // System continues execution here when watchdog timed out }THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}
void setup_watchdog(int ii)
{
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms} ii is 0,1,2...9
// 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;
Serial.println(ww);
MCUSR &= ~(1 << WDRF);
// start timed sequence
WDTCSR |= (1 << WDCE) | (1 << WDE);
// set new watchdog timeout value
WDTCSR = bb;
WDTCSR |= _BV(WDIE);
}
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect)
{
watchdog_expired = 1; // set global flag
}