LED's via OBD-II UART

Hey everyone, this is my first project and I'm very new to the whole arduino thing, loving it so far though.

My project involves using a sparkfun OBD-II UART board This One to send vehicle data (RPM only for now) to my Arduino Pro Micro to, for now, control a couple sticks of RGBW Adafruit NeoPixels (16 led's total) and, later, a screen.

I'm attempting to use the vehicle's OBD-II RPM data to establish parameters to light up the neopixel leds, to create a shift-light.

I have managed to establish communication over the serial interface between the arduino and the OBD-II board, as I can see the board's obd-II, RX and TX led's all lighting up rapidly, I assume that this indicates a succesfful transfer of data between the two boards - that the arduino is receiving RPM information. Without a screen, i'm unsure how to confirm this.

I have also managed to establish basic principles for the lighting of the neopixel sticks, and I can get them to light up on their own.

I cannot, however, seem to get them to react to changes in RPM data, my use of the "if" and "else" commands seem to not function and, in my existing test-code, the leds stay in the "else" mode as though RPM is not changing. I am only using the first two led's to test for now, i want them to be dim when idling and then full brightness when i go above 1500rpm, for the sake of testing. At the moment they just stay in the dim setting.

This is the code I have made thus far, I have tried putting the LED code behind the vehicleRPM code inside void loop(), but that turns off the leds altogether and renders any code ineffective. I'm unsure how to proceed and any help would be great, thanks.

//RPM Shift Lights using SparkFun OBD-II UART board and
//Adafruit NeoPixel LED Sticks
//NeoPixel codes is (#,#,#,#,#) = (numberOfLed,Red,Green,Blue,White) numberOfLed = 0-15, Color is in brightness 0-255

#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 16
#define BRIGHTNESS 50

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);

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

int vehicleRPM=0;

void setup() {
  Serial1.begin(9600);
  //Wait for a little while before sending the reset command to the OBD-II-UART
  delay(1500);
  //Reset the OBD-II-UART
  Serial1.println("ATZ");
  //Wait for a bit before starting to send commands after the reset.
  delay(2000);
  //Delete any data that may be in the serial port before we begin.
  Serial1.flush();
strip.begin();
  strip.show(); // Initialize all pixels to 'off'}
}

void loop() {
  if(vehicleRPM > 1500){
  strip.setPixelColor(0, 255, 0, 0, 0);
  strip.setPixelColor(1, 255, 0, 0, 0);
  strip.show();
  }
else {
  strip.setPixelColor(0, 20, 0, 0, 0);
  strip.setPixelColor(1, 20, 0, 0, 0);
  strip.show(); }
  
  //Delete any data that may be in the serial port before we begin.  
  Serial1.flush();
  //Query the OBD-II-UART for the Vehicle rpm
  Serial1.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
  vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
 delay(100);
}



//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;
  //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(Serial1.available() > 0){
      //Start by checking if we've received the end of message character ('\r').
      if(Serial1.peek() == '\r'){
        //Clear the Serial buffer
        inChar=Serial1.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 = Serial1.read();
        //Add the new character to the string, and increment the index variable.
        rxData[rxIndex++]=inChar;
      }
    }
  }
}

Why don't you use the Serial object to send the data to the controlling PC?

You should read the documentation of what Serial1.fllush() does (Hint: it does NOT empty the RX buffer)

Also, in your getResponse() function, you never check to see if you have room in your rxData array to store the incoming byte. What happens if the board sends 40 characters before sending '\r'?

I was speaking to someone last night and they gave me the idea pylon had, to check the incoming serial through the PC ide monitor. I had to add some serial. code underneath the serial1. code, and i could then see the incoming rpm data through the monitor.

I also figured out if I set the serial and led codes in their own void and run the voids in a loop i can get them to run independently, got some random rpm fluctuations in the data but all sorted after resetting obd timing via AT0 and AT ST 01 and adding a 75ms delay to the 010C command, all is working now!

Thanks anyway guys :slight_smile: