ATMega start up/reboot problem

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have an ATMega8 on which I have loaded some code that will take commands via usart and operate/rotate a servo.

On power up the servo controller code is in an OFF state; meaning that chip will not accept commands from the PC. I have a momentary switch connected to an input pin. When the pin is pressed the ON/OFF state toggles from OFF to ON. While OFF no commands are accepted. On start-up or reset, the code will send a message to the PC terminal indicating that the current ON/OFF state - using printf() - stating that "The ServoController is currently OFF. Press Button to turn ON."

The code seems to work as intended, with the following glitch - On startup, I am getting the startup message twice. On reset, I only get it once. So I am guessing that for some reason, on startup the ATMega8 is rebooting?

I am using an external 16 MHZ clock - crystal oscillator. My fuse setting is "6 CK 65 ms - Slowly rising power."

I had the servo wired to its own power source, but had the ground for that power source and the ground for the ATMega8 circuit connected. This is the configuration that seemed to work correctly when I was experimenting with the servo without implementing the usart to communicate commands (I was using the momentary switch instead). However, to see if the servo circuit was the source of - or a contribution to - the issue I am having, I disconnected it from the circuit and ran the code with just the chip. The result was the same.

In am not sure that the code is important, and it is long, so I am not posting it here. If I am mistaken in this respect, and seeing the code would be helpful, let me know and I will do so.

Any idea as to what might be causing the reboot on power up?

