Author Topic: WebbotLib for 22+ Servos  (Read 20383 times)

0 Members and 1 Guest are viewing this topic.

Offline Hasan999Topic starter

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
WebbotLib for 22+ Servos
« on: January 23, 2010, 04:53:04 PM »
EDIT: Just to save your time, instead of reading from here...(since some of the problems were resolved), please proceed to page 2, and start reading from my post #50 with Topic: "Servos Do Not Hold Tight !"

---------------------------------------------------------------------------------------------------

[Axon Microcontroller - Servos: HS-422]

Since I am using a lot of servos that, when run simultaneously, they exceed 20ms between pulses !

I was wondering if I connect a few servos in pairs (using Y-harness), to use 1 port instead of 2, would that decrease the processing time?

i.e. just for example:

Code: [Select]
for(;;){
servo(PORTA,1,650);
servo(PORTA,2,650); // <-- this won't be there if I use Y-harness*
delay_ms(18); }

*would it reduce overall processing time for that loop?

btw, I don't have Y-wires, i'll do it manually since I have extra extender wires... would that work fine?

Thanks !


admin edit: as requested, marked as solved - it was a painful 2 months for everyone :P
« Last Edit: March 14, 2010, 11:39:19 AM by Admin »

Offline z.s.tar.gz

  • Supreme Robot
  • *****
  • Posts: 540
  • Helpful? 5
  • Linux Guru
Re: Y-harness on servos
« Reply #1 on: January 23, 2010, 05:51:09 PM »
It would take less processing time, but you would basically be treating two servos as one.

What I would do in your situation would be to buy a bunch of little PWM chips that can replicate the signal even after you've stopped sending it.
You would need one per servo.
Save yourself the typing. Just call me Zach.

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: Y-harness on servos
« Reply #2 on: January 23, 2010, 06:20:14 PM »
Hi,

Or 1 I/O-line could drive up to 9 servos through a 4017 (+ glue).

Just output a signal with the PW for servo 1, then the PW for servo 2 etc. and make a longer pulse (+ a bit circuitry) for resetting to keep it synchronized.

A small µcontroller could be used as well.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: Y-harness on servos
« Reply #3 on: January 23, 2010, 09:12:59 PM »
How many servos?

Look into using WebbotLib, it is better for handling 15+ servos.
(see Axon II tutorial for step-by-step instructions)

Offline Hasan999Topic starter

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
WebbotLib for 22+ Servos
« Reply #4 on: January 24, 2010, 09:10:09 AM »
[Axon Microcontroller - Servos: HS-422]

As per a lot of members' (including Admin's) advice, I started using Webbot Library...

Although it uses interrupts to control servos, I am facing the same problem again...

I'll be using 26 servos (but since I didn't calibrate the wheels yet, i'm using 22 servos for the start)

Problem: the servos jitter !

For less than 4 servos, no jitteriness (each servo is held tight)
For 12 servos, slight vibration (holding not so tight, easily movable by hand)
For 16+ servos, a lot of jitteriness !

Code: [Select]
#include "sys/axon.h"
#include "uart.h"
#include "rprintf.h"
#include "servos.h"
#include "a2d.h"

SERVO S1 = MAKE_SERVO(FALSE, J6,1500, 500);
SERVO S2 = MAKE_SERVO(FALSE, A6,1500, 500);
SERVO S3 = MAKE_SERVO(FALSE, E7,1500, 500);
SERVO S4 = MAKE_SERVO(FALSE, H2,1500, 500);
SERVO S5 = MAKE_SERVO(FALSE, C1,1500, 500);
SERVO S6 = MAKE_SERVO(FALSE, A5,1500, 500);
SERVO S7 = MAKE_SERVO(FALSE, E2,1500, 500);
SERVO S8 = MAKE_SERVO(FALSE, H6,1500, 500);
SERVO S9 = MAKE_SERVO(FALSE, C0,1500, 500);
SERVO S10 =MAKE_SERVO(FALSE, A4,1500, 500);
SERVO S11 =MAKE_SERVO(FALSE, E3,1500, 500);
SERVO S12 =MAKE_SERVO(FALSE, H5,1500, 500);
SERVO S13 =MAKE_SERVO(FALSE, C3,1500, 500);
SERVO S14 =MAKE_SERVO(TRUE,  A2,1500, 500);
SERVO S15 =MAKE_SERVO(FALSE, E4,1500, 500);
SERVO S16 =MAKE_SERVO(TRUE,  H4,1500, 500);
SERVO S17 =MAKE_SERVO(FALSE, C4,1500, 500);
SERVO S18 =MAKE_SERVO(FALSE, A1,1500, 500);
SERVO S19 =MAKE_SERVO(FALSE, E5,1500, 500);
SERVO S20 =MAKE_SERVO(FALSE, H3,1500, 500);
SERVO S21 =MAKE_SERVO(FALSE, A7,1500, 500);
SERVO S22 =MAKE_SERVO(FALSE, A3,1500, 500);
/*
SERVO W1 =MAKE_SERVO(FALSE, C2,1500, 500);
SERVO W2 =MAKE_SERVO(FALSE, C6,1500, 500);
SERVO W3 =MAKE_SERVO(FALSE, E6,1500, 500);
SERVO W4 =MAKE_SERVO(FALSE, C5,1500, 500);
*/
SERVO_LIST servos[] = {&S1,&S2,&S3,&S4,&S5,&S6,&S7,&S8,&S9,&S10,&S11,&S12,&S13,&S14,&S15,&S16,&S17,&S18,&S19,&S20,&S21,&S22};

