Society of Robots - Robot Forum

Software => Software => Topic started by: D1g1talDragon on July 07, 2008, 10:40:14 PM

Title: Clunky newbie programming woes!
Post by: D1g1talDragon on July 07, 2008, 10:40:14 PM
Hi everyone!  I've been lurking around this site for a few weeks while I was working on my first AVR based 'bot, and unfortunately have to make my first post one that makes me feel a little slow...

I've basically been making a differential drive platform that's as modular and open as possible, purely as a training platform.  I'm pretty new to the AVR thing, so I figured I'd start simple and build up.  I've perused the code snippets, and I'm using Admin's "delay_cycles" method for controlling the servo pulses, since PWM makes my head hurt at the moment.

Bear with me, here comes my issue...

My code is thus:
Code: [Select]
while(1)

{
// Servo Test Code
i=250;    //Drive Fwd
while(i>0)
{
PORT_ON(PORTD, 0); //Left Servo Forward
delay_cycles(25);
PORT_OFF(PORTD, 0);
delay_cycles(200);

PORT_ON(PORTD, 1); //Right Servo Forward
delay_cycles(44);
PORT_OFF(PORTD, 1);
delay_cycles(200);
i--;
}

delay_cycles(500);

i=250;    //Drive Right
while(i>0)
{
PORT_ON(PORTD, 0); //Left Servo Forward
delay_cycles(25);
PORT_OFF(PORTD, 0);
delay_cycles(200);

PORT_ON(PORTD, 1); //Right Servo Back
delay_cycles(25);
PORT_OFF(PORTD, 1);
delay_cycles(200);
i--;
}

delay_cycles(500);
}

return 0;
}

(delay_cycles is straight outta SoR_utils.h)

Should be pretty simple.  I just want to run forward, then turn right a bit.  Now the funny part.  When the micro is hooked up to my AVR Dragon from inside AVR Studio, the code runs great.  Servos move forward, then right with no issues.  But once the Dragon is disconnected, and the bot is powered from the onboard 5V supply, the servos move one at a time, in a jerky motion.  It's almost as if the AVR had dropped its clock speed or something.  I'm running a dedicated 6VDC supply to the servos, and using a 5V regulator I built based on an LM7805, nothing fancy but the output is rock solid.

Any ideas?
Title: Re: Clunky newbie programming woes!
Post by: pomprocker on July 08, 2008, 10:00:12 AM
your code is saying "left then right" 250 times, then wait, then steer right 250 times.
Title: Re: Clunky newbie programming woes!
Post by: D1g1talDragon on July 08, 2008, 11:21:43 AM
Aha! Felt like I was missing something simple...

Thanks for the help.
Title: Re: Clunky newbie programming woes!
Post by: pomprocker on July 08, 2008, 12:09:05 PM
If you want to go straight you have to command the left and right servo forward at the same time at opposite pulse widths since one is mounted backwards.
Title: Re: Clunky newbie programming woes!
Post by: D1g1talDragon on July 08, 2008, 07:15:26 PM
So with the current code structure, what would be a good example of how to implement that?  I'm a little confused as to how to use this "delay method" to make the pulse widths I need to both servos at the same time.  Single servos, cake.   ;D  I have an idea of what I'm trying to ask in my head, but I seem to be having some difficulty putting it down in actual text...

Maybe it'd just be easier to try to stumble through the PWM stuff instead for what I want to accomplish here?

Thanks again for the response.
Title: Re: Clunky newbie programming woes!
Post by: pomprocker on July 08, 2008, 08:57:49 PM
Here is code from the $50 robot. I am running mine at 8mhz instead of 1mhz so i multiplied all my values by 8.
Code: [Select]

void servo_left(signed long int speed)
{
PORT_ON(PORTD, 2);
delay_cycles(speed);
PORT_OFF(PORTD, 2);//keep off
delay_cycles(1600); // 200 * 8
}

void servo_right(signed long int speed)
{
PORT_ON(PORTD, 3);
delay_cycles(speed);
PORT_OFF(PORTD, 3);//keep off
delay_cycles(1600); // 200 * 8
}

