Society of Robots - Robot Forum

Software => Software => Topic started by: airman00 on August 16, 2008, 11:16:12 PM

Title: cycles timing question
Post by: airman00 on August 16, 2008, 11:16:12 PM
23/.992*(time in milliseconds) = number of cycles

From where do we get the 23/.992 ?

Also, how would this formula change if the microcontroller was running at 16mHz

Btw I am writing a function for the Axon that is mS based instead of cycles , just to make it easier for me. I might write a function for angle also , once I have the mS done . Easier for me to go from mS to angle , then from cycles to angle .  ;)

Thanks
Title: cycles timing question
Post by: Admin on August 17, 2008, 11:17:31 AM
Quote
From where do we get the 23/.992 ?
My oscilloscope.

Quote
Also, how would this formula change if the microcontroller was running at 16mHz
If you are going from 1 MHz to 16 MHz, it should be:
23/.992*(16MHz/1MHz)*(time in milliseconds) = number of cycles

AVRlib has these functions that will already work on the Axon:
delay_ms(1000);
delay_us(1000);

However, I remember that AVRlib had some bug that if you put a variable in it like this:
delay_us(variable);
that it won't work if the variable went above 255. So thats why I created the cycles method for servos. Plus, on the $50 Robot, timer interrupts are limited.
Title: cycles timing question
Post by: airman00 on August 17, 2008, 12:40:17 PM
can AVRlib deal with fractions? ]

If I write a  macro for mS, can I do
Code: [Select]
servo(1.5)
Or can it not handle the 1.5?

Title: cycles timing question
Post by: Admin on August 17, 2008, 04:53:50 PM
Quote
If I write a  macro for mS, can I do
Code: [Select]
servo(1.5)Or can it not handle the 1.5?

I just tried both of these:
Code: [Select]
PORT_ON(PORTE, 6);
delay_ms(1.9);
PORT_OFF(PORTE, 6);
delay_ms(1);
and
Code: [Select]
PORT_ON(PORTE, 6);
delay_ms(1);
PORT_OFF(PORTE, 6);
delay_ms(1);

and got a frequency of 471 Hz for both.

This also shows that the ATmega640 clock isn't perfect (5.8% error), as it should have been 500Hz. The $50 Robot clock will not be perfect either.
Title: Re: cycles timing question
Post by: airman00 on August 17, 2008, 07:48:35 PM
However, I remember that AVRlib had some bug that if you put a variable in it like this:
delay_us(variable);
that it won't work if the variable went above 255. So thats why I created the cycles method for servos. Plus, on the $50 Robot, timer interrupts are limited.

does that mean that this wont work? Or is the bug fixed already?

#define servo(port,number,position)   (PORT_ON(port,number), delay_us(position), PORT_OFF(port,number))

I made it time based instead of cycles based - its just easier for me .
Title: Re: cycles timing question
Post by: pomprocker on August 18, 2008, 10:42:50 AM
just use 1500uS instead of 1.5mS
Title: Re: cycles timing question
Post by: airman00 on August 18, 2008, 03:25:58 PM
just use 1500uS instead of 1.5mS

yea that was what I was planning to use but admin said there was a bug for using variables above 255 in delay_us.  I wanted to know if the macro would work since its not really a variable , but rather passing numbers - i think.

Title: Re: cycles timing question
Post by: pomprocker on August 18, 2008, 03:34:37 PM
also check out <util/delay.h>

http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
Title: Re: cycles timing question
Post by: airman00 on August 18, 2008, 09:03:44 PM
will this work :

Code: [Select]
Set up code:
'set up servo macro
#define servo(port,number,position)   (PORT_ON(port,number), delay_us(position), PORT_OFF(port,number))
'hardware define:
#define servo1( position ) servo(PORTE,6,position)

Then when I want to control the servo :
Code: [Select]
servo1(1500)
The only reason I can see for it not to work is because of that bug Admin mentioned. But I was wondering if one of the more seasoned programmers can help me out.