SERVO_DRIVER bank1 = MAKE_SERVO_DRIVER(servos);

void appInitHardware(void){
// Set UART0 to 19200 baud
uartInit(UART0, 115200);
//uartInit(UART0, 19200);
// Tell rprintf to output to UART0
rprintfInit(&uart0SendByte);

// Initialise the servo controller
servosInit(&bank1, TIMER1_COMPAREA);
//servoPWMInit(&bank1);
// Give each servo a start value of 'stop'

act_setSpeed(&S1,0);
act_setSpeed(&S2,0);
act_setSpeed(&S3,0);
act_setSpeed(&S4,0);
act_setSpeed(&S5,0);
act_setSpeed(&S6,0);
act_setSpeed(&S7,0);
act_setSpeed(&S8,0);
act_setSpeed(&S9,0);
act_setSpeed(&S10,0);
act_setSpeed(&S11,0);
act_setSpeed(&S12,0);
act_setSpeed(&S13,DRIVE_SPEED_MIN);
act_setSpeed(&S14,DRIVE_SPEED_MIN);
act_setSpeed(&S15,DRIVE_SPEED_MIN);
act_setSpeed(&S16,DRIVE_SPEED_MIN);
act_setSpeed(&S17,0);
act_setSpeed(&S18,0);
act_setSpeed(&S19,0);
act_setSpeed(&S20,0);
act_setSpeed(&S21,0);
act_setSpeed(&S22,0);

}

// The loopStart parameter has the current clock value in ìS
TICK_COUNT appInitSoftware(TICK_COUNT loopStart){
return 0; // dont pause after
}
// This routine is called repeatedly - its your main loop
TICK_COUNT appControl(LOOP_COUNT loopCount, TICK_COUNT loopStart){

act_setSpeed(&S1,0);
act_setSpeed(&S2,0);
act_setSpeed(&S3,0);
act_setSpeed(&S4,0);
act_setSpeed(&S5,0);
act_setSpeed(&S6,0);
act_setSpeed(&S7,0);
act_setSpeed(&S8,0);
act_setSpeed(&S9,0);
act_setSpeed(&S10,0);
act_setSpeed(&S11,0);
act_setSpeed(&S12,0);
act_setSpeed(&S13,DRIVE_SPEED_MIN);
act_setSpeed(&S14,DRIVE_SPEED_MIN);
act_setSpeed(&S15,DRIVE_SPEED_MIN);
act_setSpeed(&S16,DRIVE_SPEED_MIN);
act_setSpeed(&S17,0);
act_setSpeed(&S18,0);
act_setSpeed(&S19,0);
act_setSpeed(&S20,0);
act_setSpeed(&S21,0);
act_setSpeed(&S22,0);

return 20000;
}

I tried reducing return 20000; to return 0;, but still the same jitteriness !

I have also tried making different banks, drivers etc, by grouping servos... (edit)then only a few servos work !

I tried that in this way: ...(just an example)

Code: [Select]
SERVO_LIST servo1[] = {&S1,&S2,&S3,&S4};
SERVO_LIST servo2[] = {&S5,&S6,&S7,&S8};

SERVO_DRIVER bank1 = MAKE_SERVO_DRIVER(servo1);
SERVO_DRIVER bank2 = MAKE_SERVO_DRIVER(servo2);

servosInit(&bank1, TIMER1_COMPAREA);
servosInit(&bank2, TIMER1_COMPAREA);

