Hallo BeeWee,
ändere mal die Zeile
- unsigned int wheel_factor;
nach
- float wheel_factor;
Gruß
Werner
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:
Die Odometriesensoren funktionieren beide, habe sie mit dem SelfTest getestet.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); } }
Weiß jemand, woran das liegen könnte?
BeeWee[fade:e7bfbc102e][/fade:e7bfbc102e]
Hallo BeeWee,
ändere mal die Zeile
- unsigned int wheel_factor;
nach
- float wheel_factor;
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
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
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.
Lieber Asuro programieren als arbeiten gehen.
@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 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?
Gruß
mic
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
@radbruch
Ich finde, dass das als Lösung zu einfach wäre.
(Hoffentlich war es das aber!)
Lieber Asuro programieren als arbeiten gehen.
tut mir Leid, aber das war immer noch nicht die Lösung :/
Jetzt wird es seltsam (imho):
Ich habe zum Test dieses Script geschrieben:
Wenn ich das ausführe, fährt er erst 5 Sekunden im Kreis, danach aber relativ gerade. Hat jemand eine Ahnung, wie das geht?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); } }
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
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Lesezeichen