PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ASURO: Motorsteuerungslibrary



stochri
29.07.2005, 23:41
Hallo Miteinander,
hier die um ein paar Motorsteuerungsfunktionen erweiterte asuro.c.

Neu hinzu gekomme Funktionen:

Wheelspeed: misst die Radgeschwindigkeit in der Interuptroutine
Go(+-) gerade Bewegung forwärts/rückwärts
Turn(+-) Drehung links rechts

Im Testprogramm habe ich einen einfachen Regler implementiert

Wäre schön, wenn Ihr eure Erfahrungen posted.

Gruss,
stochri

Andun
30.07.2005, 11:26
Mal kurz als Zwischenfrage, bevor ich es ausprobiere:

Hast du die normale Datei erweitert, oder gleich shcon, die schon erweiterte?

Also die von Weja und waste? Wäre wohl besser, wenn es diese ist.

So long

Andun

P.S.: Ich werde deine Datei aber auch mal ausprobieren, wenn cih Zeit hab.

stochri
30.07.2005, 18:03
Hallo Andun,
ich habe die Bibliothek von weja genmomen und erweitert. Im wesentlichen die Interruptroutine für die Odometrie.
Die verschiedenen Versionsänderungen sind aber ausführlich dokumentiert.

Gruss,
stochri

Andun
30.07.2005, 22:12
Achso. Ok.

Achso. Jetzt versteh ich glaub ich auch erst den Sinn der Sache.

Du hast die Odometrie mit in die Bewegung eingebaut. Richtig?

Ich hab mich nämlich schon gewundert. :D

Ist in der Lib, denn auch die IR-Abstandsmessung drin? Weil das hab ich auch noch vor anzubringen, und es wäre auch doof wenn hier im RN mehrere erweiterte Libs rum fliegen.

Nachtrag:

Also nach ausprobieren und auch nach nachgucken in der asuro.c hab ich jetzt gesehen, dass du ja immer nur an der linken Scheibe schaust, wie man fährt. Ich fände es aber ungemein praktisch, wenn du in die Go() gleich die Encoder Geschichte, fürs wirklich grade aus mit reinpacken würdest. Also die Differenz vom rechten und linken Odo messen und dann entweder auf der einen Seite schneller, oder halt langsamer werden. Du weißt doch was ich meine. :D

Das wäre praktisch, sonst hat die Go Funktion nicht so den nutzen, außer dass sie halt eine feste anzahl von schritten fährt.

So long

Andun

P.S.: In der Drehung wäre ein Vergleich von rechts und links auch nicht schlecht.

Nachtrag die 2.:

Also jetzt hab ich auch das nachgeguckt. :D Die Änderungen von waste für die IR-Abstandmessungen, hast du ja noch nicht drin. Wäre nett, wenn du die noch mit in das File übernimmst. Dann haben wir glaub ich was gutes geschaffen. :D

izaseba
30.07.2005, 23:56
Wäre nett, wenn du die noch mit in das File übernimmst.

Wo liegt das Problem es selber zu machen :-s

Gruß Sebstian

payce
31.07.2005, 02:08
Frage (interessehalber): Was für einen Regler hast du denn eingebaut? P-Regler, Fuzzy...?

Würde mich nur interessieren, weil ich mal was Ähnliches machen will (wenn mein Asuro endlich da ist).

Gruß pay.c

Vogon
31.07.2005, 11:05
... Was für einen Regler hast du denn eingebaut? P-Regler, ..
Ich versuche gerade den PI-Regler aus dem Buch "Mobile Roboter" zum Rug-Warrior ans laufen zu bekommen.

