Hallo Roboaktiv
Na, dann wollen wir mal:
Zuerst eine Anmerkung zu den Zeilennummern: Ich habe dein Programm mit einem Klick auf Bild hier markiert, dann kopiert und dann in meinen Editor eingefügt. Möglicherweise stimmen deshalb die von mir angegebenen Zeilennummern nicht mit deinen überein. Ursache dafür wären dann Leerzeilen oder ein Zeilenvorschub(=Enter) zwischen dem code-Tag und der ersten Progammzeile in deinem Posting.
Zeile 15/16: Ein integer ist beim ATMega8 zwar maximal 65535 groß, aber die Odometrie verwendet nur 10 Bits, also ist der Maxwert 1023.
Zeile 20: Hier sollte vielleicht eine Pause sein, damit der Motor hochdrehen kann.
Zeile 22-37: Das solltest du in einer Schleife mehrmals tun damit die Ritzel Zeit haben sich zu bewegen! So liest du genau einmal einen Wert ein! Und if kleiner else if größer wäre eleganter
Zeile 41/44: Den Mittelwert bildet man mit dieser Formel: (max+min)/2
Zeile 50-54:Bei jedem Schleifendurchgang mit data[1] > datamit[1] wird der Zähler hochgezählt, auch wenn das Rad stehen würde! Deshalb prüft man auf die helle Kante, merkt sich, dass zuletzt hell war, prüft dann auf die dunkle Kante, merkt sich, dass zuletzt dunkel war usw,usw...
Ab Zeile 50: Ich vermute, du willst das mal anschauen und zählst deshalb die Umdrehungen und die Impulse pro Umdrehung. Und hast auch deshalb die SerWrite()s drin. Im echten Leben würde das nicht funktionieren. 4 Umdrehungen mit der 6er Codescheibe sind 24 Segmente. Also fährt man auch auf 24 (besser auf 22, der Bremsweg zählt ja weiter), und sendet dann den Wert, denn während SerWrite() kann der asuro nichts anderes tun und würde vielleicht Impulse übersehen.
Möglichweise ist das noch nicht alles. Ich konnte dein Programm aber leider nicht compilieren und testen, weil ich einen "implicit declaration of function `sprintf' "-Fehler gemeldet bekomme. Und da ich string.h bei meinen Programmen nicht anwende, war ich zu faul die Ursache dafür zu suchen.
Ich mache das so:
Ich teile den Bereich zwischen max und min in drei Teile, oberes Drittel ist high, unteres Drittel ist low und prüfe dann, in welchem Drittel der eingelesene Wert liegt und merke mir das als Bit. Wenn das bit nicht gesetzt ist, prüfe ich auf high, wenn erkannt setzte ich das bit und prüfe auf low und lösche, wenn erkannt das bit wieder usw,usw..
Jeder Bitwechsel wird gezählt und dabei die StatusLED umgeschaltet. Die 6er Scheibe hat dann 12 Impulse pro Umdrehung und ein Stoppen auf den Kante zählt keinen Unsinn:
Übrigens heißen meine Variablen hinten alle _l bzw. _r. Ich teste dann nur den Code für eine Seite, kopiere den Code und suche&ersetze dann in der Kopie das _l durch ein _r.Code:void Count(){ OdometrieData(data); if (!odo_bit_l & (data[0] > odo_high_l)) { odo_bit_l=1; count_l ++; StatusLED(YELLOW); } if (odo_bit_l & (data[0] < odo_low_l)) { odo_bit_l=0; count_l ++; StatusLED(OFF); } if (!odo_bit_r & (data[1] > odo_high_r)) { odo_bit_r=1; count_r ++; StatusLED(RED); } if (odo_bit_r & (data[1] < odo_low_r)) { odo_bit_r=0; count_r ++; StatusLED(OFF); } }
Ich würde string.h nicht einbinden und alle Ausgaben mit SerWrite()/PrintInt() erledigen. Jedes #include bläht möglicherweise den Code auf. Aber das ist in erster Linie Geschmackssache.
Ich hoffe, dass hilft dir etwas auf die Sprünge.
Gruß
mic
Falls es jemanden interessieren sollte:
Das ist das Programm, aus dem der Zählcode stammt. Das waren meine c-Anfänge, mit Datum vom 8.1.07, da hatte ich den asuro grad 2 Wochen. Und das sieht man auch, es stecken noch einige Fehler drin.Die Funktion: Der asuro wird auf dem Boden stehend eingeschaltet. Er fährt dann ein Stüch vorwärts und misst die Min-/Maxwerte, wenn er fertig ist, blickt er. Man muss ihn dann hochheben und wieder auf den Boden setzen. Wieder auf dem Boden beschleunigt er auf eine vorgegebene Geschwindigkeit, verzögert wieder auf 0 und sendet die Zählerstände. Dann das selbe rückwärts. Endlos bis der Akku leer ist:
Code:#include <asuro.h> unsigned char sw_data, i, tmp_char, step, speed_min, speed_max, rampe_v, rampe_r; unsigned int data[2], j, tmp_int; unsigned long loop_count, rampe_delay; unsigned char odo_bit_l, odo_bit_r; unsigned int odo_min_l, odo_max_l, odo_low_l, odo_high_l; unsigned int odo_min_r, odo_max_r, odo_low_r, odo_high_r; unsigned int count_l, count_r, count_soll_l, count_soll_r; unsigned int speed_l, speed_r, speed_max_l, speed_max_r, speed_soll_l, speed_soll_r; void hochheben() { // blinken: gelb=hochheben green=hinsetzen dauergreen=los LineData(data); tmp_char=data[0]+data[1]+20; // Schwelle für aufheben vom Boden do { LineData(data); StatusLED(OFF);Msleep(300); StatusLED(YELLOW); Msleep(150); } while ((data[0]+data[1]) < tmp_char); do { LineData(data); StatusLED(OFF);Msleep(300); StatusLED(GREEN); Msleep(150); } while ((data[0]+data[1]) > tmp_char); StatusLED(GREEN); Msleep(2000); } int init_odo() { StatusLED(YELLOW); MotorDir(RWD,FWD); odo_min_l=odo_max_l=odo_low_l=odo_high_l=count_l=0; odo_min_r=odo_max_r=odo_low_r=odo_high_r=count_r=0; MotorSpeed(150,150); for (j==0; j<5000; j++) { OdometrieData(data); if (data[0] < odo_min_l) odo_min_l=data[0]; if (data[0] > odo_max_l) odo_max_l=data[0]; if (data[1] < odo_min_r) odo_min_r=data[1]; if (data[1] > odo_max_r) odo_max_r=data[1]; for (i=0; i<200; i++); } MotorSpeed(0,0);Msleep(100); OdometrieData(data); odo_low_l=((odo_min_l + odo_max_l)/3); // je ein drittel high-nix-low odo_high_l=((odo_min_l + odo_max_l)/3)*2; if (data[0] >= ((odo_min_l + odo_max_l)/2)) odo_bit_l=1; else odo_bit_l=0; odo_low_r=((odo_min_r + odo_max_r)/3); // je ein drittel high-nix-low odo_high_r=((odo_min_r + odo_max_r)/3)*2; if (data[1] >= ((odo_min_r + odo_max_r)/2)) odo_bit_r=1; else odo_bit_r=0; MotorDir(BREAK,BREAK); } void Count(){ OdometrieData(data); if (!odo_bit_l & (data[0] > odo_high_l)) { odo_bit_l=1; count_l ++; StatusLED(YELLOW); } if (odo_bit_l & (data[0] < odo_low_l)) { odo_bit_l=0; count_l ++; StatusLED(OFF); } if (!odo_bit_r & (data[1] > odo_high_r)) { odo_bit_r=1; count_r ++; StatusLED(RED); } if (odo_bit_r & (data[1] < odo_low_r)) { odo_bit_r=0; count_r ++; StatusLED(OFF); } } int MotorRampe(unsigned char sp_l, unsigned char sp_r, unsigned int r) { if (loop_count > rampe_delay) { if (sp_l != speed_l) { if (sp_l > speed_l) speed_l ++; if (sp_l < speed_l) speed_l --; rampe_delay=loop_count+r; } if (sp_r != speed_r) { if (sp_r > speed_r) speed_r ++; if (sp_r < speed_r) speed_r --; rampe_delay=loop_count+r; } MotorSpeed(speed_l,speed_r); } return ((sp_l == speed_l) && (sp_r == speed_r)); } void run(void) { } int main(void) { Init(); SerWrite("\nHallo\nBatterie: ",17); PrintInt(Batterie()); init_odo();// hochheben(); step=loop_count=rampe_delay=speed_l=speed_r=count_l=count_r=0; speed_min=0; speed_max=250; rampe_v=15; rampe_r=15; do { loop_count ++; switch (step) { case (0): MotorDir(FWD,FWD); FrontLED(ON); BackLED(OFF,OFF); count_l=count_r=0; step++; break; case (1): if (MotorRampe(speed_max,speed_max,rampe_v)) step++; break; case (2): if (MotorRampe(speed_min,speed_min,rampe_r)) step++; break; case (3): MotorDir(RWD,RWD); FrontLED(OFF); BackLED(ON,ON); SerWrite("\n",1);PrintInt(count_l); SerWrite("\n",1); PrintInt(count_r); step++; break; case (4): if (MotorRampe(speed_max,speed_max,rampe_v)) step++; break; case (5): if (MotorRampe(speed_min,speed_min,rampe_r)) step=0; break; case (98): MotorDir(BREAK,BREAK); step++; break; case (99): FrontLED(OFF); BackLED(OFF,OFF); step=99; break; } Count(); } while (1); return 0; }
Lesezeichen