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:
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 !!
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:
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