help: STRANGE BEHAVIOUR IN SLEEP MODE

hi everyone,
the project about which i’m asking help is based on an attiny45; the code is pasted at the end.

what the program does:
-it sets the tiny in sleep mode
-after three cycles of watchdog timer it wakes up, reads the status of 2 analog inputs, reads vcc and sends them via morse code (txpin and sendmsg function).
-loop

the problem i haven’t been able so solve is related to the strange execution of the sleep/wake cycles:
when powered up the tiny waits for the right amount of time (given by WDT settings and by Watchdog_counter value) and then transmits the code, but after that it fires randomly (after 4 seconds, and then after 30, and so on).

thanks

#include <avr/sleep.h>
#include <avr/wdt.h>
int iSensor = 0;
int iiSensor = 0;
char analogiString[6];
char analogiiString[6];
const int txpin = 0; 
char vbatt[6];
char itemp[6];
int n=0;
int watchdog_counter = 0;
#define ITEMPOFFSET 0
void setup() {
pinMode(0, OUTPUT); 
pinMode(1, OUTPUT);  
pinMode(3,INPUT);
pinMode(4,INPUT);  
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT
sleep_enable();
}
void loop() {
setup_watchdog(8);
ADCSRA &= ~(1<<ADEN); //Disable ADC, saves ~230uA
sleep_mode(); 
if(watchdog_counter > 3)
{
watchdog_counter = 0;
ADCSRA |= (1<<ADEN); //Enable ADC
delay (200);                                                
                                        readsensors(); 
                                        digitalWrite (1, HIGH); // TX ENABLE
                                        delay(200);
                                        
                                        sendmsg(vbatt) ;
                                         
                                        sendmsg(itemp) ;
                                        
                                        sendmsg(analogiString);
                                        
                                        sendmsg(analogiiString);

                                        digitalWrite (1, LOW); // TX disABLE 
}
}
void readsensors () {
analogReference(INTERNAL1V1); 
delay (200);
iSensor = 0;
iiSensor = 0;
n=0;
for (n = 0; n < 5; n++){
iSensor = iSensor + analogRead(3);    
iiSensor = iiSensor + analogRead(4);    
delay(200);}
iSensor = iSensor / 5;    
iiSensor = iiSensor / 5;
sprintf ( analogiString, "%d ", iSensor );
sprintf ( analogiiString, "%d ", iiSensor );
sprintf ( vbatt, "%d ", readVcc() );
sprintf ( itemp, "%d ", read_Chip_Temp() );
}                                             
ISR(WDT_vect) {
watchdog_counter++;
}
struct t_mtab { char c, pat; } ;
struct t_mtab morsetab[] = {
	{'.', 106},
	{',', 115},
	{'?', 76},
	{'/', 41},
        {'t', 53},
        {'+', 42},
        {'=', 49},
	{'A', 6},
	{'B', 17},
	{'C', 21},
	{'D', 9},
	{'E', 2},
	{'F', 20},
	{'G', 11},
	{'H', 16},
	{'I', 4},
	{'J', 30},
	{'K', 13},
	{'L', 18},
	{'M', 7},
	{'N', 5},
	{'O', 15},
	{'P', 22},
	{'Q', 27},
	{'R', 10},
	{'S', 8},
	{'T', 3},
	{'U', 12},
	{'V', 24},
	{'W', 14},
	{'X', 25},
	{'Y', 29},
	{'Z', 19},
	{'1', 62},
	{'2', 60},
	{'3', 56},
	{'4', 48},
	{'5', 32},
	{'6', 33},
	{'7', 35},
	{'8', 39},
	{'9', 47},
	{'0', 63}
} ;
#define N_MORSE  (sizeof(morsetab)/sizeof(morsetab[0]))
#define SPEED  (18)
#define DOTLEN  (1200/SPEED)
#define DASHLEN  (3*(1200/SPEED))
void
dash()
{
digitalWrite(txpin, HIGH) ;
delay(DASHLEN);
digitalWrite(txpin, LOW) ;
delay(DOTLEN) ;
}
void
dit()
{
digitalWrite(txpin, HIGH) ;
delay(DOTLEN);
digitalWrite(txpin, LOW) ;
delay(DOTLEN);
}
void
send(char c)
{
int i ;
if (c == ' ') {
delay(7*DOTLEN) ;
return ;
}
for (i=0; i<N_MORSE; i++) {
if (morsetab[i].c == c) {
unsigned char p = morsetab[i].pat ;
while (p != 1) {
if (p & 1)
dash() ;
else
dit() ;
p = p / 2 ;
}
delay(2*DOTLEN) ;
return ;
}
}
}
void
sendmsg(char *str)
{
while (*str)
send(*str++) ;
}
void setup_watchdog(int timerPrescaler) {
if (timerPrescaler > 9 ) timerPrescaler = 9; //Limit incoming amount to legal settings
byte bb = timerPrescaler & 7; 
if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary
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
}
uint16_t readVcc(void)
{
uint16_t result;
ADMUX = (0<<REFS0) | (12<<MUX0);
delay(200); // Wait for Vref to settle
ADCSRA |= (1<<ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
n=0;
result = 0; 
for (n = 0; n < 5; n++){
result = result + ADCW;   
delay(50);
}
result = result / 5;   
return 1126400L / result; //1.1*1024*1000
}
int read_Chip_Temp() 
{ 
ADMUX = (1<<REFS1) | (15<<MUX0);
delay(200); // Wait for ADMUX setting to settle
ADCSRA |= (1<<ADSC); //Start temperature conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
int temperature = (high << 8) | low; 
return temperature - 273 + ITEMPOFFSET;
}

hi everyone,
the project about which i’m asking help is based on an attiny45; the code is pasted at the end.

what the program does:
-it sets the tiny in sleep mode
-after three cycles of watchdog timer it wakes up, reads the status of 2 analog inputs, reads vcc and sends them via morse code (txpin and sendmsg function).
-loop

the problem i haven’t been able so solve is related to the strange execution of the sleep/wake cycles:
when powered up the tiny waits for the right amount of time (given by WDT settings and by Watchdog_counter value) and then transmits the code, but after that it fires randomly (after 4 seconds, and then after 30, and so on).

thanks

#include <avr/sleep.h>
#include <avr/wdt.h>
int iSensor = 0;
int iiSensor = 0;
char analogiString[6];
char analogiiString[6];
const int txpin = 0; 
char vbatt[6];
char itemp[6];
int n=0;
int watchdog_counter = 0;
#define ITEMPOFFSET 0
void setup() {
pinMode(0, OUTPUT); 
pinMode(1, OUTPUT);  
pinMode(3,INPUT);
pinMode(4,INPUT);  
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT
sleep_enable();
}
void loop() {
setup_watchdog(8);
ADCSRA &= ~(1<<ADEN); //Disable ADC, saves ~230uA
sleep_mode(); 
if(watchdog_counter > 3)
{
watchdog_counter = 0;
ADCSRA |= (1<<ADEN); //Enable ADC
delay (200);                                                
                                        readsensors(); 
                                        digitalWrite (1, HIGH); // TX ENABLE
                                        delay(200);
                                        
                                        sendmsg(vbatt) ;
                                         
                                        sendmsg(itemp) ;
                                        
                                        sendmsg(analogiString);
                                        
                                        sendmsg(analogiiString);

                                        digitalWrite (1, LOW); // TX disABLE 
}
}
void readsensors () {
analogReference(INTERNAL1V1); 
delay (200);
iSensor = 0;
iiSensor = 0;
n=0;
for (n = 0; n < 5; n++){
iSensor = iSensor + analogRead(3);    
iiSensor = iiSensor + analogRead(4);    
delay(200);}
iSensor = iSensor / 5;    
iiSensor = iiSensor / 5;
sprintf ( analogiString, "%d ", iSensor );
sprintf ( analogiiString, "%d ", iiSensor );
sprintf ( vbatt, "%d ", readVcc() );
sprintf ( itemp, "%d ", read_Chip_Temp() );
}                                             
ISR(WDT_vect) {
watchdog_counter++;
}
struct t_mtab { char c, pat; } ;
struct t_mtab morsetab[] = {
	{'.', 106},
	{',', 115},
	{'?', 76},
	{'/', 41},
        {'t', 53},
        {'+', 42},
        {'=', 49},
	{'A', 6},
	{'B', 17},
	{'C', 21},
	{'D', 9},
	{'E', 2},
	{'F', 20},
	{'G', 11},
	{'H', 16},
	{'I', 4},
	{'J', 30},
	{'K', 13},
	{'L', 18},
	{'M', 7},
	{'N', 5},
	{'O', 15},
	{'P', 22},
	{'Q', 27},
	{'R', 10},
	{'S', 8},
	{'T', 3},
	{'U', 12},
	{'V', 24},
	{'W', 14},
	{'X', 25},
	{'Y', 29},
	{'Z', 19},
	{'1', 62},
	{'2', 60},
	{'3', 56},
	{'4', 48},
	{'5', 32},
	{'6', 33},
	{'7', 35},
	{'8', 39},
	{'9', 47},
	{'0', 63}
} ;
#define N_MORSE  (sizeof(morsetab)/sizeof(morsetab[0]))
#define SPEED  (18)
#define DOTLEN  (1200/SPEED)
#define DASHLEN  (3*(1200/SPEED))
void
dash()
{
digitalWrite(txpin, HIGH) ;
delay(DASHLEN);
digitalWrite(txpin, LOW) ;
delay(DOTLEN) ;
}
void
dit()
{
digitalWrite(txpin, HIGH) ;
delay(DOTLEN);
digitalWrite(txpin, LOW) ;
delay(DOTLEN);
}
void
send(char c)
{
int i ;
if (c == ' ') {
delay(7*DOTLEN) ;
return ;
}
for (i=0; i<N_MORSE; i++) {
if (morsetab[i].c == c) {
unsigned char p = morsetab[i].pat ;
while (p != 1) {
if (p & 1)
dash() ;
else
dit() ;
p = p / 2 ;
}
delay(2*DOTLEN) ;
return ;
}
}
}
void
sendmsg(char *str)
{
while (*str)
send(*str++) ;
}
void setup_watchdog(int timerPrescaler) {
if (timerPrescaler > 9 ) timerPrescaler = 9; //Limit incoming amount to legal settings
byte bb = timerPrescaler & 7; 
if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary
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
}
uint16_t readVcc(void)
{
uint16_t result;
ADMUX = (0<<REFS0) | (12<<MUX0);
delay(200); // Wait for Vref to settle
ADCSRA |= (1<<ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
n=0;
result = 0; 
for (n = 0; n < 5; n++){
result = result + ADCW;   
delay(50);
}
result = result / 5;   
return 1126400L / result; //1.1*1024*1000
}
int read_Chip_Temp() 
{ 
ADMUX = (1<<REFS1) | (15<<MUX0);
delay(200); // Wait for ADMUX setting to settle
ADCSRA |= (1<<ADSC); //Start temperature conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
int temperature = (high << 8) | low; 
return temperature - 273 + ITEMPOFFSET;
}

You know, this isn't exactly an arduino project.

I think you need to make watchdog_counter "volatile."

You manipulate watchdog_counter in an ISR so you should declare it 'volatile'.

goodinventor:
You know, this isn't exactly an arduino project.

The ATTINY series of AVR's are discussed more often on the forum.

The TINY code with small modifications - e.g. register names - can be run on an UNO / MEGA.
The other way around is only possible for small sketches...

Please do not cross post ...

HELLO AND THANKS FOR YOUR HELP!

i have corrected the volatile integer, and if i isolate the sleepmode and wdt functions the program works.
however if i add the functions to send morse and read sensors it behaves strangely.
there is probably a problem in how i read sensors and print the values into an array to be sent to the SENDMSG() function.
here is the alleged defective part of code::::::

thanks

int iSensor = 0;
int iiSensor = 0;
char analogiString[6];
char analogiiString[6];
char vbatt[6];
char itemp[6];
int n=0;

void setup() {
pinMode(0, OUTPUT); 
pinMode(1, OUTPUT);  
pinMode(3,INPUT);
pinMode(4,INPUT);  
}


void loop() {
                                        
                                        readsensors(); 
                                        delay(200);
                                        
                                        sendmsg(vbatt) ;
                                         
                                        sendmsg(itemp) ;
                                        
                                        sendmsg(analogiString);
                                        
                                        sendmsg(analogiiString);
 
}
}




void readsensors () {
analogReference(INTERNAL1V1); 
delay (200);
iSensor = 0;
iiSensor = 0;
n=0;
for (n = 0; n < 5; n++){
iSensor = iSensor + analogRead(3);    
iiSensor = iiSensor + analogRead(4);    
delay(200);}
iSensor = iSensor / 5;    
iiSensor = iiSensor / 5;
sprintf ( analogiString, "%d ", iSensor );
sprintf ( analogiiString, "%d ", iiSensor );
sprintf ( vbatt, "%d ", readVcc() );
sprintf ( itemp, "%d ", read_Chip_Temp() );
}                                             





uint16_t readVcc(void)
{
uint16_t result;
ADMUX = (0<<REFS0) | (12<<MUX0);
delay(200); // Wait for Vref to settle
ADCSRA |= (1<<ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
n=0;
result = 0; 
for (n = 0; n < 5; n++){
result = result + ADCW;   
delay(50);
}
result = result / 5;   
return 1126400L / result; //1.1*1024*1000
}




int read_Chip_Temp() 
{ 
ADMUX = (1<<REFS1) | (15<<MUX0);
delay(200); // Wait for ADMUX setting to settle
ADCSRA |= (1<<ADSC); //Start temperature conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
int temperature = (high << 8) | low; 
return temperature - 273 + ITEMPOFFSET;
}

here i the allegedly defective part of code::::::

Unusual indenting. And, it doesn't compile.

Your “readVcc()” function mucks with the ADC registers. I don’t know if analogRead() is smart enough to fix that next time you go to take a reading. That could put your analogReads WAY off. I recommend you save the current state of the ADC registers you muck with and restore them after you get your voltage reading.

uint16_t readVcc(void) {
  int OldADMUX = ADMUX;
  int OldADCSRA = ADCSRA;
  uint16_t result;
  ADMUX = (0<<REFS0) | (12<<MUX0);
  delay(200); // Wait for Vref to settle
  ADCSRA |= (1<<ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCW;    
  ADMUX = OldADMUX;
  ADCSRA = OldADCSRA;
  return 1126400L / result;   //1.1*1024*1000
}

Since you didn’t request a new reading in your loop I took out the part where you read the same value five times. If you want to average five values you will want to put the ADSC code INSIDE the loop.