PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : bis zu 12 Servos gleichzeitig ansteuern



blenderkid
20.03.2008, 19:51
Hi,

ich habe zwar oft einen Servo zum laufen gekriegt, aber jetzt möchte ich bis zu 12 Servos gleichzeitig laufen lassen. Die Funktionen der Servos sollten nicht blockierend sein. Weiß jemand wie das zu bewerkstelligen ist ?

Ich brauche es dafür:
Ich habe dem RP6 4 Beine mit je 3 gelenken verpasst. Ich probiere jetzt seit min 3 Tagen an dem Programm aber kriegs nicht hin. Es gibt immer Probleme mit der Zeit des PWM.

DIV blenderkid

thietho
20.03.2008, 22:03
Da habe ich was für Dich!
Bin allerdings heute nicht zu Hause, werde Dir aber den Code dann senden

radbruch
20.03.2008, 22:16
Acht Servos an den LEDs und ADC0/1:


// Vierbeiniger RP6 (erste Tests des neuen Beines) 24.2.2008 mic

#include "rblib.h"
#include "rblib.c"

#define vli_on (PORTC|=SL1)
#define vli_off (PORTC&=~SL1)
#define vri_on (PORTA |= 1)
#define vri_off (PORTA &= ~1)
#define hli_on (PORTC|=SL2)
#define hli_off (PORTC&=~SL2)
#define hri_on (PORTC|=SL3)
#define hri_off (PORTC&=~SL3)
#define vla_on (PORTB|=SL4)
#define vla_off (PORTB&=~SL4)
#define vra_on (PORTA |= 2)
#define vra_off (PORTA &= ~2)
#define hla_on (PORTB|=SL5)
#define hla_off (PORTB&=~SL5)
#define hra_on (PORTB|=SL6)
#define hra_off (PORTB&=~SL6)

uint8_t vli, vri, hli, hri, vla, vra, hla, hra; // Positionen der Servos
uint8_t i;

int main(void)
{
rblib_init();
cli();
TCCR0 = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0 |= (0 << COM00) | (0 << COM01); // ohne OCR-Pin
TCCR0 |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE0); // Interrupt ein
OCR0 = 9; // 100kHz?

DDRC |= 0x70; // LED1-3 auf Ausgang und low
PORTC &= ~0x70;
DDRB |= 0x83; // LED4-6 auf Ausgang und low
PORTB &= ~0x83;
//DDRC |= 0x3; // SCL und SDA auf Ausgang und low
//PORTC &= ~0x3;
DDRA |= 3; // ADC0 und ADC1 auf Ausgang und low
PORTA &= ~3;
vli=vla=vri=vra=hli=hla=hri=hra=100;
sei();
delay(150);

vri=120;delay(20);
vli=80;delay(20);
hri=120;delay(20);
hli=80;delay(20);

vri=80;delay(20);
vli=120;delay(20);
hri=80;delay(20);
hli=120;delay(20);

while(1){
vla=90; vra=110; hla=110; hra=90; delay(5);
vla=70; vra=130; hla=140; hra=60; delay(20);
//for(i=0; i<40; i++) { vli=120-i; vri=80+i; hli=120-i; hri=80+i; delay(5); }
vli=80; vri=120; hli=80; hri=120; delay(30);
vla=90; vra=110; hla=110; hra=90; delay(10);
vla=vra=hla=hra=100; delay(5);
vri=80;delay(5);
vli=120;delay(5);
hri=80;delay(5);
hli=120;delay(5);
}
return 0;
}
ISR (TIMER0_COMP_vect)
{
static uint16_t count=1; // Servoansteuerung

(count>vli)?vli_off:vli_on;
(count>vla)?vla_off:vla_on;
(count>vri)?vri_off:vri_on;
(count>vra)?vra_off:vra_on;
(count>hli)?hli_off:hli_on;
(count>hla)?hla_off:hla_on;
(count>hri)?hri_off:hri_on;
(count>hra)?hra_off:hra_on;

if(count<2000) count++; else count=0;
}