Title: Re: cycles timing question
Post by: pomprocker on August 18, 2008, 11:42:10 PM
instead of using software based pwm, why don't you use the pwm capabilities built into the avr?
Title: Re: cycles timing question
Post by: airman00 on August 19, 2008, 05:24:22 AM
instead of using software based pwm, why don't you use the pwm capabilities built into the avr?

Because there are only 9 PWM channels but I have a lot of servos
Title: Re: cycles timing question
Post by: Ro-Bot-X on August 19, 2008, 05:45:04 AM
Arduino has a ServoTimeTimer1 that works like you described: Servo1(1500). Check it out here: http://www.arduino.cc/playground/ComponentLib/Servotimetimer1 (http://www.arduino.cc/playground/ComponentLib/Servotimetimer1)
Title: Re: cycles timing question
Post by: airman00 on August 19, 2008, 06:21:25 AM
thanks RobotX but I think the code is pin specific ,

Will that code I posted above work?
Title: Re: cycles timing question
Post by: JesseWelling on August 19, 2008, 06:50:34 AM
I'm working on a configurable PWM C code that is somewhat object oriented and utilizes hardware timers but It's not quite working yet. Any one who wants to look at it can but to make it compile you'd have to take out a bunch of debug stuff. And if any one can find the bug before I can let me know. Once I get this working I need to make it a more general solution (For any F_CPU) and then Add support for more than one timer.
Title: Re: cycles timing question
Post by: airman00 on August 20, 2008, 05:28:29 AM
What I want to do is to be able to control the servos the same way that the SSC-32 controls it.
Its command to control the servos are :
Code: [Select]
'RA,                    RK,      RH,       LA,                LK,                 LH,        speed
#0 P1427      #1 P1292   #2 P1292  #16 P1573    #17 P1708    #18 P1708   T500
Where RA is right ankle,RK is Right Knee, RH is Right Hip, etc.
The pulse is in uS as you can see by the " P1427" which is a pulse for 1427 uS.

I want to control the servos from the Axon in a way similar to this . I want a macro that does servo1(1427) . Can anyone help me to write this macro? I still don't know if a bug exists for having a variable larger than 255 in a delay_us macro. 

And I'd rather not use UART from the Axon to control the SSC-32 , I want it all done on the Axon.
Title: Re: cycles timing question
Post by: pomprocker on August 20, 2008, 11:52:40 AM
can you write your own function

Code: [Select]
void pulse(uint8_t microseconds) {

     while (microseconds > 0) {
          delay_us(1);
          microsecs--;
     }  // end while loop

} // end pulse function
Title: Re: cycles timing question
Post by: paulstreats on August 20, 2008, 05:29:03 PM
The way I got around it in Pic18's running a 20mhz clock was like the sample below.

Basically you call the function and pass the degree that you want the servo to turn to as the parameter (0 = far right. 180 = far left on servo. 90= servo centered). so i would write move_servo(90) to center the servo.

The thing is that its a freak occurence that running a 20mhz clock produces the correct servo angle when the angle degree is multiplied by 4 (in the PIC because it delays according to instruction cycles). But maybe it can be modified to your needs...


Code: [Select]
void move_servo(unsigned int duty){

SERVO1 = 1;
Delay10TCYx(duty);
Delay10TCYx(duty);
Delay10TCYx(duty);
Delay10TCYx(duty);
SERVO1 = 0;
}

There is obviously a small loss in precision by having to call the delay 4 times but its not going to be huge.

Doing it this way means that nothing else can happen while the servo is being pulsed. If you are wanting to do that then you need some serious speed.

Try to find the common denominator between the delay functions and the servo angles and you will eventually come up with something that will work for you.
Title: Re: cycles timing question
Post by: Admin on August 22, 2008, 08:56:41 AM
You could just write a quickie function that converts milliseconds to cycles . . .
Title: Re: cycles timing question
Post by: airman00 on August 22, 2008, 08:58:30 AM
You could just write a quickie function that converts milliseconds to cycles . . .

