SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By Mee_n_Mac
#144356
BTW I now think you do need to have the OBD plugged into the car. It get's it's power via the DLC connector. No car power = no OBD power and no (good) communication.
By Mee_n_Mac
#144357
Here's that code with the rxData now hard limited to 20 characters max.
Code: Select all
#include <LiquidCrystal.h>

#define LCD_RS 4
#define LCD_ENABLE 5

#define LCD_DATA1 7
#define LCD_DATA2 8
#define LCD_DATA3 12
#define LCD_DATA4 13

LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA1, LCD_DATA2, LCD_DATA3, LCD_DATA4);
#define ContrastPin 6
#define BrightnessPin 9


//This is a character buffer that will store the data from the serial port
char rxData[20];
byte rxIndex=0;

//Variables to hold the speed and RPM data.
int vehicleSpeed=0;
int vehicleRPM=0;

void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  Serial.begin(9600);
  
  //Delete any data that may be in the serial port before we begin.
  delay (100);
  Serial.flush();

  //Init and clear the old data from the LCD.
  lcd.begin(16, 2);
  lcd.clear();
  // Put a Hello World message on the LCD.
  lcd.print("  Initializing  ");
  delay (1000);  
  lcd.setCursor(0, 1);
  lcd.print(" Reseting OBDII ");
  delay (2000);  // allow user time to look towards OBDII LEDs
  
  //Reset the OBD-II-UART
  Serial.println("ATZ");
  
  // Show both responses - if any
  getResponse();  // get first response
  
  // Show what came back.
  lcd.clear();
  // Now show what are we doing.
  lcd.print("Reset response");
  lcd.setCursor(0, 1);
  if(rxIndex)
  {
    lcd.print("rxIndex1 = ");
    lcd.print(rxIndex);
    delay (2000);
    lcd.setCursor(0, 1);
    lcd.print("                ");  // erase prior response
    delay(100);         // allow LCD time to refresh 
    lcd.print(rxData);  // should be cmd echo ??
    // lcd.print(" Got a message");
  }
  else
  {
    lcd.print("no response #1");
  }
  delay (2000);  // wait just long enough for user to see 1st response
  
  // Now get 2nd response, a blank line ??
  getResponse();
  lcd.setCursor(0, 1);
  lcd.print("                ");  // erase prior response
  delay(100);         // allow LCD time to refresh
  if(rxIndex)
  {
    lcd.print("rxIndex2 = ");
    lcd.print(rxIndex);
    delay (2000);
    lcd.setCursor(0, 1);
    lcd.print("                ");  // erase prior response
    delay(100);         // allow LCD time to refresh
    lcd.print(rxData);  // should be ??? 
    // lcd.print(" Got a message");
  }
  else
  {
    lcd.print("no response #2");
  }
  
  // Now get 3rd response, a blank line ??
  getResponse();
  lcd.setCursor(0, 1);
  lcd.print("                ");  // erase prior response
  delay(100);         // allow LCD time to refresh
  if(rxIndex)
  {
    lcd.print("rxIndex3 = ");
    lcd.print(rxIndex);
    delay (2000);
    lcd.setCursor(0, 1);
    lcd.print("                ");  // erase prior response
    delay(100);         // allow LCD time to refresh
    lcd.print(rxData);  // should be ???
    // lcd.print(" Got a message");
  }
  else
  {
    lcd.print("no response #3");
  }
  
  // Now get 4th response, ELM ... ??
  getResponse();
  lcd.setCursor(0, 1);
  lcd.print("                ");  // erase prior response
  delay(100);         // allow LCD time to refresh
  if(rxIndex)
  {
    lcd.print("rxIndex4 = ");
    lcd.print(rxIndex);
    delay (2000);
    lcd.setCursor(0, 1);
    lcd.print("                ");  // erase prior response
    delay(100);         // allow LCD time to refresh
    lcd.print(rxData);  // should be ELM ... 
    // lcd.print(" Got a message");
  }
  else
  {
    lcd.print("no response #4");
  }
  delay (5000);  // wait long enough for user to see responses
  
  //Delete any data that may be in the serial port before we do next step
  Serial.flush();
  
  //Now command the OBDII to auto-detect the proper protocol as done in example 1.
  Serial.println("ATSP0");
  // Again show both responses - if any
  getResponse();
  
  // Show what came back.
  lcd.clear();
  lcd.print("Auto protocol");
  lcd.setCursor(0, 1);
  if(rxIndex)
  {
    lcd.print("rxIndex5 = ");
    lcd.print(rxIndex);
    delay (2000);
    lcd.setCursor(0, 1);
    lcd.print("                ");  // erase prior response
    delay(100);         // allow LCD time to refresh
    lcd.print(rxData);  // should be cmd echo ?
    // lcd.print(" Got a message");
  }
  else
  {
    lcd.print("no response #5");
  }
  delay (2000);  // wait just long enough for user to see 1st response
  
  // Now get 2nd real response ??
  getResponse();
  lcd.setCursor(0, 1);
  lcd.print("                ");  // erase prior response
  delay(100);         // allow LCD time to refresh
  if(rxIndex)
  {
    lcd.print("rxIndex6 = ");
    lcd.print(rxIndex);
    delay (2000);
    lcd.setCursor(0, 1);
    lcd.print("                ");  // erase prior response
    delay(100);         // allow LCD time to refresh
    lcd.print(rxData);  // should say OK
    // lcd.print(" Got a message");
  }
  else
  {
    lcd.print("no response #6");
  }
  delay (5000);  // wait long enough for user to see responses

  //Hoping the above worked, now put the speed header on the first row.
  lcd.clear();
  lcd.print("Speed: ");
  //Put the RPM header on the second row.
  lcd.setCursor(0, 1);
  lcd.print("RPM: ");
  //Wait for a bit before starting to send commands after the reset.
  delay(2000);
}