(Ganz toll finde ich das mein ASURO Musik machen kann - habe gerade das Programm 020 von http://home.planet.nl/~winko001/AsuroIdx.htm geladen ! )

stochri
31.07.2005, 11:45
Hallo Vogon,
wenn Dein PI-Regler läuft, kannst Du das Ergebnis ja mal posten.

@payce
Den Regler den ich eingebaut habe ist ein einfacher inkremental Regler. Auf deutsch: wenn Abweichung dann Incrementiere/Decrementiere Motorleistung.
Es war einfach eine Zeitfrage.


Gruss,
stochri

Vogon
31.07.2005, 11:59
wenn Dein PI-Regler läuft, kannst Du das Ergebnis ja mal posten.
Na klar!
Ich muss aber erst verstehen wie das Programm arbeitet. Es läuft auf dem Rug Warrior als eigene Task. Bin am überlegen wo ich das reinhängen kann?

Andun
31.07.2005, 12:05
Achja. Was vielleicht in der Lib auch noch nett wäre, wenn man an die Go() oder Turn() funktion als 2. Parameter noch die geschwindigkeit angeben kann. Vielleicht auch mit nem Standart wert, so dass man in nicht unbedingt angeben muss. (Das geht doch beim einfachen C auch, oder?)

Also ich werd dass vielleicht sonst auch mal heute machen. :D

Also dann aber aufgebaut auf der weja/waste Lib.

So long

Andun

Vogon
31.07.2005, 12:15
Danke, hatte gerade den gleichen Gedanken. Wir sollten, soweit es möglich ist, mit der gleichen Lib arbeiten.

Der PI-Regler ist HIER auf den Seiten 27 bis 30 beschrieben :
http://ag-vp-www.informatik.uni-kl.de/Lehre/Praktikum/Versuchsanleitung.pdf
Wer sich auch mal dran versuchen möchte - ich habe das Programm für den Motorola 6811 mal abgeschrieben:



/************************************************** *****************************
*
* Description: Asuro PI-Regler 0.01
*
************************************************** ***************************/



/* Bestandteile der Geschwindigkeitssteuerung der Motoren: */
/* Steuerkette zur Pulsbreiten-Modulation */
/* Geschwindikeitsregelkreis */


/* >>>>>>>>> Steuerkette zur Pulsbreiten-Modulation <<<<<<<<<< */


int DDRD = 0x1009; /* Port D Datenrichtung */
int OC1M = 0x100c; /* Ausgabevergleich 1 Maske */
int OC1D = 0x100d; /* Ausgabevergleich 1 Daten */
int TOC1 = 0x1016; /* Ausgabevergleich-Zeitgeber 1*/
int TOC2 = 0x1018; /* Ausgabevergleich-Zeitgeber 2 (inker Motor) */
int TOC3 = 0x101a; /* Ausgabevergleich-Zeitgeber 3 (rechter Motor) */
int TCTL1= 0x1020; /* Zeitgeber-Steuerung 1, 8Bit Register */

/* motor_index: 0 => Linker Motor, 1 => Rechter Motor */
int sign[2] = {1,1}; /* Vorzeichen fuer Motorlaufrichtung */


/* Hilfsfunktionen */

float abs(float arg) /* Absolutwet */
{
if (arg < 0.0) return -arg;
else return arg;
}

int get_sign(float val) /* Vorzeichen des arguments finden */
{
if (val > 0.0) return 1;
else return -1;
}


/* Einschrenkung des wertebereichs von val */
float limit_range(float val, float low, float high)
{
if (val < low) return low;
else if (val > high) return high;
else return val;
}

void init_pwm() /* initia. der Pulsbreiten-Modulation */
{
poke(DDRD,0b00110010); /* Port D; ausgabe 5,4,3,1; eingabe 0 */
poke(OC1M,0b01100000); /* Ausgabevergleich aendert PA5 und PA6 */
poke(OC1D,0b01100000); /* OC1-Vergleich schaltet PA5 und PA6 */
bit_set(TCTL1,0b10100000); /* OC3 schaltet PA5 aus, OC2 schaltet PA6 aus */
pokeword(TOC1,0); /* wenn zeitgeber (TCNT) = 0, OC1 erfolgreich */
pokeword(TOC2,1); /* Mindestzeit fuer OC2 */
pokeword(TOC3,1); /* Mindestzeit fuer OC3 */
}

/* das Vorzeichen wird gesondert behandelt
da wir nur einen Kanal-Encoder haben */
float pwm_motor(float vel, int motor_index)
{
float vel_1;
if (sign[motor_index] > 0) /* wahl der laufrichtung */
bit_set(portd,dir_mask[motor_index]);
else
bit_clear(portd,dir_mask[motor_index]);
vel_1 = limit_range(vel,1.0,99.0);
/* 1 < Pulsbreiten-Modulation - Tastverhaeltnis 100 */
pokeword(TOCx[motor_index], (int) (655.36 * vel_1));
return vel_1;
}


/* Pulsbreiten_Modulationsbefehl hoechster Prioritaet */
void move(float l_vel,float r_vel) /* R,L vel: [-100.0. 100.0] */
{
sign[0] = get_sign(l_vel); /* Laufrichtung */
sign[1] = get_sign(r_vel);
pwm_motor(abs(l_vel),0); /* Pulsbreitenmod. setzen */
pwm_motor(abs(r_vel),1);
}


/* >>>>>>>>>>>>>>>>>>>>>>>>> Regelkreis <<<<<<<<<<<<<<<<<<<<<<<< */

float control_interval = 0.25; /* Regelkreis so oft durchlaufen */
float des_vel_clicks = 0.0; /* Geschw.-Sollwert in Imp. per Zeitinterw. */
float des_bias_clicks = 0.0; /* Gewuenschte Vorspannung in Imp. per Zeitinterw. */
float power[2] = {0.0,0.0}; /* Einschaltbefehl zum Motor */
float integral = 0.0; /* Integral der Geschw.differenz */
float k_integral = 0.10; /* Integraler Fehlerzuwachs */
float k_pro = 1.0; /* Proportionaler Zuwachs */

/* Setzen, Speichern von power */
void alter_power(float error,int motor_index)
{
power[motor_index] = limit_range(power[motor_index] + error, 0.0, 100.0);
pwm_motor(power[motor_index], motor_index);
}

float integrate( float left_vel, float right_vel, float bias)
{
float integral = limit_range((integral + left_vel + bias - right_vel), -1000.0,1000.0);
return integral;
}
void speed_control()
{
int left_vel, right_vel, lweg=0,rweg=0;
float integral_error, left_error, right_error;
while(1)
{
left_vel = get_left_clicks();
right_vel = get_right_clicks();
rweg += right_vel;
lweg += left_vel;
integral_error = k_integral * integrate((float)left_vel, (float)right_vel, des_bias_clicks);
left_error = k_pro * (des_vel_clicks - (float)left_vel - integral_error);
right_error = k_pro * (des_vel_clicks - (float)right_vel + integral_error);
alter_power(left_error, 0);
alter_power(right_error, 1);
printf("vel=%d:%d",right_vel,left_vel);
printf(" weg=%d:%d\n",rweg,lweg);
/* printf(" err=%d:%d\n",righterror,left_error); */
sleep(control_interval);
}
}

float k_clicks = 8.0 / 100.0;

void set_velocity(float vel, float bias)
{
des_vel_clicks = k_clicks * vel;
des_bias_clicks = k_clicks * bias;
sign[0] = get_sign(vel -bias);
sign[1] = get_sign(vel + bias);
}

void start_speed_control()
{
init_pwm();
init_motors();
init_velocity();
get_right_clicks();
get_left_clicks();
start_process(speed_control());
}






Andun
31.07.2005, 13:57
Hä? Ich versteh jetzt leider nicht, was das von dir jetzt genau bringt. :D

Könnte mir mal jemand erklären, was ein PI-Regler ist?

Danke

Also ich hab jetzt mal die Lib erweitert, bzw. die Go() geändert.

Leider kennt C ja keine Vorgabeargumte.

Hier erstmal der Code:

void Go(int distance, int speed)
{
int enc_count = 0;
int tot_count = 0;
int diff = 0;
int l_speed = speed, r_speed = speed;
enc_count=abs(distance);

// enc_count=distance*10000;
// enc_count/=12823;

Encoder_Set(0,0); // reset encoder

MotorSpeed(l_speed,r_speed);
if(distance<0) MotorDir(RWD,RWD);
else MotorDir(FWD,FWD);

while(tot_count<enc_count) {
tot_count += encoder[LEFT];
diff = encoder[LEFT] - encoder[RIGHT];
if (diff > 0) { //Left faster than right
if ((l_speed > speed) || (r_speed > 244)) l_speed -= 10;
else r_speed += 10;
}
if (diff < 0) { //Right faster than left
if ((r_speed > speed) || (l_speed > 244)) r_speed -= 10;
else l_speed += 10;
}
Encoder_Set(0,0); // reset encoder
MotorSpeed(l_speed,r_speed);
Msleep(1);
}
MotorDir(BREAK,BREAK);
Msleep(200);
}

Noch kurz eine Erklärung:
Diese Konstruktion "if ((l_speed > speed) || (r_speed > 244))" dient dazu, dass der Wert erstens nicht unter den eingestellten Speed und 2. nicht über 255 geht. Ich denke, der Rest ist ersichtlich.

Es ist also ratsam, als maximal Geschwindigkeit, vielleicht 230 zu verwenden.

Bitte mal test, und sonst nochmal melden, wenn Fehler drin sind.

So long

Andun

stochri
31.07.2005, 18:52
Hallo Andun,

zum PI-Regler:
Ein Regler ist im allgemeinen in einer Regelschleife eingebaut.
Zuerst wird die Differenz zwischen Soll- und Ist- berechnet und mit diesem Wert der Regler angesteuert.
Bei einem PI-Regler ( proportional- integral- Regler ) wird die Differenz einfach mit einem Faktor multipliziert und zusätlich der Integrallwert der Differenz hinzuaddiert. (http://de.wikipedia.org/wiki/PID-Regler)

Zu den Motorsteuerroutinen:
Meiner Meinung nach ist der beste Test für Motorsteuerung das Zeichnen des Haus vom Nikolaus (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=10291&highlight=asuro+wettbewerb)

1. Nur wenn die Motorsteuerung wirklich exakt arbeitet kommt der Roboter wieder zum Ausgangspunkt zurück.

2. Wenn man einen Stift an den Roboter montiert, ist sehr genau dokumentiert. wie gut der Gleichlauf der Regelung funktioniert.

Gruss,
stochri
[/url]

stochri
31.07.2005, 21:31
Hier die selbe, etwas verbesserte Libray.
( ausro.c endlich mit verbesserter Printstr-Funkiton, bei der man nicht die Buchstaben zählen muss )

siehe auch:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=10806&postdays=0&postorder=asc&start=66

Gruss,
stochri

Vogon
10.08.2005, 21:11
wenn Dein PI-Regler läuft, kannst Du das Ergebnis ja mal posten.
Mein erstes Ergebniss ! Der ASURO fährt auch bei belastung geradeaus. Auch das langsam fahren sieht garnichtmal so schlecht aus.

stochri
10.08.2005, 21:45
Hallo Vogon,
ich habe Deinen Code mal überflogen. Sieht nicht schlecht aus von weitem und ist sauber strukturiert.

Du bist der erste hier im Forum, der mal einen PI-Regler auf dem ASURO realisiert hat. Gratulation.

Heute komme ich leider nicht mehr dazu, das ganze zu auszuprobieren, aber demnächst ...

Kleiner Tip: es wäre nicht schlecht, wenn Du Deinen Nickname in den Header der Files schreibts, dann kann man das Ganze Dir zu ordnen. Wenn Du Dir schon so viel Arbeit mit dem Programmieren machst, solltest Du ( bzw. Dein Nick ) auch die Loorbeeren ernten.

Viele Grüße,
stochri

MadMan2k
11.02.2006, 19:15
ich hab dazu mal ne frage:
wie berücksichtigt ihr unterschiedliche untergründe und die beiden möglichen Odometrieauflösungen?
Sollte man nicht noch einen proportionalitätsfaktor einbauen und eine dokumentation zur messung schreiben?

oder konkret:
wie habt ihr den proportionalitätsfaktor berechnet? ich hab die gröber odometriescheibe benutzt und nun dreht der roboter zu weit...

robotcool
11.02.2006, 19:24
Hey habe ien frage mit welchen pogramm kann man die sahcne an sehen

mfg robotcool

Andun
12.02.2006, 13:54
also wir haben die feine scheibe verwendet. Du müsstest halt die Berechnungen alle umrechnen ....

Ansehen kann man die Programme so wie aller anderen Dateien auch: Im Editor ... Wenn du das allerdings nciht weißt, dann kannst du mit dem Inhalt wahrscheinlich auch nciht viel anfangen.

Andun

MadMan2k
12.02.2006, 14:18
und an eben diesen berechnungen bin ich interessiert.
ihr seid ihrgendwie auf einen faktor von 166/360 gekommen - nach meiner Messung stimmt er, wenn ich ihn auf 100/360 ändere.

bei der Go Funktion ist der faktor jedoch auskommentiert, sodass sich die angabe wohl auf die anzahl der "ticks" bezieht.

naja ich bin grad sowieso dabeid as ganze etwas umzukrempeln...

stochri
12.02.2006, 15:58
bei der Go Funktion ist der faktor jedoch auskommentiert, sodass sich die angabe wohl auf die anzahl der "ticks" bezieht.

Die Go Funktion wollte ich ursprünglich so programmieren, dass man die Weglänge in [mm] angeben kann.
Im ersten Anlauf hat das allerdings nicht funktioniert ( vermutlich weil ich bei den Konstanten das L für long vergessen habe ).
Da ich beim Programmieren ein wenig in Eile war, habe ich einfach die Skalierung auf die Einheit [mm] weggelassen. Eigentlich wollte ich das später dann mal irgendwann korrigieren.
Wenn sich also jemand die Zeit nimmt und die Umrechnung korrekt in die Routine einbaut ...

Gruss,
stochri

stochri
12.02.2006, 16:04
ihr seid ihrgendwie auf einen faktor von 166/360 gekommen - nach meiner Messung stimmt er, wenn ich ihn auf 100/360 ändere. .

Folgender Algorithmus
1. Motoren einschalten
2. Encoder beobachten und solange drehen bis Zielposition erreicht

Problem:
Die Motoren laufen nach dem Ausschalten nach, d.h. der Asuro dreht zu weit.

Der Faktor für die Drehung habe ich experimentell bestimmt.

Allerdings muss man sagen, dass beim verwendeten Prinzip entweder für sehr kleine Umdrehungen oder größere Umdrehungen Ungenauigkeiten auftreten.

Gruss,
stochri

MadMan2k
12.02.2006, 19:34
Wenn sich also jemand die Zeit nimmt und die Umrechnung korrekt in die Routine einbaut ...
jo ich bin grad sowieso dabei dei lib ein wenig aufzräumen...

MadMan2k
13.02.2006, 18:05
so, fertig:
http://www.madman2k.net/files/libasuro_1.0.7z

wenn wer mal zu viel Zeit haben sollte kann er das ganze mal für beide Scheiben und in Abhängigkeit von Batteriespannung und Geschwindigkeit durchrechnen...

stochri
13.02.2006, 18:31
gute Änderungen sollte man vielleicht in die ASUOR-Lib einarbeiten:

http://sourceforge.net/project/showfiles.php?group_id=155217

Der Maintainer ist m.a.r.v.i.n hier im vorum, glaube ich.

Sternthaler
13.02.2006, 19:09
@MadMan2k
Kannst du bitte mal mitteilen, mit welchem Programm man den Inhalt aus libasuro_1.0.7z wieder herstellen kann?
Es ist kein ASCII und winzip mault mich an, dass es kein gültiges Archiv-Format ist. (winzip habe ich als Version 6.3 unter win98)
Ist es compress bzw. uncompress aus der Unix-Welt?

Schon mal vielen Dank

MadMan2k
13.02.2006, 19:50
http://www.7-zip.org/

Andun
13.02.2006, 20:01
Ich glaube du würdest der Welt auch einen Gefallen tun, wenn du es als .zip oder .rar hochlädst, damit sich nciht jeder extra das Prog installieren muss.#

Andun

MadMan2k
13.02.2006, 20:16
hmm.. 7z komprimiert doppelt so gut wie zip und das erst bei normalen einstellungen.
Davon abgesehen kann WinRAR auch mit 7z umgehen - ich würde aber dennoch zu 7zip raten, da es kostenlos und frei (http://de.wikipedia.org/wiki/Freie_Software) ist.

aber wenns so ein umstand ist:
http://www.madman2k.net/files/libasuro_1.0.zip

Sternthaler
13.02.2006, 20:56
@MadMan2k
Danke, sowohl für den Zipper-Link, als auch für die Datei.
Zipper wird mal gleich zum testen geladen.

Rakke
15.02.2006, 15:02
Hei zusammen,

ist länger her, da habe ich eine erweiterte ASURO-lib eingestellt (https://www.roboternetz.de/phpBB2/viewtopic.php?t=7571&postdays=0&postorder=asc&start=22).
In der habe ich die Funktion go(..) als go_rakke(..) so erweitert, dass zunächst eine Phase der Langsamfahrt kommt, dann Beschleunigung auf einen Höchstwert, Halten der Geschwindigkeit, Bremsen und schließlich kriechen ans Ziel. Dadurch wird das überfahren des Ziels ganz gut vermieden. Alle Werte sind über defines parametrierbar. Ist die Fahrtstrecke zu kurz für alle Phasen, werden nur die machbaren durchfahren. Allerdings kann go_rakke(..) keine Einheiten, sondern zählt bislang nur Tix - das sollte das kleinere Problem sein.

Gruß
Rakke

Rookie-Robot
03.03.2006, 16:53
Hallo Leute,

ich habe mir den ASURO erst kürzlich zusammengebaut und habe hier jetzt von einer "asuro.c" lib-Erweiterung gelesen. Habe mir diese heruntergeladen, nur wie kann ich diese Datei nun implementieren, das er beim compilieren auch auf diese zurückgreift?

Danke, für Eure Tips.

Rookie

Lunarman
03.03.2006, 17:18
Gaaaanz einfach. Alte irgendwo sicherschutzbrennen, alte durch neue ersetzen - fertig.

MadMan2k
03.03.2006, 18:32
von mir gibts ein kleines Update:
http://www.madman2k.net/?module=comments&id=32