PDA

View Full Version : ODOMETRY with ATmega8



maddy_nish
03-03-2011, 11:45 PM
Hi,

I tried realizing odometry in atmega8. Im using PWM to control motor speed for course correction. Time being i have programmed the micro for the robot to move in a straight line and stop after moving 1m. I'm using external interrupts for counting wheel rotation. 5 pulses = 1 full rotation of wheel. Wheel circumference is approx 6cm.
But now course correction to move in a straight line is not happening. The robot moves in almost a zig zag path.
But i tried counting wheel rotation alone with external interrupt without using PWM it works fine. But this straight line motion of robot is not working , im using PWM to control motor speed. Pls help i have also pasted my code below.

Code compiled using AVRstudio4


#include<avr/io.h>

//#include<avr/signal.h>
#include<avr/interrupt.h>


void DELAY_US( uint16_t microseconds );
void DELAY_MS( uint16_t milliseconds );

#define MCU_FREQ 8000000UL



volatile int32_t Left_Tick = 0;
volatile int32_t Right_Tick = 0;



void init(void)
{

TIMSK = 0;


// RM PWM, LM PWM
DDRB=(1 << PB1)|(1 << PB2);



//Setup timer 1 -> PWM
//Setup PB0, PB1 with 8 bit PWM
TCCR1A = _BV(WGM10) //8 bit, phase correct PWM
|_BV(COM1A1)
|_BV(COM1B1);

TCCR1B = _BV(CS10) //No prescale
|_BV(WGM12); //Fast PWM
}







int main()

{
DELAY_US(200);

DDRD=0;
PORTD=255;
//unsigned int i;

GIMSK|=(1<<INT0);
GIMSK|=(1<<INT1);
MCUCR|=(1<<ISC01);
MCUCR|=(1<<ISC11);

char flag=1;

sei();

init();
DELAY_US(100);

DDRC=255;
PORTC=5;
OCR1A=254;//RIGHT SPEED
OCR1B=254;//LEFT SPEED
while(1)
{


if(Left_Tick==Right_Tick && flag==1)
{
PORTC=5;//both motors forwArd
OCR1A++;
OCR1B++;
if(OCR1A>252)
{
OCR1A=252;
}
if(OCR1B>252)
{
OCR1B=252;
}
DELAY_US(600);
}


if((Left_Tick-Right_Tick)<0)
{

OCR1A=OCR1A-1; //slow right motor
if(OCR1A<170)
{
OCR1A=170;

}



DELAY_US(100);
}



if((Left_Tick-Right_Tick)>0)
{

OCR1B=OCR1B-1; //slow left motor
if(OCR1B<170)
{
OCR1B=170;

}

}




if(((Left_Tick+Right_Tick)/2)*(6/5) > 100) //Wheel circ=6cms , 5 ticks per rotation
{
PORTC=0; //stop both motors
flag=0;

}

DELAY_US(200);

}// End of While

}//End of main







SIGNAL(SIG_INTERRUPT0)
{

Left_Tick++;

}

SIGNAL(SIG_INTERRUPT1)
{

Right_Tick++;

}



// DELAY - micro seconds
void DELAY_US( uint16_t microseconds )
{
register uint16_t loop_count;
/* 8mhz clock, 4 instructions per loop_count */
loop_count = microseconds * 2;

__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" ( loop_count )
: "0" ( loop_count )
);
}

// * DELAY_- milli seconds
void DELAY_MS( uint16_t milliseconds )
{
uint16_t i;
for ( i = 0; i < milliseconds; ++i )
{
DELAY_US( 1000 );
}
}

vikas
03-04-2011, 03:59 AM
The concept is wrong, what you are doing will lead to zig zag motion.
You need to implement something called PID for motion control.

Look at this tutorial

http://letsmakerobots.com/node/865

PS: i was too gonna write and article on this ... but no time :|.

maddy_nish
03-04-2011, 09:12 AM
Oh! Thanks for the correction.