void loop(){
  //Delete any data that may be in the serial port before we begin. 
  Serial.flush();
  //Set the cursor in the position where we want the speed data.
  lcd.setCursor(7, 0);
  //Write over the old speed data, and then reset the cursor position.
  lcd.print("        ");  // need 8 spaces for speed data per old code
  lcd.setCursor(7, 0);
  
  //Query the OBD-II-UART for the Vehicle Speed
  Serial.println("010D");
  
  //Get the response from the OBD-II-UART board. We get two responses
  //because the OBD-II-UART echoes the command that is sent.
  //We want the data in the second response.
  getResponse();
  getResponse();
  //Convert the string data to an integer
  if(rxIndex) // test to see if anything was received from OBDII
  {
    vehicleSpeed = strtol(&rxData[6],0,16);
    //Print the speed data to the lcd
    lcd.print(vehicleSpeed);
  }
  else
  {
    lcd.print("No data");
  } 
  delay(100);
  
  //Delete any data that may be left over in the serial port.
  Serial.flush();
  //Move the serial cursor to the position where we want the RPM data.
  lcd.setCursor(5, 1);
  //Clear the old RPM data, and then move the cursor position back.
  lcd.print("          ");  // need 10 spaces for RPM data ?
  lcd.setCursor(5, 1);

  //Query the OBD-II-UART for the Vehicle rpm
  Serial.println("010C");
  //Get the response from the OBD-II-UART board
  getResponse();
  getResponse();
  //Convert the string data to an integer
  //NOTE: RPM data is two bytes long, and delivered in 1/4 RPM from the OBD-II-UART
  if(rxIndex) // test to see if anything was received from OBDII
  {
    vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
    //Print the rpm data to the lcd
    lcd.print(vehicleRPM);
  }
  else
  {
    lcd.print("No data");
  }
  
  //Give the OBD bus a rest
  delay(300);
}