I'm confused

Didn't you say that the Axon cannot do 23/.992 since it will round up and will end up being 23/1 ???

I want it accurate also.
Title: Re: cycles timing question
Post by: Admin on August 22, 2008, 09:07:00 AM
23/.992*(time in milliseconds) = number of cycles

Lets say you want 1.5ms, then you get 34 cycles.

Or 1.1ms, 25. Or 2ms, 46.

This is already way more accurate than your servos will be, trust me :P

The Axon runs 16 times faster than the $50 Robot, so you'll get 16x higher accuracy on the cycles method.
Title: Re: cycles timing question
Post by: pomprocker on August 22, 2008, 09:52:13 AM
I'm no expert but I was reading on AVRfreaks that servo delays are for n00bs, and that the proper thing to do would be to use timers. The higher resolution the timer the better.
Title: Re: cycles timing question
Post by: Admin on August 22, 2008, 10:46:42 AM
Nope not for n00bs. It has a lot to do with your processing requirements, if you have other interrupts running, how many servos you plan to use, how many timers you have, etc.

For example, if you only have 4 servos, thats only a ~25ms delay per second. Hardly worth the frustration of implementing timer interrupts.

Now if you are making a 25 servo biped with tons of sensor processing, well thats another story . . .
Title: Re: cycles timing question
Post by: airman00 on August 22, 2008, 03:22:14 PM
I did what pomprocker suggested. Thanks!!!

Heres the macro:
Code: [Select]
void pulse(uint8_t microseconds) {

     while (microseconds > 0) {
          delay_us(1);
          microseconds--;
     }  // end while loop

} // end pulse function


and heres the modified servo define code:
Code: [Select]
//define the servo function macro
#define servo(port,number,position)   (PORT_ON(port,number), pulse(position), PORT_OFF(port,number))

To call the macro I just do :
Code: [Select]
servo_1(1500)  // where 1500 is the pulse in microseconds.


Title: Re: cycles timing question
Post by: Admin on August 22, 2008, 03:55:03 PM
Looks exactly like my cycles code, but with a timer delay inside of it . . . I not sure which is more accurate, probably the only way to know is by comparing both with an oscope . . .

your code:
Code: [Select]
void pulse(uint8_t microseconds) {

     while (microseconds > 0) {
          delay_us(1);
          microseconds--;
     }  // end while loop

} // end pulse function

my cycles code (with your variables):
Code: [Select]
void pulse(uint8_t microseconds) {

     while (microseconds > 0) {
          microseconds--;
     }  // end while loop

} // end pulse function
Title: Re: cycles timing question
Post by: airman00 on August 22, 2008, 04:06:46 PM
one second

the servos are turning but no matter what I give them 1000 - 2000 they will always turn the most extreme 2000 point. This reminds me of my PULSOUT problems the PIC microcontroller where the oscillator speed caused issues. 

I'll get back to you guys once I try a solution.
Title: Re: cycles timing question
Post by: airman00 on August 22, 2008, 04:10:28 PM
found the issue :

Exactly the same problem with my PIC . Dividing the amount in microseconds by 16 solves the problem. I think delay_us might be faulty.

This works

Code: [Select]
void pulse(unsigned long int microseconds) {
     microseconds=microseconds/16;
     while (microseconds > 0) {
          delay_us(1);
          microseconds--;
     }  // end while loop

} // end pulse function

Btw I changed it to unsigned long int b/c its easier for me to understand the code at a glance
Title: Re: cycles timing question
Post by: dunk on August 22, 2008, 05:41:54 PM
so i'm no C expert but you guys have me thinking about C data types...

Airman: when you first tried to use the "uint8_t" type to define "microseconds" you were limiting that variable to 1 bite = 8 bits = a maximum value of 255.
the type "unsigned long int" you use later is possibly a little excessive allowing 4 bites = max value of 4294967295. but hey, you have plenty of memory on the AVR right?

