go away spammer

Author Topic: How to Control Many Servos  (Read 3819 times)

0 Members and 1 Guest are viewing this topic.

Offline er1ckTopic starter

  • Jr. Member
  • **
  • Posts: 11
  • Helpful? 0
How to Control Many Servos
« on: August 04, 2009, 05:49:48 PM »
Hello All, i need help about how to control many servos for same time?

i'm using this code to control 1 servo:

Code: [Select]
for (i=0;i<100;i++)
{
   PORTC.0=1;
   delay_us(1500);
   PORTC.0=0;
   delay_us(18000);
}

but i' got problem when i wanto control many servos with do simultaniosly function.
« Last Edit: August 04, 2009, 06:11:57 PM by er1ck »

Offline GearMotion

  • Supreme Robot
  • *****
  • Posts: 489
  • Helpful? 24
  • Two decades+ of Embedded Design
    • CircuitGizmos
Re: How to Control Many Servos
« Reply #1 on: August 04, 2009, 06:27:12 PM »

I submit this suggestion:

Code: [Select]
for (i=0;i<100;i++)
{
   PORTC.0=1;
   delay_us(1500);
   PORTC.0=0;
   delay_us(500);

   PORTC.1=1;
   delay_us(1500);
   PORTC.1=0;
   delay_us(500);

   PORTC.2=1;
   delay_us(1500);
   PORTC.2=0;
   delay_us(500);

   PORTC.3=1;
   delay_us(1500);
   PORTC.3=0;
   delay_us(500);

   delay_us(12000);

}

Will that work? Or do you have reason sequential commands will not work?

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: How to Control Many Servos
« Reply #2 on: August 04, 2009, 07:14:35 PM »
Check out my Axon code!

Offline sonictj

  • Supreme Robot
  • *****
  • Posts: 416
  • Helpful? 11
    • Tim's Workshop
Re: How to Control Many Servos
« Reply #3 on: August 04, 2009, 07:54:05 PM »
My solution would be to use a CLPD / FPGA you can easily build a counter/timer circuit in one to control as many servos as you want.  However that is only a viable solution if you have a programmer for those devices, and the understanding.

Another method I've seen is using an AVR's SPI port connected to a few seial to parallel shifters.  You simulate pwm in the same way as with toggling a port, but you can control even more devices with less i/o.  The lynxmotion  servo controller works this way.  The schematic is posted on their site somewhere in the manuals. 

Offline er1ckTopic starter

  • Jr. Member
  • **
  • Posts: 11
  • Helpful? 0
Re: How to Control Many Servos
« Reply #4 on: August 04, 2009, 08:49:49 PM »

I submit this suggestion:

Code: [Select]
for (i=0;i<100;i++)
{
   PORTC.0=1;
   delay_us(1500);
   PORTC.0=0;
   delay_us(500);

   PORTC.1=1;
   delay_us(1500);
   PORTC.1=0;
   delay_us(500);

   PORTC.2=1;
   delay_us(1500);
   PORTC.2=0;
   delay_us(500);

   PORTC.3=1;
   delay_us(1500);
   PORTC.3=0;
   delay_us(500);

   delay_us(12000);

}

Will that work? Or do you have reason sequential commands will not work?


Firsly, thanks for all Feedback.. i just found problem, when i use this code and ADD LilneFlower function on my mobile robot. when robot run... All servos, not working fine, all just shaking i'm using :

uC: ATMega8535
PORTB As input from proximity sensor
PORTD as motor Output (using L298 IC)
PORTC.1,2,3 i use for 3 Servos look like this picture:




When i try using Servo() function... servo working fine, and when i try using linefolower() function is good too... but when i using all, My servo just going to shaking

must i use 2 Microcontroller??

Offline er1ckTopic starter

  • Jr. Member
  • **
  • Posts: 11
  • Helpful? 0
Re: How to Control Many Servos
« Reply #5 on: August 04, 2009, 08:52:46 PM »
For admin, How much your axon?? and what method of payment? then, can you send it to indonesia?

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: How to Control Many Servos
« Reply #6 on: August 04, 2009, 08:54:52 PM »
It sounds more like you have a poorly tuned feedback control loop. Poor control will cause shaking. Please show us your control code.


Quote
For admin, How much your axon?? and what method of payment? then, can you send it to indonesia?
Everything you need to know is here:
http://www.societyofrobots.com/axon/
 :P

Offline er1ckTopic starter

  • Jr. Member
  • **
  • Posts: 11
  • Helpful? 0
Re: How to Control Many Servos
« Reply #7 on: August 05, 2009, 03:45:45 AM »
All my code here:

Code: [Select]
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 7/16/2009
Author  :
Company :
Comments:


Chip type           : ATmega8535L
Program type        : Application
Clock frequency     : 11.059200 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 128
*****************************************************/

#include <mega8535.h>
#include <delay.h>

unsigned int i;


void maju()
{       //Maju
      PORTD=0b01101100;
      //delay_ms(3000);
 }