//The getResponse function collects incoming data from the UART into the rxData buffer
// and only exits when a carriage return character is seen. Once the carriage return
// string is detected, the rxData buffer is null terminated (so we can treat it as a string)
// and the rxData index is reset to 0 so that the next string can be copied.
void getResponse(void){
  char inChar=0;
  rxIndex=0;
  unsigned long TimeIn = millis();
  //Keep reading characters until we get a carriage return or time out
  while(inChar != '\r'){
    //If a character comes in on the serial port, we need to act on it.
    if(Serial.available() > 0){
      //Start by checking if we've received the end of message character ('\r').
      if(Serial.peek() == '\r'){
        //Clear the Serial buffer
        inChar=Serial.read();
        //Put the end of string character on our data string
        rxData[rxIndex]='\0';
        //Reset the buffer index so that the next character goes back at the beginning of the string.
        //rxIndex=0;
      }
      //If we didn't get the end of message character, just add the new character to the string.
      else{
        //Get the new character from the Serial port.
        inChar = Serial.read();
        //Add the new character to the string, and increment the index variable.
        rxData[rxIndex++]=inChar;
        if(rxIndex > 18)
        {
          rxData[rxIndex]='\0';   // add the null string terminator in last place
          inChar = '\r';          // set incoming character to CR to cause an exit
        }
      }
    }
    if (millis() - TimeIn > 1000) // wait 1 sec for some kind of response
    {
      break;
    } 
  }
}
I'm still unsure how any condition could ever make rxIndex show as a || or ||| ???? But I do think I have a handle on why the LCD went blank after sending it the 1'st rxData response.
By Mee_n_Mac
#144358
Here's a way to prove/disprove part of the last TOTM. Load this sketch and see if you can predict ahead of time what'll happen. Just need the Arduino and LCD and PC.
Code: Select all
#include <LiquidCrystal.h>

#define LCD_RS 4
#define LCD_ENABLE 5

#define LCD_DATA1 7
#define LCD_DATA2 8
#define LCD_DATA3 12
#define LCD_DATA4 13

LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA1, LCD_DATA2, LCD_DATA3, LCD_DATA4);
#define ContrastPin 6
#define BrightnessPin 9


void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  Serial.begin(9600);

  //Init and clear the old data from the LCD.
  lcd.begin(16, 2);
  lcd.clear();
  // Put a Hello World message on the LCD.
  lcd.print("  Initializing  ");   // 16 chars
  delay (1000);  
  lcd.setCursor(0, 1);
  lcd.print("    the LCD     ");   // 16 chars
  delay (5000);
}

void loop(){
  // Now send too many 111s
  lcd.clear();
  delay (1000);
  lcd.print("111111111111111111"); // 18 111s should wrap to next line
  delay (2000);                   // delay long enough to see 11 on line 2
  lcd.setCursor(0, 1);
  lcd.print("222222222222222222"); // 18 222s, should now wrap to top line ??
  delay (2000);
}
By djarmyssg
#144366
Mac.. Sorry I didnt get back to you brother. I had to spend some "Q" time with the wife.. But I uploaded the last program.. and it seems that all it did was just DROP the pieces that didnt fit on the screen.. it didnt convert it, or change the numbers at all... Im beginning to think its a translation issue..... When I changed the code a bit to send the "RXindex" to the serial monitor. and I got the CMD ECHO to show.... but im not getting anything after that.. Ill try to see what I can get
By Mee_n_Mac
#144368
Again, just for giggles, give this a try. It should display a count that is no different in nature than rxIndex.
Code: Select all
#include <LiquidCrystal.h>

#define LCD_RS 4
#define LCD_ENABLE 5

#define LCD_DATA1 7
#define LCD_DATA2 8
#define LCD_DATA3 12
#define LCD_DATA4 13

LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA1, LCD_DATA2, LCD_DATA3, LCD_DATA4);
#define ContrastPin 6
#define BrightnessPin 9
byte counter = 0;

void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  Serial.begin(9600);

  //Init and clear the old data from the LCD.
  lcd.begin(16, 2);
  lcd.clear();
  // Put a Hello World message on the LCD.
  lcd.print("  Initializing  ");   // 16 chars
  delay (1000);  
  lcd.setCursor(0, 1);
  lcd.print("    the LCD     ");   // 16 chars
  delay (5000);
  lcd.clear();
  lcd.print("Count = ");
}

void loop(){
  delay (1000);
  lcd.print(counter);
  counter++;
}
Did the "rxIndex hard limited code" make any difference ?

