Archive for the 'Micromouse' Category

R2 Project Log - Motors

After a minor slip up with a probe killed my primary R2 bot (shorted VBATT to 5VCC, bye bye processor and drive chips) I’ve tonight soldered up another of my spare R2 boards to take over the mantle.

And the motor drive code i was debugging at the time works!

Tomorrow, i add a battery monitor circuit and the sensors, so i’ll finally have al the major electronic systems tested and good to go ready for the motor mounts.

#define F_CPU 1000000UL
#include < avr/io.h>
#include < util/delay.h>
#include < avr/interrupt.h>
 
#include "r2.h"
 
int main(void) {
	// Activate all the LEDs, set their pins to output
	bit_set(LED_WHITE_L_DDR, LED_WHITE_L_BIT);
	bit_set(LED_WHITE_R_DDR, LED_WHITE_R_BIT);
	bit_set(LED_RED_L_DDR, LED_RED_L_BIT);
	bit_set(LED_RED_R_DDR, LED_RED_R_BIT);
	bit_set(LED_YELLOW_FL_DDR, LED_YELLOW_FL_BIT);
	bit_set(LED_YELLOW_FR_DDR, LED_YELLOW_FR_BIT);
	bit_set(LED_YELLOW_RL_DDR, LED_YELLOW_RL_BIT);
	bit_set(LED_YELLOW_RR_DDR, LED_YELLOW_RR_BIT);
 
	// Activate the motor's control lines
	bit_set(MOTOR_R_ENABLE_DDR, MOTOR_R_ENABLE_BIT);
	bit_set(MOTOR_R_PHASE_DDR, MOTOR_R_PHASE_BIT);
	bit_set(MOTOR_L_ENABLE_DDR, MOTOR_L_ENABLE_BIT);
	bit_set(MOTOR_L_PHASE_DDR, MOTOR_L_PHASE_BIT);
 
	// turn on the motors
	bit_set(MOTOR_R_ENABLE_PORT, MOTOR_R_ENABLE_BIT);
	bit_set(MOTOR_R_PHASE_PORT, MOTOR_R_PHASE_BIT);
	bit_set(MOTOR_L_ENABLE_PORT, MOTOR_L_ENABLE_BIT);
	bit_set(MOTOR_L_PHASE_PORT, MOTOR_L_PHASE_BIT);
 
	// turn on the white and red LEDs
	bit_set(LED_WHITE_L_PORT, LED_WHITE_L_BIT);
	bit_set(LED_WHITE_R_PORT, LED_WHITE_R_BIT);
	bit_set(LED_RED_L_PORT, LED_RED_L_BIT);
	bit_set(LED_RED_R_PORT, LED_RED_R_BIT);
 
	// enable internal pullup on PD0
	bit_set(PORTD, BIT(0));
	// enable external interrupts
	EIMSK = BIT(INT0) | BIT(INT1);
	// enable global interrupts
	sei();
 
	// loop forever
	while (1)
	{
 
		delayms(500);
	}
	return 0;
}
 
// delay for up to 65k milliseconds
void delayms(uint16_t millis) 
{
	// loop, delaying 1ms each iteration
	while ( millis ) 
	{
		_delay_ms(1);
		millis--;
	}
}
 
// this catches the Interrupt sent from pin INT0
ISR(INT0_vect) 
{
	//Turn everything off
	bit_clear(LED_WHITE_L_PORT, LED_WHITE_L_BIT);
	bit_clear(LED_WHITE_R_PORT, LED_WHITE_R_BIT);
	bit_clear(LED_RED_L_PORT, LED_RED_L_BIT);
	bit_clear(LED_RED_R_PORT, LED_RED_R_BIT);
 
	bit_clear(MOTOR_R_ENABLE_PORT, MOTOR_R_ENABLE_BIT);
	bit_clear(MOTOR_R_PHASE_PORT, MOTOR_R_PHASE_BIT);
	bit_clear(MOTOR_L_ENABLE_PORT, MOTOR_L_ENABLE_BIT);
	bit_clear(MOTOR_L_PHASE_PORT, MOTOR_L_PHASE_BIT);
 
 
	// loop forever, flashing our indicators.
	while(1)
	{
		bit_flip(LED_YELLOW_FL_PORT, LED_YELLOW_FL_BIT);
		bit_flip(LED_YELLOW_FR_PORT, LED_YELLOW_FR_BIT);
		bit_flip(LED_YELLOW_RL_PORT, LED_YELLOW_RL_BIT);
		bit_flip(LED_YELLOW_RR_PORT, LED_YELLOW_RR_BIT);
		delayms(500);
	}
}

