mega48, Timer2 do not register OCR2A change

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

Hi guys.

I`m on my way to make a 4channel servo controller, but i am having some weird problem using Timer2.

How it works:

Timer0 is turning on the output to the relevant servo-channel and starts Timer2, when timer2 reaches a certain value it pulls the pin low and turns of timer2.

The problem is that after transmitting (RS232) a new value to the OCR2A register the pulse length will not change. It works first time, but second time it does not. I have verified that the register equals the new value by returning it over RS232. I have also checked Anyone have an idea on what is wrong?

#include 
#include 

#define USART_BAUDRATE 115200
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

unsigned char Byte = 0;

unsigned int ServoPosition[4] = {10, 200, 100, 128};
unsigned int i = 1, j = 0, DS = 0;

int main()
{
	DDRD = 0xFF;
	DDRC = 0x00;
	DDRB = 0xFF;
	PORTD = 0x01;
	UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
	UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
   	UCSR0B = 0x98;// Turn on the transmission and reception circuitry
   	UCSR0C = 0x06;


	// Timer Setup:
	TCCR0A = 0x02;
	TCCR0B = 0x03; // Clockdivisor 64
	OCR0A = 130; // Adjust to give ~200Hz
	OCR0B = 0xFF;
	TIMSK0 |= 0x02;
	// Timer2 setup:
	TCCR2A = 0x05;
	TCCR2B = 0x00; // Clock Disabled as standard;
	OCR2B = 0xFF;
	OCR2A = 0xFF; //100; // Adjust to give ~200Hz
	TIMSK2 |= 0x02;
	TIFR0 = 0;
	TIFR2 = 0;
	sei();
	
	while(1)
	{
		//while((UCSR0A & UDRE0)){}
		//UDR0 = OCR2A;
	};
return 0;
}


// USART Interrupt:
ISR(USART_RX_vect)
{
	Byte = UDR0;
	UDR0 = OCR2A;
	//ServoPosition[0] = Byte;
	//OCR2A = Byte;

}

//	TIMER0_Interrupt: Base frequency 50hz*number of servos
// 200Hz for 4 channels

ISR(TIMER0_COMPA_vect)
{
	if((!((TCNT2 == 0x00) | (TCNT2 == 0xFF)))&(TCNT2 != Byte))  // Check according to ERRATA
	{
		OCR2A = Byte;
	}

	if(i == 0x08)
	{
		i = 0x01;
	}
	PORTB = i;
	i = i << 1; // Shift i so that next ouput it pulsed next
	TCNT2 = 0; // Reset Timer2 counter to achieve better precision
	TCCR2B |= 0x02; // Turn on Timer2;
	
}

ISR(TIMER2_COMPA_vect)
{
	PORTB = 0;
	TCCR2B = 0; // Turn of timer2
}

By the way, sorry the code is a bit messy...

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

I don't really understand what is going on here with the timer starting and stopping, but a glance indicates that you meant && instead of & in the following (and probably || instead of | ?):

Quote:

if((!((TCNT2 == 0x00) | (TCNT2 == 0xFF)))&(TCNT2 != Byte))

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

Thanks for pointing that out, i`ve changed it now.

I`m really just experimenting a bit with RC servo control. Basically Timer0 starts the pulse, Timer2 stops it at a given time(in between 1 and 2mS roughly)

Not sure how i could explain it better, but then again, words have never been my thing ;)

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

Got it to work, had put timer2 into a PWM mode instead of CTC-mode.

Still, feel free to comment on my method, and thanks for reading.

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

There are many, many threads on the Forums for "hobby servo" pulse handling. Search them out.

Lee

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

Yeah i know, and i have searched around, but it is way more fun to figure out something for myself. Weirdly enough i think it is fun to reinvent the wheel, weird aint it?

Kim