Device to Nano Serial Communication at 38400 Failing

I am using a Ebay ELM327 obdii device that is locked at 38400 Baud. I wrote a simple program to read and log data. The program works fine on my Arduino Mega using Serial to communicate with the Serial Monitor on the PC and Serial1 to communicate with the device.

However, my intent was to use a Nano so I could fit the arduino inside the ELM327 enclosure. I modified the program to use softwareserial to communicate with the ELM327 device leaving the RX and TX pins open for programming and communication with the Serial Monitor on the PC.

The Nano seems to receive a couple of packets of invaild data from the device and then all communication stops. I monitored the byte by byte output and I was getting strange characters mixed with vaild characters.

I thought this may be due to using software serial so I modified the program to use TX and RX and write to an SD card and then problem was the same.

It seems to work fine on Mega and Uno but not the Nano.

I had to increase the delays during to loop from 25 to 200 to even get it to display any data.

My theory is the Nano cannot communicate at 38400 baud and therefore is receiving incomplete or garbled data streams from the ELM327 device.

Any help would be appreciated

#include <SoftwareSerial.h>

SoftwareSerial obd(2,3);

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

//Variables to hold the Vehicle data from OBDii Device
int vehicleVSS=0; //in KPH
int vehicleRPM=0; //RPM

void setup(){
  
  obd.begin(38400);
  Serial.begin(38400);
  
  Serial.println("Program Start");
  
  //Wait for a little while before sending the reset command to the OBD-II-UART
  delay(3000);
  
  //Reset the OBD-II-UART
  obd.println("ATZ");
 
  //Make sure TX has completed
  obd.flush();
  
  //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.  
  while(obd.available() > 0)
  {
    obd.read();
  }
  
//Query the OBD-II-UART for the Vehicle RPM
  obd.print("010C\r");
  
//Wait for TX to finish
  obd.flush();

  getResponse();
  getResponse(); //this should contain the data we want
  vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
  getResponse();
  Serial.println(vehicleRPM);
  delay(200);
  
// Clear Rx buffer  
  while(obd.available() > 0)
  {
    obd.read();
  }    
  
//Query the OBD-II-UART for the Vehicle Speed in Km/H
  obd.print("010D\r");
  
  // Wait for TX to finish
  obd.flush();
  
  getResponse();
  getResponse();
  vehicleVSS = strtol(&rxData[6],0,16); //this is KPH for MPH multiply by 0.621371;
  getResponse();
  Serial.println(vehicleVSS);
  delay(200);
}

void getResponse(void){
  char inChar=0;
  
  //Keep reading characters until we get a carriage return
  while(inChar != '\r'){
    //If a character comes in on the serial port, we need to act on it.
    if(obd.available() > 0){
      //Start by checking if we've received the end of message character ('\r').
      if(obd.peek() == '\r'){
        //Clear the Serial buffer
        inChar=obd.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 = obd.read();
        //Add the new character to the string, and increment the index variable.
        rxData[rxIndex++]=inChar;
      }
    }
  }
}

perhaps teensy ? http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293624867

// i think software emulation of a com port is always a bit slower, do you have to use that ?

Comparing a hardware UART to a software implementation really isn't all that helpful. If you change the code on the Mega to use SoftwareSerial, do you see problems there as well?

In terms of hardware connections, you aren't forgetting to connect a ground are you?

Thanks for the replies. I planned on using an SD card to record the data anyway so I switched the ELM327 communications to the hardware RX and TX. Now it works fine. It took a little back and forth with the sd card starting from a very basic program just logging the responses to the finalized program I was using on the MEGA. I took a look at the Teensy and it looks like it would be the right choice next time. That way I could use the hardware serial for the ELM327 and the built in USB to monitor the program on the serial monitor. Again Thanks.

There's a bug in the 1.0.1 version of SoftwareSerial that's likely affecting your code:

//Make sure TX has completed obd.flush();

The action for flush() changed in Arduino 1.0. It now waits for the transmission of outgoing serial data to complete, as your code expects. (Prior to 1.0, flush() instead removed any buffered incoming serial data.) EXCEPT someone forgot to change this behavior for SoftwareSerial, so it still behaves the old way and deletes any previously buffered received characters and doesn't care anything about characters being transmitted.

I just tracked this down today for a problem I'm having and saw your report while searching the forum. Not sure this will fix your problem, but it's sure not going to help any. I'll cross-post this to the Installation and Troubleshooting forum and hopefully it will get fixed by the next release.

and hopefully it will get fixed by the next release.

Dream on.