Thanks.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have any clue if the extra message is caused by
- a reset that occurs after power up,
- your UART code,
- or your main code which might do something based upon the reset source flags in MCUCSR (if you don't evaluate them: maybe you should!)
?

I tend to post off-topic replies when I've noticed some interesting detail.
Feel free to stop me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

buffi wrote:
Do you have any clue if the extra message is caused by
- a reset that occurs after power up,
- your UART code,
- or your main code which might do something based upon the reset source flags in MCUCSR (if you don't evaluate them: maybe you should!)
?

I am pretty sure that it is happening only on power up. I have a section of code that prints a specific message only on startup or reset, the code prints other messages at other times. Only the startup/reset message is repeating. Moreover, the message is repeating only when the power is turn on (or if the power is turned off then on again). I have a reset button attached to the chip, and the message does not repeat if the program resets as a result of pressing the reset button.

I was just reading in the datasheet about the source flags in MCUCSR; and ma trying to make heads and tail of it. :?

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I am pretty sure that it is happening only on power up.

Quote:

I was just reading in the datasheet about the source flags in MCUCSR; and ma trying to make heads and tail of it.

Yes, this will be very valuable in this case. Log the cause of every reset to EEPROM locations, and count them. Read back the info with your ISP and decode.

Remember to clear the cause right after you process it.

If you get a zero cause, then your code is running amok--often an uninitialized variable.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Yes, this will be very valuable in this case. Log the cause of every reset to EEPROM locations, and count them. Read back the info with your ISP and decode.

Remember to clear the cause right after you process it.

If you get a zero cause, then your code is running amok--often an uninitialized variable.


OK - I was a little (OK...ALOT) :oops: overwhelmed by writing MCUCSR to EEPROM. I read Dean's tutorial on EEPROM, and searched these forums, and started to get an inkling; but still have a way to go.

In the meantime, I found this thread, where clawson suggested some code to write the value of MCUCSR to USART. I think that work, and the value I got was 0.

So, if I am interpreting the datasheet correctly, that means there is not reset, correct? And that my code is running amok! :(

Interesting thing - the behavior only occurs when power to the chip is turn on, it only happens once (not repeatedly) - printf statement in question prints 2x, and it does not happen if I press the reset button I have wired to pin 1.

What next....

And as always...thanks for your help and patience.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Update -

I added some printf instructions to my code in order to see if I could get an idea of where it was running amok. The main part of the code is a while loop. So I added the following code snippets at the beginning and the end of the loop, respectively:

/*At beginning of loop*/
if((Test > 0) & (Test <21))//Test -- Diagnotic for reboot issue
		{
		printf("just entered while loop.\nthis is loop #d \n\n", Test);
		}

/*At end of loop*/
if((Test > 0) & (Test < 21))//Test-- Diagnotic for reboot issue
		{
		printf("about to exit while loop.\nthis is loop #d \n\n", Test);
		Test++;
		}

When I run this code, I observe that the terminal prints the message at the beginning of the loop 9 times; but it restarts during the middle of printing the message at the end the 9th time. Further, it is crashing during that 9th print instruction at varying points - each time I test it different snippets of the 9th print instruction are printed to the terminal before the code starts over. After it starts over, the code seems to behave normally. And, again, this behavior is only observed upon powering up, and not if I press the reset button attached to pin1.

I have posted my entire code below:

//Set includes

#include 
#include 
#include 
#include 		// need "--std=c99"
#include 

//Declare and initialize some variables

//Declare and initialize some variables

typedef unsigned char	u8;

#define KEY_PIN		PINC

#define PC0		0
#define	PC1		1
#define	PC2		2
#define	PC3		3
#define	PC4		4
#define	PC5		5

#define CMD_FCCW	'1' //for ServoCommand
#define CMD_CENTER	'2'
#define CMD_FCW		'3'
#define CMD_INVALID	'4'

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE 103

enum { OFF, ON};//for OnOffStatus
				//OFF->0
				//ON->1
																
u8 key_state;//state of key 1->pressed (active low)
u8 key_press;//detects key press 1->key pressed
u8 key_press_mask;//mask to clear key_press					
u8 ServoCommand;//holds setting for action servo should take
u8 ct0 = 0xFF; //holder to counter debounce states
u8 ct1 = 0xFF; //holder to counter debounce states
u8 OnOffStatus; // on/off status of servo control
u8 ServoCommandReceived; // detects receipt of servo command 
u8 Test = 1; //Test varuable

//Declare and define functions

void usart_init(void);
void timer1_init(void);
void timer2_init(void);
static int usart_putc(char c, FILE *stream);
void request_instruct(u8 TermInst);
u8 on_off_status__change(u8 key_mask);

//Setup stream for stdio

FILE mystdio = FDEV_SETUP_STREAM(usart_putc, NULL, _FDEV_SETUP_WRITE);//Setup stream for stdin to USART
	
int main (void) //main routine
{

//Configure input and output pins

	DDRB |= (1 << 1); //pin PB1(OC1A) set to output
	PORTB &= ~(1 << 1); //initialize as low

	DDRC = 0; //pins on PORTC as input
	PORTC = 255; //enable internal pull-up resistor on PC
	
	DDRC |= ((1 << PC2) | (1 << PC3)); //pins PC2 and PC3 set to output
	PORTC &= ~(1 << PC2); //initialize PC2 as low; "ON" indicator LED
	PORTC |= (1 << PC3); //initialize PC3 as high; "OFF" indicator LED
	
//Enable interrupts

	TIMSK |= (1 << OCIE2); // Enable CTC interrupt on timer2
	UCSRB |= (1 << RXCIE); //Enable USART RX interrupt
	sei(); //  Enable global interrupts
	
// Initiation routines

	usart_init(); //initiate USART
	timer1_init(); //initiate timer1 and PWM
	timer2_init(); //initiate time2 for debounce
	stdout = &mystdio; //set mystdio as stdout (standard output)
	request_instruct(OFF); // initiate communication with the terminal
							//send terminal meassage that servo control is OFF
	printf("This is Line 102 is double.\n");//Diagnotic for reboot issue
	
	while (1) //loop to ...
	{
		if((Test > 0) & (Test <21))//Test -- Diagnotic for reboot issue
		{
		printf("just entered while loop.\nthis is loop #d \n\n", Test);
		}
		
		if(on_off_status__change((1<<PC5))) //has PC5 been pressed?
		{
			OnOffStatus ^= (1 << 0);// flip on/off status of servo control;
									//on->off, off->on; 0 = OFF; 1 = ON
									
			PORTC ^= (1 << PC2); //toggle "On" LED
			PORTC ^= (1 << PC3); //toggle "Off" LED
			
			if(OnOffStatus == OFF)
			{
				request_instruct(OFF);//send terminal meassage that servo control is OFF
				printf("Line 128 is double.\n");
			} //end if(OnOffStatus == 0)
				
			else
			{
				request_instruct(ON);//send terminal meassage that servo control is ON
			} //else
		}	// end if(on_off_status__change...)
			
		if (ServoCommandReceived & (1 << 0)) //check to see if there has been a servo command received
			{
				ServoCommandReceived &= ~(1 << 0); //clear ServoCommandReceived
				if(OnOffStatus == OFF) //if command is received when status is OFF
				{
					request_instruct(OFF); //send terminal meassage that servo control is OFF
					printf("Line 150 is double.\n");
				} //end if(OnOffStatus == OFF)
				
				if(OnOffStatus == ON) //if command is received when status is ON
				{
					TCCR1B |= (1 << CS11);//servo is on; set up timer1 with 8 prescaler
												//(External clock (crystal oscillator) at 16Mhz)
					switch(ServoCommand) //rotate/operate servo based on the command inputed by user
					{
						case CMD_FCCW:
							OCR1A = 0x4B0; //1200 equates into a duty cycle of approx 3# (rotate to -90 degress (left))
							request_instruct(CMD_FCCW); //send terminal meassage that servo rotating FCCW
							break;
						
						case CMD_CENTER:
							OCR1A = 0xBB8; //3000 equates into a duty cycle of approx 7.5# (rotate to 0 degress (center))
							request_instruct(CMD_CENTER); //send terminal meassage that servo rotating center
							break;

						case CMD_FCW:
							OCR1A = 0x12C0; //4800 equates into a duty cycle of approx 12# (rotate to 90 degress (right))
							request_instruct(CMD_FCW); //send terminal meassage that servo rotating FCW
							break;	
							
						default:  //in case of invalid ServoCommand
							request_instruct(CMD_INVALID); //send terminal meassage that servo command is invalid
					} //end swtich
				} //end end if(OnOffStatus == 1)
			} // end if(servo_command_received...)
		
		if((Test > 0) & (Test < 21))//Test-- Diagnotic for reboot issue
		{
		printf("about to exit while loop.\nthis is loop #d \n\n", Test);
		Test++;
		}

		
	} //end while

} //end main
	
/*********************************/
/*********************************/

//Declare and define functions

/*********************************/
//USART SETUP ROUTINE
void usart_init(void) //Set up and configure USART communications for ATMega8
{
	UCSRB |= (1 << RXEN | 1 << TXEN); // Turn on the transmission and reception circuitry
	UCSRC |= (1 << URSEL | 1<< UCSZ0 | 1<< UCSZ1); //8-bit character sizes - URSEL bit set to select the UCRSC register 
	UBRRL |= BAUD_PRESCALE; //Load lower 8-bits of the baud rate value into the low byte of the UBRR register 
	UBRRH |= (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
								 //(highest byte needs to be 0 in order to clear URSEL and be able to write to UBBRH
								 
} //end usart_init

/*********************************/
//TIMER1 SETUP ROUNTINE (FOR PWM)
void timer1_init(void)//Set up and configure timer1 parameters for PWM 
{					  //other than OCRA1 and CS11 (which are set in main based on input)
	
	TCCR1A |= (1 << COM1A1);//set OC1A (PB1) to clear on Compare Match, and set at BOTTOM (non-iverting mode)
	TCCR1A |= (1 << WGM11);// Configure timer1 for Fast PWM mode (Mode 14)
	TCCR1B |= ((1 << WGM12) | (1 << WGM13));
	ICR1 = 0x9C3F; //Set frequency of timer1 and PWM; 39,999 give a count of 40,000 (TOP +1) which equates into a frequency of 50hz

}//end timer1_init()

/*********************************/
//TIMER2 SETUP ROUTINE (FOR DEBOUNCE)
void timer2_init(void)//Set up and configure timer2 parameters for switch debounce routine 
{
	
	TCCR2 |= (1 << WGM21);// Configure timer2 in CTC mode (non-PWM)
	TCCR2 |= ((1 << CS22) | (1 << CS21));//set up timer2 with 1024 prescaler (External clock (crystal oscillator) at 16Mhz)
	OCR2 = 0x9C; ////Set compare to 625, equates to 10ms at prescale of 1024
	
}//end timer2_init()

/*********************************/
//USART OUTPUT ROUTINE
static int usart_putc(char c, FILE *stream)
{

	if(c == '\n')
	{
	
		usart_putc('\r', stream);
		
	} //end if

	loop_until_bit_is_set(UCSRA, UDRE);

	UDR = c;
	
	return 0;

} //end usart_putc()

/*********************************/
//NEED ACTION ROUTINE (SWITCH PRESSED?)
u8 on_off_status__change(u8 key_mask)//determine if key has been pressed
{

	ATOMIC_BLOCK(ATOMIC_FORCEON)
	{
		key_press_mask = key_mask;//mask to clear key_press
		key_mask &= key_state & key_press; //read key; has key been pressed?
		key_press &= ~key_press_mask; //reset key_toggle 
	}//end ATOMIC_BLOCK(ATOMIC_FORCEON)

	return key_mask;
	
}//end on_off_status__change()

/*********************************/
//PRINT REQUEST INSTRUCTION ROUTINE
void request_instruct(u8 TermInst)
{

//TODO:  SETUP ARRAY TO HOLD STRINGS ->"ON", "OFF", FCCW", "CENTER", "FCW", ETC.
	
	switch(TermInst)
	{
		case OFF: //send terminal meassage that servo control is OFF
			printf("\n\nThe Servo Controller is currently OFF.\n");
			printf("Please press button to start.\n");
			break;
			
		case ON://send terminal meassage requesting ServoCommand
			printf("Please enter: 1 to rotate full counter-clockwise, 2 to center, or 3 to rotate full clockwise.\n");
			printf("Press button to turn Servo Controller OFF.\n");
			printf("Thank you.\n");
			break;
			
		case CMD_FCCW: //send terminal meassage acknowledging receipt of servo command
					//and that servo rotating FCCW
			printf("ServoCommand received...\n");
			printf("...rotating servo full counter clockwise.\n");
			request_instruct(ON);//send terminal meassage requesting ServoCommand
			break;

		case CMD_CENTER://send terminal meassage acknowledging receipt of servo command
					//and that servo rotating Center
			printf("ServoCommand received...\n");
			printf("...rotating servo center.\n");
			request_instruct(ON);//send terminal meassage requesting ServoCommand
			break;
			
		case CMD_FCW://send terminal meassage acknowledging receipt of servo command
					//and that servo rotating FCW
			printf("ServoCommand received...\n");
			printf("...rotating servo full clockwise.\n");
			request_instruct(ON);//send terminal meassage requesting ServoCommand
			break;
			
		case CMD_INVALID://send terminal meassage that ServoCommand is invalid
			printf("Invalid ServoCommand entered, please try again.\n");
			request_instruct(ON);//send terminal meassage requesting ServoCommand
	} //end switch
	

} //end request_instruct()

/*********************************/
//ISR ROUTINE - USART RECEPTION
ISR(USART_RXC_vect)
{

//TODO: READ SERVO COMMAND
	
	ServoCommand = UDR; // Fetch the recieved byte value into the variable "ByteReceived"
	ServoCommandReceived |= ( 1<< 0 ); //set ServoCommand to indicate that a servo command was received from terminal

} //end ISR()

/*********************************/
//ISR ROUTINE - DEBOUNCE
ISR(TIMER2_COMP_vect)
{

	u8 i;

	i = key_state ^ ~KEY_PIN;		// key changed ?
	ct0 = ~( ct0 & i );			// reset or count ct0
	ct1 = ct0 ^ (ct1 & i);		// reset or count ct1
	i &= ct0 & ct1;			// count until roll over ?
	key_state ^= i;			// then toggle debounced state
	key_press |= key_state & i;		// 0->1: key press detect
	
  
}//end ISR() 

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Strange development...I recently purchased an STK500. Previously, I had the ATMega8 on a breadboard and the code issues described above were when the ATMega8 was on that board with a 16Mhz canned oscillator as an external clock. I changed the code to use the 3.6864Mhz external clock provided by the STK500 and I placed the ATmega8 on the STK500 and re-programmed the chip...and the problem did not occur when I ran the code on the STK500!

Russ