R2 Project Log - External Interrupts

I’ve done some playing, and worked out how to turn on the external interrupts on the atmega128 I am using for R2.

Code:

#define F_CPU 1000000UL
#include < avr/io.h>
#include < util/delay.h>
#include < avr/interrupt.h>
 
#include "r2.h"
 
int main(void) {
	// Activate all the LEDs, set their pins to output
	bit_set(LED_WHITE_L_DDR, LED_WHITE_L_BIT);
	bit_set(LED_WHITE_R_DDR, LED_WHITE_R_BIT);
	bit_set(LED_RED_L_DDR, LED_RED_L_BIT);
	bit_set(LED_RED_R_DDR, LED_RED_R_BIT);
	bit_set(LED_YELLOW_FL_DDR, LED_YELLOW_FL_BIT);
	bit_set(LED_YELLOW_FR_DDR, LED_YELLOW_FR_BIT);
	bit_set(LED_YELLOW_RL_DDR, LED_YELLOW_RL_BIT);
	bit_set(LED_YELLOW_RR_DDR, LED_YELLOW_RR_BIT);
 
	// enable internal pullup on PD0
	bit_set(PORTD, BIT(0));
	// enable external interrupts
	EIMSK = BIT(INT0) | BIT(INT1);
	// enable global interrupts
	sei();
 
	// turn on the white and red LEDs
	bit_set(LED_WHITE_L_PORT, LED_WHITE_L_BIT);
	bit_set(LED_WHITE_R_PORT, LED_WHITE_R_BIT);
	bit_set(LED_RED_L_PORT, LED_RED_L_BIT);
	bit_set(LED_RED_R_PORT, LED_RED_R_BIT);
 
	// loop forever
	while (1)
	{
		delayms(500);
	}
	return 0;
}
 
// delay for up to 65k milliseconds
void delayms(uint16_t millis)
{
	// loop, delaying 1ms each iteration
	while ( millis )
	{
		_delay_ms(1);
		millis--;
	}
}
 
// this catches the Interrupt sent from pin INT0
ISR(INT0_vect)
{
	//Turn everything off
	bit_clear(LED_WHITE_L_PORT, LED_WHITE_L_BIT);
	bit_clear(LED_WHITE_R_PORT, LED_WHITE_R_BIT);
	bit_clear(LED_RED_L_PORT, LED_RED_L_BIT);
	bit_clear(LED_RED_R_PORT, LED_RED_R_BIT);
 
	// loop forever, flashing our indicators.
	while(1)
	{
		bit_flip(LED_YELLOW_FL_PORT, LED_YELLOW_FL_BIT);
		bit_flip(LED_YELLOW_FR_PORT, LED_YELLOW_FR_BIT);
		bit_flip(LED_YELLOW_RL_PORT, LED_YELLOW_RL_BIT);
		bit_flip(LED_YELLOW_RR_PORT, LED_YELLOW_RR_BIT);
		delayms(500);
	}
}

Changing Trigger Mode:

By default, the interrupt triggers when the pin is brought low. If we want to change this behavior, we need to poke at the External Interrupt Control Registers, EICRA (for INT0 - INT3) and EICRB (for INT4 - INT7).

Each interrupt pin has 2 bits in the EICR Registers, ISCxO and ISCx1. This Gives 4 possible options for triggering:

  • 0 0: Default, Trigger when INTx is held low
  • 0 1: Not Used
  • 1 0: Trigger when INTx changes from 1 to 0
  • 1 1: Trigger when INTx changes from 0 to 1