//rest same

Please help me figure out the problem... in order to operate 22+ servos without jitteriness !

Thanks !

« Last Edit: January 24, 2010, 02:05:36 PM by Hasan999 »

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #5 on: January 24, 2010, 12:06:41 PM »
You need to use an extra SERVO_DRIVER for each multiple of 10 servos since each driver times it's assigned servos in a round-robin fashion.

In your code where you try multiple SERVO_DRIVERs it looks like you try to assign each driver to the same timer....
Code: [Select]
servosInit(&bank1, TIMER1_COMPAREA);
servosInit(&bank2, TIMER1_COMPAREA);

Try assigning each driver to a different timer.

 

Offline Hasan999Topic starter

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
Re: WebbotLib for 22+ Servos
« Reply #6 on: January 24, 2010, 01:19:06 PM »
Quote
Try assigning each driver to a different timer.

when I try with different Timers... only the servos using TIMER1_COMPAREA work, the others don't get any pulse !

bank1 servos work in this case:

Code: [Select]
SERVO_LIST servo1[] = {&S1,&S2,&S3,&S4,&S5,&S6,&S7,&S8};
SERVO_LIST servo2[] = {&S9,&S10,&S11,&S12,&S13,&S14,&S15};
SERVO_LIST servo3[] = {&S16,&S17,&S18,&S19,&S20,&S21,&S22};

SERVO_DRIVER bank1 = MAKE_SERVO_DRIVER(servo1);
SERVO_DRIVER bank2 = MAKE_SERVO_DRIVER(servo2);
SERVO_DRIVER bank3 = MAKE_SERVO_DRIVER(servo3);

servosInit(&bank1, TIMER1_COMPAREA);
servosInit(&bank2, TIMER2_COMPAREB);
servosInit(&bank3, TIMER3_COMPAREC);

Also, i was wondering, the "return 20000;" is it an additional delay? or does it mean that it will re-loop afte 20ms from the start? ...should I keep it 20000 or 0 ?

Thanks..
« Last Edit: January 24, 2010, 02:10:33 PM by Hasan999 »

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #7 on: January 24, 2010, 02:18:56 PM »
Quote
btw I re-tried for all  the servos in different banks but using same TIMER1, I notice that the jitteriness is even worse ! (slower)
You would expect performance to get worse as you are now attempting to run three conflicting code threads on one timer resource.

