e-Bike Tuning mit Geschwindigkeitssensor / Überbrückung und einem ATTINY85

Das Aushebeln der Geschwindigkeitsbegrenzung des e-Bike Motors ist auf normalen Straßen nicht erlaubt! Folgendes Szenario ist lediglich für den privaten Gebraucht auf einem abgegrenzten privaten Areal gedacht.

Lösungsansatz

Bei Ebike, dessen Geschwindigkeit mit einem Reed- Kontakt gemessen wird, stoppt die Motor-Unterstützung bei 25 km/h. Es soll eine Lösung erarbeitet werden, mit welcher diese Begrenzung ‚BEI BEDARF‘ aufgehoben werden kann und bei Defekt der Steuerung nicht (wie bei anderen Lösungen) ganz abgeschaltet wird.

Vorgehensweise

Zuerst muss ermittelt werden, wie die Spannung des Reed-Kontaktes ist, damit die Spannung entsprechend eingestellt werden kann.

  1. Zuerst wird am eBike per Pedalabzieher das Pedal entfernt und die Kabel freigelegt.
  2. Danach wird das Kabel zum Reed-Kontakt ermittelt und die Spannung (zwischen den Kontakten vom Steuergerät) gemessen. In diesem Fall waren das 5V.
  3. Es wurde ermittelt, dass die Geschwindigkeit des Ebikes ermittelt wird, indem der Reed-Kontakt pro Radumdrehung das 5V + Signal gegen Ground zieht.
    Es scheint, dass diese Methodik bei vielen / allen ebike-Herstellern etabliert ist.
  4. Um den Motor-Stopp bei 25 km/h zu verhindern muss nun das Reed-Signal ab 25km/h unterbrochen werden. dazu gibt es 2 Optionen, wir lassen nur jedes 2. Signal durch, oder wir simulieren dem Tacho ca. 25 km/h.

Lösung

Es wird am eBike in der Nähe des Motores eine Leitung gesucht, die geschaltet werden kann. In diesem Fall hat das Fahrrad ein Licht und dieses kann über den Tacho aktiviert werden. Dieses möchten wir nutzen um die 25km/h Drosselung zu deaktivieren.

Dazu wird am 12V Kabel ein Step-Down Regler angeschlossen, der einen ATTINY85 versorgt, welcher Reedsignal emuliert oder ab 25km/h begrenzt.
Auch soll, wenn die 12V nicht anliegen die Steuerung komplett original laufen. Dazu wird ein Wechsel-Relais verwendet, das die Steuerleitung vom Reed-Kontakt bei Anliegen von 12V unterbricht und an den ATMEL umleitet. Im Stromlosen Zustand der LIcht-Leitung, wird das Reedsignal unverändert weitergeben. Sollte der ATMEL also defekt gehen oder verrückt spielen, läuft das Rad unverändert.

Die Schaltung sieht wie folgt aus:

Der ATTINY85 wird über das ARUDINO-Studio über einen Arduino-ISP programmeirt.
Der Prototyp-Programmcode ist wie folgt und kann erweitert / angepasst werdne.

#define OUT_PIN PB1 // Zu VCC der Signalleitung
#define IN_PIN PB0  // Meldung von Reedkontakt

// Parameter zur Steuerung

const int UMFANG          = 2300;  //Radumfang in mm
const int SIGNALDELAY     = 60;    // Verzögerung in ms
const int SIGNAL_DURATION = 60;    // Dauer in ms für das Signal

unsigned long simDelay;

// Durschnittsgeschwindigkeit
float overrideKmh = false;
const int numMeasurements = 3;
int speedMeasurements[numMeasurements];
int currentIndex = 0;
float kmhAvg = 0;

void setup() {
    pinMode(PB1, INPUT);
    digitalWrite(PB1, LOW);
    
    pinMode(PB2, INPUT);
    digitalWrite(PB2, LOW);

    pinMode(PB3, INPUT);
    digitalWrite(PB3, LOW);
  
    pinMode(PB4, INPUT);
    digitalWrite(PB4, LOW);

    pinMode(PB5, INPUT);
    digitalWrite(PB5, LOW);
    
    randomSeed(analogRead(A0)); // Seed für die Zufallszahlengenerierung
     
    // Deaktiviere den analogen Comparator
    ACSR = (1 << ACD); // Setze das Bit ACD im ACSR-Register auf 1
    // Deaktiviere den ADC (Analog-Digital-Wandler)
    ADCSRA &= ~(1 << ADEN); // Lösche das Bit ADEN im ADCSRA-Register
    
    
    pinMode(OUT_PIN, OUTPUT);       // Rückmeldung an den Tacho
    digitalWrite(OUT_PIN, HIGH);   
    
    pinMode(IN_PIN, INPUT_PULLUP);  // Wird nach Ground gezogen vom Reedkontakt

    // Delay frü 24kmh festlegen, 1 Radumdrehung in ms
    simDelay = UMFANG / 24 * 3.6;

    // Durschnitt initialisiern
    for (int i = 0; i < numMeasurements; i++) {
      speedMeasurements[i] = 0;
    }    
}

void loop() {
  checkReedSignal();    
  if (overrideKmh){
    doOverride();
  }    
}

void checkReedSignal(){
  static unsigned long lastSignal = 0;
  int ReedSignal = digitalRead(IN_PIN);  // Read the state of PIN_IN
  static int ReedSignalOld;

  // Zurücksetzen auf 0
  if( (millis() - lastSignal) > (simDelay * 1.5) )  {
    overrideKmh = false;
  }
  
  // Wenn Signal empfangen wird und vorher aus war:
  if ( ReedSignal == LOW && ReedSignalOld == HIGH){
      if( (millis() - lastSignal) > SIGNALDELAY ){ // Prellschutz
          // Geschwindigkeit ermitteln
          float kmh = UMFANG / (millis() - lastSignal) * 3.6;

          speedMeasurements[currentIndex] = kmh;
          currentIndex = (currentIndex + 1) % numMeasurements;

          float sumSpeed = 0;
          for (int i = 0; i < numMeasurements; i++) {
              sumSpeed += speedMeasurements[i];
          }
          kmhAvg = sumSpeed / numMeasurements;

          if(kmhAvg > 24){
            overrideKmh = true;
          } elseif( kmhAvg < 23) {
              overrideKmh = false;
              sendSignal();   
          }
          
          lastSignal = millis();
      }
  }
  
  ReedSignalOld = ReedSignal; 
} // End Function checkReedSignal();

void doOverride(){
  static unsigned long lastOverride = 0;
  if(millis() - lastOverride > simDelay * 0.9 ){
    sendSignal();    
    lastOverride = millis();
  }
  
}

void sendSignal(){
  static unsigned long LastSend = 0;

  // Kein Signal senden, das kürzer ist als 24kmh
  if( millis() - LastSend < simDelay ) return;
  
  digitalWrite(OUT_PIN, LOW);
  delay(SIGNAL_DURATION);
  digitalWrite(OUT_PIN, HIGH);
  LastSend = millis();
}

Fazit

Mit dieser Schaltung und dem Programmcode funktioniert die Überbrückung und die Motor-Unterstützung wird ab 25km/h nicht aufgehoben.

Der Programmcode sollte noch etwas optimiert werden, um Schwankungen oder falsche Signale abzufangen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.