critique my robot code (first try)

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

I'm new to this and thought I would attempt to make a robot that moved based on distance.  It should be pretty clear how this works.  I just really want to know what incredibly stupid mistakes I have made.

 

So far this is all theoretical and I have been testing using the simulator.

 

Sorry if this is silly, but I'm learning.  This is my 3rd ever AVR project.

 

The first was a simple row of LEDs with selectable rotating patterns and speeds.

The second was a Linear fader tester with touch sense support - ADC0 went directly to a uint8 which got sent to a 74hc595 and 8 leds to give a binary readout.

 

 * Robot.cpp
 *
 * Created: 1/22/2016 10:26:53 AM
 *  Author: Chris

 This will be an automated robot built off ultrasonic distance sensors.  The processor is running at 8MHZ and the time comes directly off of the overflow buffer of timer0
 What this means is the timer add's 1 every .031 second.  By taking the timervalue and multiplying it by .031 we have the time it took for the ping to be recieved.
 Using the average of 1125fps speed of sound we can than calculate distance in feet.

 Time = (timervalue * .031)/2
 Speed = 1125
 distance = Speed * Time / 12 - which gives us inches

 //PC4 and PC5 TWI pins

 pin assignment -
 ping B0
 listen interupt PD2
 left motor forward PD6 OC0A
 right motor forward PD5 OC0B
 left motor backward PB3 OC2A
 rightmotor backward PD3 OC2B
 SDA PC4
 SCL PC5

 From LCD.H

 LCD_PORT         PORTC
 LCD_DATA0_PORT   LCD_PORT
 LCD_DATA1_PORT   LCD_PORT
 LCD_DATA2_PORT   LCD_PORT
 LCD_DATA3_PORT   LCD_PORT
 LCD_DATA0_PIN    0
 LCD_DATA1_PIN    1
 LCD_DATA2_PIN    2
 LCD_DATA3_PIN    3
 LCD_RS_PORT      LCD_PORT
 LCD_RS_PIN       4
 LCD_RW_PORT      LCD_PORT
 LCD_RW_PIN       5
 LCD_E_PORT       PORTB
 LCD_E_PIN        4
 */ 

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <i2cmaster/twimaster.c>
#include <lcd/lcd.c>
#include <lcd/lcd.h>

#define pingport PORTB
#define pingpin PORTB0
#define leftmotor OCR2A
#define rightmotor OCR2B
//#define leftmotorforward OCR0A
//#define rightmotorforward OCR0B
//#define leftmotorbackward OCR2A
//#define rightmotorbackward OCR2B

uint64_t timer;
float time = 0;
double distance = 0;
uint8_t speed = 0;
#define pwm  (255 + speed - 128);

void initializepwm ()  // setup pwm 31250
{
	TCCR0B |= 1<<CS00;
	TIMSK0 |= 1<<TOIE0;  // timer setup  should probably move this....
	//TCCR0B |= 1<<CS02; //Prescaller /256

	//TCCR0A |= 1<<COM0A0;
	//TCCR0A |= 1<<COM0A1; //Phase correct PWM
	//TCCR0A |= 1<<WGM00;

	TCCR2B |= 1<<CS21;   //Prescaller /256
	TCCR2B |= 1<<CS22;

	TCCR2A |= 1<<COM2A0;
	TCCR2A |= 1<<COM2A1;   //Phase correct PWM
	TCCR2A |= 1<<WGM20;
}

void setupints ()
{
	EICRA |= 1<<ISC00;
	EICRA |= 1<<ISC01; //rising edge on int0
	EIMSK |=1<<INT0;  //start int0
	sei();
} 

void calculatedistance()
{
	//timer = 0;  // reset the timer
	pingport |= 1<<pingpin;  //ping high
	_delay_us(10);         //send for 10 microseconds
	pingport &= (~(1<<pingpin)); // ping low
	_delay_ms(2);
	//between the ping and the settup interrupts, this should calculate distance in inches.
}