Code: [Select]
servosInit(servosInit(&bank2, TIMER2_COMPAREB);
servosInit(&bank3, TIMER3_COMPAREC);
The code you have tried won't work for the following reasons:

Timer2 is an 8 bit timer and these functions require a 16 bit - so use timers 3-5 instead.

Your bank3 code tries to assign a register which doesn't exist. TIMERx_COMPAREA or TIMERx_COMPAREB correspond to the two compare registers associated with each timer so use A or B but not C.

Try:
Code: [Select]
servosInit(&bank2, TIMER3_COMPAREA);
servosInit(&bank3, TIMER4_COMPAREA);

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #8 on: January 24, 2010, 09:59:31 PM »
Quote
// Give each servo a start value of 'stop'
You don't need to do this, WebbotLib starts all servos off by default at zero degrees.

Quote
servosInit(&bank1, TIMER1_COMPAREA);
servosInit(&bank2, TIMER2_COMPAREB);
servosInit(&bank3, TIMER3_COMPAREC);
You can run all servos from the same timer, no need to use multiple timers. Its actually better just to use one.
That being said, on my 20-servo robot fish, I run half my servos using PWM, the other half using a single timer interrupt.

As hopslink said, your servo timer must be 16 bit (check ATmega640 manual, or Axon II datasheet, to determine which is which).

Also, are all your servos HS-422? Is torque constantly being applied to them? How much jitter? Do the servos overheat while they jitter?


ps - Hasan999, keep your related posts together. I just merged your last two posts. ;D

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #9 on: January 25, 2010, 03:58:31 AM »
Quote
You can run all servos from the same timer, no need to use multiple timers. Its actually better just to use one.
While that is possible by writing your own servo driver code I am not sure that the Webbotlib servo functions work in that manner (though I may well be wrong...).

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #10 on: January 25, 2010, 04:20:07 AM »
Quote
You can run all servos from the same timer, no need to use multiple timers. Its actually better just to use one.
While that is possible by writing your own servo driver code I am not sure that the Webbotlib servo functions work in that manner (though I may well be wrong...).
My ERP uses 12 servos, all running from:
servosInit(&bank2, TIMER3_COMPAREA);

My 20 servo robot fish uses all of the PWM pins, and a timer for the remaining servos:
Code: [Select]
SERVO rib1_left = MAKE_SERVO(TRUE, E3, 1500, 500);
SERVO rib2_left = MAKE_SERVO(TRUE, E4, 1500, 500);
SERVO rib4_left = MAKE_SERVO(FALSE, E5, 1500, 500);
SERVO rib5_left = MAKE_SERVO(FALSE, E6, 1500, 500);
SERVO bulk_left = MAKE_SERVO(TRUE, E7, 1500, 1000);

SERVO rib1_right = MAKE_SERVO(FALSE, A7, 1500, 500);
SERVO rib2_right = MAKE_SERVO(FALSE, J6, 1500, 500);
SERVO rib4_right = MAKE_SERVO(TRUE, C7, 1500, 500);
SERVO rib5_right = MAKE_SERVO(TRUE, A6, 1500, 500);
SERVO bulk_right = MAKE_SERVO(FALSE, C5, 1500, 1000);

SERVO rib1_left_back = MAKE_SERVO(FALSE, H2, 1500, 500);
SERVO rib2_left_back = MAKE_SERVO(FALSE, H3, 1500, 500);
SERVO rib4_left_back = MAKE_SERVO(TRUE, H4, 1500, 500);
SERVO rib5_left_back = MAKE_SERVO(TRUE, H5, 1500, 500);
SERVO bulk_left_back = MAKE_SERVO(TRUE, H6, 1500, 1000);

SERVO rib1_right_back = MAKE_SERVO(TRUE, C4, 1500, 500);
SERVO rib2_right_back = MAKE_SERVO(TRUE, C3, 1500, 500);
SERVO rib4_right_back = MAKE_SERVO(FALSE, C2, 1500, 500);
SERVO rib5_right_back = MAKE_SERVO(FALSE, C1, 1500, 500);
SERVO bulk_right_back = MAKE_SERVO(FALSE, C0, 1500, 1000);

SERVO_LIST servos[] = {&rib5_left,&bulk_left,&rib1_right,&rib2_right,&rib4_right,&rib5_right,&bulk_right,&rib1_left_back,&bulk_left_back,&rib1_right_back,&rib2_right_back,&rib4_right_back,&rib5_right_back,&bulk_right_back};
SERVO_LIST servos_PWM[] = {&rib1_left,&rib2_left,&rib4_left,&rib2_left_back,&rib4_left_back,&rib5_left_back};

SERVO_DRIVER bank1 = MAKE_SERVO_DRIVER(servos);
SERVO_DRIVER bank2 = MAKE_SERVO_DRIVER(servos_PWM);

servosInit(&bank1, TIMER1_COMPAREA);
servoPWMInit(&bank2);

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #11 on: January 25, 2010, 05:31:23 AM »
You would know better than me, but this was my reasoning...

From Webbot's documentation:
Quote
Most servos require a pulse that is between 1ms and 2ms to control them. These pulses need to be sent every 20ms or so - some servos are more tolerant and are happy with every 40ms or so.
Given the longest pulse time of 2ms then this code could drive anywhere between 10 or 20 servos depending on the repeat pulse timing required by the servos.

So it is possible that Webbotlib can handle up to 20 tolerant servos with one driver, however if the servos are not tolerant you can only guarantee that 10 will work.  

Quote
My ERP uses 12 servos, all running from:
servosInit(&bank2, TIMER3_COMPAREA);
Quote
My 20 servo robot fish uses all of the PWM pins, and a timer for the remaining servos:

12 and 14 servos on one driver...

...Hasan999 wants to drive 26 servos, and from his testing...
Quote
For 12 servos, slight vibration (holding not so tight, easily movable by hand)
For 16+ servos, a lot of jitteriness !

It is very possible there are other factors at play here. However assuming that 26 servos will be stretching things for one driver seemed reasonable.

Webbotlib documentation suggests:
Quote
Note that if you have lots of servos you can break them down into separate lists each with their own driver and timer.

EDIT - '9' (Sorry Hasan)
  
« Last Edit: January 25, 2010, 08:27:39 AM by hopslink »

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #12 on: January 25, 2010, 07:19:43 AM »
He wants 26 servos . . .

Axon II has 15 hardware PWM pins. Then he uses a timer interrupt driver for the other 11. So even at 2ms per servo, thats 22ms delay tops between servo pulses.

For the original Axon, with 7 PWM, so 19 using the timer interrupt. Thats still ~38ms per servo, so still acceptable, although it really depends on each servo. I've done 20 servos on the Axon using WebbotLib without a problem.

Probably not the problem, so going to hopslink's other point . . . which I think is the real problem . . .

Quote
For 12 servos, slight vibration (holding not so tight, easily movable by hand)
For 16+ servos, a lot of jitteriness !
Hasan999, if I had to guess, you:
1) aren't using a proper battery. With 26 servos, each draining 0.5A average, thats 13A (a lot). What is your battery rated for? Did you measure the voltage with everything running? A drop in voltage means a drop in torque.
2) aren't reducing cross interference. Wiggle the servo wires, and I bet you'll see increased jittering.

 ;D