Admin: when you were talking about the bug with delay_us accepting  a max value of 255 near the start of this thread, delay_us in AVRlib is written to accept the type "unsigned short" which i  believe is the same as "unsigned short int" should be good for 2 bytes...
this strikes me as a compiler issue rather than a AVRlib issue.
what compiler do you use?
i'm guessing you could chance AVRlib's timer.c to make delay_us use type "int" instead of "short int" as a workaround.


dunk.
Title: Re: cycles timing question
Post by: pomprocker on August 22, 2008, 05:58:50 PM
They are typdefs

http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/docs/html/avrlibtypes_8h-source.html (http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/docs/html/avrlibtypes_8h-source.html)

Title: Re: cycles timing question
Post by: Admin on August 22, 2008, 06:11:16 PM
Quote
so i'm no C expert but . . . the type "unsigned long int" you use later is possibly a little excessive allowing 4 bites = max value of 4294967295.
Isn't it 65535? And isn't it spelled 'byte'? Don't you work for google? ;D

Quote
Admin: when you were talking about the bug with delay_us accepting  a max value of 255 near the start of this thread, delay_us in AVRlib is written to accept the type "unsigned short" which i  believe is the same as "unsigned short int" should be good for 2 bytes...
this strikes me as a compiler issue rather than a AVRlib issue.
what compiler do you use?
i'm guessing you could chance AVRlib's timer.c to make delay_us use type "int" instead of "short int" as a workaround.
I should reclarify that I first read and I *think* even experienced this problem about 1.5-2 years ago. I don't really remember anymore, shoddy memory from the days I was an AVR noob . . . but yea I think if I change it to 'long int' it should work . . . Im using the gcc compiler. I'll try it out when I have time and add it to the next Axon software upgrade if it works.
Title: Re: cycles timing question
Post by: dunk on August 22, 2008, 06:20:00 PM
Quote
Isn't it 65535
65535 would be 2 bytes.
4 bytes = max value of 0xFFFFFFFF = 4294967295.

Quote
And isn't it spelled 'byte'?
bahh. fix your website's spilling chacker.


dunk.
Title: Re: cycles timing question
Post by: Admin on August 22, 2008, 10:20:17 PM
Hmmmm but on gcc for microcontrollers it sets unsigned int to 256, where its 8 bit, or 2^8.

And for unsigned long int, it is 65535, for 2^16.

Its not the same as on a PC where an unsigned long int is 2^32, or 4294967296.
(not 4294967295 ;D)
Title: Re: cycles timing question
Post by: dunk on August 23, 2008, 05:00:21 AM
Quote
Hmmmm but on gcc for microcontrollers it sets unsigned int to 256, where its 8 bit, or 2^8.
really? i didn't know that. got link?

the link to the AVRlib file Pomprocker posted should take precedence over GCCs defaults though. http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/docs/html/avrlibtypes_8h-source.html (http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/docs/html/avrlibtypes_8h-source.html)
i usually use AVRlib which is probably why i've never picked up on this before.

Quote
(not 4294967295 Grin)
well if we want to get pedantic about it.... i was talking about the highest value in a 4 byte int so, yes 4294967295.
it's 4294967296 different values. from 0 to 4294967295. the highest value is 4294967295. (0 takes up one place.)
the same as the highest value for a 1 byte integer is 255 (not 256).


dunk.
Title: Re: cycles timing question
Post by: Admin on August 23, 2008, 06:38:55 AM
Hmmmm I should have read though that link further . . . this is odd tho . . . because when I declare an unsigned long int, my variable resets at 65535 . . . yet this code says 4294967295 for unsigned long ints . . .

Sorry for being 'pedantic', I was just poking fun :P
Title: Re: cycles timing question
Post by: dunk on August 23, 2008, 12:16:12 PM
Quote
Sorry for being 'pedantic', I was just poking fun Tongue
yes. me too. bring it.

maybe i should make it more obvious....
naaa. you'll work it out.


