Forum: Mikrocontroller und Digitale Elektronik ELM327 mit Arduino steuern


von Filth _. (filth)


Lesenswert?

Hallo,

ich versuche ein ELM327 mit einem Arduino zu steuern. Zuerst manuell 
über Hterm getestet:
1
>ATZ
2
3
ELM327 v1.3a
4
5
>atrv
6
12.6V
7
8
>atsp0
9
OK
10
11
>0100
12
SEARCHING...
13
41 00 BE 3E B8 00 
14
15
>010c
16
41 0C 00 00 
17
18
>010c
19
41 0C 12 54 
20
21
>010c
22
41 0C 11 B0 
23
24
>010c
25
41 0C 11 AC

Jetzt versuche ich das gleiche mit diesem Programm zu erreichen, was 
nicht klappt. Ich bekomme keine Werte ausgegeben. Jemand eine Idee 
warum?
1
#include <SoftwareSerial.h>
2
3
// RX, TX  --> debug
4
SoftwareSerial softwareSerial(4, 5);
5
6
7
void setup() {
8
    softwareSerial.begin(19200);
9
    Serial.begin(9600);
10
    
11
    delay(1500);
12
13
    softwareSerial.println("boot");
14
15
    //Reset the OBD-II-UART
16
    readOBDId("ATZ\r", 0);
17
    delay(5000);
18
19
    // no echo
20
    readOBDId("ATE0\r", 0);
21
    delay(1000);
22
23
    // no linefeed
24
    readOBDId("ATL0\r", 0);
25
    delay(1000);
26
27
    // auto detect protocol
28
    readOBDId("ATSP0\r", 0);
29
    delay(5000);
30
31
    // auto detect protocol
32
    readOBDId("0100\r", 0);
33
    delay(5000);
34
35
    softwareSerial.println("boot done");
36
}
37
38
// -------------------------------------------------------------------//
39
String readOBDId(String id, int numBytes){
40
    Serial.print(id);
41
    Serial.flush();
42
43
    String data = "";
44
    String result ="";
45
    char inChar;
46
    // only if there are bytes in the serial buffer execute the following code
47
    while(true) {      
48
      if(Serial.available()) {
49
  
50
          //keep reading and printing from serial untill there are bytes in the serial buffer
51
          while (Serial.available()>0){
52
              inChar = Serial.read();  //read Serial
53
              if(inChar == '\r' || inChar == '\n') {
54
                  break;
55
              }
56
              data += String(inChar);
57
              result = data;
58
          }
59
          
60
          softwareSerial.print("raw data: ");
61
          softwareSerial.println(data);
62
  
63
          if(result.length() > 4 && numBytes > 0) {
64
              int pos1 = data.indexOf(id);
65
              result = data.substring(pos1+3, pos1+(numBytes*2)+4);
66
              result.replace(" ", "");
67
          }
68
69
          softwareSerial.print("processed data: ");
70
          softwareSerial.println(result);          
71
          return result;
72
      }
73
      else {
74
        delay(20);
75
      }  
76
    }
77
}
78
79
void loop() {
80
  String rpm = readOBDId("010C\r", 2);
81
  softwareSerial.print("rpm: ");
82
  softwareSerial.println(rpm);
83
84
  delay(4000);
85
}

von Marc S. (marc_s86)


Lesenswert?

was ists für ein arduino? software serial funktioniert nur auf pins mit 
pin change interrupt.

von Filth _. (filth)


Lesenswert?

Es ist ein Arduino Pro Mini 3.3v, 8MHz

Das mit den Pins wusste ich gar nicht. Hier ist das auch nochmal 
erklärt:
http://www.arduino.cc/en/Reference/SoftwareSerial

Ich besorge mir etwas mit mehr Hardware serials....

Ist das Programm ansonsten so brauchbar? Komme aus der Java Welt...

: Bearbeitet durch User
von Marc S. (marc_s86)


Lesenswert?

wie äußert sich das nicht klappen?

von Filth _. (filth)


Lesenswert?

Ich sehe auf dem Softwareserial "Müll" - da sind teilweise 
abgeschnittene Ausgaben oder vertauschte Zeichen. Manchmal ists auch so 
wie erwartet.

Beispiel:
Erwartet wird Ausgabe wie "41 0C 00 00"
Stattdessen kommt zB "414 0C 00000" oder "C 0000 04" usw.

von Tom (Gast)


Lesenswert?