So, to turn on INT1, and set it to trigger on a rising edge, we,d use the following code:

// enable external interrupt
EIMSK = BIT(INT0);
//  set the interrupt to trigger on a rising edge
EICRA |= BIT(ISC00) | BIT(ISC01);

Video:

R2 Project Log - Battery Monitor Circuit

After playing with R2’s circuit, I realized I had left no ADC ports for monitoring my battery!  As it is a LiPo battery, it needs a low-voltage cutoff at 6v, or it will not be chargeable again.  I built a simple circuit with an attiny13 and a potential divider, which will trigger an interrupt on my main processor when the battery voltage gets to 6.2v.

Circuit Diagram:

R2\'s Cutoff Schematic

Code:

#define F_CPU 10000000UL
#include <avr /io.h>
#include <util /delay.h>
 
// delay for up to 65k milliseconds
void delayms(uint16_t millis) 
{
	// loop, delaying 1ms each iteration
	while ( millis ) 
	{
		_delay_ms(1);
		millis--;
	}
}
 
// initialise the adc
void init_adc ( void )
{
	//select external (VCC) voltage as the reference voltage (x0xx xxxx) 
	ADMUX = 0x00;
	//enable ADC (1000 0000)
	ADCSRA |= 0x80;
}
 
// read the specified adc
int adc_read ( uint8_t n )
{
	// set the adc to the chosen channel
	ADMUX = n;
	// start the ADC conversion, set the ADC clock to cpu clock / 16 (0100 0100)
	ADCSRA |= 0x44;
	// wait for the adc conversion to be completed
	while((ADCSRA & 0x40) !=0){};
	// return the adc result
	return ADC;
}
 
int main(void) 
{
	// set PB0 to output
	DDRB |= 1< <PB3;
	// turn on the ADC
	init_adc();
	// set up our variables
	int reading = 0, prev = 0, temp = 0;
	// loop for ever
	while(1) {
		// take a new adc reading
		reading = adc_read(2);
		// average it with the previous reading
		temp = (reading + prev) / 2;		
		// if the voltage is less than 6
		if ( temp > 185 )
		{
			// turn the output pin on
			PORTB &= ~(1< <PB3);
		}
		else
		{
			// turn the output pin off
			PORTB |= 1<<PB3; /* LED off */
		} 
		// save the current reading
		prev = reading;
		// wait for 20ms
		delayms(20);
	}
	return 0;
}

Photos:

R2 Project Log - Soldering complete!

I have finished soldering up r2, and have temporarily put him onto a microrobotics gearbox, until i can get round to making his custom aluminium motor mount / odometry harness, to get him as low as possible.

Now to write some software PWM code to get the motors running.

R2 Project Log - It’s Alive!

I spent Thursday & Friday evenings wiring up enough of the board to flash some LEDs, then set out to program it… Without success :(

After ripping apart the board, replacing the uC, and checking every single connection with a 10x Loupe, i turned to google, and found that the atmega128 is programmed differently to the other AVRs i’ve used, it has it’s own PDI and PDO pins connected to the first USART for uploading the program.

I wish someone had told me that before i bought the board!

Luckily, i had brought the USART pins out to their own header on the board, so after wiring up a programming adaptor, i was finally able to get some life!

R2 Project Log - Partially Assembled

After waiting for some new parts to arrive ( 1206 resistors dont fit on 0805 pads :/ )  I’ve sat down to do some assembly tonight.  Hopefully i’ll  manage to get it lighting those LEDs this week.

R2 Project Log - Boards are here!

Got into work this morning after two weeks sunning myself in Menorca to find my boards have arrived!

I’ll have to make a start at populating them tonight, see if i can’t get it flashing some lights or something for UKMM 08!

R2 Project Log - Board ordered

I’ve just sent off the board design for R2, 5 boards should arrive in a couple of weeks!

Hopefully i’ll be able to get the regulator all the LEDs and the processor working for the end of June, so i have something to show off at UKMM 2008!

Here are some renders i’ve exported from Gerbv Gerber Viewer, looking good!