Gangerkennung #Mathe

Hi,

es geht darum den derzeitigen Gang aus der Gescwindigkeit und der Drehzahl zu berechnen.
So wie es jetzt ist geht es auch.
Aber sobald ich die Übersetzung der Gänge ändere haut es nicht mehr hin, weil dann der “gearFactor” in einem ganz anderen Bereich ist. Was auch irgendwie Sinn macht.
Ich bin mir nur nicht sicher, ob ich das überhaupt noch so kompakt hinkriege oder ob ich für jede Variante eine eigene
“Erkennungsfunktion” schreiben muss.

Wahrscheinlich müssten die Vergleichswerte irgendwie “dynamisch” von irgendwas abgeleitet werden.
Komme aber nicht drauf wie.

//Gears
int rpm; //Drehzahl
int vel; //Geschwindigkeit

int gear;
const float PrimaryM5xx [3][2]   = {
				   //Primärübersetzung
                                   {20.0,65.0},   //S51
                                   {21.0,62.0},   //S70
                                   {0.0,0.0}      //Custom
                                   };
const float GearsM5xx   [7][5][2]= {
				   //Gänge
                                  {
                                    // M531
                                    {10.0,44.0},
                                    {17.0,38.0},
                                    {22.0,34.0},
                                    {0.0,0.0},
                                    {0.0,0.0}
                                  },
                                  {
                                    //M541 S51/S70
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {0.0,0.0,}
                                  },
                                  {
                                    //M541 SR80
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {20.0,36.0},
                                    {23.0,32.0},
                                    {0.0,0.0}
                                  },
                                  {
                                    //5-Gang MS50
                                    {12.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {23.0,32.0}
                                  },
                                  {
                                    //5-Gang Nachbau kurz
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {23.0,32.0},
                                  },
                                  {
                                    //5-Gang Nachbau lang
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {24.0,32.0}
                                  },
                                  {
                                    //Custom
                                    {0.0,0.0},
                                    {0.0,0.0},
                                    {0.0,0.0},
                                    {0.0,0.0},
                                    {0.0,0.0}
                                  },
                                 };
                                 
const float SecondaryM5xx  [5][2]   = {
                                      //Sekundärübersetzung
                                      {15.0,34.0},    //S51
                                      {16.0,34.0},    //S70
                                      {16.0,31.0},    //SR80
                                      {15.0,51.0},    //MS50
                                      {0.0,0.0}       //Custom
                                     };

int gearsNr = 1;                                     
float Primary = PrimaryM5xx[0][1] / PrimaryM5xx[0][0];
float Secondary = SecondaryM5xx[0][1] / SecondaryM5xx[0][0]; 
float i1 =GearsM5xx [gearsNr][0][1] / GearsM5xx [gearsNr][0][0]*Primary*Secondary;
float i2 =GearsM5xx [gearsNr][1][1] / GearsM5xx [gearsNr][1][0]*Primary*Secondary;
float i3 =GearsM5xx [gearsNr][2][1] / GearsM5xx [gearsNr][2][0]*Primary*Secondary;
float i4 =GearsM5xx [gearsNr][3][1] / GearsM5xx [gearsNr][3][0]*Primary*Secondary;
float i5 =GearsM5xx [gearsNr][4][1] / GearsM5xx [gearsNr][4][0]*Primary*Secondary; 

float iFactor = i1*i2*i3*i4;                                    

float gearFactor=0.0;



void loop(){

  gearFactor = (vel * iFactor)/rpm;
    
    if (gearFactor < 300){
      gear = 0;
    }
    else if (gearFactor > 300 && gearFactor < 400){
      gear = 1;
    }
    else if (gearFactor > 500 && gearFactor < 600){
      gear = 2;
    }
    else if (gearFactor > 700 && gearFactor < 800){
      gear = 3;
    }
    else if (gearFactor > 900 && gearFactor < 1000){
      gear = 4;
    }     
    else if (gearFactor > 1000){
      gear = 0;
    }
}

Gruß

schUk0

Hallo,
es ist richtig, das es keinen gearFactor von

300
400
500
600
700
800
900
1000

und keinen von

=400 && <=500
=600 && <=700
=800 && <=900

gibt? Hast Du das mal im seriellen Monitor überprüft?
Gruß und Spaß
Andreas

In meinem Versuchsaufbau gibt es diese Werte schon, da ich Drehzahl und Geschwindigkeit unabhängig voneinander einstellen kann.
Allerdings Würden in diesem Fall am lebenden Objekt wohl komische Geräusche entstehen.
Dementsprechend sollte dann auch kein Gang angezeigt werden.
Die Bereiche sind so groß gefasst, da ich noch nicht weiß, wie sehr die Wirklichkeit von der Berechnung abweicht.

In meiner Tabelle (Anhang) bleibt dieser Wert absolut gleich, da ich dort nur die Drehzahl ändert und dementsprechend die Geschwindigkeit für den jeweiligen Gang.

Gruß

schUk0

Bildschirmfoto vom 2017-02-19 20-04-05.png

Bildschirmfoto vom 2017-02-19 20-04-47.png

Wo in Deinem Sketch ist die Setup() Funktion?
Bitte erklähr die Werte der Arrays. Was bedeutet "iFactor = i1i2i3*i4;" ??

Grüße Uwe

Komme aber nicht drauf wie.

Warum nicht einen "Lernmodus" einführen?
(ich würde gar nicht auf eine andere Idee kommen)

combie:
Warum nicht einen “Lernmodus” einführen?
(ich würde gar nicht auf eine andere Idee kommen)

?

uwefed:
Wo in Deinem Sketch ist die Setup() Funktion?
Bitte erklähr die Werte der Arrays. Was bedeutet “iFactor = i1i2i3*i4;” ??

Grüße Uwe

iFactor sind die zusammenmultiplizierten Übersetzungen der Gänge 1 - 4 oder 5 je nach Setup.

void setup () spielt hierfür zwar keine Rolle… aber ich haus mal mit rein.

Ansonsten ist es nur ein Ausschnitt weil die 9000 Character nicht reichen für den Sketch.

Drehzahl (rpm) und Geschwindigkeit (vel) werden per I2C empfangen und direkt auf einem , ebenfalls I2C Display dargestellt.
Nachdem der Gang (gear) berechnet wurde, wird er auch auf diesem angezeigt.
Und das funktioniert auch.

Ziel ist es, die Übersetzung später vom Nutzer einstellbar zu machen.
Je nach Fahrzeugtyp.

Hier ein neuer Versuch.
Jetzt passt es sich auf Veränderungen an…allerdings sind jetzt die Werte irgendwie komisch.

Ich häng mal die Tabelle an, in der ich die Formeln “entwickelt” habe.
Hoffe man sieht ein bisschen durch :o

//Gears
int gear;
const float PrimaryM5xx [3][2]   = {
                                   {20.0,65.0},   //S51
                                   {21.0,62.0},   //S70
                                   {0.0,0.0}      //Custom
                                   };
const float GearsM5xx   [7][5][2]= {
                                  {
                                    // M531
                                    {10.0,44.0},
                                    {17.0,38.0},
                                    {22.0,34.0},
                                    {0.0,0.0},
                                    {0.0,0.0}
                                  },
                                  {
                                    //M541 S51/S70
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {0.0,0.0,}
                                  },
                                  {
                                    //M541 SR80
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {20.0,36.0},
                                    {23.0,32.0},
                                    {0.0,0.0}
                                  },
                                  {
                                    //5-Gang MS50
                                    {12.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {23.0,32.0}
                                  },
                                  {
                                    //5-Gang Nachbau kurz
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {23.0,32.0},
                                  },
                                  {
                                    //5-Gang Nachbau lang
                                    {10.0,44.0},
                                    {16.0,40.0},
                                    {19.0,36.0},
                                    {22.0,34.0},
                                    {24.0,32.0}
                                  },
                                  {
                                    //Custom
                                    {0.0,0.0},
                                    {0.0,0.0},
                                    {0.0,0.0},
                                    {0.0,0.0},
                                    {0.0,0.0}
                                  },
                                 };
                                 
const float SecondaryM5xx  [5][2]   = {
                                      //Sekundärübersetzung
                                      {15.0,34.0},    //S51
                                      {16.0,34.0},    //S70
                                      {16.0,31.0},    //SR80
                                      {15.0,51.0},    //MS50
                                      {0.0,0.0}       //Custom
                                      };

int primaryNr  = 0;
int secondaryNr = 0;
int gearsNr = 3; 
                                    
float Primary = PrimaryM5xx[primaryNr][1] / PrimaryM5xx[primaryNr][0];

float Secondary = SecondaryM5xx[secondaryNr][1] / SecondaryM5xx[secondaryNr][0];
 
float i1 =GearsM5xx [gearsNr][0][1] / GearsM5xx [gearsNr][0][0]*Primary*Secondary;
float i2 =GearsM5xx [gearsNr][1][1] / GearsM5xx [gearsNr][1][0]*Primary*Secondary;
float i3 =GearsM5xx [gearsNr][2][1] / GearsM5xx [gearsNr][2][0]*Primary*Secondary;
float i4 =GearsM5xx [gearsNr][3][1] / GearsM5xx [gearsNr][3][0]*Primary*Secondary;
float i5 =GearsM5xx [gearsNr][4][1] / GearsM5xx [gearsNr][4][0]*Primary*Secondary; 

float iFactor = i1*i2*i3*i4*i5;                                    

float gearFactor=0.0;

int wheelCirc = 1880;




void setup() {
  // put your setup code here, to run once:
  state = true;
  
  pinMode(btVal, INPUT);
  attachInterrupt(digitalPinToInterrupt(interPin1),whichBt,RISING);
  
  
  
  Serial.begin(9600); 

  Wire.begin();
  
  //EEPROM.get(wheelCircAddress,wheelCirc);
  //EEPROM.get(numberOfWheelsensorsAddress,numberOfWheelsensors);  

}



void loop(){

float v1 = (rpm/i1)*(wheelCirc/1000)*0.06;
  float gF1 = (v1*iFactor)/rpm;
    
  float v2 = (rpm/i2)*(wheelCirc/1000)*0.06;
  float gF2 = (v2*iFactor)/rpm;
  
  float v3 = (rpm/i3)*(wheelCirc/1000)*0.06;
  float gF3 = (v3*iFactor)/rpm;
  
  float v4 = (rpm/i4)*(wheelCirc/1000)*0.06;
  float gF4 = (v4*iFactor)/rpm;
  
  float v5 = (rpm/i5)*(wheelCirc/1000)*0.06;
  float gF5 = (v5*iFactor)/rpm;

  gearFactor = (vel * iFactor)/rpm;
    
     if (gearFactor < gF1 ){
      gear = 0;
    }
    else if (gearFactor > gF1 - (gF1/20)  && gearFactor < gF1 + (gF1/20)){
      gear = 1;
    }
    else if (gearFactor > gF2 - (gF2/20)  && gearFactor < gF2 + (gF2/20)){
      gear = 2;
    }
    else if (gearFactor > gF3 - (gF3/20)  && gearFactor < gF3 + (gF3/20)){
      gear = 3;
    }
    else if (gearFactor > gF4 - (gF4/20)  && gearFactor < gF4 + (gF4/20)){
      gear = 4;
    } 
    else if (gearFactor > gF5 - (gF5/20)  && gearFactor < gF5 + (gF5/20)){
      gear = 5;
    }    
    else if (gearFactor > gF5 + (gF5/20)){
      gear = 0;
    }

}

Gruß

schUk0

Man kann keine Tabelle anhängen :o

Dann muss es ohne gehen.
Eigentlich sind aber alle Formeln im Sketch enthalten.

Gruß

schUk0

schUk0:
Man kann keine Tabelle anhängen :o

Blöder als das finde ich Deinen Sketch. Der ist wg. nicht-Formatierung quasi nicht lesbar. Bevor Du Tabellen postest, solltest Du Deinen Sketch überarbeiten :slight_smile: Strg-T ist oft ein guter Anfang (löscht allerdings keine überflüssigen oder widersinnigen Leerzeilen).

Gruß

Gregor

Falls es noch jemanden interessiert,

ich habs…glaub ich zumindest :grinning:

Auf jeden Fall bin ich irgendwie viel zu kompliziert an die Sache ran gegangen.

Achtung! Nur Code-Schnipsel !

Als erstes wählen wir die gewünschte Getriebeart aus und berechnen für jeden Gang die Gesamtübersetzung.
Den Berechnungsteil werde ich später wohl noch in den Loop einfügen, weil die ganzen Sachen über ein Menü manipulierbar sein sollen.
Bin mir nur noch nicht sicher wie, weil ich die wichtigsten Parameter über das Menü im EEPROM speichern will um nicht bei jedem Fahrzeugstart alles neu einstellen zu müssen.
Das wird dann wahrscheinlich spätestens in dem Moment kompliziert, wo jemand das komplette Setup selbst auswählen möchte.
Aber dazu fällt mir hoffentlich nach was elegantes ein.
Und zum Testen war es so auch einfacher.

//Gears
int gear;
const float PrimaryM5xx [3][2]   = {
  //Primärtrieb
  {20.0, 65.0},  //S51
  {21.0, 62.0},  //S70
  {0.0, 0.0}     //Custom
};
const float GearsM5xx   [7][5][2] = {
  {
    // M531
    {10.0, 44.0},
    {17.0, 38.0},
    {22.0, 34.0},
    {0.0, 0.0},
    {0.0, 0.0}
  },
  {
    //M541 S51/S70
    {10.0, 44.0},
    {16.0, 40.0},
    {19.0, 36.0},
    {22.0, 34.0},
    {0.0, 0.0,}
  },
  {
    //M541 SR80
    {10.0, 44.0},
    {16.0, 40.0},
    {20.0, 36.0},
    {23.0, 32.0},
    {0.0, 0.0}
  },
  {
    //5-Gang MS50
    {12.0, 44.0},
    {16.0, 40.0},
    {19.0, 36.0},
    {22.0, 34.0},
    {23.0, 32.0}
  },
  {
    //5-Gang Nachbau kurz
    {10.0, 44.0},
    {16.0, 40.0},
    {19.0, 36.0},
    {22.0, 34.0},
    {23.0, 32.0},
  },
  {
    //5-Gang Nachbau lang
    {10.0, 44.0},
    {16.0, 40.0},
    {19.0, 36.0},
    {22.0, 34.0},
    {24.0, 32.0}
  },
  {
    //Custom
    {0.0, 0.0},
    {0.0, 0.0},
    {0.0, 0.0},
    {0.0, 0.0},
    {0.0, 0.0}
  },
};

const float SecondaryM5xx  [5][2]   = {
  //Sekundärtrieb
  {15.0, 34.0},   //S51
  {16.0, 34.0},   //S70
  {16.0, 31.0},   //SR80
  {15.0, 51.0},   //MS50
  {0.0, 0.0}      //Custom
};

int primaryNr = 0;        //Auswahl des Primärtriebs
int gearsNr = 1;          //Auswahl des Getriebes
int secondaryNr = 0;      //Auswahl des Sekundärtriebs
int gearTolerance = 20;   //Anzeigetoleranz (weniger ist mehr)
float Primary = PrimaryM5xx[primaryNr][1] / PrimaryM5xx[primaryNr][0];                    //Primärübersetzung
float Secondary = SecondaryM5xx[secondaryNr][1] / SecondaryM5xx[secondaryNr][0];          //Sekundärübersetzung
float U1 = GearsM5xx [gearsNr][0][1] / GearsM5xx [gearsNr][0][0] * Primary * Secondary;   //Gesamtübersetzung 1. Gang
float U2 = GearsM5xx [gearsNr][1][1] / GearsM5xx [gearsNr][1][0] * Primary * Secondary;   //Gesamtübersetzung 2. Gang
float U3 = GearsM5xx [gearsNr][2][1] / GearsM5xx [gearsNr][2][0] * Primary * Secondary;   //Gesamtübersetzung 3. Gang
float U4 = GearsM5xx [gearsNr][3][1] / GearsM5xx [gearsNr][3][0] * Primary * Secondary;   //Gesamtübersetzung 4. Gang
float U5 = GearsM5xx [gearsNr][4][1] / GearsM5xx [gearsNr][4][0] * Primary * Secondary;   //Gesamtübersetzung 5. Gang
float realU=0.0;                                                                          //Variable für tatsächliche Übersetzung

Im Loop nehmen wir nun die Drehzahl (rpm) und die Geschwindigkeit (vel) und berechnen mittels des, dem System bekannten, Radumfangs (wheelCirc) die tatsächliche Gesamtübersetzung in diesem Moment.

getData();    //Daten (Geschwindigkeit und Drehzahl) vom Sensor empfangen
  
  realU = rpm*60.0/vel*(wheelCirc/1000.0)/1000.0;     //Tatsächliche Übersetzung berechnen

Nun müssen wir diese “echte” Übersetzung nur noch mit den, weiter oben berechneten, Sollwerten der Gänge übereinander legen, eine kleine Toleranz hinzufügen und

if (realU > U1 - (U1 / gearTolerance)  && realU < U1 + (U1 / gearTolerance)) {
    gear = 1;
  }
  else if (realU > U2 - (U2 / gearTolerance)  && realU < U2 + (U2 / gearTolerance)) {
    gear = 2;
  }
  else if (realU > U3 - (U3 / gearTolerance)  && realU < U3 + (U3 / gearTolerance)) {
    gear = 3;
  }
  else if (realU > U4 - (U4 / gearTolerance)  && realU < U4 + (U4 / gearTolerance)) {
    gear = 4;
  }
  else if (realU > U5 - (U5 / gearTolerance)  && realU < U5 + (U5 / gearTolerance)) {
    gear = 5;
  }
  else gear = 0;

et voilà !

Beispiele aus dem Serial Monitor:


3000 RPM
29 km/h
Uebersetzung: 11.67
Gang: 4


4615 RPM
29 km/h
Uebersetzung: 17.95
Gang: 2


5454 RPM
42 km/h
Uebersetzung: 14.65
Gang: 3

“Skaliert” auch automatisch je nach Anzahl der Gänge des ausgewählten Getriebes.

Vielleicht hilft das ja mal jemandem und ich hoffe mein Code ist jetzt etwas lesbarer.

Ist übrigens keine Hausaufgabe oder Uni-Projekt.
Nur Spaß an der Herausforderung.

Gruß

schUk0

Hallo schUk0,

ich verstehe nicht so recht, was der Radumfang dort soll.
Klar, damit berechnest Du das exakte Übersetzungsverhältnis. Aber Grundsätzlich benötigst Du doch nur "ein" Verhältnis. Und zwar zwischen Drehzahl und Geschwindigkeit.

Du kannst auch auf ein Setup verzichten. Es reicht einen "Reset" zu implementieren und der Rest ist selbstlernend.
Sofern im EEPROM noch nix abgespeichert ist, setzt man dort die gemessenen Verhältnisse (sortiert) ein.
Eine gewisse Toleranz sollte berücksichtigt werden, damit man nicht "Zwischengänge" misst, weil die Räder sich abfahren, die Genauigkeit bei steigender Drehzahl genauer wird, usw.
Nun fährt man los und das System lernt von Gang zu Gang selbst.

Fertig ist die Laube :slight_smile:

Da denk ich morgen nochmal drüber nach :sleeping: :sleeping:

Klingt aber schonmal interessant. :wink:
Zumindest krieg ich die Raddrehzahl (welches sei jetzt mal dahin gestellt) auch als Rohdaten wenn ich will.
Jetzt wo ich so schreibe, machts immer mehr Sinn...

Aber jetzt gehts erstmal inne Kiste. Sonst sitz ich hier noch wenn der Wecker klingelt :stuck_out_tongue_closed_eyes:

Gruß

schUk0

Ich muss nochmal fragen. :grinning:

Wie kann ich mir diesen "Lernprozess" vorstellen?
Finde da irgendwie nichts zu im Netz.
Gibts da Erfahrene im Forum?
Will ja nicht die Lösung, aber mal ein schematischer Tipp wär nicht schlecht.

Vielleicht dass man einmal alle Gänge durchschaltet in so einer Art Initialisierungsfahrt?

Wie würde das System dann am sinnvollsten einen Schaltvorgang erkennen?
Kupplungsschalter?
Starke Änderung der Übersetzung? (klingt irgendwie gut)

Wird nur lustig das dann zu simulieren mit 2 Drehpotis die auf nem Breadboard stecken :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:
Aber das wird wohl auch gehen.

Am Fahrzeug testen geht noch nicht, weil ich die Hardware erst dementsprechend "entwickeln" muss.
Ich denke mal der Arduino mag die Spannung, die ich am Pickup von der Zündung kriege, nicht so sehr.
Hatte an Optokoppler mit entsprechender Schaltung drum herum gedacht oder ist das overkill?

Gruß

schUk0

So ganz verstehe ich die Problematik nicht. Berechnet man die aktuelle Übersetzung, aus der Drehzahl des Motors und der Antriebswelle(n), dann muß das einigermaßen konstante Werte für jeden Gang eines Getriebes ergeben. Falls man die Abtriebsdrehzahl nicht direkt bekommt, können Abweichungen durch Schlupf und Kardangetriebe auftreten, man sollte also den Mittelwert zwischen linkem und rechtem angetriebenen Rad bilden. Wird der Unterschied zwischen beiden Rädern zu groß, dann dreht eines wohl durch (Glatteis...) oder ist blockiert (Vollbremsung, Aquaplaning).

Beim Lernen sollte es reichen, ein paar Sekunden in einem Gang zu bleiben, und wenn die Messung über dieses Zeitintervall ein ausreichend konstantes Übersetzungsverhältnis ergibt, kann man diese Übersetzung abspeichern.

Das ist natürlich das Risiko bei einem Auto.
Wird die Geschwindigkeit nicht an der Antriebsachse gemessen, kann es bei Schlupf zu ungewünschten Ergebnissen kommen.
Das aber mal ausgeklammert.

Ein "Lernmodus" wäre praktisch ein leeres Array (sonst aus dem dem EEPROM gefüllt).
Man berechnet dann das aktuelle Verhältnis von Geschwindigkeit und Drehzahl.
Dieses Verhältnis sollte eine gewisse Zeit anliegen (Schaltvorgang ignorieren). -> Machen externe Ganganzeigen ebenfalls so. Die zeigen die Gänge immer erst nach ca. 1 Sekunde an.
Geschwindigkeit = 0 und Drehzahl > 0 ausgenommen (Leerlauf).
Das Verhältnis nun sinnvoll runden, dass bei kleineren Abweichungen kein Gangwechsel erkannt wird.
Nun wird der Wert im array[1] abgelegt (array[0] mal "N" vorbehalten).

Ändert sich das gerundete Verhältnis nun und bleibt ca. eine Sekunde bestehen, wird dieses ebenfalls abgespeichert. Ist es größer als array[1] wird es an die 2. Stelle gespeichert.
Sortiert man die Gänge, so kann in der Lernphase auch wild geschaltet werden, die Gänge werden trotzdem erkannt.

Nun immer so weiter, bis man die Lernphase abschließt. Oder eben "offen lässt" Dann kann man die Ganganzeige schon ein paar Tage verwenden, bis man z.B. auf die Autobahn fährt und überraschen den 6. Gang findet :slight_smile:
Je nach dem ob man nun das Abspeicher-Prozedere beendet oder weiterlaufe lässt, könnte man auf die Gedenksekunde verzichten. Die Verhältnisse stehen ja nun fest.

Um schneller die Gänge anzeigen zu können und Gasspielereien bei getretener Kupplung nicht zu missinterpretieren, finde ich den Lernmodus schon praktisch.
Eleganter ist es natürlich, dass man nicht zum Anlernen einmal alle Gänge durchschalten muss. Ist ja ggf. nicht immer möglich.

Trib:
Wird die Geschwindigkeit nicht an der Antriebsachse gemessen, kann es bei Schlupf zu ungewünschten Ergebnissen kommen.

Jede Antriebsachse hat in einem Auto ein Differential, das bei Kurvenfahrten eine größere Drehzahl des äußeren Rads erlaubt. Deshalb wäre der ideale Ansatzpunkt die Antriebswelle vom Getriebe zum Differential, ansonsten müssen die möglicherweise unterschiedlichen Drehzahlen der beiden angetriebenen Räder (links und rechts) berücksichtigt werden.

Deshalb messen die meisten Autos die Geschwindigkeit auch nicht an einem Rad, sondern am Getriebeausgang :slight_smile:
Kenne nur ein paar Japaner, bei denen die Geschwindigkeit bei durchdrehenden Reifen gleich bleibt. Da kann man aber bestimmt auch den Tacho durch Rückwertsfahren zurückdrehen :smiley:

Da ich nix von Sensoren an Kurbelwelle und Rädern gelesen habe, gehe ich daher mal davon aus, dass die Werte vom Tacho oder per OBD II kommen.

Optimierungspotential gibt es aber sicherlich noch. Bei Ungereimtheiten würde ich immer den zuletzt gültigen Gang anzeigen. Macht mein Auto auch so. Allerdings hat mein Wagen offensichtlich einen Sensor ob die Kupplung getreten ist.

Die werte kommen aus einem anderen Arduino, der Zündimpulse und Raddrehzahl a’la Fahrradcomputer (Reed-Kontakt) verwurstet.
Könnte mir aber vorstellen das später mal durch speziell dafür gedachte ICs zu tauschen.

OBD war in dem Baujahr noch Quark im Schaufenster…
Für die, die es noch nicht erkannt haben, es geht um DDR-Mopeds.

Jedoch versuche ich möglichst “typenoffen” zu bleiben und so wenig Installationsaufwand wie möglich zu erzeugen.
Interessante Herrausforderung ist dabei ein Gerät zu entwickeln, das an der ganzen Bandbreite der Fahrzeuge funktioniert.
Das kann dann 3 Gänge und 60 Km/h oder auch 6 Gänge und 150 Km/h bedeuten.
Dafür wäre die Methode des Selbstlernens natürlich optimal und dann ist die Fahrzeugbindung ja dann auch nicht mehr notwendig.
Das mit dem Magnetkontakt am Rad stört mich dabei eigentlich schon,zumal dann bei niedrigen Geschwindigkeiten die Update-Rate unangenehm absackt, aber mir ist keine andere Möglichkeit bekannt die Abtriebsdrehzahl mit der benötigten Genauigkeit festzustellen ohne tiefgreifende Änderungen am Fahrzeug vorzunehmen.

Eine Idee wie ich das umsetzen könnte habe ich mir durch eure Tipps auf jeden Fall erstmal machen können.

Eventuell soll es ganz am Ende sogar in ein rundes (80mm?) Tachogehäuse passen.
Aber, da ich möglichst alles selbst (natürlich mit ein bisschen Hilfe hier und da :smiley: ) “entwickeln” möchte, wird bis dahin noch etwas Zeit ins Land gehen denke ich.
Verkaufen würde ich es allerdings nicht wollen. Höchstens eine Anleitung zum Nachbauen und eventuell eine Kleinserie wegen der Mindestmengen die man bei Elektronikteilen häufig abnehmen muss.
Die wird dann aber maximal gegen irgendwas getauscht.

Gruß

schUk0

Update:

Hab jetzt mal ein bisschen rumgespielt.
Eine Lernfahrt ist, mal abgesehen vom Gefahrenpotential, auch recht unpraktisch zu programmieren.

Hier nun erstmal die Version, die jedes mal auf 0 geht, wenn man eine bestimmte Geschwindigkeit unterschreitet (hier zum testen 15 Km/h).
Und jedes mal, wenn die Übersetzung sich um x % ändert (hier sinds jetzt 20% (tolerance = 5;))
wird entweder der Gang rauf, oder runter gezählt.
Geht erstmal ganz gut…Besonders der 10. fährt sich sehr angenehm :smiley:

Achtung Ausschnitt!

 if (S10) {
    if (vel > 15 ) {
      if (millis() - tU > 2000) {
        realUTemp = realU;        //Übersetzungsverhältnis speichern 
        gear = 1;
        S10=!S10;
        tU = millis();
      }
    }
  }
  else if (!S10) {
    if (millis() - tU > 2000) {
      if (realU > realUTemp + (realUTemp / tolerance)) {
        gear ++;
        realUTemp = realU;
        tU = millis();
      }
      else if (realU < realUTemp - (realUTemp / tolerance)) {
        gear --;
        realUTemp = realU;
        tU = millis();
      }
      else if (vel < 15) {
        gear = 0;
        tU = millis();
        S10=!S10;
      }
    }
  }