Mousebot

Overview

The Mousebot is our attempt to create a robot that can navigate a maze. It has no name, but we borrow the name of the competition which inspired it originally.

links

http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf
atmega8 datasheet

schematic

mouseschematic.png

code

// ***********************************************************
//
// Project:  Differential Drive Robot with Wheel Encoders
// Author:  Charles Hart 2007
//
// Module description:  Control and Testing sans PID functions
//
// ***********************************************************
 
#define F_CPU 8000000            //Reflects desired system clock in Hz
 
#include <avr/io.h>              // Most basic include files
#include <avr/interrupt.h>       // Add the necessary ones
#include <util/delay.h> 
 
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
/* see atmega datasheet for more info on the preceding definitions */
 
//Hardware configuration definitions
//////////////// 
#define MOTORPORT      PORTD
#define MOTOR_A_EN     PD4
#define MOTOR_A_DIR    PD6
#define MOTOR_B_EN     PD5
#define MOTOR_B_DIR    PD7
#define WW_A_DIR       PB0
#define WW_B_DIR       PB1
 
//Function prototypes
//////////////// 
void set_direction(uint8_t direction);
void set_turn(uint8_t angle, uint8_t velocity);
 
//Global Variables
//////////////// 
uint32_t ticks_a = 0;             //ticks for motor a
uint32_t ticks_b = 0;             //ticks for motor b
static uint8_t foo;
 
//Interrupts 
//////////////// 
ISR(USART_RXC_vect) 
{
   char ReceivedByte;  //UDR is strange, one address with different values for r/w
   ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ReceivedByte"
   UDR = ticks_a; // send the number of encoder ticks back to the computer
}
 
ISR(INT0_vect)
{
  ticks_a++;    //just count ticks for now
}
 
ISR(INT1_vect)
{
  ticks_b++;
}
 
ISR(TIMER1_COMPA_vect)
{ //control speed of wheels
    //turn off motor A
    MOTORPORT &= ~(1<<MOTOR_A_EN);
}
 
ISR(TIMER1_COMPB_vect)
{ //control speed of wheels
    //turn off motor B
    MOTORPORT &= ~(1<<MOTOR_B_EN);
}
 
// the pulse train goes like:
//  TIMER1_OVF          TIMER1_COMP(a/b) TIMER1_COMP(a/b)
// \/                  \/               \/
//..======---.....======---.....======---...
//legend: . no motors    = both motors   - one motor
ISR(TIMER1_OVF_vect)
{
    //go about 15 feet/3071ticks before quitting
    if(ticks_a < 0xBFF)  
    {    
        //set direction to always be forward
        MOTORPORT &= ~(1<<MOTOR_A_DIR) & ~(1<<MOTOR_B_DIR);
 
        //turn on the motors
        MOTORPORT |= (1<<MOTOR_A_EN) | (1<<MOTOR_B_EN);
    }
}
 
void set_direction(uint8_t direction)
{
    if(direction) 
    {
        //forward
        MOTORPORT &= ~(1<<MOTOR_A_DIR) & ~(1<<MOTOR_B_DIR);
    }
    else
    {
        //reverse
        MOTORPORT |= (1<<MOTOR_A_DIR) | (1<<MOTOR_B_DIR);
    }
    return;
}
 
void set_turn(uint8_t angle, uint8_t velocity)
{
    /***********************************
     *  65535
     *    ^   |.....,,,,,
     *    |   |    ,.
     *  OCR1X |   ,  .     . = left motor
     *    |   |  ,    .    , = right motor
     *    v   | ,      .
     *    0   +----------100--
     *           angle---->
     ************************************/
    //velocity and angle are on 1-100 scale btw 
    if(angle < 50) //turning right (right motor limited/turns off first)
    {
         OCR1A = (velocity*angle*2*6.55)+35;
         OCR1B = (velocity*50*2*6.55)+35;
    }
    else           //turning left (left motor limited/turns off first)
    {
         OCR1A = (velocity*50*2*6.55)+35;
         OCR1B = (velocity*(100-angle)*2*6.55)+35;    
    }
}
 
//Main Program
//////////////// 
 
int main(void)
{
    //Initialization 
    TCCR0 = (1<<CS02) | (1<<CS00);        //Timer clock =system clock /64
    TIMSK = 1<<TOIE0;                     //Enable Timer0 Overflow Interrupt
 
    UCSRB |= (1 << RXEN) | (1 << TXEN);       // Turn on the tx/rx hardware
    UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
 
    UBRRL = BAUD_PRESCALE; // Load lower 8-bits of baud rate value into the low byte of the UBRR register
    UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of baud rate value into the high byte of the UBRR register
 
    UCSRB |= (1 << RXCIE); // Enable USART Rx Complete interrupt (USART_RXC)
 
    GICR |= (1 << INT0) | (1 << INT1);    //enable external interrupts
    //...rising edge interrupts
    MCUCR |= (1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11);
 
    //First set up duty cycle via timer1a and b
    //that means i want the counter to interrupt
    //at both compare registers, and continue to MAX.
    //..======---.....======---.....======---...
    TCCR1A = 0;             // Normal timer mode
    TCCR1B = 1;               //timer1 clock = sytem clock
    TIMSK  = (1<<OCIE1A) | (1<<OCIE1B) | (1<<TOIE1);
                        //Enable interrupts for compare 1a, 1b,
                        //and overflow 1.
                        //clobbers/disables timer0 interuppt too
 
    DDRD = 0xF0;        //Set Port D upper nibble as output
                        //lower nibble as input
 
    sei();              //Enable interrupts globally
 
    while(1)            //infinite looooooooooooooooooop
    {
      // set speed
      //go straight for 1000 ms
      set_turn(50, 80);
      _delay_ms(100);
      set_turn(0,50);
      _delay_ms(500);
      set_turn(50,0);
      _delay_ms(1000);
      //asm volatile("nop");    //volatile ensures nonoptimization, nop nop
    }
 
   return 0;                                            
}
Page tags: mousebot
page_revision: 8, last_edited: 1207170161|%e %b %Y, %H:%M %Z (%O ago)
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License