Die Libs dienen nur zum debuggen, mit io.h und interrupt.h sollte es auch funktionieren. Mit der RP6-Lib ist kein Timer mehr frei :(

Ach, fast vergessen: delay() ist 'ne Zählschleife, die Servos brauchen ja auch etwas Zeit um die Positionen anzufahren:

void delay(uint8_t d)
{
uint16_t d1, dummy;
for (d1=d*255; d1>0; d1--) dummy^=d1;
}


Gruß

mic

blenderkid
21.03.2008, 10:03
Hi radbruch,

ich glaube ich verstehe den Code so halb. Was macht die Zeile:
(count>vli)?vli_off:vli_on;
Und ist das mit dem delay eine blockierende Funktion?
Wie lange blockiert delay() die schleife?

Und wann wird ISR aufgerufen?

DIV blenderkid

radbruch
21.03.2008, 11:09
Hallo


(count>vli)?vli_off:vli_on; bedeutet if(count>vli) vli_off; else vli_on; Es wird vom Kompiler aber zum selben Code übersetzt.

Count wird in der ISR von 0 bis 1999 hochgezählt, das ergibt den 20ms-Intervall. Solange der Positionswert des Servos kleiner als count ist wird der Impuls ausgegeben, bei Position==100 sind das 1ms. (Wenn man den 20ms-Intervall verkürzt, werden die Servos "agressiver", verlängern macht sie träge)


Und ist das mit dem delay eine blockierende Funktion?Ja. Anstelle der delays kannst du aber auch Berechnungen machen. Ich schreibe die Abläufe erst mit langen delays und kürze dann die Verzögerungen bis es "flüssig" aussieht. (Durch Änderungen innerhalb der delay()-Funktion kann man ALLE Bewegungen beeinflussen!)


Wie lange blockiert delay() die schleife?Da es eine Zählschleife ist hängt das von der Taktgeschwindigkeit des Kontrollers ab.


Und wann wird ISR aufgerufen?Alle 10 us, dann ergeben 100 Aufrufe 1ms, das sollte Servo-Mitte sein.

Meine "Beine" haben je zwei Servos, in den defines sind die Pins nach dem Schema vorne-links-innen, vorne-links-aussen, vorne-rechts-innen, vorne-rechts-aussen.... definiert. Bei 6 Beinen würde sich eine Erweiterung mit mitte-links-innen, mitte-links-aussen... anbieten.

Das sind auch meine ersten Gehversuche. Ich definiere feste Abläufe für die Schritte und rufe diese dann nacheinander ab. Z.B. für ein einzelnes Bein: vla anheben, vli nach vorne schwenken, vla absenken. Für zwei Beine gleichzeitig: vla+hra anheben, schwenken, absenken... Dabei gebe ich immer die Zielpositionen der Servos an und warte kurz bis sie die Position erreicht haben. Bei zwei gleichzeitig bewegten Beinen starte ich das Zweite etwas verzögert wegen den Stromspitzen. Während zwei Beine vorgesetzt werden, schwenken die anderen vier ein Stück nach hinten. btw sollten die Servos eine eigene Stromversorgung haben!

Ich werde mir übrigends auch noch zwei weitere Beine basteln, denn mit vier Beinen mit je zwei Bewegungsebenen fällt er um...

Gruß

mic

[Edit]
Ich habe erst jetzt gelesen dass du vier Beine mit je drei Gelenken gebaut hast. Ich glaube, der RP6 kann mit vier Beinen nicht gehen weil er ein relativ hohes Gewicht hat und sein Schwerpunkt beim Anheben eines Beines ja über den anderen Beinen, die dann alles tragen müssen, sein muss damit er nicht umfällt. Meine Beschreibungen oben bezogen sich auf sechs Beine, sorry.

blenderkid
21.03.2008, 15:09
Danke radbruch,
ich werde es einfach mal mit 4 beinen probieren.
Ich kann anstatt der LEDs aber auch die IOs des M32 benutzen oder?

danke blenderkid

blenderkid
21.03.2008, 15:52
#define vli_on (PORTC|=IO_PD5)
#define vli_off (PORTC&=~IO_PD5)
#define vlm_on (PORTC |= IO_PC2)
#define vlm_off (PORTC &= ~IO_PC2)
#define vla_on (PORTC|=IO_PC3)
#define vla_off (PORTC&=~IO_PC3)
#define vri_on (PORTC|=IO_PC5)
#define vri_off (PORTC&=~IO_PC5)
#define vrm_on (PORTC|=IO_PC7)
#define vrm_off (PORTC&=~IO_PC7)
#define vra_on (PORTC |= IO_PD6)
#define vra_off (PORTC &= ~IO_PD6)


uint8_t vli, vlm, vla, vri, vrm, vra; // Positionen der Servos
uint8_t i;







/************************************************** ***************************/
// Main function - The program starts here:


void delay(uint8_t d)
{
uint16_t d1, dummy;
for (d1=d*255; d1>0; d1--) dummy^=d1;
}


int16_t main(void)
{
initRP6Control();
initLCD();

writeString_P("\n\nRP6 CONTROL M32 I2C Master Example Program!\n");
writeString_P("\nMoving...\n");

// ---------------------------------------
WDT_setRequestHandler(watchDogRequest);
BUMPERS_setStateChangedHandler(bumpersStateChanged );
ACS_setStateChangedHandler(acsStateChanged);
BATTERY_setLowVoltageHandler(batteryVoltageLow);

// ---------------------------------------
I2CTWI_initMaster(100);
I2CTWI_setRequestedDataReadyHandler(I2C_requestedD ataReady);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);

sound(180,80,25);
sound(220,80,25);

setLEDs(0b1111);

showScreenLCD("################", "################");
mSleep(500);
showScreenLCD("I2C-Master", "Behaviours");
mSleep(1000);
setLEDs(0b0000);

// ---------------------------------------
// Setup ACS power:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_ACS_POWER, ACS_PWR_HIGH);
// Enable Watchdog for Interrupt requests:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true);
// Enable timed watchdog requests:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT_RQ, true);

startStopwatch1();
startStopwatch2();
startStopwatch4();


showScreenLCD("Active Behaviour", "");



cli();
TCCR1B = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR1B |= (0 << COM00) | (0 << COM01); // ohne OCR-Pin
TCCR1B |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE0); // Interrupt ein
OCR1A = 9; // 100kHz?




