Umfrage Odometrie

redtop

Member
Da ich auch bei meinem aktuellen, wie auch bei meinen "alten" Mowern Probleme mit der Odometrie habe würde ich gerne mal wissen, bei wem sie funktionert, Probleme macht oder Funktioniert. Interessant währe auch ob One- oder Two Way Encoder.

Stefan
 
Hallo Stefan,

bei mir funktioniert sie. Allerdings gibts wohl manchmal Probleme bei der 2W-Odo, weil einfach zu viele Interrupts ausgelöst werden und dadurch nicht genug Rechenzeit für andere Aufgaben bleiben.
Ich habe mir erst mal einen Teiler mit 'nem NANO dazwischen gebastelt und auf 1W-Odo umgestellt. Das funktioniert im Moment sehr gut. Bin aber auch noch am testen...

VG
Reiner

Das hier ist auch interessant in dem Zusammenhang!
 
Odometrie: Ja, 1Weg. ohne ISR_NOBLOCK mit direkt pinRead in der ISR.
Original Ardumower Motoren und Odo.
2Wege Odo hat auch funktioniert(nur ca 30min getestet), mann muss ein System aber nicht unnoetig stressen. Sehen den Vorteil von 2Weg auch nicht wirklich.
 
Funktioniert
Habe allerdings nur One Way eingestellt. In der aktuellen DEV Version habe ich die Interrupt Einstellungen geändert. Funktioniert aber nur mit dem Mega. Ich habe z.B die Motordrehzahl (Mähmotor) und die RC Steuerung ausgeschaltet und nur Oneway Odometrie eingestellt.
Den Sketsch habe ich so verändert das wenn man eine der Einstellungen deaktiviert die entsprechenden Interrupts mit abgeschaltet werden.
Wichtig zu wissen ist dabei das der Mega bei Änderungen neu gestartet werden muss sonst geht das nicht.
Wenn man dann in die Seriellen Konsole geht und sich dort die Konfiguration ausgeben lässt kann man sehen ob die entsprechenden Interrupts ein oder ausgeschaltet sind.
Die Auslesung erfolgt direkt über eine Bitread Anweisung aus dem Mega.

Gruß
Uwe
 
Hi,
Odo (Gabellichtschranke mit 60 imp/Radumdrehung) funktioniert bei mir mittlerweile gut, allerdings auch wie bei den Anderen mit Änderungen am Source.
Also als Antwort,
Azurit latest : NEIN
Nach Anpassungen : JA
 
@Reiner
@Uwe

ich meine die Original Version ohne Anpassungen von euch


Alos beide nein.

Ich möchte einfach nur mal wissen ob es out off the Box geht oder nicht, falls nicht könnte man die Lösungen, die Ihr gefunden habt, In die Offizielle Version einfließen lassen, damit es bei den Neueinsteigern weniger Frust gibt.
 
Roland schrieb:
Wie hast du diese denn montiert? Hast du mal ein Bild? Rein interessehalber :)

Hab die Gabellichtschranke mit einem Druckteil an der Motorhalterung befestigt, versuch mal das Bild hier rein zu bringen ;)

....Hat nicht geklappt, so sollte es aber funktionieren:

https://www.dropbox.com/s/8a29offsutij244/Gabellichtschr.gif?dl=0[/img]
 
Zuletzt bearbeitet von einem Moderator:
Hi,

also ich habe jetzt glaube ich fast alle Änderungen drin in meinem Code. Ich könnte das in den Masterbranch einpflegen, möchte aber noch ein bisschen testen. Ein paar Wochen brauch ich noch...

VG
Reiner
 
@ reiner kannst du mir die Änderungen als diff senden ?

Dann könnte ich das hier auch testen.

Ich fand denn Ansatz von Roland sehr interessant, wonach nur die Steigende Flanke einen Interrupt auslöst und dadurch der pin nicht mals mehr abgefragt werden muss, da man ja weis das ein Interrupt ausgelöst wurde.

Stefan
 
Wenn ich das richtig verstehe, wird hier die ISR für die Odometrie und den Mower RPM definiert ?


