PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro steuert Servo aber wie???



lars_94
06.05.2010, 19:25
Hallo,
Ich wollte an meinen Asuro einen Servo anschließen (habe auch gesehen, dass es dazu schon Beiträge gibt, aber ich verstehe nicht wie ich ihn ansteuern soll)
Ich hab ihn jetzt einfach mal an di BackLED gepackt. Aber irgenswie versteh ich nicht wie ich ihn steuern soll (in einem Beitrag wird gesagt normal blinken lassen, der nächste sacht der braucht eine Signallänge????)
Also kann mir das jemand Erklären???
Ein großes DANKESCHÖN schon mal im vorraus.
Gruß Lars

josua
06.05.2010, 20:58
man muss die servo- stromversorgung an gnd und vcc hängen und die signalleitung an z.B. die back-led. dann lässt man die led im programm in einem bestimmten takt (irgendwas mit 10-100ms oder so, müsst ich nachgucken) blinken, indem man ledon und ledoff sowie sleep(irgendwas) in eine forschleife packt!!!

gruß josua

Thund3r
06.05.2010, 21:08
Hallo

Genau!

So sieht zB der Quelltext aus:


...
int x;
for(x=0; x<18; x++)
{
Servo(33);
}
...
void Servo(int pos)
{

StatusLED(GREEN);
Sleep(pos);
StatusLED(OFF);
Sleep(255);Sleep(255);Sleep(255); Sleep(255);Sleep(255);Sleep(255);
StatusLED(GREEN);
Sleep(pos);
StatusLED(OFF);
Sleep(255);Sleep(255);Sleep(255); Sleep(255);Sleep(255);Sleep(255);

}

Damit kann man dann zB sowas hier machn:

https://www.roboternetz.de/phpBB2/viewtopic.php?t=53861

Gruß Thund3r

lars_94
07.05.2010, 14:09
Hallo, die Bewegung mit dem Uhrzeigersinn hab ich hinbekommen, sobald ich Taster 1 drücke geht der Servo los, lasse ich wieder los, hört der Servo auf zu drehen.


#include "asuro.h"
int main (void)
{
unsigned int i;
Init();
StatusLED(GREEN);
while(1) {
if (PollSwitch()==32) {
BackLED (ON,ON);
for (i = 0; i < 6; i++) {
Sleep (255);}
BackLED (OFF,OFF);
for (i = 0; i < 1; i++) {
Sleep (200);}
}
else if (PollSwitch()==16) {
BackLED (ON,ON);
for (i = 0; i < XXX ; i++) {
Sleep (255);}
BackLED (OFF,OFF);
for (i = 0; i < 1; i++) {
Sleep (200);}
}
else {BackLED(OFF,OFF);
}
}
return 0;
}

mit dem else if wollte ich die andere Richtung nehemen aber wie?
(was muss bei den drei x für ne Zahl rein )

radbruch
07.05.2010, 15:21
Hallo

Der Drehwinkel eines Servos ist von der Impulslänge des Ansteuersignals abhängig. Der Bereich geht von ca. 0,5ms (ms=Millisekunde) bis 1,5ms (je nach Servo und Doku auch1-2ms) für ca. 180 Grad. Der Impuls sollte ca. alle 20ms wiederholt werden (nicht nach 20ms!).

Das Problem ist nun die Zeitmessung für solche doch recht kurze Impulse. Neben Zählschleifen (dazu komme ich später noch) bietet sich hierfür ein Sleep() an. Die kürzeste Zeit dabei ist abhängig von der Version der Library. Bei der orginalen CD-Lib dauert ein Sleep(1) 1/72000Sek, bei den erweiterten Libs 1/36000Sek. Eine Millisekunde (=Servomitte) dauert dann Sleep(72) bzw. Sleep(36). Die Werte für 1/2ms sind jeweils die Hälfte, für 1,5ms entsprechend 150% ;)

Für 20ms der Pause wären es Sleep(20*36) (oder 72, das erspare ich mir jetzt aber, im Folgenden nur noch Daten für neue Libs) oder Sleep(720). Das ist mehr als in ein Byte geht, deshalb verteilen wir das auf mehrere Aufrufe: Sleep(255); Sleep(255); Sleep(210); Weil wir den Impuls ja alle 20ms wiederholen wollen, müssen wir noch die schon verstrichene Zeit für die Impulslänge abziehen. Ein kompletter Impuls mit folgender Pause würde dann so aussehen:

BackLED (ON,ON);
Sleep(winkel); // Winkel ca. 18-54
BackLED (OFF,OFF);
Sleep(255);
Sleep(255);
Sleep(210-winkel);

Da das Servo aber auch Zeit benötigt um die geforderte Position anzufahren, muss man den Impuls mehrmals senden. Wie lange das Servo genau braucht weiß man dabei allerdings nicht. Die Zeit für 50 gesendete Impulse beträgt genau 1 Sekunde (0,02s*50) Ein Programm das im Sekundenwechsel Impulse für zwei Servopositionen erzeugt könnte so aussehen:

