
Der Leitungscode ist dabei folgendermaßen:
2T Low, 1T High = 0-Bit
1T Low, 2T High = 1-Bit.
High ist auf der Leitung vom Controller mit 10V, Low mit 0V repräsentiert. Am Tacho ist das die Schwarz/Weiße Leitung.
T = 604µs.
Die Übertragungssequenz wird mit einem einzelnen 1T "High"-Puls eingeleitet.
Danach folgen dann direkt 12 Bytes (ohne irgendwelche Start- oder Stopbits), also 96 einzelne Bits:
Code: Alles auswählen
data[0]=0x08; // Header Byte#1
data[1]=0x61; // Header Byte#2
data[2]=0x00; // 0x08 -> P, höhere Prio als "R" und als Gang
data[3]=0x70; // 0x10 -> ECU, 0x20 -> throttle, 0x40 -> Motor
data[4]=0x23; // 0x00 -> 0. Gang, 0x01 -> 1. Gang, 0x02 -> 2. Gang, 0x03 -> 3. Gang, 0x20 -> ((!)), 0x80 -> 4. Gang
// 0x81 -> 5. Gang, 0x82 -> 6. Gang, 0x83 -> 7. Gang,
data[5]=0x00; // 0x04 -> Rückwärts-Gang "R", höhere Prio als Gang, niedrigere Prio als "P"
data[6]=0x20; // RPM/10A Balken: 0x20 = 100A, 1x28 = 130A
// Die folgenden 2 Byte: data[7] & data[8] repräsentieren die Geschwindigkeit in mph
data[7]=0x00; // data[7]=0x0X
data[8]=0x00; // data[8]=0xYZ;
// mph = X*16+Y+Z/16
data[9]=0x00; // keine Funktion
data[10]=0x00; // keine Funktion
// data[11] = X-Or Checksumme von data[0] bis data[10]
Im nächsten Byte wird das "P"= Park Symbol eingeschaltet, dieses hat höhere Priorität als bspw. ein Gang, oder das "R"= Rückwärtsgang Symbol.
Darauf folgt ein Byte (data[3]) mit dem die Symbole für ECU, Throttle und (M)otor ein und ausgeschaltet werden können.
Mit dem nächsten Byte kann sowohl der Gang codiert, als auch das Brems-Kontroll-Symbol "((!))" ein oder ausgeschaltet werden.
In Byte data[5] kann das "R"ückwärts-Symbol in die Anzeige gebracht werden. Es hat höhere Priorität als ein (zuvor angezeigter) Gang, aber eine niedrigere Prio als das "P"-Symbol.
Mit dem nächsten Byte geht es nun dem x10A/RPM Balken an den Kragen. Bei 0x20 werden 100A angezeigt, bei 0x28 ist Vollausschlag (130A) angesagt. Los geht's mit 0x01 (wo gerade 2 Dots vom Balken angezeigt werden).
Soo, als nächstes kommt die Geschwindigkeit in den folgenden 2 Bytes. Die wird in mph (miles per hour) an den Tacho übertragen.
0x0X und 0xYZ bilden dabei wie folgt die Geschwindigkeit in mph = X*16 + Y + Z/16.
Jetzt könnte man sich fragen: wieso gibts da überhaupt eine Nachkommastelle (Z/16), es werden doch sowieso nur ganze km/h (mph) angezeigt? Die Antwort ist einfach: Zur (genaueren) Berechnung der zurückgelegten Strecke.
Dann kommen noch 2 Bytes, bei denen ich keine Funktion feststellen konnte.
Abgerundet wird das ganze Bouquet mit einer X-Or Prüfsumme für die ersten 11 Bytes.
Ich hänge meinen Arduino-Sketch für das Testprogramm zum Ansteuern des Tachos hier mal an:
Code: Alles auswählen
// Copyright "jeff-jordan", User vom Elektroroller-Forum.de
// 10.05.2022
// Arduino Sketch für die Ansteuerung des E-Odin 2.0 Tachos, zwecks Protokoll-Test.
// Verwendetes Board: Arduino Nano
// Genutzte Arduino PINs:
const byte ledPin = 13; // Aktivitaetsanzeige
const byte outputPin = 4; // Ausgang Richtung Tacho
const int timePause = 325; //in ms
const int timeLow = 604; //in us
// Ausgabepuffer
byte data[11];
void setup()
{
pinMode(outputPin, OUTPUT);
digitalWrite(outputPin,0);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin,0);
data[0]=0x08; // Header Byte#1
data[1]=0x61; // Header Byte#2
data[2]=0x00; // 0x08 -> P, höhere Prio als "R" und als Gang
data[3]=0x70; // 0x10 -> ECU, 0x20 -> throttle, 0x40 -> Motor
data[4]=0x23; // 0x00 -> 0. Gang, 0x01 -> 1. Gang, 0x02 -> 2. Gang, 0x03 -> 3. Gang, 0x20 -> ((!)), 0x80 -> 4. Gang
// 0x81 -> 5. Gang, 0x82 -> 6. Gang, 0x83 -> 7. Gang,
data[5]=0x00; // 0x04 -> Rückwärts-Gang "R", höhere Prio als Gang, niedrigere Prio als "P"
data[6]=0x20; // RPM/10A Balken: 0x20 = 100A, 1x28 = 130A
// Die folgenden 2 Byte: data[7] & data[8] repräsentieren die Geschwindigkeit in mph
data[7]=0x00; // data[7]=0x0X
data[8]=0x00; // data[8]=0xYZ;
// mph = X*16+Y+Z/16
data[9]=0x00; // keine Funktion
data[10]=0x00; // keine Funktion
// data[11] = X-Or Checksumme von data[0] bis data[10]
}
void writeStart()
{
digitalWrite(outputPin,1);
delayMicroseconds(timeLow);
digitalWrite(outputPin,0);
}
void write0()
{
digitalWrite(outputPin,0);
delayMicroseconds(timeLow * 2);
digitalWrite(outputPin,1);
delayMicroseconds(timeLow);
digitalWrite(outputPin,0);
}
void write1()
{
digitalWrite(outputPin,0);
delayMicroseconds(timeLow);
digitalWrite(outputPin,1);
delayMicroseconds(timeLow * 2);
digitalWrite(outputPin,0);
}
void writeSequence(byte* seq, int len)
{
int i,j;
byte out;
for (i=0;i<len; i++)
{
out = seq[i];
for (j=0;j<8;j++)
{
if (out & 0x80) write1 (); else write0();
out=out<<1;
}
}
digitalWrite(outputPin,0);
}
void loop() {
int i;
static byte out;
int checksum = 0;
static int count =0;
digitalWrite(ledPin,1);
writeStart();
checksum = 0;
for (i=0;i<11; i++) // schreibt die ersten 11 Bytes
{
// XOR Checksumme mitfuehren
checksum=checksum ^ data[i];
writeSequence(&data[i],1);
}
// XOR Checksumme senden
out = checksum;
writeSequence(&out,1);
// Senden fertig
digitalWrite(ledPin,0);
delay(timePause);
}