Ich frage mal, da kein Schaltbild vorhanden:

Einen RS232 Pegelwandler hast du doch dazwischen, oder...  ;-)

von Filth _. (filth)


Lesenswert?

Ich benutze dieses Teil hier:

https://www.sparkfun.com/products/9555

TX/RX/GND einfach an den uC und gib ihm ;)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Das hatten wir doch gerade schon mal mit der Soft-UART beim Arduino?
Ah, ja, siehe hier:
Beitrag "GPS Sensor - UART Ausgabe"

Vllt. kannst du da Erkenntnisse draus ziehen. Nur noch mal zur Klärung: 
Am DB9 hast du dein Adapterkabel auf OBD-II und auf der 6-pol 
Stiftleiste (wo GRN und BLK dransteht) den Arduino über ein paar 
Dämpfungswiderstande auf Pin 4 und 5 des Port A?
Ziehst du die Versorgung des ELM aus der OBD Buchse oder dem Arduino?

: Bearbeitet durch User
von Filth _. (filth)


Lesenswert?

Der ELM bzw das obd-interface wird über die OBD Buchse gespeist. Der 
Arduino hängt ohne Dämpfungswiderstände direkt an den TX/RX Pins vom 
Interface.

von filth (Gast)


Lesenswert?

Mir geht es speziell um meine String readOBDId(String id, int numBytes){
 Methode. Kann man das beim uC so machen? Kann es erst morgen mit dem 
Teil http://www.amazon.de/dp/B00FLL8OZG/ref=pe_386171_38075861_TE_item 
testen

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

filth schrieb:
> Mir geht es speziell um meine String readOBDId(String id, int numBytes){
>  Methode.

Das kannst du leicht über dein Startup rausfinden, du musst dir ja nur 
mal den Antwortstring auf

Filth __ schrieb:
> //Reset the OBD-II-UART
>     readOBDId("ATZ\r", 0);
>     delay(5000);

ausgeben, also
1
String result;
2
    result = readOBDId("ATZ\r",12);
3
    softwareSerial.print(result);
Frag mich nicht, ob die Syntax stimmt, ich bin Arduino Ignorant. Aber 
dann weisst du zumindest, ob die Routine richtig ist, denn der ELM muss 
ja mit der Version antworten. Vermutlich ist es auch sinnvoll, nicht auf 
eine feste Anwortlänge zu setzen, sondern die Routine entweder nach 
Timeout oder dem EOF Zeichen (CR? LF?)des ELM zu beenden.

: Bearbeitet durch User
von Marc S. (marc_s86)


Lesenswert?

anstatt einfach einen neuen arduino zu kaufen wäre es sinnvoller zu 
sagen was denn nicht klappt und wie du das ganze verkabelt hast.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Marc S. schrieb:
> anstatt einfach einen neuen arduino zu kaufen wäre es sinnvoller zu
> sagen was denn nicht klappt und wie du das ganze verkabelt hast.

Diese Fragen sind aber schon beantwortet:

Filth __ schrieb:
> Beispiel:
> Erwartet wird Ausgabe wie "41 0C 00 00"
> Stattdessen kommt zB "414 0C 00000" oder "C 0000 04" usw.

Filth __ schrieb:
> TX/RX/GND einfach an den uC und gib ihm ;)

Da der TE auch Zeichen bekommt, ist die Verkabelung (bis auf die o.a. 
Dämpfungswiderstände) funktionsfähig.

von 3162534373 .. (3162534373)


Lesenswert?

Moin,
ich hab zwar nur den 323, aber möglicherweise ist es das gleiche 
Problem.
Irgendwie passt die Baudrate nicht perfekt beim ELM, sodass es nicht 
sicher mit dem AVR ging.
Ich musste die Baudrate geringfügig in den Registern ändern.

MfG

: Bearbeitet durch User
von Marc S. (marc_s86)


Lesenswert?

Matthias Sch. schrieb:
> Marc S. schrieb:
>> anstatt einfach einen neuen arduino zu kaufen wäre es sinnvoller zu
>> sagen was denn nicht klappt und wie du das ganze verkabelt hast.
>
> Diese Fragen sind aber schon beantwortet:
>
> Filth __ schrieb:
>> Beispiel:
>> Erwartet wird Ausgabe wie "41 0C 00 00"
>> Stattdessen kommt zB "414 0C 00000" oder "C 0000 04" usw.

das hab ich glatt überlesen.

ich würde noch probieren den software serial langsamer zu machen.

von filth (Gast)


Lesenswert?

Danke für den Tipp! Setze ich die Register einfach so in dem Programm?

void setup() {
...
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;
...
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Filth __ schrieb:
> Serial.begin(9600);

Schau nochmal in den Libraries, aber eigentlich sollte es gehen, wenn du 
z.B.
[c]
 Serial.begin(9580);
// oder
 Serial.begin(9630);
[/]
benutzt, die Library sollte dir die Register richtig besetzen. Das 
gleiche gilt für die Soft-UART.

von filth (Gast)


Lesenswert?

http://forum.arduino.cc/index.php?topic=183209.0

Im letzten Beitrag ist ein Beispiel, was funktionieren soll. Er benutzt 
die 9600 baud. Ich werde das mal testen

von filth (Gast)


Lesenswert?

Ich habe die software Serial nun auf einen "richtigen" Pin gelegt und 
den Code verändert. Es kommen keine "kaputten" Ausgaben mehr, aber es 
gibt noch ein Problem:


Serielle Ausgabe:
Start...
[STOPPED]
[ELM327 v1.3a]
[>ATE0]
[>OK]
[>OK]
[>SEARCHING...41 0C 00441 441441 0C 00 00 ]
[441 0C 41 441 0441 0441 0C 00 00 ]
[>41 0C 00 00 ]
[>41 0C 00 00 ]
[>41 0C 00 00 ]
[>41 0C 00 00 ]
[>41 0C 00 00 ]
[>41 0C 00 00 ]
[>41 0C 00 00 ]
[>4141 0C 00 00 ]
[441 0C 00 00 ]
[441 0C 00 00 ]
[441 0C 00 00 ]
[441 0C 00 00 ]
[>4141 0C 00 00 ]
[441 0C 00 00 ]
[441 0C 00 00 ]
[441 0C 00 00 ]
[441 0C 00 00 ]
[>4141 0C 00 00 ]

Also eigentlich recht gut, nur nach ein paar Ausgaben, ist immer die 5te 
Zeile eingerückt und eine "41" zu viel. Hat jemand eine Idee warum?
1
#include <Arduino.h>
2
#include <Wire.h>
3
#include <SoftwareSerial.h>
4
5
String inputString = "";         // a string to hold incoming data
6
SoftwareSerial softwareSerial(8, 9);
7
8
9
int  serIn;
10
char serInString[100];  // array that will hold the different bytes  100=100characters;
11
                        // -> you must state how long the array will be else it won't work.
12
int  serInIndx  = 0;    // index of serInString[] in which to insert the next incoming byte
13
int  serOutIndx = 0;    // index of the outgoing serInString[] array;
14
15
//This is a character buffer that will store the data from the serial port
16
char rxData[20];
17
char rxIndex=0;
18
19
//Variables to hold the speed and RPM data.
20
int vehicleSpeed=0;
21
int vehicleRPM=0;
22
23
void setup()
24
{
25
  Serial.begin(9600);
26
  softwareSerial.begin(19200); 
27
28
  softwareSerial.println("Start...");
29
  delay(1000);
30
  
31
  Serial.flush();
32
  Serial.println("ATZ");
33
  delay(1000);
34
  Serial.print("ATZ\r");
35
  delay(5000);
36
  
37
  Serial.print("ATE0\r");
38
  delay(1000);
39
  
40
  Serial.print("ATL0\r");
41
  delay(1000);
42
  
43
  Serial.print("ATSP0\r");
44
  delay(1000);
45
46
  Serial.print("0100\r");
47
  delay(5000);  
48
}
49
50
51
void readOBD() {
52
     char inChar;
53
  String rec = "[";
54
 // only if there are bytes in the serial buffer execute the following code
55
  if(Serial.available()) {    
56
       
57
    //keep reading and printing from serial untill there are bytes in the serial buffer
58
     while (Serial.available()>0){
59
        inChar = Serial.read();  //read Serial        
60
         if(inChar == '\r' || inChar == '\n') break;
61
        rec += String(inChar);
62
     }
63
     rec += "]";
64
     if(rec.length() > 4) 
65
     {
66
       softwareSerial.println(rec);
67
     }
68
     else {
69
       rec = "";
70
     }
71
  }
72
}
73
74
void loop()
75
{
76
  Serial.println("010C");
77
  readOBD();
78
79
  delay(200);
80
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.