Forumslader per I²C auslesen

Aktuelle Versionen des Forumsladers besitzen eine I²C/TWI Schnittstelle, über die sowohl der Zustand des Laders (z.B. Akkuspannung, Verbraucherstrom) als auch nützliche Zusatzinformationen wie Geschwindigkeit und Kilometerzahl ausgelesen werden können. In der Praxis gibt es ein paar Stolpersteine zu beachten…

Hardware

Forumslader v3.2 I2C Schnittstelle am JP1 auf der rechten Seite der Platine. Rechteck = Pin1. Platinenlayout:  J. & S. During / forumslader.de

Forumslader v3.2
I2C Schnittstelle am JP1 auf der rechten Seite der Platine. Rechteck = Pin1.
Platinenlayout: J. & S. During / forumslader.de

Forumslader v4.0 I2C Schnittstelle am JP1 auf der rechten Seite der Platine. Rechteck = Pin1. Platinenlayout:  J. & S. During / forumslader.de

Forumslader v4.0
I2C Schnittstelle am JP1 auf der rechten Seite der Platine. Rechteck = Pin1.
Platinenlayout: J. & S. During / forumslader.de

Forumslader v5 I2C Schnittstelle am JP1 auf der linken Seite der Platine. Rechteck = Pin1. Platinenlayout:  J. & S. During / forumslader.de

Forumslader v5
I2C Schnittstelle am JP1 auf der linken Seite der Platine. Rechteck = Pin1.
Platinenlayout: J. & S. During / forumslader.de

Der Anschluss erfolgt über die 4-polige Stiftleiste mit 2,54mm Rastermaß auf der Platinenoberseite.
Die Pinbelegung ist dabei

  1. GND (oben durch Rechteck gekennzeichnet)
  2. +5V2
  3. SCL
  4. SDA

Laut technischer Beschreibung zum I²C verfügt der Forumslader über Pullup-Widerstände and den SDA und SCL Leitungen. Im Schaltplan zur Version 3.2a (neuere Schaltpläne werden leider nicht veröffentlicht) sind diese Widerstände mit einem Wert von jeweils 10KΩ angegeben.

Unabhängig vom verwendeten Kabel war in meinen Tests ein zusätzlicher 10KΩ Pullup-Widerstand an SCL notwendig. Diese zwei parallelen 10kΩ Widerstände ergeben zusammen effektiv 5kΩ.
Ohne den zusätzlichen externen Pullup-Widerstand wurden keinerlei Daten empfangen.

Forumslader I2C Schaltplan

Für meine Tests verwendete ich einen Arduino Leonardo, der entweder durch kurze Drahtbrücken oder ein ca. 1m langes USB-Kabel mit dem Forumslader verbunden wurde.

Software
Der FL arbeitet als Master mit einer gemächlichen SCL Taktfrequenz von ca. 5kHz.

Forumslader SCL Taktfrequenz ≃5kHz

Forumslader SCL Taktfrequenz ≃5kHz


In Regelmässigen Abständen wird unter anderem ein FLD Paket an ein Slave-Gerät mit der Addresse 52 gesendet.
(Laut Doku ist dies in V4.0 immer der Fall, davor muss das senden des FLD Pakets zuerst aktiviert werden.)
Will man also die Daten des Forumsladers empfangen, muss man als Slave mit der Addresse 52 am I²C-Bus lauschen.

Hier ein Code-Schnipsel für den Arduino, der eben dies tut und die empfangenen Daten am seriellen Bus (Baudrate 9600) ausgibt:

/*
 * Forumslader I2C demo for Arduino Leonardo
 * 2014 bstegmaier.de
 * Any copyright is dedicated to the Public Domain.
 *
 * forumslader arbeitet als master
 * slave address fixed to 0b00110100 = 52 (discard LSB, as it's the R/W flag)
 * interface-widerstaende im FL
 * clock scl ca 5kHz
 * ab FLv4.0 ist datensatz FLD immer vorhanden,
 *    in früheren versionen muss er durch slave aktiviert werden
 */


