Innovate LC-2 wideband RS232 Display

Hi

I am a newbie.

I have an Innovate LC-2 wideband that has RS232 serial output I would like to use to display the output onto a screen for example.

I have searched the forums and threads until I found code that would decode the format.

The serial format use to be described here

https://www.innovatemotorsports.com/support/downloads/Seriallog-2.pdf

I would like you kind folk with more experienced to check the sketch and help me define the variables properly and suggest improvements or which display to use.

I will be using the SoftwareSerial library as I will be using an Uno with RS232 shield from ebay.

Thank you in advance

// #include <SoftwareSerial.h>

int  EGO_rx_byte;
char EGO_packet[20];
int  EGO_packet_index;
char EGO_status;
char EGO_conn;
char EGO_data;
char EGO_lambda;
int Lambda;



void setup() {
    Serial.begin(19200);
    Serial.println("<Arduino is ready>");
}


void loop() {
  // put your main code here, to run repeatedly:

  if (Serial.available() > 0) {
      EGO_rx_byte=Serial.read();                                            // pull data from serial
      if ( (EGO_rx_byte & 0xA2) == 0xA2 ) {                                 // synchronization byte - bits 15-8 1x1xxx1x 
         EGO_packet[0] = EGO_rx_byte;                                       // Store buffer data to Packet
         EGO_packet_index = 0 ;                                             // This is the start of the header packet, bits 15-8      
      }
      else if ((EGO_packet_index == 0) && ((EGO_rx_byte & 0x80) == 0x80)) { // If index = 0 & bit 7 = 1 = 2nd syncro byte
         EGO_packet_index=1;                                                // this is second half of header packet, bits 7-0
         EGO_packet[1]=EGO_rx_byte;                                         // store buffer data to packet
      }
      else if ((EGO_packet_index == 1) && ((EGO_rx_byte & 0x42) == 0x42)) { // If index = 1 & 0x42 is set on next packet likely valid LC2 packet...
         EGO_packet_index=2;                                                // This was the third packet in six - Zero indexed               
         EGO_packet[2]=EGO_rx_byte;                                         // Store buffer data to packet
      }
      else {
        EGO_packet_index++;                                                 // all else are data packets, increment the packet counter by one
        EGO_packet[EGO_packet_index]=EGO_rx_byte;                           // Store buffer data to packet in series
      }
      if (EGO_packet_index == 5) {                                          // Done recieving packets, ready to construct data... 2 words per EGO, 1 header packet        
         EGO_status = (EGO_packet[2] & B00011100) >> 2;                     // status bits are in word 1 bits 12-10                
         EGO_data = (EGO_packet[2] & B00000001) << 7;                       // AFR Multiplier - think this is programmed with lmprogrammer - bits 8, 6-0
         EGO_data += EGO_packet[3] & B01111111;                             // these are the 6-0 bits         
         EGO_lambda = EGO_packet[4] & B00111111;                            // 13 bit lambda value, data depends on status bits
         EGO_lambda = EGO_lambda << 7;                                      // shift bits from first half of data packet
         EGO_lambda += (EGO_packet[5] & B01111111);                         // add bits from second half of packet       
         switch (EGO_status) {                                              // Output data depends on Status
         case 0: Lambda = EGO_lambda; EGO_conn = 13;                        // EGO Output is valid - Lambda in 10 bit scale
         if (Lambda > 1023){Lambda = 1023;}break;                           // Megasquirt expects 0-1023 input value                       
         case 1:Lambda = 1023;EGO_conn = 13;break;                          // EGO Output is valid - reporting O2% in 1/10%
         case 2:EGO_conn = 10;Lambda =  500;break;                          // Free air calibration 
         case 3:EGO_conn = 11;Lambda =  500;break;                          // Need Calibration
         case 4:EGO_conn = 12;Lambda =  500;break;                          // Warmup
         case 5:EGO_conn = 10;Lambda =  500;break;                          // Heater Calibration
         case 6:EGO_conn = EGO_lambda;Lambda =  500;break;                  // Error code 1-9    
         case 7:EGO_conn = 0;Lambda =  500;break;                           // Reserved 
         default:Lambda =  507;EGO_conn = 0;break;                          // Something else is happening, output 14.7 and error 
      }                                                                            
    } 
  }
}

One thing you will need to do is make sure your data variables are of type byte or uint8_t and not char since you are dealing with 8 bit values and shifting them left and right. With signed values, you will mostly likely get the wrong results.

