Motorrad Steuergerät mit Arduino auslesen

Hallo zusammen,
ich möchte ein Steuergerät einer Suzuki SFV650 auslesen. Um die entsprechenden Zünd- und Einspritzkennfelder später an den richtigen Stellen abändern zu können, möchte ich diese zuerst auslesen. Sie sind abhängig von der Drehzahl und der Last (0-5V Poti an der Drosselklappe).
Ich möchte dazu meinen Mega ADK R3 und ein SD Datalogger Shield nutzen.
Leider bin ich recht neu in der Programmier Angelegenheit und habe bisher lediglich mit dem Starter Kit einige simple Schaltungen und Beispiele ausprobiert, aber alleine wenn ich auf die SD Karte (2GB, FAT32 formatiert) zugreifen möchte, stoße ich schon an meine Grenzen. Bekomme keine Verbindung mit dem “SD Card Example”.
Jedenfalls habe ich im Netz schon so ziemlich alle Teilstücke meines Projektes gefunden um es umzusetzen, aber um alles gemeinsam zu realisieren möchte ich Euch um Hilfe bitten.

Ich stelle mir das folgendermaßen vor. Unten sieht man das Signal, welches das Steuergerät vom Kurbelwellen Sensor bekommt, 22 High/Low Peaks und dann zwei leere als Referenz der Position. Dieses Signal möchte ich erzeugen in verschiedenen Drehzahlen, es muss jedoch nicht perfekt sein, und dem Steurgerät schicken.Dann mit dem Datenlogger die heraus kommenden Werte aufzeichnen.
Ich habe zwei Wege gefunden um ein Sinussignal zu erzeugen.
-1. PWM Werte in einen Array schreiben und anschließend filtern
-2. Einen Spungsteiler mit mehreren Abgriffen bauen und jeweils dort mit DO’s zu beschalten und dann auch filtern/glätten
Bisher tendiere ich zum zweiten, da sich die Drehzahl von 1000 bis 12000/min ändert und ich ja demendsprechend den Filter beim PWM ständig ändern müsste, Nummer 2 scheint mir nicht so empfindlich, oder wie seht ihr das?
Da der Arduiono keine negativen Spannungen erzeugen kann, wird sich die Sinuswelle zwischen 0-5V bewegen. Diese Signal würde ich mit einem TL081 OPV verstärken und mit dem Offset verschieben wollen. Dann brauch man eigentlich “nur” noch alle 24 Signale, die zwei letzten mit delay auszublenden.
Den Lastwert würde ich für jede Messreihe einfach über einen Spannungsteiler neu setzen.

Bin für jede Hilfe dankbar.

Signal.jpg

funkendoc: Bin für jede Hilfe dankbar.

Ich habe Dein Posting zwei mal gelesen und komme nicht so recht darauf, womit man Dir am ehesten helfen könnte. Daher die Fragen:

Das mit dem Auslesen klappt schon? Du weißt auch, wie die ausgelesenen Daten zu interpretieren sind? Und Du weißt auch, welche Daten Du ändern/zurückschicken musst, um zu erreichen, was Du möchtest? Welche Komponenten hast Du bereits?

Gruß

Gregor

funkendoc: Ich möchte dazu meinen Mega ADK R3 und ein SD Datalogger Shield nutzen.

Hallo, für die SD-Karte wird der SPI-Bus benutzt, der beim UNO und beim Mega an unterschiedlichen Pins zu finden ist. Das muß möglicherweise konfiguriert werden.

Hallo funkendoc,

das Steuergerät kennt die Zündzeitpunkte und Kennfelder. Warum fragst Du es nicht gleich selbst? Schreibst Du ja auch im Titel, um dann zu erklären, dass Du einen Sensor/Poti auslesen möchtest :open_mouth:

Die grundsätzliche Kommunikation mit dem Steuergerät: OBD Bike Interface

Um an die Daten zu kommen und auch Kennfelder überschreiben zu können, solltest Du dich noch hier einlesen. Wichtig ist es, erst einmal herauszufinden welches Steuergerät verbaut ist und ob das zu den ausles- & überschreibbaren gehört.

Wenn Du allerdings, wie Du selbst schreibst, noch nicht so viel Erfahrung in der Programmierung hast, rate ich Dir davon ab! Im schlimmsten Fall schrottest Du Dir die ECU. Hat Deine Maschine noch eine Wegfahrsperre, so muss in diesem Falle ein neues Steuergerät, Kabelbaum und Zündeinheit her. Das übersteigt bei weitem den Restwert der Maschine.