« Last Edit: January 25, 2010, 07:23:15 AM by Admin »

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #13 on: January 25, 2010, 09:19:00 AM »
Quote
I've done 20 servos on the Axon using WebbotLib without a problem.
I kind of stand corrected then... that's me over there in the corner with the pointy hat on :-[ . But I'm learning all the time :)

Although...
Quote
...no need to use multiple timers
Quote
Axon II has 15 hardware PWM pins.

Who's suggesting using multiple timers now? :P

Horses for courses, there's more than one way to skin a cat??? etc. Either way Axon is more than capable of driving 26 servos.

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #14 on: January 25, 2010, 09:32:03 AM »
Quote
Who's suggesting using multiple timers now?
The hardware PWM pins don't use timer interrupts, so thats why I used them. :P

Offline Hasan999Topic starter

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
Re: WebbotLib for 22+ Servos
« Reply #15 on: January 25, 2010, 11:54:54 AM »
Lets get back to my problem... shall we  ;D

Quote
your servo timer must be 16 bit (check ATmega640 manual, or Axon II datasheet, to determine which is which).
I'm using Axon1...
so it should be: 0 and 2 of 8-bit, and 1,3,4,5 of 16-bit

Quote
What is your battery rated for?

I bought this one (by mistake - before buying the microcontroller)

Code: [Select]
http://www.lynxmotion.com/Product.aspx?productID=67&CategoryID=48
BUT, I cut the pack, removed 1 cell, to make it a 6V battery. (seems fine - being using it since months now)

Quote
Did you measure the voltage with everything running?
yea I tried just now, the voltage directly from the battery (fully charged) = 7.24V and once running, the voltage across the (servo) ports = 6.1V

Quote
if I had to guess, you aren't reducing cross interference.
I have no idea what you mean't by that :P but, please read on... I think the problem is not an electrical one*

-------------------------------------------------------------------------

I tried Admin's code of Robot Fish, i.e. using PWM and TIMER1 (2 banks)

Code: [Select]
SERVO_LIST servo1[] = {&S1,&S2,&S4,&S5,&S6,&S7,&S8,&S9,&S10,&S11,&S13,&S14,&S15,&S17,&S18,&S21,&S22};
SERVO_LIST servo2[] = {&S12,&S16,&S20,&S3,&S19 };

SERVO_DRIVER bank1 = MAKE_SERVO_DRIVER(servo1);
SERVO_DRIVER bank2 = MAKE_SERVO_DRIVER(servo2);

servosInit(&bank1, TIMER1_COMPAREA);
servoPWMInit(&bank2);

Result: the Servos do not jitter anymore !... BUT they are not holding tight either ! (i.e. they do not get pulses every after 20ms, definately beyond 40ms or something - I can drag the running servos easily with my hand !)

Quote
For the original Axon, with 7 PWM, so 19 using the timer interrupt. Thats still ~38ms per servo, so still acceptable
I have already built the 4-legged robot, it is too heavy !.. and that is the reason I need the servos to remain TIGHT otherwise, the whole robot collapses (because of the gap in ms when the servos do not get signal) - I really need the  servos to get signal within 20ms throughout. (if not 26 servos, then at least 20 - because I 'can' pair some to single ports)

*What I have observed is that, if I use only 1 servo, it gets signal every after 20ms accurately (it holds its position so tight that I cannot move it manually ! - this is what I want !) ...but apparently that "20ms" keeps increasing as I add more and more (act_setSpeed) servos !

I don't understand why does it increase the delay when it is all running on "interrupts" !  :-\
« Last Edit: January 25, 2010, 12:06:36 PM by Hasan999 »

paulstreats

  • Guest