dunk.
Title: Re: cycles timing question
Post by: airman00 on August 23, 2008, 10:16:40 PM
But still why did i have to do this for it to work?
Code: [Select]
microseconds=microseconds/16;
Title: Re: cycles timing question
Post by: pomprocker on August 23, 2008, 11:04:27 PM
well the delay_us function is calculated by whats in global.h right?

so whats your F_CPU?
Title: Re: cycles timing question
Post by: airman00 on August 24, 2008, 05:46:33 AM
well the delay_us function is calculated by whats in global.h right?

so whats your F_CPU?
16mhz
Title: Re: cycles timing question
Post by: pomprocker on August 24, 2008, 12:13:59 PM
maybe the function we came up with is a combination of a cycle delay and a timer delay
Title: Re: cycles timing question
Post by: airman00 on August 24, 2008, 11:22:25 PM
OK so even when dividing by 16 I dont get the correct position

I'll play around with this thing later . It seems like cycles based timing would be more accurate anyways
Title: Re: cycles timing question
Post by: airman00 on August 24, 2008, 11:46:06 PM
According to Admin to calculate the cycles from mS you use the formula below
23/.992*(16MHz/1MHz)*(time in milliseconds) = number of cycles
Also, it says on the Axon page to use 700 cycles as the centering cycle

Now if we solve :
23/.992 = 23.1854839
and we say that 1.5mS is the pulse needed to center a servo

23.1854839 *(16) * (1.5) = 556.451614

So where do we get the 700 cycles from???
My only guess would be for 20mhz since for that it would be
23.1854839 * 20 * 1.5 = 695.564517
Title: Re: cycles timing question
Post by: Admin on August 25, 2008, 04:46:48 AM
Thats the equation for the $50 Robot, not the Axon. Use this:
234/1.003*(time in milliseconds) = number of cycles

Also, centering can be different if you modded the servo differently. You might find it centering between 500-700.

(Where did I say 700 so I can update that?)
Title: Re: cycles timing question
Post by: airman00 on August 25, 2008, 07:35:52 AM
By the axon sample code page

Quote
SERVO CENTER CODE

      People ask all the time for the code used to center the servo. Well, here you go!

      while(1)
         {
         if(button_pressed())
            {
            wheel_left(700);
            delay_ms(20);
            }
         }
Title: Re: cycles timing question
Post by: airman00 on August 25, 2008, 07:51:28 AM
Use this:
234/1.003*(time in milliseconds) = number of cycles
That means that
(234 / 1.003) * 1.5 = 349.95015
Shouldn't it be higher than 349 ?

Also if we look into this post about the "magic numbers" - http://www.societyofrobots.com/robotforum/index.php?topic=2724.0
We see that he correctly says
Quote
Let’s compute how many cycles the 1.5 ms correspond. For this case, the number of cycles would be…
23/.992*(1.5) = 34.8 (let’s make an integer of 35).

So thats 34.8 @ 1 mHz ( speed of 50 dollar robot) and guess what 34.8 * 16 ( speed of Axon) is ? Its  556 .
I know I am basically just repeating the formula I posted up before , but this is my logic to get 556.

Also, centering can be different if you modded the servo differently. You might find it centering between 500-700.
I am using the servos in my bipedal robot and I am not modifying them. 1.5 mS is the standard pulse for centering servos.
Title: Re: cycles timing question
Post by: airman00 on August 25, 2008, 08:40:09 AM
hmmm for some reason 700 seems to be  the center point of the servo much more so than 556 is .

Also if you do the math  A pulse of 3 mS would equal 700 cycles , and 3mS/2  gives you 1.5mS , the code to center it.
I need some serious explaining here .


Update:
I've been playing around with it more and it turns out that the formula below seems to be the correct one

(234 / 1.003) * 2 * mS  or even easier just do       466.6 * mS = number of cycles
Example:  466.6 * mS = 699.9 cycles  // around 700 cycles