#include "asuro.h"
int main (void)
{
unsigned char c;
Init();
StatusLED(GREEN); // ist nach Init() immer grün!
while(1)
{
StatusLED(RED);
for (c = 0; c < 50; c++)
{
BackLED (ON,ON);
Sleep(20); // Impuls Wert ca. 18-54
BackLED (OFF,OFF);
Sleep(255); // Pause
Sleep(255);
Sleep(210-20);
}
StatusLED(GREEN);
for (c = 0; c < 50; c++)
{
BackLED (ON,ON);
Sleep(50);
BackLED (OFF,OFF);
Sleep(255);
Sleep(255);
Sleep(210-50);
}
}
return 0;
}
(nicht getestet)

Anstelle von Sleep(winkel); kann man auch eine Zählschleife verwenden. Dadurch wird die Auflösung des Servos besser. Meine Variante sieht meist so aus:

unsigned int i, dummy;

BackLED (ON,ON);
i=winkel; // irgendwas bei ca. 1000-5000?
while(i--) dummy^=i;
BackLED (OFF,OFF);

Gruß

mic

[Edit]
zwei Servos gleichzeitig:

BackLED (ON,OFF);
Sleep(20); // Impuls Servo1 Wert ca. 18-54
BackLED (OFF,ON);
Sleep(50); // Impuls Servo2
BackLED (OFF,OFF);
Sleep(255); // Pause
Sleep(255);
Sleep(210-20-50);
;)

lars_94
07.05.2010, 16:08
hi also den oben stehenden code(der noch mit sleep ist)funktioniert nicht, der servo dreht wieder nur in eine Richtung. Könntest du mir den mit der Zählschleife evtl erklären???
Gruß Lars

radbruch
07.05.2010, 16:53
Hallo

Bleiben wir erstmal bei Sleep(), denn damit muss es auch funktionieren. Welche Version der Library verwendest du? Mit der orginalen CD-Version müssen alle Sleep()s verdoppelt werden!

BackLED (ON,ON);
Sleep(40); // Impuls Wert ca. 36-108, Mitte ca. 72
BackLED (OFF,OFF);
Sleep(255); // Pause Sleep(20*72-winkel)
Sleep(255);
Sleep(255);
Sleep(255);
Sleep(255);
Sleep(165-40);

Gruß

mic

lars_94
07.05.2010, 16:58
ich verwende zur zeit v 2.80

radbruch
07.05.2010, 17:17
Hallo

v2.8 kenne ich leider nicht, aber ich vermute, sie läuft auch mit 1/36000er Takt. Dann kannst du den Code mit den doppelten Sleep()s vergessen.

Wie hast du denn das Servo angeschlossen? Rot auf +, Braun auf - und Orange (oder was sonst noch übrig ist) auf BackLED?

Hier noch ein Programm das auf meinem Asuro gelaufen ist. Mit den Tastern 1,3,4 und 6 gibt man feste Positionen vor, mit 2 und 4 (jeweils die mittleren Tasten auf jeder Seite) "steppt" das Servo auf die eine oder andere Seite:


#include "asuro.h"

#define servo_stellzeit 30
unsigned char sw0,sw1, servo_pos;

void servo(unsigned char winkel){
unsigned int count=0;
do{
count++;
BackLED(ON,ON); Sleep(winkel);
BackLED(OFF,OFF); Sleep(255); Sleep(255); Sleep(255);
}while (count<servo_stellzeit);
}

int main(void) {

Init();
StatusLED(OFF);
sw0=PollSwitch();
servo_pos=45;
servo(servo_pos);
do{
sw1=sw0;
sw0=PollSwitch();
if ((sw0) && (sw0==sw1)){
switch(sw0){
case 1: servo_pos=80; break;
case 2: if (servo_pos<80) servo_pos++; break;
case 4: servo_pos=45; break;
case 8: servo_pos=45; break;
case 16: if (servo_pos>10) servo_pos--; break;
case 32: servo_pos=10; break;
}
StatusLED(YELLOW);
} else { StatusLED(GREEN); }
servo(servo_pos);
}while (1);
return 0;
}


Gruß

mic

lars_94
07.05.2010, 17:28
ok das klappt schonmal aber wie bekomm ich das hin, das er sich andersherum dreht????

lars_94
07.05.2010, 18:12
also folgenden Beitrag erstma vergessen (Zitat:ok das klappt schonmal aber wie bekomm ich das hin, das er sich andersherum dreht????)
so ich hab das so gemacht das weiße PWM kabel an die BackLED und an das rote-, so wie das schwarze Kabel hab ich ne eigene Batteriebox angeschlossen, mit ebenfalls 4,8V spannung.

radbruch
07.05.2010, 18:31
Hallo,