Another way of working through this is like a state machine. Rather than having a lot of if/else if/... statements, have a current state you are in and only look for the values required in that state. At first, you are WAITING looking for the first SYNC byte (0xA2) and then looking for the second sync byte (0x80), etc.

Finally, when you are all done and a complete packet has been received, parse it.

Untested code:

// #include <SoftwareSerial.h>

byte EGO_packet[20];
int  EGO_packet_index;
byte EGO_status;
byte EGO_conn;
byte EGO_data;
byte EGO_lambda;
int Lambda;

bool finished;

enum { WAITING, SYNC1, LC2, DATA };
int state;

void setup() {
  Serial.begin(19200);
  Serial.println("<Arduino is ready>");
  state = WAITING;
  finished = false;
}

void loop() {

  if (Serial.available() == 0) {
    // no input, so loop
    return;
  }
  byte EGO_rx_byte = Serial.read();                                          // pull data from serial

  switch ( state ) {
    case WAITING: // waiting for first sync byte
      if ( EGO_rx_byte & 0xA2 ) {                                 // synchronization byte - bits 15-8 1x1xxx1x
        // start of packet
        EGO_packet[0] = EGO_rx_byte;                                       // Store buffer data to Packet
        state = SYNC1;
      }
      break;

    case SYNC1: // rec'd SYNC1, waiting for SYNC2
      if (EGO_rx_byte & 0x80) {
        // bit 7 = 1 = 2nd syncro byte
        EGO_packet[1] = EGO_rx_byte;
        state = LC2;
      }
      else {
        // we didn't get 2nd sync byte so abort
        state = WAITING;
      }
      break;

    case LC2:  // rec'd SYNC2, waiting for LC2 byte
      if (EGO_rx_byte & 0x42) {
        // 0x42 is set on next packet likely valid LC2 packet...
        EGO_packet[2] = EGO_rx_byte;
        EGO_packet_index = 2;                                              // This was the third packet in six - Zero indexed
        state = DATA;
      }
      else {
        // bad data, abort
        state = WAITING;
      }
      break;

    case DATA:  // receiving data
      EGO_packet[++EGO_packet_index] = EGO_rx_byte;                         // Store buffer data to packet in series
      if (EGO_packet_index == 5) {
        // Done recieving packets, ready to construct data... 2 words per EGO, 1 header packet
        finished = true;
      }
      break;
  }

  if ( !finished ) {
    return;
  }

  // received a complete packet, so parse it up

  EGO_status = (EGO_packet[2] & B00011100) >> 2;                     // status bits are in word 1 bits 12-10
  EGO_data = (EGO_packet[2] & B00000001) << 7;                       // AFR Multiplier - think this is programmed with lmprogrammer - bits 8, 6-0
  EGO_data += EGO_packet[3] & B01111111;                             // these are the 6-0 bits
  EGO_lambda = EGO_packet[4] & B00111111;                            // 13 bit lambda value, data depends on status bits
  EGO_lambda = EGO_lambda << 7;                                      // shift bits from first half of data packet
  EGO_lambda += (EGO_packet[5] & B01111111);                         // add bits from second half of packet
  switch (EGO_status) {                                              // Output data depends on Status
    case 0:
      Lambda = EGO_lambda; EGO_conn = 13;                        // EGO Output is valid - Lambda in 10 bit scale
      if (Lambda > 1023) {
        Lambda = 1023;
      }
      break;                          // Megasquirt expects 0-1023 input value
    case 1: Lambda = 1023; EGO_conn = 13; break;                       // EGO Output is valid - reporting O2% in 1/10%
    case 2: EGO_conn = 10; Lambda =  500; break;                       // Free air calibration
    case 3: EGO_conn = 11; Lambda =  500; break;                       // Need Calibration
    case 4: EGO_conn = 12; Lambda =  500; break;                       // Warmup
    case 5: EGO_conn = 10; Lambda =  500; break;                       // Heater Calibration
    case 6: EGO_conn = EGO_lambda; Lambda =  500; break;               // Error code 1-9
    case 7: EGO_conn = 0; Lambda =  500; break;                        // Reserved
    default: Lambda =  507; EGO_conn = 0; break;                       // Something else is happening, output 14.7 and error
  }

  // reset everthing
  finished = false;
  state = WAITING;
}

Welcome Your link is broken.

I realised after. I will update it when I find another source.

Thank you

blh64

thank you. I like your concept of a state machine.