DDRD |= IO_PD5; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PD5; // SERVO_OUT -> LOW
DDRD |= IO_PC2; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PC2; // SERVO_OUT -> LOW
DDRD |= IO_PC3; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PC3; // SERVO_OUT -> LOW
DDRD |= IO_PC5; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PC5; // SERVO_OUT -> LOW
DDRD |= IO_PC7; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PC7; // SERVO_OUT -> LOW
DDRD |= IO_PD6; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PD6; // SERVO_OUT -> LOW

vli=vlm=vla=vri=vrm=vra=100;

sei();
while(true)
{

uint8_t key = getPressedKeyNumber();
// This function returns a 0 if no key is pressed and
// the key number from 1 to 5 otherwise.

if(key) // If a key is pressed... (key != 0)
{
// ... we update the values
// on the LCD display:

switch(key)
{
case 1:

break;

case 2:

break;
}
}
//behaviourController();

task_LCDHeartbeat();
task_checkINT0();
task_I2CTWI();


vri=120;delay(20);
vli=80;delay(20);
vra=120;delay(20);
vla=80;delay(20);


}
return 0;
}


ISR (TIMER1_COMP_vect)
{
static uint16_t count=1; // Servoansteuerung

(count>vli)?vli_off:vli_on;
(count>vlm)?vlm_off:vlm_on;
(count>vla)?vla_off:vla_on;
(count>vri)?vri_off:vri_on;
(count>vrm)?vrm_off:vrm_on;
(count>vra)?vra_off:vra_on;

if(count<2000) count++; else count=0;
}


bei dem Code kriege ich volgenden Fehler:

Compiling: RP6Control_10_Move2.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Control_10_Move2.lst -I../../RP6lib -I../../RP6lib/RP6control -I../../RP6lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Control_10_Move2.o.d RP6Control_10_Move2.c -o RP6Control_10_Move2.o
RP6Control_10_Move2.c:1010: warning: 'TIMER1_COMP_vect' appears to be a misspelled signal handler

und die Beine bewegen sich nicht.

DIV blenderkid

radbruch
21.03.2008, 16:06
Ich kann anstatt der LEDs aber auch die IOs des M32 benutzen oder?
Na klar. Ich habe kein M32 und muss deshalb diese "Klimmzüge" machen weil die RP6-Base nur zwei wirklich freie Pins hat(ADC0/1). Um helfen zu können muss ich mich erstmal mit dem M32 vertraut machen...

Gruß

mic

radbruch
21.03.2008, 17:54
RP6Control_10_Move2.c:1010: warning: 'TIMER1_COMP_vect' appears to be a misspelled signal handler
Der Timer1 beim Mega32 hat zwei Kanäle, die Interrupts heisen hier "TIMER1 COMPA" und "TIMER1 COMPB". Der Name der ISR für OCR1A wäre dann: TIMER1_COMPA_vect

blenderkid
22.03.2008, 15:12
cli();
TCCR1A = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR1A |= (0 << COM00) | (0 << COM01); // ohne OCR-Pin
TCCR1A |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE0); // Interrupt ein
OCR1A = 9; // 100kHz?



sind diese Angaben für die M32 richtig, denn es klappt nicht. :cry: :cry: :cry: :cry: :cry:

radbruch
22.03.2008, 15:36
Das Erweiterungmodul taktet doch mit 16MHz, oder? Dann muss in OCR1A 20 (oder 19?) anstelle der 9. Außerdem glaube ich nicht dass die Register vom Timer0 direkt auf den Timer1 übertragbar sind. Das hier passt sicher nicht:

TIMSK = (1 << OCIE0); // Interrupt ein

Hier wird der Timer0-Interrupt aktiviert. Im Zweifel kannst du das mal mit Timer0 testen. Dann müßte der Base-Code mit angepasstem OCR-Wert funktionieren. Ein bisschen must du schon selbst im Datenblatt forschen...

blenderkid
19.05.2008, 16:20
Hi, ich hatte jetzt erst wieder zeit etwas für die Beine zu machen und habe diese Fragen:

1. Was ist OCR?

2. Was ist der unterschied zwischen Timer0/1?

3. Was ist OCR1A/B?

4. Was machen die Zeilen eigendlich, ich habe sie nur kopiert:
TCCR1A = (0 << WGM00) | (1 << WGM01);
TCCR1A |= (0 << COM00) | (0 << COM01);
TCCR1A |= (0 << CS02) | (1 << CS01) | (1 << CS01) | (0 << CS00);
TIMSK = (1 << OCIE0);
OCR1A = 20;


5. Wo kriege ich das Datenblatt her, nicht die Anleitung


:oops:

Dirk
19.05.2008, 17:11
5. Wo kriege ich das Datenblatt her, nicht die Anleitung
Auf der RP6-CDROM:
"ATMEGA32.PDF" im Verzeichnis "Documentation\Datasheets"

In dem Datenblatt werden auch deine Fragen 1..4 beantwortet.

Gruß Dirk

blenderkid
19.05.2008, 18:12
OOh, mist ich komme damit einfach nicht zurecht ich habe jetzt diese Einstellungen:

TCCR1A = (0 << WGM10) | (1 << WGM11); // CTC-Mode
TCCR1A |= (0 << COM1A0) | (0 << COM1A1); // ohne OCR-Pin
TCCR1A |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE1A); // Interrupt ein
OCR1A = 19; // 100kHz?




DDRC |= IO_PC6; // SERVO_OUT -> OUTPUT
PORTC &= ~IO_PC6; // SERVO_OUT -> LOW
DDRC |= IO_PC2; // SERVO_OUT -> OUTPUT
PORTC &= ~IO_PC2; // SERVO_OUT -> LOW
DDRC |= IO_PC3; // SERVO_OUT -> OUTPUT
PORTC &= ~IO_PC3; // SERVO_OUT -> LOW
DDRC |= IO_PC5; // SERVO_OUT -> OUTPUT
PORTC &= ~IO_PC5; // SERVO_OUT -> LOW
DDRC |= IO_PC7; // SERVO_OUT -> OUTPUT
PORTC &= ~IO_PC7; // SERVO_OUT -> LOW
DDRD |= IO_PD6; // SERVO_OUT -> OUTPUT
PORTD &= ~IO_PD6; //