void mundur()
{     
      //Mundur
      PORTD=0b01110010;
      //delay_ms(3000);
}
void bkiri()
{                     
      //belok kiri
      //PORTD=0b01101010; <=asli
      PORTD=0b01101000;
      //delay_ms(3000);
}
void bkanan()
{     
      //belok kanan
      //PORTD=0b01110100;  <== asli
      PORTD=0b01100100;
      //delay_ms(3000);
}

void xkiri()
{                     
      //belok kiri
      PORTD=0b01101010;
      //PORTD=0b01101000;
      //delay_ms(3000);
}
void xkanan()
{     
      //belok kanan
      PORTD=0b01110100;
      //PORTD=0b01100100;
      //delay_ms(3000);
}

void gerak()
{
    if (PINB==0b00011000 || PINB==0b00001000  || PINB==0b00010000  || PINB==0b00011100  || PINB==0b00111000)
    {maju();}
    if (PINB==0b00001100 || PINB==0b00000100 || PINB==0b00000110 || PINB==0b00000010 || PINB==0b00000111)
    {bkiri();}
    if (PINB==0b00110000 || PINB==0b00100000 || PINB==0b01100000 || PINB==0b01000000 || PINB==0b11100000)
    {bkanan();}
    if (PINB==0b00000011 || PINB==0b00000001 || PINB==0b00000101 || PINB==0b00001111 || PINB==0b00011111)
    {xkiri();}
    if (PINB==0b11000000 || PINB==0b10000000 || PINB==0b10100000 || PINB==0b11110000 || PINB==0b11111000)
    {xkanan();}
    if (PINB==0b00000000)
    {mundur();}


}
//servo1
void s1_atas()
    {
      for(i=0;i<40;i++)
       {
        //0 derajat
        PORTC.0=1;
        gerak();
        delay_us(600);
        PORTC.0=0;
        gerak();
        delay_us(18900);
        gerak();
       }
       //delay_ms(1000); 
    }
void s1_bawah()
    {
       for (i=0;i<40;i++)
       {
        //180 derajat
        PORTC.0=1;
        gerak();
        delay_us(2400);
        PORTC.0=0;
        gerak();
        delay_us(18100);
        gerak();
        }
       //delay_ms(1000);
    }

   
//servo2

void s2_depan()
    {
      for(i=0;i<700;i++)
       {
        //0 derajat
        PORTC.1=1;
        gerak();
        delay_us(650);
        PORTC.1=0;
        gerak();
        delay_us(18900);
        gerak();
       }
       //delay_ms(1000); 
    }
void s2_belakang()
    {
       for (i=0;i<700;i++)
       {
        //180 derajat
        PORTC.1=1;
        gerak();
        delay_us(2350);
        PORTC.1=0;
        gerak();
        delay_us(18100);
        gerak();
        }
       //delay_ms(1000);
    }
void s2_atas()
    {
       for (i=0;i<30;i++)
       {
        //180 derajat
        PORTC.1=1;
        gerak();
        delay_us(1500);
        PORTC.1=0;
        gerak();
        delay_us(18100);
        gerak();
        }
       //delay_ms(1000);
    }
   
//servo3

void balik_ki3()
    {
      for(i=0;i<40;i++)
       {
        //0 derajat
        PORTC.2=1;
        gerak();
        delay_us(600);
        PORTC.2=0;
        gerak();
        delay_us(18900);
        gerak();
       }
       //delay_ms(1000); 
    }
void balik_ka3()
    {
       for (i=0;i<30;i++)
       {
        //180 derajat
        PORTC.2=1;
        gerak();
        delay_us(2400);
        PORTC.2=0;
        gerak();
        delay_us(18100);
        gerak();
        }
       
       //delay_ms(1000);
    }
void balik_dpn3()
    {
      for (i=0;i<30;i++)
       {
        //90 derajat
        PORTC.2=1;
        gerak();
        delay_us(1500);
        PORTC.2=0;
        gerak();
        delay_us(18500);
        gerak();
        }
       //delay_ms(1000); 
    }
// Declare your global variables here

 
      // Place your code here
      //belakang();
      //depan();
void servox()
{
      balik_dpn3();
     
      s1_atas();
      s2_atas();
      s2_depan();
     
     
      s2_atas();
      s1_bawah();
      s2_belakang();
     
      s2_atas();
      balik_ka3();
      s2_belakang();
     
      s2_atas();
      balik_ki3();
      s2_belakang();
      s2_atas();
}
     
     
     


void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

while (1)
      {
      // Place your code here
     
      //gerak();
      servox();
      }
}


i'm use diferen power for Microcontroller, for motor whell, and for motor servo..
with 8 sensor photodiode for lineflower and using CodeVisionAVR to compile my code

Offline benji

  • Supreme Robot
  • *****
  • Posts: 830
  • Helpful? 0
Re: How to Control Many Servos
« Reply #8 on: August 15, 2009, 02:01:41 PM »
firstival the code posted by Gearmotion might work but its totally inefficient, it obliges too many delay number calclulations and
it will be totally annoying if you want to move your servos stack smoothly (meaning: little delays between changing high pulse times)