#define I2C_ADDR 0b00110100

#include <Wire.h>


void setup()
{
    Serial.begin(9600);
    while (!Serial.available());
    Serial.read();

    Serial.println("I2C slave for forumslader");
    Serial.print("Listening to address ");
    Serial.println(I2C_ADDR);
    Serial.println("========================");

    Wire.begin(I2C_ADDR);
    Wire.onReceive(receiveEvent);
}

void loop()
{
    // do nothing
    delay(1000);
}

void receiveEvent(int byteCount)
{
    for (int i = 0; i < byteCount; ++i) {
        char c = Wire.read();

        if (c == '$') {
            // prepend line-break
            Serial.println("");
        }

        Serial.print(c);

        if (c == ';') {
            // append line-break
            Serial.println("");
        }
    }
}

Aber Achtung: Der Forumslader verwendet beim Versenden seiner Pakete repeated start Bedingungen. Das heißt anstatt nach dem Versenden von einzelnen Daten-Bytes eine Stop-Bedingung (SCL high; SDA steigende Flanke) zu versenden und somit den Bus freizugeben wird sofort mit einer erneuten Start-Bedigung (SCL high; SDA fallende Flanke) weiter gemacht. Dies hat an Multi-Master I²C Systemen den Vorteil, dass der aktuelle Master im Besitz des Busses bleibt und kein anderes Gerät die Kommunikation unterbrechen kann.

Logic analyzer am I2C-Bus zeigt repeated start Bedingung des Forumsladers

Logic analyzer am I2C-Bus zeigt repeated start Bedingung des Forumsladers

Dieses Detail der I²C-Spezifikation wird jedoch leider in der Wire-Library des Arduino im Slave-Modus nicht unterstützt.
Der Bug ist schon seit mehreren Jahren bekannt und in Anbetracht der Popularität von Arduinos ist es umso erstaunlicher, dass er noch nicht behoben wurde.

Verwendet man die original Wire-Library trotzdem, empfängt man nur unvollständige Bruchstücke:

I2C slave for forumslader           
Listening to address 52
========================

$L,19,255,0,0,1.,-00,00,,3,229,180,30,1,78617,172ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$L,19,255,0,0,1.,-00,00,,3,228,180,30,1,79,17,172ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$L,19,255,0,0,1.,-00,00,,3,222,180,30,1,79,17,172ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$L,19,255,0,0,1.,-00,00,,3,220,180,30,1,79,17,125;
ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!

Als möglicher Workaround kann man in der Datei /usr/share/arduino/hardware/arduino/avr/libraries/Wire/utility/twi.c einfach das twi_stop in Zeile 468 auskommentieren. (Siehe auch Patch von Nate Williams)

    if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
        twi_rxBuffer[twi_rxBufferIndex] = '\0';
    }
    // sends ack and stops interface for clock stretching
    twi_stop();
    // callback to user defined callback
    twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);

Et voila:

I2C slave for forumslader
Listening to address 52
========================
ý!ý!ý!ý!ý!ý!ý!
$FLD,19,255,0,0,10.9,-0.00,0.00,+,2,233,180,30,1,7896,1676,12752;
ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$FLD,19,255,0,0,10.8,-0.00,0.00,+,2,232,180,30,1,7896,1676,12752;
ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$FLD,19,255,0,0,10.8,-0.00,0.00,+,2,231,180,30,1,7896,1676,12752;
ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$FLD,19,255,0,0,10.8,-0.00,0.00,+,3,230,180,30,1,7896,1676,12752;
ý!ý!ý!ý!ý!ý!ý!ý!ý!ý!
$FLD,19,255,0,0,10.8,-0.00,0.00,+,3,229,180,30,1,7896,1676,12752;

Es scheint so als könne man auch Befehle an den FL schicken, da er regelmäßig versucht vom Bus zu lesen. Dies findet vermutlich v.a. beim Anschluss des Forumslader-Displays und des Bluetooth-Moduls (bis v4.0?) eine Rolle.

Logic analyzer am I2C-Bus zeigt Leseversuche des Forumsladers

Logic analyzer am I2C-Bus zeigt Leseversuche des Forumsladers

Da ich nicht weiß, was der FL hier für Daten erwartet, habe ich dies nicht getestet.

Datensätze

Die Empfangenen FLD-Pakete haben leichte Ähnlichkeiten mit NMEA 0183 Datensätzen. Die Pakete starten immer mit “$FLD”, gefolgt von durch Komma getrennten Feldern. Ein Datensatz endet durch ein Semikolon.

Beispiel: Der Datensatz
$FLD,19,255,0,0,10.8,-0.00,0.00,+,3,229,180,30,1,7896,1676,12752;
kann wohl wie folgend interpretiert werden

Wert Einheit Beschreibung & offene Fragen
$FLD Start des Datenpakets
19 Menüebene Nur relevant für das Forumslader-Display.
255 leer
0 Schaltstufe Je nach Geschwindigkeit werden zwei verschiedene Schaltstufen verwendet um die größtmögliche Leistung zu erhalten.

  1. mit Spannungsverdoppler für langsamer Fahrt
  2. mit Brückengleichrichter

Siehe JensD Post im Radreise-Forum

0 Frequenz Nabendynamo Hz Ein Dynamo Wechselspannungsquelle deren Frequenz von der Drehzahl abhängt. Sind

  • Impulse per Umdrehung PPR Abhängig vom Dynamo; Typische Werte: SON 13, Shimano 14, SRAM 18
  • Radumfang U in Meter

bekannt, kann hierraus die Geschwindkeit berechnet werden:
v = 3.6\ \nu\ \frac{U}{\mathrm{PPR}}

10.8 Akkuspannung V
-0.00 Akkustrom A Bei >0 wird der Pufferakku aufgeladen, bei <0 entladen.
0.00 Verbraucherstrom A Strom, der über die 12V aus USB5V Ausgänge fließt.
+ Stromverbrauchschwelle ? Bedeutung unbekannt.
3 Status Akku 0 U<=Umin; 1 U>Umin; 2 U>15%; 3 U>30%; 4 U>45%; 5 U>60%;
6 U>75%; 7 U>90%
Wie groß Umin und Umax sind ist mir nicht bekannt.
229 Ausschaltzeit s Wenn keine Impulse mehr vom Dynamo empfangen werden und auch der Verbraucherstrom (fast) null ist, wird der FL nach diesem Zeitintervall abgeschalten.
180 Zuschalten nach Akku voll s Wenn die Akkus voll sind, werden sie für eine gewisse Zeit nicht mehr weiter geladen -> Überladungsschutz
30 12V Verbraucher zuschalten s Wenn die Akkus leer sind, werden für eine gewisse Zeit alle Ausgänge zu den Verbrauchern abgeschalten -> Tiefentladungsschutz
1 Modus Verbraucher
  1. Automatik
  2. an
  3. aus
  4. Netzteil

Bedeutung nicht ganz klar.

7896 Zähler Dyanoimpulse / 4096 Kann als Kilometerzähler eingesetzt werden. Änlich wie oben bei der Geschwindigkeit müssen hierzu PPR und U bekannt sein. Dann gilt für die Gefahrenen Kilometer:
d = 4096\ n_\mathrm{Impulse}\ \frac{U}{\mathrm{PPR}}
1676 Startcounter Zählt wie oft FL automatisch oder manuell eingeschalten wurde.
12752 Gesamtfahrtzeit min Wie wird diese Berechnet?
; Ende Datenpaket

Die Implementierung eines Parsers für FLD-Datensätze werde ich in einem anderen Post beschreiben.

Edits

  • 2015-01-19: Berechnung Geschwindigkeit/Distanz aus Datensatz

Leave a Reply

Your email address will not be published. Required fields are marked *