Re: WebbotLib for 22+ Servos
« Reply #16 on: January 25, 2010, 12:52:51 PM »
Try running your program for all 26 servos BUT only plug 1 servo in. If it holds tight then it is likely to be a power problem, if not then a programming problem.

You battery is rated for MAX discharge 10~16 amps. 16 amps would likely be for a brand new battery, used straight after a full charge. I would look at a more conservative estimate at being 10~12 amps. Bearing in mind that you have already removed 1 cell, this will affect its performance to some degree from the original specs. Remember admin saying above that your 26 servos will be drawing 13amps - and that doesnt include anything else that you have plugged in to them. This could be where the basis of your problem is, maybe the code does need sharpening up a bit, but if your batteries are struggling then you will always get uneven results making perfecting the code even harder.

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #17 on: January 25, 2010, 01:16:32 PM »
Also, if the time between servo updates affects how tightly they hold you should see a marked difference in holding power between the hardware pwm servos and those on the software pwm bank.

Offline Hasan999Topic starter

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
Re: WebbotLib for 22+ Servos
« Reply #18 on: January 25, 2010, 02:39:44 PM »
@paulstreats...
Quote
Try running your program for all 26 servos BUT only plug 1 servo in. If it holds tight then it is likely to be a power problem, if not then a programming problem.

I tried... removed all the ports leaving 1, and I had the program to run all the servos... but that servo was not held tight while running ! (again, I could drag the position - not 20ms !)

Offline Hasan999Topic starter

  • Full Member
  • ***
  • Posts: 75
  • Helpful? 1
Re: WebbotLib for 22+ Servos
« Reply #19 on: January 25, 2010, 03:02:21 PM »
Observation: When I tried making a bank having only 1 servo (using TIMER1_COMPAREA) along with another bank having the rest of the servos (using TIMER3_COMPAREA), I noticed that the single servo was held tight ! (however, others were not)...

Hence I tried making maximum number of banks possible (that depends on the maximum number of TIMERS available). So apparently I can all use 12 (16-bit)Timers (i.e. TIMER,1,3,4,5 with COMPARE,A,B,C)

Assuming lesser servos in a bank makes it hold tight, I made my own banks according to the servos that I needed to be 100% tight (i.e. 20ms), and those that could tolerate slight weakness. (i.e. 20ms to 25ms maybe)

Code: [Select]
SERVO_LIST servo1[] = {&S1};
SERVO_LIST servo2[] = {&S2};
SERVO_LIST servo3[] = {&S3};
SERVO_LIST servo4[] = {&S4};
SERVO_LIST servo5[] = {&S5,&S6};
SERVO_LIST servo6[] = {&S7,&S8};
SERVO_LIST servo7[] = {&S9,&S10,&S11,&S12};
SERVO_LIST servo8[] = {&S13,&S14};
SERVO_LIST servo9[] = {&S15,&S16};
SERVO_LIST servo10[] = {&S17};
SERVO_LIST servo11[] = {&S18};
SERVO_LIST servo12[] = {&S19,&S20,&S21,&S22};

SERVO_DRIVER bank1 = MAKE_SERVO_DRIVER(servo1);
SERVO_DRIVER bank2 = MAKE_SERVO_DRIVER(servo2);
SERVO_DRIVER bank3 = MAKE_SERVO_DRIVER(servo3);
SERVO_DRIVER bank4 = MAKE_SERVO_DRIVER(servo4);
SERVO_DRIVER bank5 = MAKE_SERVO_DRIVER(servo5);
SERVO_DRIVER bank6 = MAKE_SERVO_DRIVER(servo6);
SERVO_DRIVER bank7 = MAKE_SERVO_DRIVER(servo7);
SERVO_DRIVER bank8 = MAKE_SERVO_DRIVER(servo8);
SERVO_DRIVER bank9 = MAKE_SERVO_DRIVER(servo9);
SERVO_DRIVER bank10 = MAKE_SERVO_DRIVER(servo10);
SERVO_DRIVER bank11 = MAKE_SERVO_DRIVER(servo11);
SERVO_DRIVER bank12 = MAKE_SERVO_DRIVER(servo12);

