Society of Robots - Robot Forum
Software => Software => Topic started by: er1ck 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:
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.
-
I submit this suggestion:
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?
-
Check out my Axon code!
-
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.
-
I submit this suggestion:
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:
(http://photos-a.ak.fbcdn.net/hphotos-ak-snc1/hs159.snc1/5940_1086393485384_1392828708_30203056_616698_n.jpg)
(http://photos-h.ak.fbcdn.net/hphotos-ak-snc1/hs159.snc1/5940_1086393405382_1392828708_30203055_3913081_n.jpg)
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??
-
For admin, How much your axon?? and what method of payment? then, can you send it to indonesia?
-
It sounds more like you have a poorly tuned feedback control loop. Poor control will cause shaking. Please show us your control code.
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
-
All my code here:
/*****************************************************
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
-
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:
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
-
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.
-
I'm not denigrating your approach.
Neither did I ;)
-
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?
-
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.
-
if you use a arduino i use ServoTimer2 i believe it holds up to 8 servos..