RP6conrad
19.05.2008, 21:01
Bei eine 10µS timer wird die ISR jeden 10µS bearbeitet ! Das sind gerade 80 takten bei RP6base (8 MHz). Wen da al die 12 Servo's gesteurt wirden, kan es knap wirden (12 * eine IF Abfrage in ISR). Die komplette ISR muss fetig sein innerhalb diese 80 Schritten. Da gibt nicht mehr fiel Zeit ubrig für al das andere zu machen. In Notfall kan man naturlich auch diese Timer nach 20µS oder 40µS aenderen. Einiges Nachteil ist das die Auflosung von Servopos grober wird. Ich programmiere die Servo's in die forhandene 100µS ISR. functioniert auch, naturlich sind dan nur ca 14 Pos moglich pro servo (von 0.8 mS bis 2.2 mS)

blenderkid
20.05.2008, 15:21
hi RP6conrad,

aber die M32 hat 16MHz dann sind das 160 Takte, hast du vllt auch ein bspl. Code für mich, wäre sehr nett, mit diesen ganzen einstellungen:

TCCR1A = (0 << WGM10) | (1 << WGM11); // CTC-Mode
TCCR1A |= (0 << COM1A0) | (0 << COM1A1); // ohne OCR-Pin
TCCR1A |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE1A); // Interrupt ein
OCR1A = 19; // 100kHz?

komme ich nicht zurecht, ich weiß nicht mal ob die so für den M32 richtig sind, ich habe mir auch das Datenblatt angeschaut, da bin ich auf die Namen gestoßen, aber anwenden kann ich die nicht. Ich weiß noch nicht mal wofür die gut sind, wofür brauch ich die Einstellungen eigentlich.

Sorry für die nervenden Fragen.

DIV blenderkid

RP6conrad
20.05.2008, 20:20
Meine Lösung für die servos in M32 mit die forhandene 100 µS timer : 2 servos wirden gesteurt ueber port C5 und portC7. Minpos servo = werte 8, maxpos servo = werte 22. Das ergibt dan eine puls von 0.8 bis 2.2 mS.
Wan servo-timer 200 erreicht (=20 mS), wird er auf 0 gesetzt, und wirden beide ports hoch gesetzt. Die ports wirden zuruck auf 0 gesetzt abhangig von die eingestellte werte "servo1" und "servo2"
In die config.h mus naturlich noch die port C5 und C7 als ausgang declariert werden !

volatile stopwatches_t stopwatches;
volatile uint8_t delay_timer;
volatile uint8_t ms_timer;
volatile uint8_t servo_timer;
volatile uint16_t sound_timer;