void robot_turn_left(void)
{
servo_left(200); // 25 * 8
servo_right(200); // 25 * 8
}

void robot_turn_right(void)
{
servo_left(352); // 44 * 8
servo_right(352); // 44 * 8
}

void robot_go_straight(void)
{
servo_left(200); // 25 * 8
servo_right(352); // 44 * 8
}

void hold_position(void)//37
{
servo_left(312);//39 * 8
servo_right(280);//35 * 8
}



Basically, you just call robot_go_sraight, right, left, hold, etc
Title: Re: Clunky newbie programming woes!
Post by: D1g1talDragon on July 08, 2008, 09:18:07 PM
That's almost exactly what I've tried, but it still seems to only do one servo, then the other, in small steps (the original issue I've been having).  Stepping through the code, it's not really sending the pulses at the same time, correct?  Your 8MHz code to move forward for example:

Code: [Select]
void robot_go_straight(void)
{
servo_left(200); // 25 * 8
servo_right(352); // 44 * 8
}

...jumps into the first function, moving the left servo for 200 ms, then has a 1952 ms delay (1600 + 352) before it's called again, since the micro is in the servo_right function.  Can't seem to find a workaround with the delay method.  I guess the bot DOES move forward, just one wheel at a time... ;D

Or am I still missing something big here?
Title: Re: Clunky newbie programming woes!
Post by: pomprocker on July 08, 2008, 10:39:56 PM
take it out of the decremented loop!!

just do something like
Code: [Select]


void servo_left(signed long int speed)
{
PORT_ON(PORTD, 2);
delay_cycles(speed);
PORT_OFF(PORTD, 2);//keep off
delay_cycles(200);
}

void servo_right(signed long int speed)
{
PORT_ON(PORTD, 3);
delay_cycles(speed);
PORT_OFF(PORTD, 3);//keep off
delay_cycles(200);
}

void robot_turn_left(void)
{
servo_left(25);
servo_right(25);
}

void robot_turn_right(void)
{
servo_left(44);
servo_right(44);
}

void robot_go_straight(void)
{
servo_left(25);
servo_right(44);
}

void hold_position(void)
{
servo_left(39);
servo_right(35);
}



while(1) {


robot_go_straight();

return 0;

} // end while loop


Title: Re: Clunky newbie programming woes!
Post by: D1g1talDragon on July 08, 2008, 11:16:48 PM
OK, I'm sure this is getting past the point of annoying you, but...

The loops were removed the last post, so that's not the issue.  Only looping is the main function.

Even using the exact code from your last post, I've got issues.  Now I just get a twitch from the servos when I power on my micro, and then nothing.  Ports were changed to reflect my configuration of using D0 and D1 for left and right.  I can use any port I want as long as it's configured for output, yes?

Sorry to keep this thread alive, but man, this is really aggravating.  I can't thank you enough for sticking with it though, I really do appreciate the help.
Title: Re: Clunky newbie programming woes!
Post by: pomprocker on July 08, 2008, 11:28:40 PM
Here is basic basic code for making your robot do nothing but go straight. If you're using the ATMega8, then download AVRlib

Code: [Select]


//AVR includes
#include <avr/io.h>     // include I/O definitions (port names, pin names, etc)
#include <avr/interrupt.h> // include interrupt support


//AVRlib includes
#include "global.h" // include global settings
#include "buffer.h" // include buffer function library
#include "rprintf.h" // include printf function library
//#include "timer.h" // include timer function library (timing, PWM, etc)
#include "a2d.h" // include A/D converter function library





//define port functions; example: PORT_ON( PORTD, 6);
#define PORT_ON( port_letter, number ) port_letter |= (1<<number)
#define PORT_OFF( port_letter, number ) port_letter &= ~(1<<number)
#define PORT_ALL_ON( port_letter, number ) port_letter |= (number)
#define PORT_ALL_OFF( port_letter, number ) port_letter &= ~(number)
#define FLIP_PORT( port_letter, number ) port_letter ^= (1<<number)
#define PORT_IS_ON( port_letter, number ) ( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number ) !( port_letter & (1<<number) )



//************CONFIGURE PORTS************
//configure ports for input or output - specific to ATmega8
void configure_ports(void)
{
DDRC = 0x00;  //configure all C ports for input
PORTC = 0x00; //make sure pull-up resistors are turned off
DDRD = 0xFF;  //configure all D ports for output
}
//***************************************

//************DELAY FUNCTIONS************
//wait for X amount of cycles (23 cycles is about .992 milliseconds)
//to calculate: 23/.992*(time in milliseconds) = number of cycles
//or (number of cycles)*.992/23 = time in milliseconds
void delay_cycles(unsigned long int cycles)
{
while(cycles > 0)
cycles--;
}
//***************************************

//*********SIMPLIFIED FUNCTIONS**********
//functions to make coding easier for a beginner
//but could cause port mixup confusion for intermediate users

void servo_left(signed long int speed)
{
PORT_ON(PORTD, 2);
delay_cycles(speed);
PORT_OFF(PORTD, 2);//keep off
delay_cycles(200);
}

void servo_right(signed long int speed)
{
PORT_ON(PORTD, 3);
delay_cycles(speed);
PORT_OFF(PORTD, 3);//keep off
delay_cycles(200);
}

void robot_turn_left(void)
{
servo_left(25);
servo_right(25);
}

void robot_turn_right(void)
{
servo_left(44);
servo_right(44);
}

void robot_go_straight(void)
{
servo_left(25);
servo_right(44);
}

void hold_position(void)
{
servo_left(39);
servo_right(35);
}
//***************************************

//*************INITIALIZATIONS***********
void initialize(void)
{
configure_ports(); // configure which ports are analog, digital, etc.
a2dInit(); // initialize analog to digital converter (ADC)
a2dSetPrescaler(ADC_PRESCALE_DIV32); // configure ADC scaling
a2dSetReference(ADC_REFERENCE_AVCC); // configure ADC reference voltage
}




int main(void)
{


initialize();

delay_cycles(42000);//two second wait delay




while(1)
{
robot_go_straight();
                        delay_cycles(400);      //a small delay to prevent crazy oscillations
         }  // end while loop

return 0;
}   // end main

Title: Re: Clunky newbie programming woes!
Post by: D1g1talDragon on July 10, 2008, 04:59:42 PM
Well, even going the most extreme route possible, and simply copying your exact code to my Mega, I'm having the same issues.  I'm thinking about trying to burn the chip straight from AVRDude on my Linux machine instead of AVRStudio, and then trying another chip if that doesn't work.  I'm finding it hard to believe all these problems are code related anymore, and hardware shouldn't be an issue, it's two freakin' outputs and a power supply!  I'm also getting kinda frustrated at seeming this clueless in my first thread here...  :-\  I'll figure it out eventually, but methinks it's time for a break and a beer.  The tackling will begin again tomorrow.   ;D

Thanks for the help Pom.
Title: Re: Clunky newbie programming woes!
Post by: ddemarco5 on July 10, 2008, 09:14:25 PM
you may have too much voltage going to your servos, causing an overload, hence the jerking.
Title: Re: Clunky newbie programming woes!
Post by: D1g1talDragon on July 10, 2008, 09:32:27 PM
Well, a quick update...

Got frustrated, started from scratch.  Even went so far as to reinstall my AVRlib so my directory structure would be unquestionable (even with no compiler errors...whatever).

Removed all headers with the exception of global.h from AVRlib.  It's pretty much the exact same program, but with everything for driving the servos in the main .c file.

And of course, for whatever magical reason, it seems to be working 100% this time around.  I have no clue why, but I don't care at this point.  I can figure that out tomorrow.   ;)

Thanks for the help guys, you've been more then patient.  I'm in trouble now though, since my LV-MaxSonar module just came in the mail along with the final touches for my mainboard.  Muahahaha... ;D
Title: Re: Clunky newbie programming woes!
Post by: krich on July 11, 2008, 11:14:18 AM
Glad you got it working! 

I've found that most of my issues originate from a loose nut on the keyboard.  Don't let it get you down, that's just the way it is.