servosInit(&bank1, TIMER1_COMPAREA);
servosInit(&bank2, TIMER1_COMPAREB);
servosInit(&bank3, TIMER1_COMPAREC);
servosInit(&bank4, TIMER3_COMPAREA);
servosInit(&bank5, TIMER3_COMPAREB);
servosInit(&bank6, TIMER3_COMPAREC);
servosInit(&bank7, TIMER4_COMPAREA);
servosInit(&bank8, TIMER4_COMPAREB);
servosInit(&bank9, TIMER4_COMPAREC);
servosInit(&bank10, TIMER5_COMPAREA);
servosInit(&bank11, TIMER5_COMPAREB);
servosInit(&bank12, TIMER5_COMPAREC);

Result: Worked as I supposed ! ...the servos are tight...finally  ;D

I gtg, I'll resume messing around with the same after 12 hour...

BTW, I didn't try but I think there could be another bank controlled using servoPWMInit(&bank13);   ;)

umm... 1 of my question remained unanswered: "what about the return 20000; ?...what if I reduce it? or make it 0;  ???

Thanks.....

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #20 on: January 25, 2010, 08:47:05 PM »
Yea, I suggest doing just 3 drivers, then. PWM, and the other servos evenly divided between two timer interrupt drivers.

The reason is that all these interrupts will slow down your main code significantly. Also, you might get extra servo jitter if interrupts interfere with other interrupts.

Quote
what about the return 20000; ?...what if I reduce it? or make it 0
It can be whatever you want. But usually I make it high for open source code made for beginners - it'll reduce various problems caused by a super fast processor on hardware that can't move at light speed . . . Try reducing it, and if nothing breaks, then you are fine. But it really depends on what the rest of your code is doing!

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,165
  • Helpful? 111
    • Webbot stuff
Re: WebbotLib for 22+ Servos
« Reply #21 on: January 26, 2010, 05:50:53 PM »
Quote
what about the return 20000; ?...what if I reduce it? or make it 0
It wont make any difference, depending on what else your main loop does, since the servo commands are happening under interrupts.
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,165
  • Helpful? 111
    • Webbot stuff
Re: WebbotLib for 22+ Servos
« Reply #22 on: January 26, 2010, 09:29:56 PM »
The servo timing is a complex thing (not an excuse - just a statement!).
My original code did the following:-
Code: [Select]
total = 0
for each servo
  pulse = calc servo pulse
  total += pulse
  emit pulse
next servo
pause 20ms - total
This code makes sure that the pulse to the first servo starts 20ms after its last pulse started.

But bad news. Take a pen'n'paper and assume that for the first pass all the servos need a 2ms pulse and on the next pulse they all need a 1ms pulse. Now look at each servo in turn. The first servo is fine but as you move through the list of servos you will see that they progressively get less and less of 20ms.

Admin said it fried his servos and this is bad (mainly coz I owe him some servos).

So with Admins advise I changed it to:
Code: [Select]
total = 0
for each servo
  pulse = calc servo pulse
  total = pulse
  emit pulse
next servo
pause 20ms - total

A subtle change - but means that the loop repeats 20ms after the starting pulse to the last servo.

So as you add more servos - then the pulse frequency to a given servo increases. ie if you have 20 servos each taking 2ms then it takes 19*2ms + 20ms = 38ms to repeat. So each servo gets a pulse about every 38ms.

This is probably why you get 'floppy' servos.

And its a beggar to change! Heres why...

Assume all servos on the first pass have a pulse of 2ms and that on the next pass the first few are also 2ms and subsequent ones are 1ms. Then the order of sending out pulses needs to change. ie for pass 2 you may need to do servo 8,9,10 then 1,2,3 in order to keep each one on their own '20ms anniversary'.

The limiting factor will be the number of servos in the bank. ie if there are 15 and they are all issuing 2ms pulses then the duration is 30ms. So its impossible to refresh them all every 20ms.

So the current work around is to use hardware PWM where you can, and split the remainder into as many banks as you can afford in timer compare channels.

In the meantime I need to think if its possible to come up with a solution that keeps servos 'tight' but without 'frying them' !!!