/**
* Timer 0 Compare ISR - This timer is used for various
* timing stuff: The delay timer for blocking delays,
* "Stopwatches" for non-blocking delays and the timing of
* the sound generation with timer2...
*
* By default, it runs at 10kHz which means this ISR is called
* every ~100µs! This is nice for timing stuff!
*/
ISR (TIMER0_COMP_vect)
{
// Blocking delay (100µs):
delay_timer++;
servo_timer++;
if (servo_timer>200) {servo_timer=0;PORTC |= IO_PC5;PORTC |= IO_PC7;}
if (servo_timer>servo2) PORTC &= ~IO_PC5;
if (servo_timer>servo1) PORTC &= ~IO_PC7;

// All 1ms based timing stuff
if(ms_timer++ >= 10) { // 10 * 100µs = 1ms

blenderkid
21.05.2008, 15:10
oops, ich glaube du hast einen Teil deines Codes vergessen zu schicken

Weißt du auch wie man den Timer schneller bekommt?

Schon mal danke

RP6conrad
21.05.2008, 19:02
Die code ist nicht gans komplett : da ist auch noch eine function für die pulslange von servo in die variabele servo1 / servo2 zu schreiben.
Die timer frequenz kannst du aendern in die "controllib.c". Mit die bits CS0, CS1 und CS2 wird die prescaler eingestellt. Standard ist die auf 8 eingestellt, zahler geht hoch bis 199. Das ergibt dan 16 MegaHz/8 = 2 MegaHz. Nach 200 tics wird er auf 0 gestellt = 10 kHz. Sie konnen diesen wert verringern : OCR0 = 20 gibt schon eine 100 kHz frequenz!
Die prescaler kan auch auf 1 gesetzt werden (CS0,CS1 und CS2 alle auf 0), dan wird bei OCR0 = 200 die frequenz 8* hoher = 80kHz.

// 10kHz Timer 0:
TCCR0 = (0 << WGM00)
| (1 << WGM01)
| (0 << COM00)
| (0 << COM01)
| (0 << CS02)
| (1 << CS01)
| (0 << CS00);
OCR0 = 199;
Naturlich wir die timer 0 auch für aendere functionen genutzt !! Die laufen dan alle schneller auch naturlich.

blenderkid
22.05.2008, 10:57
könnte man dann auch diesen Timer benutzen:

cli();

TCCR1A = (0 << COM1A1)
| (0 << COM1A0)
| (0 << COM1B1)
| (0 << COM1B0)
| (0 << FOC1A)
| (0 << FOC1B)
| (0 << WGM11)
| (0 << WGM10);
TCCR1B = (0 << ICNC1)
| (0 << ICES1)
| (0 << WGM13)
| (1 << WGM12)
| (0 << CS12)
| (1 << CS11)
| (0 << CS10);
OCR1A = 15; // 125kHz (8us)

TIMSK |= (1 << OCIE1A);
sei();

oder so ähnlich?

DIV blenderkid

RP6conrad
22.05.2008, 21:16
Timer 1 ist frei auf die M32. Die kannst du naturlich brauchen. Die richtige einstellung von al die register muss du auf das Datasheet von ATmega32 entnimmen. Und dan naturlich noch die ISR1 (interrupt sub routine timer1) programmieren. Auf die robotbase ist timer 1 für die PWM von beide motoren forgesehen.

blenderkid
25.05.2008, 10:41
Juhuu, danke an alle die mir geholfen haben, es klappt jetzt

:cheesy: :cheesy: :cheesy: :cheesy: :cheesy: :cheesy: :cheesy:


DANKE

blenderkid
26.05.2008, 13:52
Hi,

es gibt doch noch eine Sache. Ich habe jetzt erst mal 4 von 12 Servos angeschlossen und wenn ich die alle ansteuere geht der RP6 in den Standby modus. Ich glaube die Servos brauchen zuviel Strom, kann man die irgentwie so ansprechen das die Stromspitzen nicht so hoch sind. Besonders beim Start, da gehen alle Servos gleichzeitig auf du Position 100 kann man das irgendwie ändern, dass sie nicht alle auf einmal laufen?

RP6conrad
26.05.2008, 21:25
Der spannungsregler von RP6base kann nur bis ca 1 A lieferen. Wan al die servo's zusammen nach ihre position fahren, ist einfach die Strom zu hoch, und die spannung bricht zusammen. Da sind verschiedene Losungen für dieses Problem :
1. Separate Spannungsregler für die Servo's. Ist sowieso angewiesen bei mehr dan 3 Servo's ! Einfach eine 7805 forsehen die dan alle servos versorgt (masse ist gemein mit platine RP6, + 5Volt geht nach die Servo's, puls kommt noch immer von platine RP6)
2. Die Pulsen von servos nicht alle gleichzeitig starten : erst pulsreihe von servo1, 500 mS warten, pulsreihe servo2 starten, 500mS warten, pulsreihe servo 3 starten... Prinzip ist das die servos nur anfangen mit regelen ab die puls kommt. Alleine Spannung lasst die servos noch nicht fahren... Bleibt immer das Problem wan spater in Program verschiedene servos zusammen angesteuert wirden. Ansatz 1 ist die bessere Lösung !

blenderkid
27.05.2008, 13:22
hi,
wie muss ich die dann anwenden? Bekommt dann jeder Servo einen Spannungsregler?

DIV blenderkid

radbruch
27.05.2008, 16:38
Hallo blenderkind,

Meine Servos hängen auf einem zweiten 4,8V-Akkupack. Plus(rot) auf Plus Extraakku, Minus(braun) auf GND-RP6 und Signal auf Signal-RP6. Minus-Extraakku auf GND-RP6. Das ist aber nur eine Zwischenlösung weil zuviel Ballast. Geplant habe ich eine Spannungsregler-Platine mit je einem 5V/2A-Regler pro 4 Servos (4x0,5A normaler Servostrom), versorgt vom RP6-Akkupack.

Ein großes Problem ist die gleichzeitige Ansteuerung der Servos. Fast alle Beispiele für Servoansteuerungen starten alle Servos zur gleichen Zeit und stoppen sie dann einzeln je nach Drehwinkel. Der Gesamtstrom ist dabei beim Start der Servos enorm! Ich bastle im Moment an einer anderen Lösung. Die Servos erhalten ihre Impulse nacheinander. Mein Code für eine 100kHz-ISR und 8 Servos sieht im Moment so aus (und ist noch nicht richtig getestet):

ISR(TIMER2_COMP_vect)
{
static uint16_t count=0;
static uint8_t impuls=0, servo=0;
if(!impuls)
{
if(servo == 0) { impuls=vla; servo0_on; }
if(servo == 1) { impuls=vli; servo0_off; servo1_on; }
if(servo == 2) { impuls=hla; servo1_off; servo2_on; }
if(servo == 3) { impuls=hli; servo2_off; servo3_on; }
if(servo == 4) { impuls=hra; servo3_off; servo4_on; }
if(servo == 5) { impuls=hri; servo4_off; servo5_on; }
if(servo == 6) { impuls=vra; servo5_off; servo6_on; }
if(servo == 7) { impuls=vri; servo6_off; servo7_on; }
if(servo == 8) servo7_off;
if(servo < 9) servo++;
} else impuls--;
if(count < 2000) count++; else { count=servo=impuls=0; if(p) p--; }
}


Gruß

mic

blenderkid
03.06.2008, 16:07
Hi, ich habe jetzt einpaar Spannungsregler 5V 2A. Brauche ich für jedes Bein einen Spannungsregler? Ich glaube eher einen für alle, oder? Hat vielleicht jemand einen Schaltplan für sowas?

DiV blenderkid

RP6conrad
03.06.2008, 22:20
So ein Spannungsregler hat drei Beinchen. An ein Bein schliesst du der + pool von accu an (+bat auf RP6). Ein bein wird an die Masse von RP6 gelegt (gnd). Das letzte Bein fuhrt dan die geregelte 5 Volt Spannung. Diese wird dan nach alle + Anschlusse von die Servos gefuhrt (mittelanschluss Servostecker, rote draht). Eine Regler kan mehrere servos speisen. Wan die Strom mal zu hoch wird, geht der Regler nicht kaputt, aber die Spannung von 5 Volt senkt dan ab. Wicht ig ist das die richtige Beinchen an die richtige Anschluss kommen ! Mal in Datenblatt nachschauen.

radbruch
03.06.2008, 23:46
Mit "Beine" sind die Beine des Roboters gemeint.


Geplant habe ich eine Spannungsregler-Platine mit je einem 5V/2A-Regler pro 4 Servos (4x0,5A normaler Servostrom), versorgt vom RP6-Akkupack.
Da ich zwei Servos pro Bein verwende sind das ein Spannungsregler für zwei Beine. Meine 3€-Servos ziehen bei Belastung (Blockieren) etwa 1A, unbelastet ca. 300mA.

Im Datenblatt (z.B. des L7805) findet man auch Standartschaltungsbeispiele. Im Prinzip am Eingang und am Ausgang je ein großer Elko und ein kleiner Keramischer als Stütze und gegen das Schwingen.