I once built a hexapod and had 12 servos to control in the same time plus doing complex moves
I did post the algorithm in the forum long time ago
anyways
there you go:

you should make an array with the number of motors you want to control
lets say 5

unsigned int motors=[x1 ,x2 ,x3 ,x4 ,x5];

Initialize TIMER0 to incremet each 1 microsecond

Set the number of pulses and the desired periods of the high pulse for each motor in microsecs and then call the drive_motors function

x1=1500;
x2=1600;
x3=1500;
x4=1555;
x5=1620;

i=50;

drive_motors(x1,x2,x3,x4,x5,i);

now eveytime you want to make a new move you just change the x values and the i and call the function again


here is the function to include:
Code: [Select]
void drive_motors(x1,x2,x3,x4,x5,i)
{
for (x=0;x<i ;x++) i is num of minimum required pulses to reach final destination for each new move)
{

reset TIMER0;

fire TIMER0;

While (TIMER0 =< 20000)
           {
             IF (TIMER0 = X1){PORT1.1=0;}
             IF (TIMER0 = X2){PORT1.2=0;}
             IF (TIMER0 = X3){PORT1.3=0;}
             IF (TIMER0 = X4){PORT1.4=0;}
             IF (TIMER0 = X5){PORT1.5=0;}
            }
}
} << function ends

the good thing here is that you just pass the required value for each motor (position) and the number of loop itirations.
plus , its Dead accurate as long as you are stopping the loop at TIMER0 = 20000.

the negative point is you may get a delay of the designated time for a motor of the execution time of the 4 if instructions in worst case, if it happens the delay time will be very little that you dont have to worry about.

plus : I dont think he is talking about any control loop tuning here

« Last Edit: August 15, 2009, 02:06:24 PM by benji »
good ol' BeNNy

Offline GearMotion

  • Supreme Robot
  • *****
  • Posts: 489
  • Helpful? 24
  • Two decades+ of Embedded Design
    • CircuitGizmos
Re: How to Control Many Servos
« Reply #9 on: August 15, 2009, 02:15:08 PM »
firstival the code posted by Gearmotion might work but its totally inefficient, it obliges too many delay number calclulations and
it will be totally annoying if you want to move your servos stack smoothly (meaning: little delays between changing high pulse times)

No doubt.

But the original post provided little beyond the statement that a single servo works, but that the poster didn't know how to control more than one. And the poster didn't mention what might have been tried. So I posted something to try. It certainly wasn't the most efficient code to try, but it would get the job done. And the OP might learn from it.

I'm not denigrating your approach.

Offline benji

  • Supreme Robot
  • *****
  • Posts: 830
  • Helpful? 0
Re: How to Control Many Servos
« Reply #10 on: August 15, 2009, 02:22:48 PM »
Quote
I'm not denigrating your approach.

Neither did I   ;)
good ol' BeNNy

Offline er1ckTopic starter

  • Jr. Member
  • **
  • Posts: 11
  • Helpful? 0
Re: How to Control Many Servos
« Reply #11 on: October 08, 2009, 09:07:30 PM »

Code: [Select]
void drive_motors(x1,x2,x3,x4,x5,i)
{
for (x=0;x<i ;x++) i is num of minimum required pulses to reach final destination for each new move)
{

reset TIMER0;

fire TIMER0;

While (TIMER0 =< 20000)
           {
             IF (TIMER0 = X1){PORT1.1=0;}
             IF (TIMER0 = X2){PORT1.2=0;}
             IF (TIMER0 = X3){PORT1.3=0;}
             IF (TIMER0 = X4){PORT1.4=0;}
             IF (TIMER0 = X5){PORT1.5=0;}
            }
}
} << function ends

[/quote]

It's cool code sir, and thanks for this learning.. but can you tell me more how to control many servo for hexapod robot?
many people in my country i see using 3 micro, 1 for servos, 1 for sensors, and 1 micro for main controller.
i wanna know how program of micro for servos controll function, can control 12 or 18 servos? can you give me link where i can get reference about it?

Offline Neophite_404

  • Jr. Member
  • **
  • Posts: 12
  • Helpful? 0
Re: How to Control Many Servos
« Reply #12 on: October 12, 2009, 07:26:37 AM »
I have a side question about benji's code.

In the drive_motors function there are 2 instructions (reset and fire) directed to the timer (TIMER0). Are these instructions part of avr-libc? Or are they something you or someone else cooked up? And in either case, do they require a specific #include "xxx.h" line to implement them? They are the only bits that I don't understand. The rest is absolutely beautiful. Thank you.

Offline AdvsNoob

  • Robot Overlord
  • ****
  • Posts: 156
  • Helpful? 0
  • Younge Inventer
    • Uni Coding
Re: How to Control Many Servos
« Reply #13 on: November 11, 2009, 09:00:55 PM »
if you use a arduino i use ServoTimer2 i believe it holds up to 8 servos..

 


Get Your Ad Here