Code:
ISR(PCINT2_vect){
#endif
  unsigned long timeMicros = micros();
  boolean odometryLeftState = digitalRead(pinOdometryLeft);
  boolean odometryLeftState2 = digitalRead(pinOdometryLeft2);
  boolean odometryRightState = digitalRead(pinOdometryRight);  
  boolean odometryRightState2 = digitalRead(pinOdometryRight2);  
  boolean motorMowRpmState = digitalRead(pinMotorMowRpm);
  robot.setOdometryState(timeMicros, odometryLeftState, odometryRightState, odometryLeftState2, odometryRightState2);   
  robot.setMotorMowRPMState(motorMowRpmState);  
}


Das würde bedeuten das von dem Interrupt, zwei Routinen aufgerufen werden ?
Und das dann dort jeweils auch noch Berechnungen gemacht werden ?
Und Interrupts werden auch bei oneway odometrie gesetzt, obwohl Sie nicht gebraucht werden ?


nach allem was ich gelesen habe, ich Versuche mich da Einzuarbeiten, sollte doch in der Augerufenen Routine (robot.setOdometryState & setMotorMowRPMState) nur ein Status gesetzt werden.

und die eigentliche Berechnung der Odometrie bzw Steuerung erfolgt dann hier:


Code:
void Robot::calcOdometry(){



Würde es dann nicht reichen in der ISR die Ticks für rechts und links zu zählen und an die berechnung zu übergeben ?


Code:
double left_cm = ((double)ticksLeft) / ((double)odometryTicksPerCm);
  double right_cm = ((double)ticksRight) / ((double)odometryTicksPerCm);

Müsste das nicht Multipliziert werden, um die Strecke zu errechnen ?

Sorry aber ich Versuche das zu verstehen.

Gruss Stefan
 
Hallo Stefan,

bei mir sieht die erste Stelle so aus:


Code:
// Angepasst: Chris
#ifdef __AVR__
ISR(PCINT2_vect){
  unsigned long timeMicros = micros();
  boolean odometryLeftState = bitRead(PINK,4);
  boolean odometryLeftState2 = bitRead(PINK,5);
  boolean odometryRightState = bitRead(PINK,6);
  boolean odometryRightState2 = bitRead(PINK,7);
  boolean motorMowRpmState = bitRead(PINK,3);
  robot.setOdometryState(timeMicros, odometryLeftState, odometryRightState, odometryLeftState2, odometryRightState2);
  robot.setMotorMowRPMState(motorMowRpmState);
#else
ISR(PCINT2_vect){
  unsigned long timeMicros = micros();
  boolean odometryLeftState = digitalRead(pinOdometryLeft);
  boolean odometryLeftState2 = digitalRead(pinOdometryLeft2);
  boolean odometryRightState = digitalRead(pinOdometryRight);  
  boolean odometryRightState2 = digitalRead(pinOdometryRight2);  
  boolean motorMowRpmState = digitalRead(pinMotorMowRpm);
  robot.setOdometryState(timeMicros, odometryLeftState, odometryRightState, odometryLeftState2, odometryRightState2);   
  robot.setMotorMowRPMState(motorMowRpmState);  
#endif
}


wobei für den Mega nur der obere Block relevant ist. Der untere Block nach "#else" wird nur beim DUE kompiliert.
Der BitRead Befehl spart etwas Rechenzeit...

Ich schick dir nachher mal meinen Code...
 
Hallo Stefan,

PINK steht fur das Input-Statusregister der Pins des PORTs K im ATMEGA.
die Zahl dahinter ist das Bit zum entsprechenden Pin.

die Funktion OdometryState in robot.cpp zählt eigentlich nur wie oft eine Änderung eines Pins vonstatten geht

Code:
void Robot::setOdometryState(unsigned long timeMicros, boolean odometryLeftState, boolean odometryRightState, boolean odometryLeftState2, boolean odometryRightState2){
  int leftStep = 1;
  int rightStep = 1;
  if (odometryLeftSwapDir) leftStep = -1;
  if (odometryRightSwapDir) rightStep = -1;
  if (odometryLeftState != odometryLeftLastState){    
    if (odometryLeftState){ // pin1 makes LOW->HIGH transition
      if (twoWayOdometrySensorUse) { 
        // pin2 = HIGH? => forward 
        if (odometryLeftState2) odometryLeft += leftStep; else odometryLeft -= leftStep;
      } 
      else { 
         if (motorLeftPWMCurr >=0) odometryLeft ++; else odometryLeft --;
      }
    }
    odometryLeftLastState = odometryLeftState;
  } 

  if (odometryRightState != odometryRightLastState){
    if (odometryRightState){ // pin1 makes LOW->HIGH transition
      if (twoWayOdometrySensorUse) {
        // pin2 = HIGH? => forward
        if (odometryRightState2) odometryRight += rightStep; else odometryRight -= rightStep;
      }     
      else {
         if (motorRightPWMCurr >=0) odometryRight ++; else odometryRight --;    
      }
    }
    odometryRightLastState = odometryRightState;
  }  
  if (twoWayOdometrySensorUse) {
    if (odometryRightState2 != odometryRightLastState2){
      odometryRightLastState2 = odometryRightState2;    
    }  
    if (odometryLeftState2 != odometryLeftLastState2){
      odometryLeftLastState2 = odometryLeftState2;    
    }
  }    
}

mit ein paar if's für die verschiedenen Einstellmöglichkeiten die man so hat in der Pfod oder mower.cpp.

Gruess

Chris
 
In der Funktion "Robot::setOdometryState" werden die Impulse aufaddiert
In der Funktion "Robot::calcOdometry()" wird alle 0,3 Sek. die Drehzahl der Räder berechnet

***EDIT***
Da warst Du schneller Chris B)
 
Ah danke, jetzt verstehe ich es langsam. Danke.

Die Eigentliche ISR ist als gleich in der Definition mit drin und wird nicht extra aufgerufen ?

Aber dann ist immer noch das Problem, das bei Einweg Odometrie die Interrupts belegt und auch ausgewertet werden, was dann zu Fehlern führt, da ja keine Ereignisse anstehen ?


Das könnte man dann doch über ein


Code:
#ifdef __AVR__
ISR(PCINT2_vect, ISR_NOBLOCK){
#else
ISR(PCINT2_vect){
#endif
  unsigned long timeMicros = micros();


#ifdef twoWayOdometrySensorUse
  boolean odometryLeftState = digitalRead(pinOdometryLeft);
  boolean odometryRightState = digitalRead(pinOdometryRight);
  boolean odometryLeftState2 = digitalRead(pinOdometryLeft2);
  boolean odometryRightState2 = digitalRead(pinOdometryRight2);  
#else
  boolean odometryLeftState = digitalRead(pinOdometryLeft);
  boolean odometryRightState = digitalRead(pinOdometryRight);  
  boolean odometryLeftState2 = 0;
  boolean odometryRightState2 = 0;  
#endif
  
  boolean motorMowRpmState = digitalRead(pinMotorMowRpm);
  robot.setOdometryState(timeMicros, odometryLeftState, odometryRightState, odometryLeftState2, odometryRightState2);   
  robot.setMotorMowRPMState(motorMowRpmState);  
}

lösen, dann müssten aber die anderen abfragen, "if twoWayOdometrySensorUse" auch alle geändert werden.
 
So ging es doch noch nicht.

Aber so könnte es gehen


Code:
#if defined(twoWayOdometrySensorUse) && twoWayOdometrySensorUse == 1
  boolean odometryLeftState = digitalRead(pinOdometryLeft);
  boolean odometryRightState = digitalRead(pinOdometryRight);
  boolean odometryLeftState2 = digitalRead(pinOdometryLeft2);
  boolean odometryRightState2 = digitalRead(pinOdometryRight2);  
#else
  boolean odometryLeftState = digitalRead(pinOdometryLeft);
  boolean odometryRightState = digitalRead(pinOdometryRight);  
  boolean odometryLeftState2 = 0;
  boolean odometryRightState2 = 0;  
#endif



Der Compiler läuft jedenfalls durch, nur noch probieren wie er mäht

Stefan
 
Oben