-
Kalibrierung der Motoren
Hi,
ich habe ein Programm für Asuro geschrieben, das die Unterschiede der Drehgeschwindigkeiten der beiden Motoren rausfinden und ausgleichen soll. Beim Ausprobieren fährt Asuro nach der Kalibrierung aber nur im Kreis und ich komme nicht drauf, woran das liegen könnte :/
Das ist mein Code:
Code:
#include "asuro.h"
int main(void)
{
unsigned int wheel_factor;
Init();
wheel_factor = CalibrateWheels();
MotorSpeed(120, 120 * wheel_factor);
while(1);
return 0;
}
float CalibrateWheels(void) {
Write("Start calibration");
// counter
unsigned int i;
// odometry data
unsigned int data[2];
// rotation count of the wheels
unsigned int count_left = 0;
unsigned int count_right = 0;
// contains the last brightness state for the wheels
unsigned int last_state[2];
OdometrieData(data);
last_state[2] = is_bright(data[0]), is_bright(data[1]);
// the relation between the left amd the right wheel's rotation count
float relation;
// start driving
MotorDir(FWD, FWD);
MotorSpeed(120, 120);
// 5 seconds
for (i = 0; i < 100; i++) {
OdometrieData(data);
// if a wheel's brightness changed, increase the counter
if (is_bright(data[0]) != last_state[0]) {
count_left++;
}
if (is_bright(data[1]) != last_state[1]) {
count_right++;
}
last_state[2] = is_bright(data[0]), is_bright(data[1]);
TimeSleep(50);
}
relation = count_right / count_left;
// done testing, stop wheels
MotorSpeed(0, 0);
Write("Finished calibration");
return relation;
}
unsigned int is_bright(unsigned int darkness) {
if (darkness > 512) {
return 0;
} else {
return 1;
}
}
void Write(char msg) {
// Send a string via IR without having to think about the length of the string
SerWrite(msg, strlen(msg));
}
void TimeSleep(unsigned int time) {
// Sleep for ``time`` miliseconds
unsigned int i;
for (i = 0; i < time; i++) {
Sleep(72);
}
}
Die Odometriesensoren funktionieren beide, habe sie mit dem SelfTest getestet.
Weiß jemand, woran das liegen könnte?
BeeWee[fade:e7bfbc102e][/fade:e7bfbc102e]
-
Hallo BeeWee,
ändere mal die Zeile
- unsigned int wheel_factor;
nach
Gruß
Werner
-
Hallo,
danke für die Begrüßung :) edit: <-- bezieht sich auf einen gelöschten Beitrag :/
ich habe die Zeile von Werner geändert und den Schwellwert herabgesetzt aber Asuro dreht sich leider immer noch im Kreis (linkes Rad fährt, rechtes steht völlig).
BeeWee
-
Hallo BeeWee
Ups
Ich musste meinen Beitrag zurückziehen, weil ich mich nicht zu sehr blamieren wollte. Das mit dem int erschien mir so richtig, dass mein Schwellwertverdacht unmöglich stimmen konnte. Aber trotzdem nochmals ein herzliches Willkommen und ein großes Lob für das pfiffige und unkonvensionelle Programm.
Jetzt traue ich mich kaum noch was anders vorzuschlagen. Ich vermute, er dreht nach rechts, weil hier bei MotorSpeed(120, 120 * wheel_factor); irgendwas nicht stimmt. Ich verwende in meinen Programmen keine floats, deshalb kann ich nicht sagen, ob MotorSpeed() das Ergebniss dieser Multiplikation akzeptiert. Vielleicht sollte man das mal vorsichtshalber mit z.B.
float testfloat=1,001;
MotorSpeed(120, 120 * testfloat);
überprüfen.
[Edit]
Ne, daran liegts auch nicht, hab's inzwischen probiert. :(
Gruß
mic
-
Hallo BeeWee,
hast schon einmal probiert, ob dein Asuro überhaupt mit 120, 120 fährt?
Meiner fährt immer erst so mit Werten um 140, 160 an.
Wie du an dem Unterschied siehst habe ich auch das Problem, dass ein Motor (rechts) bei mir 'etwas' schlecht ist.
Es kann ja auch noch sein, dass der bei dir berechnete Wert für wheel_factor kleiner als 1 wird, dann würde natürlich dein 'Start'-Wert 120 noch kleiner werden und, zumindest mein Asuro, würde dann tatsächlich nicht mehr den einen Motor zum Rollen bringen.
-
@radbruch: :)
@Sternthaler: Ja, bei 120 fährt mein Asuro. Auch wenn ich überall 120 durch 255 ersetze ist es so, dass nach der Kalibrierung sich das linke Rad viel schneller dreht, als das rechte :/
BeeWee
-
Hallo
Ich lass nicht locker 8-[ Wenn das rechte Rad schwergängiger wäre, würden beim Kalibrieren weniger Impulse gezählt und der Faktor deshalb größer 1 sein. Das wiederrum könnte bei MotorSpeed(255,255) kritisch werden, weil die Parameter 8Bit-Werte sind und deshalb die errechnete Power modulo 256 ist. Auch wieder Quatsch, weil weniger rechte als linke Impulse den Faktor kleiner machen:
relation = count_right / count_left;
Andersrum wäre richtig. Jetzt hab ich's aber, oder? O:)
Gruß
mic
-
@radbruch
Ich finde, dass das als Lösung zu einfach wäre. ;-)
(Hoffentlich war es das aber!)
-
tut mir Leid, aber das war immer noch nicht die Lösung :/
Jetzt wird es seltsam (imho):
Ich habe zum Test dieses Script geschrieben:
Code:
#include "asuro.h"
int main(void)
{
float wheel_factor;
Init();
wheel_factor = Abc();
MotorSpeed(255, 255 * wheel_factor);
// Sleep 5 seconds
TimeSleep(5000);
MotorSpeed(255, 255 * 1.00);
while(1);
return 0;
}
float Abc(void) {
return 1.00;
}
void TimeSleep(unsigned int time) {
// Sleep for ``time`` miliseconds
unsigned int i;
for (i = 0; i < time; i++) {
Sleep(72);
}
}
Wenn ich das ausführe, fährt er erst 5 Sekunden im Kreis, danach aber relativ gerade. Hat jemand eine Ahnung, wie das geht? :-)
BeeWee
-
Hallo
Ein gutes Testprogramm, du hast das echt drauf. Ich hingegen bin immer noch C-Einsteiger, aber aus diversen Gründen komme ich einfach nicht dazu, mir das besser anzueignen. Hier mein nächster Versuch:
MotorSpeed(255, 255 * 1.00);
Das 1.00 wird vermutlich vom Komplier erkannt und nach int umgewandelt und/oder durch einen konstanten Wert ersetzt, weil das Ergebniss der Multiplikation beim Programmlauf ja immer gleich ist. Das müsste man mal im Assemblerlisting kontrollieren. Oder mit anderen Werten ungleich 1.00 versuchen. Aber es dürfte schwierig sein, den Kompiler hier auszutricksen.
Vielleicht sollte man auf eine globale Variable ausweichen und diese in der Funktion ändern. Damit würde man alle eventuellen Typkonvertierungen bei Return umgehen. Das eigentliche Problem ist dann zwar immer noch nicht erkannt, aber das Programm würde dann vielleicht funktionieren.
gruß
mic