Daher mein Tipp: Auslesen: Ja Überschreiben: Nein (Investiere dann lieber in einen PowerCommander, o.ä.)

agmue: 12.000/min = 720.000/sec entsprechen 1,4 µsec

Das sind 200 Umdrehungen in der Sekunde, oder 5 ms pro Umdrehung, nicht 720.000 und 1,4 µsec

Dann der Einspritzpunkt für 2 Zylinder oder 4 Zylinder, dann werden es bis zu 800 Punkte in der Sekunde. Da kommt man mit den Arduino´s doch locker hin.

Aber das Vorhaben vom TS habe ich auch nicht ganz begriffen :-((

Franz

Hallo zusammen, entschuldigung, ich weiß das war viel auf einmal. Ich werde versuchen das nochmal näher zu erklären. Also das ist mein Mega ADK mit dem Datalogger Shield. |500x401 Ich habe schon an einigen Stellen gelesen, dass man zur allgemeinen Kommunikation zur SD Karte den SDI Bus verwenden muss. Bei mir sollte der an Pin 50-53 liegen. Aber wo soll ich damit auf dem Datalogger hin, sehe keine entsprechende Beschriftung? Auch in dieser DOKU finde ich es nicht heraus

Im Endeffekt ist das Stichwort schon gefallen, ich verwende einen Powercommander (Sorry, wollte nicht noch tiefer in die Materie gehen um es nicht noch unübersichtlicher werden zu lassen). Der kann den Zündzeitpunkt (Grad vor oberer Totpunkt) verändern, sowie die Einspritzzeiten (Länge=Kraftstoff Menge). Hier ein Beispiel, gemessen was in den PC reingeht und was am Einspritzventil ankommt. Die kleine Verzögerung ist an der Stelle kein Problem.

|500x375

Das Problem ist, dass der PC nur Verändern kann, aber nicht sagen kann um welche Absolutwerte es sich handelt, diese sind für mich aber sehr wichtig. Man schreibt lediglich in eine leere Tabelle was man in welchem Bereich ändern möchte und der PC setzt es um. Die absoluten Werte nicht zu kennen kann den Motor schnell beschädigen oder in Sekunden Bruchteilen zerstören (Stichwort klopfende Verbrennung). Ich möchte, durch Simulation vom Kurbelwellen Signal und dem Last Poti, aufzeichen was das Steuergerät für Werte ausgibt. Dazu möchte ich den Arduino nutzen und mit dem Datalogger Shield aufzeichnen um es später auswerten zu können. Der Vorgang ist an sich recht simpel, man simuliert beipielsweise 6000 /min mit je 22 Signalen pro Umdrehung. Wären 100 Umdrehungen pro Sekunde und damit ein 2200Hz Signal. (Also jede Umdrehung 22 High/Low Peaks und dann zwei leere). Das Steuergerät gibt dann je nach Last (0-5V Poti) ein bestimmtes Zündsigal und eine bestimmte Einspritzdauer aus, diese möchte ich aufzeichnen (zur Not könnte ich es auch am Oszi direkt ablesen, ausmessen und speichern wäre aber die technisch schönere Variante). Als Beispiel, so könnte eine fertig ausgefüllte Tabelle dann aussehen.

|500x329

Die Idee ist übrigens nicht neu, sondern eher eine Weiterentwicklung. Ich habe bereits ein Steuergerät auf diese Weise ausgelesen. Nur habe ich mir dazu einen Miniatur Rotor angefertigt, den ich mittels Elektromotor direkt am Kurbelwellen Sensor laufen lassen. Die Werte habe ich dann mühselig am Oszi abgelesen. Wie ihr seht bin ich eher praktisch begabt, deswegen hoffe ich auf Eure Hilfe. Mache natürlich auch gerne Bilder und wen mein Motoren Projekt interessiert kann auch gerne einen Link dazu bekommen.

Grüße

funkendoc: Das Problem ist, dass der PC nur Verändern kann, aber nicht sagen kann um welche Absolutwerte es sich handelt, diese sind für mich aber sehr wichtig.

Genau das kannst Du über die SDS (Suzuki Diagnostic Service) auslesen. Also zumindest primär die Grundwerte des Standard-Mappings. Je nach Modell ist es dann möglich diese direkt im Steuergerät zu überschreiben. Oder eben die Differenz des PowerCommanders zu berechnen.

Habe auf die Schnelle nix für die SFV650 gefunden. Aber so wie ich Suzuki kenne, wird das Steuergerät mit anderen Modellen geteilt, die ggf. bereits ausgelesen wurden.

Klingt auf jeden Fall interessant :)

Grüß Dich,
der Gedanke liegt natürlich nahe ist auf den ersten Blick einfacher. Hab ein paar ausgelese Suzuki Maps auf dem Rechner und leider sind die nicht so brauchbar wie man sich das wünscht (siehe Anhang). Manche Werte sind komplett undefieniert und die Zündwerte sind nicht plausibel. Man bräuchte einen weiteren Spezialisten, der die Rohdaten auch in brauchbare Werte konvertiert. Und was wenn in dieser Kette irgendwo ein Fehler passiert?
Deshalb würde ich gerne, mit einem der oben genannten Ansätze und etwas Hilfe bei der Umsetzung, die Aufgabe lösen. Später möchte ich den Arduino mit dem Shield dann während Testfahrten als Datenlogger nutzen, da müsste ich mich dann sowieso mit dem Thema auseinander setzen.
Außerdem finde ich das eine gute Möglichkeit den Umgang mt dem Arduino besser zu lernen und eine spannende Aufgabe dazu :slight_smile:

funkendoc: Auch in dieser DOKU finde ich es nicht heraus

Siehe ab Seite 30. Du hast wohl leider die Kombination aus altem Layout mit Mega.

Noch schlimmer, es scheint irgendetwas dazwischen zu sein. Es ist das alte Design mit großem Prototypen Feld, aber trotzdem sind diese 6 pins/Löcher markiert. Der Verkäufer antwortet mir nicht. Bin etwas Ratlos :confused:

|480x500

Ich habe jetzt einfach mal einen 2,54er Sockel an die sechs markierten Stellen gelötet um zu testen ob es funktioniert.

|500x412 Die meiste Zeit habe ich keine Verbindung (unten), aber nach mehrmaligen Reset und Karte raus/rein hieß es plötzlich die Karte wäre korrekt verbunden (oben). Er kann aber nicht darauf zugreifen obwohl ich extra nochmal auf FAT32 formatiert habe. Jemand eine Idee?

Ich denke eigentlich dass die sechs Pins mit nichts verbunden sind, denn ich sehe keine Leiterbahnen, oder täusche ich mich?

funkendoc: Ich denke eigentlich dass die sechs Pins mit nichts verbunden sind, denn ich sehe keine Leiterbahnen, oder täusche ich mich?

Das vermute ich auch, daher Lösung siehe Seite 30 :)

