Society of Robots - Robot Forum

Software => Software => Topic started by: ed1380 on April 08, 2007, 10:33:46 AM

Title: sending out 1.5ms
Post by: ed1380 on April 08, 2007, 10:33:46 AM
I'd like to send out a 1500 ms pulse to center my servos before modding then, but don't know how to do that.
My guess would be to program the atmega8-16pc, or use a cap resistor combo for it to pulse out at 1500ms
I know the general methos. but don't know how to actually do it.
What would the code be for the avr?
Thanks
Title: Re: sending out 1500ms
Post by: ed1380 on April 10, 2007, 02:45:16 PM
please anyone. the cable should be here anytime
Title: Re: sending out 1500ms
Post by: nanob0t on April 10, 2007, 02:46:43 PM
I know this is for the $50 robot project.  I am unfamiliar with the atmega8-16pc, though.

What do you program it in?  If I know this I probably can help you.
Title: Re: sending out 1500ms
Post by: dunk on April 10, 2007, 05:13:10 PM
so you can program AVRs in C or assembly.
most people choose C for simplicities sake.

as for timing routines, the easiest way is to set up a timer interupt.
this will interupt normal code execution at the specified interval.
the actual time between interupts will depend on a few things, your AVRs clock frequency being the most obvious but it is fairly easy to work this out from the datasheet.
once you know how many milliseconds between timer interupts, just count them until you reach 1500.

hmm. i think i just made that sound easy.
the first time i did it i spent a *lot* of time trying to get my timing pulses right.
if you can borrow an oscilloscope it will make things easier.

alternatively you can hunt around for some pre written code that gives you nice, precise delays without you having to code them yourself.
http://hubbard.engr.scu.edu/avr/avrlib/ (http://hubbard.engr.scu.edu/avr/avrlib/)

dunk.
Title: Re: sending out 1500ms
Post by: ed1380 on April 10, 2007, 06:24:41 PM
What you said didn't sound easy, but at least made some sence   :-\
Would this work?

Code: [Select]
i = 1500;
while(i > 0)
{
  servo_right(23);
  servo_left(23);
  i--;
}
Title: Re: sending out 1500ms
Post by: dunk on April 11, 2007, 03:25:15 AM
hmm. not really.
i'm guessing you meant to switch a pin on, wait 1500ms, switch pin off, wait ????ms, repeat?
which would be like this:
Code: [Select]
main(){
  while (0) {
    i = 0;
    pin_on();
    while (i < 1500){
      i++;
      pause_ms(1)
    }
    pin_off();
    while i < 5000){
      i++;
      pause_ms(1)
    }
  }
}

what i was talking about was this sort of thing:
Code: [Select]
#include <avr\io.h>
#include <avr\iom8.h>
#include <avr\interrupt.h>

#define XX **insert your value here**
#define YY **insert your value here**

uint8_t tick;
/* signal handler for timer interrupt TOV0 */
ISR(TIMER0_OVF_vect) {
  /* increase tick count every time timer interupt overflows */
  tick;++;
  /* monitor tick count and set servo pin value accordingly */
  if (tick <= XX){
    /* switch servo pin on */
  }
  if ((tick > XX) && (tick <= YY))
   /*switch servo pin off */
  }
  if (tick > YY){
    /* reset timer counter */
    tick = 0;
  }
}

int main(void) {
  /* use PortB for output */
  outp(0xFF, DDRB);
  /*enable timer overflow interrupt*/
  outp((1<<TOV0), TIMSK);
  /*set timer counter initial value*/
  TCNT0=0x00;
  /*start timer without presscaler*/
  outp((1<<CS00), TCCR0);
  /* enable interrupts */
  sei();

  /*loop forever */
  while 0 {
    /* do whatever you want in here. the timer interupt routine will take care of the servo pulses */
  }
}
so this code should nearly work as is but you still have the hard work to do.
you need to find out how often the timer interupt is called with your clock frequency and put in values for XX and YY accordingly.

there's a reasonable intro to timer0 on the AVRs here:
http://winavr.scienceprog.com/avr-gcc-tutorial/control-avr-8-bit-timer-counter0-using-avr-gcc.html (http://winavr.scienceprog.com/avr-gcc-tutorial/control-avr-8-bit-timer-counter0-using-avr-gcc.html)

dunk.
(hope i haven't over complicated things...)
Title: Re: sending out 1500ms
Post by: ed1380 on April 11, 2007, 05:31:32 AM
I just got this. Since this is a light seeking robot, if we unplug or cover up the photocells it'ss automatically stop and center teh servo's.
Right?
Title: Re: sending out 1500ms
Post by: dunk on April 11, 2007, 05:53:16 PM
Quote
I just got this. Since this is a light seeking robot, if we unplug or cover up the photocells it'ss automatically stop and center teh servo's.
Right?
watching the video of this little bot, i don't think the servos are ever stationary. they are either full forward or full reverse.

after skimming through Admin's code,
i see where you were getting the servo_right(23) and servo_left(23) functions.
Admin has done all the hard work for you here and if i interpret his comments in the file: SoR_Utils.h correctly,
multiply the number in the servo_right() function by 0.0431 to get the number of milliseconds pulse sent to the servo.
for example:
servo_right(23)
23 x 0.0431 = 0.992ms

the servo_right(23) function switches on the pin, waits for 23 time delays (of 0.0431ms each) then switches off the pin again, then waits for a further 200 time delays (of 0.0431ms each).

ok, so, the center position....
35 x 0.0431 = 1.5081ms.
so if you replace the relevant part of the main() function in Admin's code with this to get both servos in their center position.
Code: [Select]
while (0) {
  servo_right(35);
  servo_left(35);
}

sorry for not taking the time to read the $50 code before taking you on a trip of AVR timing routines....
i was explaining how to do it from scratch.

hmm. now i think about it, the title of this thread requested 1500ms. that's 1.5 seconds. i think your decimal point is off there.
you want 1.5ms for the center position on a servo.

dunk.
Title: Re: sending out 1.5ms
Post by: ed1380 on April 11, 2007, 06:19:03 PM
Thank you so much.
Now that, that is solved I still have a problem.

Mind checking this out? ;D
http://www.societyofrobots.com/robotforum/index.php?topic=865.0