Any sensible suggestions (and yes I've Googled), but bearing in mind this is all under interrupts so no code that includes a delay statement please, then PM me.


Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #23 on: January 26, 2010, 10:40:02 PM »
To be honest, I think your code now is 'good enough'. I say that because different servos act differently, and I think we are in the sweet spot average of all of them (subjectively tested).

One day all servos will become digital, and when that happens, we can come back to this. ;D

(although the WebbotLib manual might want to point out typical problems and recommend solutions for very large numbers of servos)

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #24 on: January 27, 2010, 03:27:53 AM »
You could get some extra precision quite easily by doing:
Code: [Select]
total = 0
for each servo
  pulse = calc servo pulse
  total = pulse
  emit pulse
next servo
pause (20-(No_Of_Servos_In_Bank - 1))ms - total

Working on the assumption that each servo has a minimum 1ms delay.

« Last Edit: January 27, 2010, 03:34:13 AM by hopslink »

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #25 on: January 27, 2010, 03:36:32 AM »
Quote
Working on the assumption that each servo has a minimum 1ms delay.
I've used servos that have a 0.5ms to 2.5ms range (normal is 1ms to 2ms).

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: WebbotLib for 22+ Servos
« Reply #26 on: January 27, 2010, 03:45:38 AM »
Quote
I've used servos that have a 0.5ms to 2.5ms range (normal is 1ms to 2ms).

Never assume.... (picks up pointy hat and heads back to his corner ;D)

That said you define the minimum pulsewidth for each servo as you declare it in Webbotlib so you could sum those to give a Bank_Minimum_Delay and use that.


Offline Ro-Bot-X

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 1,431
  • Helpful? 25
  • Store: RoBotXDesigns.ca
    • Ro-Bot-X Designs
Re: WebbotLib for 22+ Servos
« Reply #27 on: January 27, 2010, 06:28:46 AM »
What if you make an array of servos and sort the pulse for all servos to be ascending in the array. Then you turn high all the servos at once and start counting, then turn low the servos that have the shortest pulse first (let's say 1ms...) and keep going through the array until the last servo pulse is low (let's say 2ms...), then reset the counter when it reaches 20ms (during this time you may do whatever else in the code...)? I guess a timer interrupt can be used for this.

Would that work better?
« Last Edit: January 27, 2010, 06:33:06 AM by Ro-Bot-X »
Check out the uBotino robot controller!

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: WebbotLib for 22+ Servos
« Reply #28 on: January 27, 2010, 10:00:22 AM »
Actually, Ro-Bot-X, I've had that idea for years. And you know, it might still be worth trying it.

I never implemented in the past because I never needed to. And I was a bit worried about what would happen if the servos all required the same position.

But still, I think it might be worth looking into. Webbot, thoughts?

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,165
  • Helpful? 111
    • Webbot stuff
Re: WebbotLib for 22+ Servos
« Reply #29 on: January 27, 2010, 02:04:01 PM »
Well thats the sort of thing that dedicated Servo boards do. But since they don't have anything else to do then they can do it in the foreground.
I've got to do it under interrupts.

So heres the challenge....

Once you've set all the pins high and you've worked out the sorted list. Then you may have a number of servos that need to be turned off at 'roughly' the same time - but not at 'exactly' the same time - lets say 20us apart.

So you've set a compare interrupt for the earliest, the interrupt happens and you've stopped the pulse to that servo. You now realise that you've got 20us before you turn off the next one. First you have to subtract the amount of time you've just spent processing the previous servo. So you come up with a new value for the timer compare register but if the timer counter has actually passed that value just before you set the new compare value then you will have to wait until the timer wraps all the way around to that value again.

You can't use delay_us etc as the last thing you want to do in an ISR is to 'pause' as the whole board (UARTs, Timers, everything) is dead during that time.

------
Here is a way I am thinking about solving it. Instead of 1 timer compare per bank I will use 2 timer compares.
Compare 1 will be used to measure the pulse length and to turn the pin off again
Compare 2 will be used to measure the time when the next servo pin should be turned high

When processing a servo:
Set the pin high (start of pulse)
Set Compare1 to the time when the pulse will turn off
Set Compare2 to the maximum possible pulse length for the servo (ie always >=Compare1).
Idling
Compare 1 fires and turns off the pulse. Servo done.
Idling
Compare 2 fires and we now process the next servo.

The total time for a bank is therefore controlled by Compare 2 and is the sum of all the longest possible pulses (but constant once calculated).
Since Compare2 times the start of a pulse and always takes the pessimistic case then the start of a pulse of any servo will always happen every 20ms. (Although if you have say 20 servos in one bank then each servo may fire every 40ms). But it will be consistent. Note that you don't get time for nothing so having summed all the longest values for the servos in the bank then this may exceed 20ms. In which case I would need to add a few ms extra - otherwise your foreground task, and other servo banks, would never get serviced - the cpu would just become a servo driver !

I don't have enough servos to try it myself. Other than setting it up and then moving a single servo to each pin and see what happens. So I can test the pins individually but not all together.

If anyone wants to be a guinea-pig then let me know. I could ship an 'h' file to put into your project directory.
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk