Beginners: please read this post and this post before posting to the forum.
0 Members and 1 Guest are viewing this topic.
for(;;){servo(PORTA,1,650);servo(PORTA,2,650); // <-- this won't be there if I use Y-harness*delay_ms(18); }
#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 bauduartInit(UART0, 115200);//uartInit(UART0, 19200);// Tell rprintf to output to UART0rprintfInit(&uart0SendByte);// Initialise the servo controllerservosInit(&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 ìSTICK_COUNT appInitSoftware(TICK_COUNT loopStart){return 0; // dont pause after}// This routine is called repeatedly - its your main loopTICK_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;}
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
servosInit(&bank1, TIMER1_COMPAREA);servosInit(&bank2, TIMER1_COMPAREA);
Try assigning each driver to a different timer.
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);
btw I re-tried for all the servos in different banks but using same TIMER1, I notice that the jitteriness is even worse ! (slower)
servosInit(servosInit(&bank2, TIMER2_COMPAREB);servosInit(&bank3, TIMER3_COMPAREC);
servosInit(&bank2, TIMER3_COMPAREA);servosInit(&bank3, TIMER4_COMPAREA);
// Give each servo a start value of 'stop'
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.
QuoteYou 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...).
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);
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.
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:
For 12 servos, slight vibration (holding not so tight, easily movable by hand)For 16+ servos, a lot of jitteriness !
Note that if you have lots of servos you can break them down into separate lists each with their own driver and timer.
I've done 20 servos on the Axon using WebbotLib without a problem.
...no need to use multiple timers
Axon II has 15 hardware PWM pins.
Who's suggesting using multiple timers now?
your servo timer must be 16 bit (check ATmega640 manual, or Axon II datasheet, to determine which is which).
What is your battery rated for?
http://www.lynxmotion.com/Product.aspx?productID=67&CategoryID=48
Did you measure the voltage with everything running?
if I had to guess, you aren't reducing cross interference.
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);
For the original Axon, with 7 PWM, so 19 using the timer interrupt. Thats still ~38ms per servo, so still acceptable
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.
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);
what about the return 20000; ?...what if I reduce it? or make it 0
total = 0for each servo pulse = calc servo pulse total += pulse emit pulsenext servopause 20ms - total
total = 0for each servo pulse = calc servo pulse total = pulse emit pulsenext servopause 20ms - total
total = 0for each servo pulse = calc servo pulse total = pulse emit pulsenext servopause (20-(No_Of_Servos_In_Bank - 1))ms - total
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).