um uns wieder zu syncronisieren solltest du jetzt mal dein aktuelles Programm zeigen und deine Frage verständlicher formulieren ;)

Hast du den Minuspol der Servobatteriebox auch mit dem - des asuro verbunden? Das ist zwingend nötig damit das Servo und das Signal vom asuro eine gemeinsame Basis (GND) haben.

Weil ich mir selbst nicht mehr ganz sicher war habe ich es jetzt mit meinem "asuro" getestet. Der besitzt allerdings keine BackLEDs, deshalb hängt das Servo am Tastenpin PC4:

#include "asuro.h"

#define impuls_on DDRC|=(1<<PC4); PORTC|=(1<<PC4) // Servo an Tasteneingang
#define impuls_off DDRC&=~(1<<PC4); PORTC&=~(1<<PC4)

int main (void)
{
unsigned char c;
Init();
StatusLED(GREEN); // ist nach Init() immer grün!
while(1)
{
StatusLED(RED);
for (c = 0; c < 50; c++)
{
impuls_on;
Sleep(20); // Impuls Wert ca. 18-54
impuls_off;
Sleep(255); // Pause
Sleep(255);
Sleep(210-20);
}
StatusLED(GREEN);
for (c = 0; c < 50; c++)
{
impuls_on;
Sleep(45);
impuls_off;
Sleep(255);
Sleep(255);
Sleep(255);
Sleep(210-45);
}
}
return 0;
}


Das Ergebniss sieht dann so aus:

http://i2.ytimg.com/vi/5fZTK4iMqeQ/3.jpg (http://www.youtube.com/watch?v=5fZTK4iMqeQ)
http://www.youtube.com/watch?v=5fZTK4iMqeQ

Gruß

mic

lars_94
07.05.2010, 19:08
Hi, habs jetzt geschaft



/************************************************** *************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* any later version. *
************************************************** *************************/


#include "asuro.h"
int main (void)
{
Init();
StatusLED(GREEN);
while(1) {
if (PollSwitch()==1) {
BackLED (OFF,ON);
Sleep(18); // Impuls Wert ca. 18-54, Mitte ca.36
BackLED (OFF,OFF);
Sleep(255); // Pause Sleep(20*36-winkel)
Sleep(255);
Sleep(210-54);}

else if (PollSwitch()==4) {
BackLED (OFF,ON);
Sleep(54); // Impuls Wert ca. 18-54, Mitte ca.36
BackLED (OFF,OFF);
Sleep(255); // Pause Sleep(20*36-winkel)
Sleep(255);
Sleep(210-54);}

else if (PollSwitch()==8) {
BackLED (ON,OFF);
Sleep(18); // Impuls Wert ca. 18-54, Mitte ca.36
BackLED (OFF,OFF);
Sleep(255); // Pause Sleep(20*36-winkel)
Sleep(255);
Sleep(210-18);}

else if (PollSwitch()==32) {
BackLED (OFF,ON);
Sleep(54); // Impuls Wert ca. 18-54, Mitte ca.36
BackLED (ON,OFF);
Sleep(255); // Pause Sleep(20*36-winkel)
Sleep(255);
Sleep(210-54);}

else {BackLED(OFF,OFF);}
}
return 0;
}

mit dem oberen teil steuer ich den rechten servo in die eine oder andere Richtung mit dem unteren teil steuer ich den linken servo in die eine oder andere Richtung. Habe aber nochmal ne Frage: ist es normal das der servo nicht komplett bis zu anschlag dreht???

lars_94
08.05.2010, 07:22
*mit dem oberen teil des code steuer ich den rechten servo in die eine oder andere Richtung mit dem unteren teil des code steuer ich den linken servo in die eine oder andere Richtung. Habe aber nochmal ne Frage: ist es normal das der servo nicht komplett bis zu anschlag dreht???

lars_94
11.05.2010, 15:56
hallo, nochma die Frage:
mein asuro steuert den servo jetzt(Code oben), der servo nutzt aber nur einen teil, er dreht nich bis zum anschlag. Wie kann ich das verändern????

Valen
11.05.2010, 16:21
Etwas kurzeren puls bei völlig links bzw. längere puls bei völlig rechts. Die oben geben Sleep werten sind nicht sehr genau. Und es gibt immer bau-toleranzen.

lars_94
11.05.2010, 16:58
wie viel kürzer?? statt 18 vlt. 9 oder so??
Kann man die Werte bestimmen???

Valen
11.05.2010, 17:08
Nein, bei den asurocd lib ist 18 das theoretische minimum. 36 die mittelwert, und 54 fur gegen die andere anschlag. Aber im praktische fall muss man vielleicht 16 oder 17 einstellen damit er gegen die anschlag steht. Und 55 oder 56, vielleicht ein bisshcen mehr. Einfach ausprobieren bis es passt. Du habst doch gemessen wieviel den lage fehlt? Dan proportionel anpassen.

lars_94
11.05.2010, 17:15
ok danke
gruß lars