void calculatespeed()
{
	if (distance >= 18)
	 {
		speed = 50;
	 }
	if (distance <= 12)
	 {
		speed = 25;
	 }
	else
	 {
		speed = 100;
  	 }
}

void move()
{

	leftmotor = pwm;
	rightmotor = pwm;

	if(distance <=6)
	{
		speed = 0;
		_delay_ms(200);
		leftmotor = 178;
		rightmotor = 78;
		_delay_ms(300);
		calculatedistance();
		if(distance <=12)
		{
			leftmotor = 78;
			rightmotor = 178;
			_delay_ms(600);
			calculatedistance();
			if(distance <=12)
			{
				speed = -25;
				_delay_ms(600);
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////

int main(void)
{
	//1 is output
	DDRB = 0b00011001;
	DDRC = 0b01111111; //display port
	DDRD = 0b01101000;

	initializepwm();  // set up pwm
	i2c_init();   //start i2c
	setupints();  // set up interrupts

	LCD_CLR;
	lcd_puts_P("Mr Robot ");

	distance = 250;

    while(1)
    {
		calculatedistance();
		calculatespeed();
		move();
	}

}

/////////////////////////////////////////////////////////////////////////
ISR (INT0_vect)
{
    time = timer *.031 / 2;  // calculate time using the timer
	distance = ((time * 1125)/12);
	timer = 0;
}

ISR (TIMER0_OVF_vect) //the timer overflow interrupt adds 1 to the timer and then is cleared by the overflow interrupt enable
{
	timer ++;
}

 

Last Edited: Wed. Feb 10, 2016 - 05:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So does it work? It seems not as timer should be volatile as it is shared between the 2 ISRs.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:

So does it work? It seems not as timer should be volatile as it is shared between the 2 ISRs.

 

It "appears" to work, although making timer volatile would make it more accurate wouldn't it?

 

I have just run it in simulator, so nothing practical yet.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 time = timer *.031 / 2;  // calculate time using the timer
	distance = ((time * 1125)/12);

 

what about

 

distance = (timer * 35 )/24 ; // with a 3/1000 relative error (is your sound speed, at your temperature and humidity, that accurate)

 

what is the use of twimaster?

 

You should not include lcd.c, but compile it separately (project managers ... just manage it)

 

volatile variables are meant ... to make things slower : if a variable is shared between ISR, and never used by main, optimiser -part of the compiler- wipes it out (lines using this variable are felt useless, and it is faster to get rid of them...) Declaring variables as volatile avoids this unpleasant behavior.

 

 

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

I made it volatile.  Makes sense, although it did appear to work correctly as it was.

 

TWI was meant to be additional peripherals that I would add in later to help with navigation, but now that I switched from H-bridges to a true motor controller I only need 2 PWM outputs - which are now from OCR2A/B.

 

Which means now that does nothing....  it's just left over and I should probably just delete it.

 

I suppose I could switch things around and use timer1 (OCR1A/B) as my PWM, but at this point I'll plan to just leave it as is.  If I am to build something with more peripherals I'll use a bigger chip.

 

So I guess the answer is - nothing.

 

 

This is really just an exercise in seeing if I'm on the right track and how bad I get internet shamed for my code.  It's not so much about troubleshooting as much as it is to see if I'm using the onboard peripherals properly. So far I'm quite pleased with the results!

 

Again, I have NO experience outside of these 3 projects with C or micro controllers at all.  I debated Arduino but decided to just skip that whole thing and go straight into this.

What I have learned so far comes from the datasheet, the simulator and clicking around the I/O view until I get what I want, and google - which ultimately just links to this site 9/10 times.

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

I have lots of example robot projects and code on my web site you may want to look at for ideas and examples.
http://pc.gameactive.org

"If you find yourself in an even battle, you didn't plan very well."
http://pc.gameactive.org
https://github.com/CmdrZin