Hallo wertes Forum, ich wende mich an dich, weil ich mit meinem Latein am Ende bin. Ich soll/moechte einen Roboter bauen. Er ist ausgestattet mit einem Arduino Micro. Dank einer Rueckkopplungsschleife soll es moeglich sein, dass er gerade aus faehrt, was er allerdings nicht tut. Ich glaube, dass das daran liegt, dass mein Code die Geschwindigkeit auf Basis der beiden quadratur Wheelencoder nicht richtig bestimmt. Das Prinzip fuer die Bestimmung der Geschwindigkeit ist ja: Neue_Tickanzahl = Encoderticks; (Encoderticks kommen uber einen Hardwareinterrupt direkt vom Encoder) Encoderticks = 0; (Zurueckezen der Encoderticks fuer nachfolgenden Durchlauf) Neue_Tickanzahl - Alte_Tickanzahl; Alte_Tickanzahl = Neue_Tickanzahl; und diese Berechnung eben je Dauer einer Schleife. Meine Schleifendauer ist zu kurz, was ich daran erkenne, dass ich nur ein Tick pro Schleifendurchgang erhalte. Verlaengere ich die Schleifendauer dadurch, dass ich z.B. ein delay(1000) vor diesen 4 Codezeilen einbaue, dann erhalte ich zwar 2000 Ticks pro Schleifendurchgang, aber dann spinnt mein linkes Rad. Es faehrt dann im Wechsel nach vorn und danach wieder nach hinten. Das passiert im Wechsel. Das rechte Rad hingegen fahert konstant gerade aus. Ich weiss nicht genau, wo das Problem liegt. Ich weiss aber, dass ich mir nicht im klaren bin, wie ich die Geschwindigkeit richtig bestimme. Es harpert am Verstaendnis, an welcher Stelle ich die Encoderticks zuruecksetze, wo genau im Code die Geschwindigkeit berechnet werden soll und wie lange ein Schleifendurchgang dauern sollte. Ausserdem ist der Code ein Kompendium von Codeschnipsseln aus diversen Internetquellen. Diese habe ich versucht aneinander anzupassen, was mir vielleicht teilweise auch gelungen ist. Ich habe mich darein gearbeitet und die Theorie dahinter verstanden, aber bei der Umsetzung komme ich ins Stocken, weil mir die Erfahrung im Programmieren und im Bauen von Robotern fehlt. Zudem ist da noch das Problem, dass dies eine Gruppenarbeit ist und ich in zwei Wochen mit meinem Team den Roboter vorstellen muss. Ich will nicht scheitern und noch weniger will ich meine Kollegen haengen lassen. Ich hab mich mit dieser Arbeit wohl uebernommen. Ich hab meinem Code im Anhang angehaengt. Ich bin fuer jede Hilfe dankbar. FG, Berus
Berus schrieb: > Robotercode.txt Heißen diese Arduino-Programme nicht mit Nachnamen *.ino? Probiers mal aus. Die Forensoftware dankt es dir mit Syntax-Highlighting... Berus schrieb: > dann erhalte ich zwar 2000 Ticks pro Schleifendurchgang, aber dann > spinnt mein linkes Rad. Es faehrt dann im Wechsel nach vorn und danach > wieder nach hinten. Mit der aktiven Rechezeitvernichtung per delay() stellst du dich ja jedes Mal für 1 Sekunde tot. Da würde so mansches Programm nicht mehr funktionieren. Wie wäre es, wenn du dir die Sache mit den millis() mal ansiehst? > Encoderticks = 0; (Zurueckezen der Encoderticks fuer nachfolgenden > Durchlauf) Warum setzt du die Encoderticks zurück? Lass sie doch einfach immer weiterlaufen und berechne nur die Differenz zum alten Wert:
1 | Distanz = Encoderticks - Alte_Tickanzahl; |
2 | Alte_Tickanzahl = Encoderticks; |
Delay ist Böse - wusstest Du das noch nicht? Benutz den internen Timer mit millis() - sonst bekommst du keine gleich langen Intervalle zwischen zwei Messungen weil dein Code unterschiedlich lange läuft. Ansonsten hilft nur damit beschäftigen, damit beschäftigen und nochmal damit beschäftigen. Man kann zwar erkennen, dass Du es versuchst, ganz abnehmen wird es dir aber kaum einer wollen...
Sowie in der biblischen Entstehungsgeschichte, als auch in der Regelungstechnik gibt es die s.g. EVA: -Einlesen -Verarbeiten -Ausgeben > Dank einer Rueckkopplungsschleife soll es moeglich sein, dass er gerade > aus faehrt, was er allerdings nicht tut. Aus der Aufgabenstellung wird generell nicht klar was du regelst. Geschwindigkeit oder Posisition? Jedenfalls, muss du dafür sorgen, dass die Sensordaten kalibriert vorliegen. Hier scheiterst du wohl schon. Weiterhin, ein digitaler Regler wird in Abhängigkeit der Abtastzeit erstellt, d.h man muss garantieren können, dass diese eingehalten wird.
@Lothar: ich hab es versucht. Auch durch deinen Ansatz Distanz = Encoderticks - Alte_Tickanzahl; Alte_Tickanzahl = Encoderticks; erhalte ich leider keine Geschwindigkeit/Distanz (wie du es nennst) bzw. kommt hierfuer Null heraus. Ich habe die Berechnung schon in die Rueckkopplungsschleife, die mit millis() arbeitet, hineinverschoben. Infolgedessen spinnen die Raeder wieder. Es geht so leider auch nicht. @Gast: Ich moechte ja gar nicht, dass mir jemand die ganze Arbeit abnimmt. Ich hoffe einfach nur, dass mir jemandn zeigt, wo der Wurm im Code drinne ist.
@aSma: ich moechte die Wheelnencoder verwenden, um die Geschwindigkeit der Raeder zu bestimmen. Diese Ist-Werte der Geschwindigkeiten der beinden Raeder sollen mit einem Soll-Wert verglichen werden und innerhalb einer PI-Regelung diesem angepasst werden. Diese Encoder verwende ich: https://www.pololu.com/product/3081
Um die wheelencoder aus zu werten musst du mit bestimmte Intervallen die Werte von Encodertics anschauen. Diese Intervallen macht men nicht met "Delay" ! Einen Delay ist eine Warteschleife wo nur "gewartet" wird. Darum muss man ein Timer verwenden, dan lauft ihre Program weiter. Hier ein Beispiel mit LED Blinken : https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay Auf die gleicht art und weise geht das mit die Auswertung von die Encoder. In die Schleive wo jetzt die LED angesteurt wird, kommt ihre Zuweisung Speed_L=Neue_Wert-Alte_Wert;Alte_Wert=Neue_Wert;Das Interval (1000 ?) wird soklein moglich gewahlt, aber noch immer zo gross dat bei niedrige Drehzahlen noch minimal 2 bis 4 Pulsen gezahlt werden (Speed_L=4 Pulsen/Interval).Den Grund das dieses Interval klein sein muss, ist Regel -Geschwindigkeit. Men kan nur eine neue PWM-Wert forgeben nach passieren von Interval !! Mit hochauflosende Encoder sind Intervalle von 10 - 50 ms machbar !!
Danke fuer die hilfreiche Antwort. Das bringt mich vermutlich weiter. Ich teste das aus!
Jan Heynen schrieb: > Um die wheelencoder aus zu werten musst du mit bestimmte Intervallen die > Werte von Encodertics anschauen. Diese Intervallen macht men nicht met > "Delay" ! Die beide Encoder werden aber über Interrupt ausgewertet:
1 | attachInterrupt(digitalPinToInterrupt(0), LeftEncoderEvent, CHANGE); |
2 | attachInterrupt(digitalPinToInterrupt(3), RightEncoderEvent, CHANGE); |
Berus schrieb: > Ich glaube, dass das daran liegt, dass mein Code die Geschwindigkeit auf > Basis der beiden quadratur Wheelencoder nicht richtig bestimmt. Wozu interessiert dich überhaupt die Geschwindigkeit. Wenn die Räder keinen Schlupf haben, fährt der Roboter geradeaus, wenn beide Räder gleiche Strecken fahren. > Neue_Tickanzahl = Encoderticks; (Encoderticks kommen uber einen > Hardwareinterrupt direkt vom Encoder) Hoffentlich sind deine Encoder vernünftig entprellt.
Die encoder tics zahlen macht men ueber der interrupt. Das war auch nicht das Problem (so hab ich es verstanden). Aber jetzt muss men aus diese Werte die Geschwindigkeit erfassen. Das geht dan mit die Aenderungen von tics ueber die Zeit zu berechnen (speed = differential von Strecke). Und dafur muss men dan millis() verwenden (Arduino). Delay ist nich geeignet, um das es blockierend ist.
Ich habe die Auswertung in die Schleife genommen 1 Variante: if(timeChange >= SampleTime){ SpeedL = LeftEncoderPos - oldPosL; oldPosL = LeftEncoderPos; SpeedR = RightEncoderPos - oldPosR; oldPosR = RightEncoderPos; 2 Variante: } if(timeChange >= SampleTime){ SpeedL = LeftEncoderPos - oldPosL; oldPosL = LeftEncoderPos; SpeedR = RightEncoderPos - oldPosR; oldPosR = RightEncoderPos; } Soll ich vielleicht Timer verwenden, um die Interrupts zum Zaehlen der Ticks nur in bestimmten Zeitabstaenden laufen zu lassen? Bis jetzt laufen sie staendig und ohne Pause. Ist das sinnvoll? Ich nehme einen Timer, um die Interrupt nur in bestimmten Abstaenden die Ticks zaehlen zu lassen.
Die Interrupts bleiben immer actif. Den ISR (interrupt service routine) wird nur aufgerufen beim Wechsel an Pin. Das ist naturlich das Forteil von so einen Interrupt, unabhangig von main() functioniert das nur wen notig !! Aber ihre Schleife für Speed zu berechnen darf nur einmal pro Interval laufen ! if(timeChange >= SampleTime){ timechange=0; SpeedL = LeftEncoderPos - oldPosL; oldPosL = LeftEncoderPos; SpeedR = RightEncoderPos - oldPosR; oldPosR = RightEncoderPos; } Ich weiss nicht genau wie du "timechange" berechnet, aber dus muss sicher stellen das timechange wieder auf 0 geht beim durchlaufen von die Schleife. Siehe auch noch das Arduino Beispiel.
Für die Bestimmung der Geschwindigkeit gibt es grundsätzlich zwei Methoden. Bei der ersten wird die Anzahl der Encoder-Ticks innerhalb eines (festen) Zeitintervalls bestimmt, bei der zweiten die Anzahl der Timer-Ticks zwischen zwei Encoder-Ticks. Welche Methode genauer ist, hängt vom Timertakt und von der Encoder-Tick-Frequenz (Encoderauflösung, Geschwindigkeit) ab. Beide Methoden werden beim Reziprokzähler unter einen Hut gebracht. http://www.mikrocontroller.net/articles/Frequenzz%C3%A4hlermodul#Messverfahren
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.