Du hattest Recht, vielen Dank! :slight_smile:

Die SD Zip runterladen und in der Bibliothek ersetzen (Backup nicht vergessen). Im Beispiel CardInfo dann einfach folgende Zeile suchen:

while (!card.init(SPI_HALF_SPEED, chipSelect)) {

Und dagegen ersetzen:

while (!card.init(SPI_HALF_SPEED, 10, 11, 12, 13)) {

Der Datenlogger Code funktioniert jetzt auch :slight_smile:

Weiter geht’s. Wie erzeuge ich ein einigermaßen schönes Sinussignal zwischen 100-5000Hz ohne ständig den Filter anpassen zu müssen? PWM, mehrfacher Spannngsteiler oder hat jemand einen besseren Vorschlag?

Was haltet ihr denn davon? http://deskfactory.de/arduino-da-wandler-sound

|500x415

Da wird das Signal für einen Verstärker erzeugt um Töne abzuspielen, aber es hört sich so an als könnte ich damit eine Sinuswelle erzeugen. Oder brauche ich dann wieder einen Frequenzabhängigen Filter weil es auf PWM Basis läuft?

Hallo zusammen, Also ich habe mich für die Methode mit dem mehrfachen Spannungsteiler entschieden. Dazu noch einen Kondensator mit Widerstand zur Glättung, also ein RC Filter. Bin gespannt ob es geht Nächstes Thema, die meisten Werte, die ich dann während der Fahrt loggen möchte, sind meistens analog. Zum Beispiel die Drosselklappen Stellung ist ein 0-5V Signal, besser geht es kaum. Aber um die Abgas Temperatur im Blick zu haben, habe ich bisher einen K Typ Spannungssensor benutzt, dazu das passende Messgerät. Dieses hat aber leider keinen Ausgang. Ich hab mir überlegt so ein Shield zu verwenden, es kommuniziert über den SPI Bus. Ebay Link Kann mir jemand bitte verraten wie ich den Converter ansprechen kann und wie ich die Werte genau umschlüssele. Wenn er statt 105 Grad nur 97 anzeigt, wäre das nicht weiter schlimm. Aber wenn statt 1050 Grad nur 970 dastehen schon, denn dann beginnen manche Teile zu schmelzen. Ich habe Beispiel Bibliotheken gefunden und Codes die mit 8, 9, 10 arbeiten, aber mein SPI liegt auf 10-13? Bitte um Rat.

funkendoc: aber mein SPI liegt auf 10-13?

Die Beispiele arbeiten mit softSPI, Du möchtest normale (Hard-) SPI. Aufruf:

#define MAXCS 10
Adafruit_MAX31855 thermocouple(MAXCS);

Vielen Dank für den Tipp! Habe mir die entsprechende Bibliothek geladen.

#define MAXDO   12
#define MAXCS   10
#define MAXCLK  13

Ich habe den SPI dann auf die selben Pins wie vom DatenLogger Shield gelegt, dann hat es sofort funktioniert, Danke! :)

Langsam ist alles komplett für mein Vorhaben. Habe dann mal folgende Spannungsteiler Leiter aufgebaut

|500x180

Dann habe ich mit diesem Code jeden Ausgang nacheinander geschalten um eine Peak Welle zu simulieren. Ich denke in Euren Augen ist der Code bestimmt total umständlich, bin natürlich für jede Verbesserung/Vereinfachung dankbar.

int ledPin2 = 2 ; // Namen für Variablen deklariert
int ledPin3 = 3 ;
int ledPin4 = 4 ;
int ledPin5 = 5 ;
int ledPin6 = 6 ;
int ledPin7 = 7 ;
int ledPin8 = 8 ;
int ledPin9 = 9 ;
int delay1 = XXXX ;
int delayend = XXXX ;

// the setup function runs once when you press reset or power the board
void setup() {
  
  pinMode(ledPin2, OUTPUT); // Pins als Ausgang deklariert
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
  pinMode(ledPin6, OUTPUT);
  pinMode(ledPin7, OUTPUT);
  pinMode(ledPin8, OUTPUT);
  pinMode(ledPin9, OUTPUT);
}

// the loop function runs over and over again forever
void loop() { 
  
  digitalWrite(ledPin2, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin2, LOW);    // Spannung am Ausgang wird eingeschaltet, wartet und geht wieder aus

  digitalWrite(ledPin3, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin3, LOW);    //
  
  digitalWrite(ledPin4, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin4, LOW);    // 
  
  digitalWrite(ledPin5, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin5, LOW);    // 
  
  digitalWrite(ledPin6, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin6, LOW);    // 
  
  digitalWrite(ledPin7, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin7, LOW);    //
  
  digitalWrite(ledPin8, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin8, LOW);    // 
  
  digitalWrite(ledPin7, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin7, LOW);    //
  
  digitalWrite(ledPin6, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin6, LOW);    // 
  
  digitalWrite(ledPin5, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin5, LOW);    // 
  
  digitalWrite(ledPin4, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(ledPin4, LOW);    // 
  
  digitalWrite(ledPin3, HIGH);
   delayMicroseconds(delay1);
  digitalWrite(ledPin3, LOW);    // 

  digitalWrite(ledPin2, HIGH);
   delayMicroseconds(delay1);
  digitalWrite(ledPin2, LOW);    // 
  
  delayMicroseconds(delayend);
}

So sah dann das Ergebnis dazu aus. Sogar ungefiltert durchaus brauchbar.

|500x354

Habe verschiedene Frequenzen getest, auch 5kHz waren kein Problem für den Arduino. Aber jetzt kommt etwas das sich meinem Verständis entzieht. Wieso ist die Spitze des Berges nur bei 0,5V? Wenn ich Ausgang 5 mit 5V schalte, also den 1kOhm Widerstand und dann kommt der 1kOhm gegen dig.GND, dann müsstn doch 2,5V am Messpunkt dazwischen anliegen, oder? Es liegen aber nur einige Hundert Millivolt an. Wenn ich die 5V direkt an den 1k Widerstand anlege, dann funktioniert es natürlich. Warum ist das so? Hatte davor gemessen, dass der Innenwiderstand vom Ausgang bei zirka 25ohm liegt.

funkendoc:
… dann hat es sofort funktioniert, Danke! :slight_smile:

Bitte gerne :slight_smile:

funkendoc:
… bin natürlich für jede Verbesserung/Vereinfachung dankbar.

Wenn Du die Ausgänge in ein Feld packst, kannst Du viele Dinge mit einer Schleife machen. Beispiel (ungetestet):

const byte ausgang[] = {2,3,4,5,6,7,8,9};
const byte ausgaenge = sizeof(ausgaenge);
...
for(byte j=0; j<ausgaenge; j++){
  pinMode(ausgang[j], OUTPUT); // Pins als Ausgang deklariert
}

funkendoc:
Wieso ist die Spitze des Berges nur bei 0,5V?
Wenn ich Ausgang 5 mit 5V schalte, also den 1kOhm Widerstand und dann kommt der 1kOhm gegen dig.GND, dann müsstn doch 2,5V am Messpunkt dazwischen anliegen, oder? Es liegen aber nur einige Hundert Millivolt an. Wenn ich die 5V direkt an den 1k Widerstand anlege, dann funktioniert es natürlich. Warum ist das so? Hatte davor gemessen, dass der Innenwiderstand vom Ausgang bei zirka 25ohm liegt.

Kleiner Gedankenfehler: Wenn Du Ausgang 5 mit 5V schaltest, wie sind dann die anderen Ausgänge geschaltet? Ausgang 5 ist HIGH und die anderen LOW, also GND? Dann hast Du 1KOhm mit 58Ohm gegen GND, macht 270mV Spannungsabfall.

Wenn Du alle anderen Ausgänge hochohmig schaltest, also als Eingang, dann stimmt Deine Rechnung.

agmue:
Kleiner Gedankenfehler: Wenn Du Ausgang 5 mit 5V schaltest, wie sind dann die anderen Ausgänge geschaltet? Ausgang 5 ist HIGH und die anderen LOW, also GND? Dann hast Du 1KOhm mit 58Ohm gegen GND, macht 270mV Spannungsabfall.

Wenn Du alle anderen Ausgänge hochohmig schaltest, also als Eingang, dann stimmt Deine Rechnung.

Hallo argmue,
vielen Dank, jetzt geht mir ein Licht auf! :slight_smile: Habs auch gleich ausprobiert. Ich habe einen 10kOhm Widerstand gleichzeitig auf Ausgang 5 und 6 gelegt und die andere Seite auf GND geklemmt. Wenn ich jetzt nur Pin 5 als Ausgang defieniere und HIGH schalte, dann fallen an dem Widerstand die 5V ab, alles normal. Wenn ich jetzt aber Pin 6 zusätzlich als Ausgang definiere, dann wieder nur Pin 5 auf HIGH schalte, sind es plötzlich nur noch 0,6V :o
Das scheint mir eine Verbindung nach GND minus der typischen Halbleiter Spannung (~0,6V) zu sein, oder?
Da liegt also der Fehler, da der kleinste Widerstand nur 140 Ohm beträgt, sind die Pins durch die Parallelschaltung also untereinander fast gebrückt und dadurch haut die Spannung ab. Habe ausgetestet dass ab knapp 1kOhm zwischen zwei Pins die Spannung stabil bleibt, wenn nur ein Ausgang geschalten ist.
Also Schlussfolgerung, wenn ich die Leiter mit höheren Widerständen erneut baue und diese in der Paralell Schaltung nicht unter 1kOhm zwischen den Pins kommen, dann sollte es funktionieren. Oder?

agmue:
Bitte gerne :slight_smile:
Wenn Du die Ausgänge in ein Feld packst, kannst Du viele Dinge mit einer Schleife machen. Beispiel (ungetestet):

const byte ausgang[] = {2,3,4,5,6,7,8,9};

const byte ausgaenge = sizeof(ausgaenge);

for(byte j=0; j<ausgaenge; j++){
  pinMode(ausgang[j], OUTPUT); // Pins als Ausgang deklariert
}

Dazu hätte ich noch ein paar Fragen. Schaltet der Code alle Ausgänge direkt nacheinander oder kann ich dazwischen die Dauer der Einschaltphase und den Abständen bestimmen?
Und wie kann ich damit dann 22 Signale generieren und 2 Pause lassen? Wollte das erst von Hand durch wiederholung programmieren, aber das ist ja sehr aufwendig und es geht bestimmt auch viel einfacher