Idee für die Bastler hier im Forum: Original-Tacho als "Anzeigemedium" weiter verwenden und zusätzliche Infos, wie bspw. die tatsächliche Akku-Restkapazität über den x10A/RPM Balken anzeigen (100% = 100A(h) -> data[6]=0x20. Der Balken ist im normalen Tacho-Betrieb ohnehin nicht zu gebrauchen.
Warum Original-Tacho? Nun, der TÜV will sich das Bike ja alle 2 Jahre anschauen.... und die Frage nach der ABE für eine selbstgebaute RASPBERRY-PI Anzeige wird man nicht so einfach positiv beantworten könen

_________

Wo der Tacho nun schon mal ausgebaut (aber wieder zugeklebt

1. Die Anzahl der Balken hängt direkt von der Batteriespannung ab. Aber Achtung: der Tacho hat dafür eine sehr hohe Zeitkonstante. Es kann daher schon mal 3 - 5 Minuten dauern, bis die korrespondierenden Balken angezeigt werden.
2. Ich habe hier eine Messreihe, in 0,5 V Schritten durchgeführt:
Code: Alles auswählen
U ≤ 61,5V -> 1 Balken (blinkt)
U ≥ 62,0V & U < 64,5V -> 2 Balken
U ≥ 64,5V & U < 66,5V -> 3 Balken
U ≥ 66,5V & U < 69,0V -> 4 Balken
U ≥ 69,0V & U < 71,5V -> 5 Balken
U ≥ 71,5V & U < 74,0V -> 6 Balken
U ≥ 74,0V & U < 76,0V -> 7 Balken
U ≥ 76,0V & U < 77,5V -> 8 Balken
U ≥ 77,5V & U < 80,0V -> 9 Balken
U ≥ 80,0V -> 10 Balken
By the way: Der komplette Tacho zieht etwa 21mA.