At this point I'm wondering if it wouldn't be easier to have the Arduino just act as a USB to serial converter. Have it talk to the OBD via a "soft" UART on a separate set of pins and just relay data sent via the serial monitor to the OBD and visaversa. Then you can replicate Example 1 directly and see if the OBD can talk to your car.
By djarmyssg
#144369
Mac, No there was no diffrence.... But I do believe that using the arduino as a serial converter might be exactly what I need... Im actually starting to think there might be something wrong with the shield!!!
By Mee_n_Mac
#144371
If the above is a confusing output (and the LCD doesn't wrap onto the next line) then if you want, give this a try. It's even more like trying to "print" a number to the LCD ... as the tutorial code did.
Code: Select all
#include <LiquidCrystal.h>

#define LCD_RS 4
#define LCD_ENABLE 5

#define LCD_DATA1 7
#define LCD_DATA2 8
#define LCD_DATA3 12
#define LCD_DATA4 13

LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA1, LCD_DATA2, LCD_DATA3, LCD_DATA4);
#define ContrastPin 6
#define BrightnessPin 9
byte counter = 0;

void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  Serial.begin(9600);

  //Init and clear the old data from the LCD.
  lcd.begin(16, 2);
  lcd.clear();
  // Put a Hello World message on the LCD.
  lcd.print("  Initializing  ");   // 16 chars
  delay (1000);  
  lcd.setCursor(0, 1);
  lcd.print("    the LCD     ");   // 16 chars
  delay (5000);
  lcd.clear();
  lcd.print("Count = ");
}

void loop(){
  delay (1000);
  lcd.setCursor(0, 1);
  lcd.print("     ");
  lcd.print(counter);
  counter++;
}
Then when you tire of trying to figure out why the LCD doesn't act like it should, the following code is a direct lift of the Arduino soft UART example. I believe you have pins 2 and 3 free so connect the OBD to those and see if you can use the below to have your terminal talk through the Arduino to the OBD and visa versa.
Code: Select all
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup()  
{
  Serial.begin(9600);
  Serial.println("Ready");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  //mySerial.println("Hello, world?");
}

void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}
If I understand it properly, all it does is look for a byte on the soft UART and if available, copy it to the real UART output and thus to the PC serial monitor. Then does the same in the opposite direction, from real UART/PC to the soft UART (and to the OBD). You should be able to replicate Example #1.

http://arduino.cc/en/Reference/SoftwareSerial
By djarmyssg
#144372
Ok well I tried that.... seems like when I send the atz command, I can see the OBD shield reseting.... But I cant seem to get anything to print back to the terminal?? getting the ATZ to acttually do something through the terminal, makes me believe that the board is actually getting the commands... No sure why I cant get it to show them back on the screen though!!!
By Mee_n_Mac
#144374
At one point we were seeing the command echoed back. If you can see the 4 LEDs on the OBD blink when you send the ATZ and/or ATSP0 commands I have to believe the Arduino is sending data to the OBD and it's being received. That you can only occasionally see the OBD return data makes me think there's an intermittant connection or there's a voltage difference btw the ground on the Arduino and the ground on the OBD. If you have a DVM see if you can measure any voltage btw the 2 grounds. Do that again while sending the ATZ as often as you can. Perhaps it would be a good idea to verify that wire is well soldered at the OBD end. And verify continuity of the Tx out wire of the OBD as well. Measure them while wiggling the wires or just go ahead and resolder them.

While a DVM can't react fast enough to catch the bits, you should make sure the voltage at the Arduino input end (Rx) of the wire from the OBD is at the proper high level for a stop bit, >4V. Then pound the ATZ commands and see if the DVM reads any differently. You can try that for the Tx end as well, to see what it should look like, as we think the OBD is getting data.
By Mee_n_Mac
#144376
While your terminal program should be able to tell you the same data as displayed below ...
Code: Select all
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

#define LCD_RS 4
#define LCD_ENABLE 5
#define LCD_DATA1 7
#define LCD_DATA2 8
#define LCD_DATA3 12
#define LCD_DATA4 13

LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA1, LCD_DATA2, LCD_DATA3, LCD_DATA4);

SoftwareSerial mySerial(2, 3); // RX, TX

unsigned long counter1 = 0;
unsigned long counter2 = 0;
unsigned long last = 0;

void setup(){
  //Set the PC for 9600
  Serial.begin(9600);
  
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);

  //Init and clear the old data from the LCD.
  lcd.begin(16, 2);
  lcd.clear();
  // Put a Hello World message on the LCD.
  lcd.print(" Bytes from OBD ");   // 16 chars
  lcd.setCursor(0, 1);
  lcd.print(" Bytes from PC  ");   // 16 chars
  delay (5000);
  Serial.println("Ready");
}


void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read()); // send byte to PC
    counter1++;
  if (Serial.available())
    mySerial.write(Serial.read()); // send byte to OBD
    counter2++;
  if ((millis()-last) > 500)  // only update the LCD every 500 msecs
  {
    last=millis();
    lcd.clear();
    lcd.print(counter1);  //show how many bytes received from OBD
    lcd.setCursor(0, 1);
    lcd.print(counter2);  //show how many bytes received from PC
  }
}
The whole ground wire issue makes me think there's something odd with the wiring. Perhaps instead of trying the above you should completely disconnect everything btw the Arduino and LCD. Afterall you're driving a 3.3V device with 5V lines. Perhaps that's affecting the ability of the Arduino to receive the data from the OBD ??? And then have only 3 wires, the Tx/Rx lines btw the Arduino and OBD and the ground wire, OBD directly to the Arduino, just as shown in the Fritzing diagram back on page1. Get rid of the protoboard. Simplify the setup as much as possible !! There's less to go wrong that way.
By djarmyssg
#144449
Mac... sorry i didnt get back to you. Had to do the whole mothers day thing with my wife. But I did remove everything except the OBD shield and the arduino.. Still not getting anything back from the shield... It seems to me that it will TAKE commands... but it wont SEND anything in return. going to test the connection between the TX/RX pins, and the corresponding pins on the STN1110 itself... see if I get a diffrent reading between the 2... since i know the RX line works (since i can send the ATZ command and see it reset) Im gonna base my results on the Ohms between that!
By djarmyssg
#144453
Ok quick test leads me to believe the board is bad...... I tested straight from the chip, to the output on the board Chip pin 13 to RX input (TX on arduino) .2ohms. Chip pin 13 to TX (RX on arduino) OL... Chip pin 14 to TX (RX arduino) .2 ohms.... Chip pin 14 to RX (TX on arduino) 270.1 K ohms!!! So this leads me to believe that the the Messages being SENT are getting messed up since the TX is somehow getting high resistance from the RX!!!!! I would figure that if i go from TX to RX I should get "OL" thoughts??????
By Mee_n_Mac
#144457
I'll have to look at the schematic but 270K isn't so low that it should cause problems. Anytime you use a DVM to measure resistance with unpowered circuitry in the path, you can get odd results as you may partially bias some of the transistors on.

So Tx from Arduino to Rx on STN1110 ... about 0 ohms.
So Tx from STN1110 to Rx on Ardjuino ... also about 0 ohms. Give this connection a good wiggling workout while measuring it.

At one point we did see the ATZ and ATSP0 echoed back, did we not ?
By Mee_n_Mac
#144458
FWIW I read the STN1110 manual (preliminary) and it said the default baud rate is 38400. I wonder if SFE somehow sets this before shipping their board ... or the manual is now wrong ... or ??? Would it be worth a try to change all the baud rates to that and see what happens ? It might be interesting to see what the STN1110 LEDs do with a wrong baud rate.
By djarmyssg
#144460
Ya.. we saw it echoed... but it was an echo from the arduino..... not from the OBDshield. Also If you look here..
http://www.sparkfun.com/datasheets/Widg ... RT-v13.pdf It says pin 14 (TX-0) has a 4.7k resistor to 5V.... I issolated that risistor and only get 2.2k... could this be an issue??? I'll definitly try to change the baudrate... and see what happens.. Wont be able to test until a lil later. but i'll keep researching and see what I get.