ECOM J2KN Emission Analyzer Data via USB to Arduino

I have a ECOM J2KN emission analyzer that I need some assistance in extracting data from. This analyzer usually connects to a computer via USB. It uses a CP2102 USB to UART IC and the associated driver to create a virtual COM port. The USB protocol (attached) transmits data in ASCII.

Is there any recommendations or guidance for communication? The things that I have looked at haven't provided much insight yet. Such as using a USB shield? Can I cut the USB cord and use RX/TX? Could I connect it to the computer and driver and pull in values?

In looking at the CP2102 data sheet and searching for examples I can't quite determine I can make anything work without some assistance first. Let me know if you need more information? I plan on using an UNO or MEGA.

Protokoll J2K-I_2012_04_24(1).pdf (173 KB)

Update

I found a USB host shield (that I have) that uses the MAX3421e (USB Peripheral/Host Controller). And found USB_Host_Shield_Library_2.0 that has the CP210x by henla464. I loaded the CP210xLoopback code below with the serial output. Questions now include if this works how do I combine this and send/receive the data to the analyzer?

Note!! Dumb idea before about cutting the cord....Continuing to research and look through examples

#include <CP210x.h>
#include <usbhub.h>

#include "pgmstrings.h"
#include <SPI.h>

class CP210xAsync : public CP210xAsyncOper
{
  public:
    uint8_t OnInit(CP210x *pftdi);
};

uint8_t CP210xAsync::OnInit(CP210x *cp210x)
{
  uint8_t rcode = 0;
  rcode = cp210x->IFCEnable();

  if (rcode)
  {
    return rcode;
  }

  rcode = cp210x->SetBaudRate(115200);

  if (rcode)
  {
    return rcode;
  }

  rcode = cp210x->SetDataBits(8);
  if (rcode)
  {
    return rcode;
  }

  rcode = cp210x->SetStopBits(CP210X_STOP_BITS_1);
  if (rcode)
  {
    return rcode;
  }

  rcode = cp210x->SetParity(CP210X_PARITY_NONE);
  if (rcode)
  {
    return rcode;
  }

  rcode = cp210x->SetFlowControl(CP210X_FLOW_CONTROL_OFF);
  if (rcode)
  {
    return rcode;
  }


  return rcode;
}

USB Usb;
//USBHub Hub(&Usb);
CP210xAsync cp210xAsync;
CP210x cp210x(&Usb, &cp210xAsync);

void setup()
{
  Serial.begin( 115200 );
#if !defined(MIPSEL)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");

  delay( 200 );
}

void loop()
{
  Usb.Task();

  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
  {
    uint8_t  rcode;
    char strbuf[] = "DEADBEEF";
    //char strbuf[] = "The quick brown fox jumps over the lazy dog";
    //char strbuf[] = "This string contains 61 character to demonstrate FTDI buffers"; //add one symbol to it to see some garbage
    //Serial.print(".");

    rcode = cp210x.SndData(strlen(strbuf), (uint8_t*)strbuf);

    if (rcode)
      ErrorMessage<uint8_t>(PSTR("SndData"), rcode);

    delay(50);

    uint8_t  buf[64];

    for (uint8_t i = 0; i < 64; i++)
      buf[i] = 0;

    uint16_t rcvd = 64;
    rcode = cp210x.RcvData(&rcvd, buf);

    if (rcode && rcode != hrNAK)
      ErrorMessage<uint8_t>(PSTR("Ret"), rcode);

    // The device reserves the first two bytes of data
    //   to contain the current values of the modem and line status registers.
    if (rcvd > 2)
      Serial.print((char*)(buf));

    delay(10);
  }
}

Results

Start
configuredevice: 0
CP210x Init
init 1: 0
Addr:01
NC:01
Conf.Val: 01
Iface Num: 00
Alt.Set: 00
Conf.Val: 01
Iface Num: 00
Alt.Set: 00
NumEP:03
Conf:01
CP210x configured
configuredevice 2: 0
attempt config: 0
config rcode 1:0

Does anyone have any thoughts on a Serial Driver like this USB Host Serial Driver for CP210x? Appears once setup I could communicate directly through serial?

So I got some code working and getting the expected ASCII code!!!!! My code needs some cleaning up due to it being a combination of several different examples and my inputs. So I need some help deciphering and converting the output. Hopefully I can get some response or should I start a new thread?
This would be my typical/expected response, but seems when I send the command my response starts anywhere in the string (ex if you look at the serial output below)
$8C82;01C5;0200000000;0300D2;040000;050000;060000;070000;088000;09FFF7;0A02EB;0B8000;0C02CA;0D8000;0E8000;0F8000;10016B;1113;1212;2E8000;7A
Where $8C82 is 0x00 answer 1 BYTE; 01C5 is 0x01 Status 1 1 Byte; 0200000000 is 0x03 Error status 4 long-word;
0300D2 is command 0x03 O2 in percent, 2 word; 03 first byte is the index of the data remaining is the actual data
040000 is command 0x04 CO in ppm, 2 word; 04 first byte is the index of the data remaining is the actual data

What is the best way to pull out the actual data values and convert it to decimal? Also what is the best way to do a check sum?

/*Protocol
  The baud rate is not fixed and will be adjusted via a corresponding external program,
  otherwise 8 bit, no parity, 1 start/stop bit. Data will be send and received in ASCII.
  The maximum size of a record is 256 characters. The first character of a record is "$" (0x24),
  the last one is carriage return CR (0x0D). In between these two characters is the actual information.
  The first byte (2+3rd character, described with "GG") in HEX indicates the number of all
  transmitted characters. The second byte (4+5th character) in HEX is the command. Any possible
  following (use-)characters (described with "HH..XX") can contain different information.
  The number of (use-)characters is equal to the number of the received/send characters minus 8.
  The last byte in HEX is a checksum value, which will be calculated by simply adding theprevious
  characters.A break of more than 4 seconds during data receiving resets the data receive.
  Within the answer the commands are added with 0x80.

  Command 1 (0x01) : Write EEProm of USB Interface (only for USB-interface)
  Send : $1201HHHHIIJJKK,CHKS,CR
  Answer: $1281HHHHIIJJKK,CHKS,CR
  HHHH : Serial number
  II : RF-channel
  JJ : Setup 0x80 = Remote 0=No 1=yes 0x40 = Fahrenheit 0=°C 1=°F 0x20 = Data structure 0=DAS 1=new commands
  KK : Baud rate 0x00 = 300 0x01 = 600 0x02 = 1200 0x03 = 2400 0x04 = 4800 0x05 = 9600 0x06 = 19200 0x07 = 38400 0x08 = 57600 0x09 =115200
  Example send : $12013039054002E2,CR
  Example answer : $12813039054002EA,CR
  Serial number : 0x3039 = 12345
  RF-channel: 0x05 = 5
  Setup : 0x40 = Fahrenheit
  Baud rate : 0x02 = 1200 Baud

  Command 2 (0x02) : Read all values Send : $0802EE,CR Answer: $GG82;HHHH;...;,CHKS,CR
  The following values are transmitted : (see point 3.) 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
  Bits 0x0100 and 0x0200 in "Status USB interface" were cleared after sending the values.
*/

#include <CP210x.h>
#include <usbhub.h>
#include "pgmstrings.h"
#include <SPI.h>

class CP210xAsync : public CP210xAsyncOper
{
  public:
    uint8_t OnInit(CP210x *pftdi);
};

uint8_t CP210xAsync::OnInit(CP210x *cp210x)
{
  uint8_t rcode = 0;
  rcode = cp210x->IFCEnable();
  if (rcode)
  {
    return rcode;
  }
  rcode = cp210x->SetBaudRate(9600); //changed from 115200
  if (rcode)
  {
    return rcode;
  }
  rcode = cp210x->SetDataBits(8);
  if (rcode)
  {
    return rcode;
  }
  rcode = cp210x->SetStopBits(CP210X_STOP_BITS_1);
  if (rcode)
  {
    return rcode;
  }
  rcode = cp210x->SetParity(CP210X_PARITY_NONE);
  if (rcode)
  {
    return rcode;
  }
  rcode = cp210x->SetFlowControl(CP210X_FLOW_CONTROL_OFF);
  if (rcode)
  {
    return rcode;
  }
  return rcode;
}

USB     Usb;
//USBHub Hub(&Usb);
CP210xAsync cp210xAsync;
CP210x cp210x(&Usb, &cp210xAsync);

void setup()
{
  Serial.begin( 9600 );//115200
#if !defined(MIPSEL)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");
  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");
  delay( 200 );
}

void loop()
{
  Usb.Task();
  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
  {
    //send to analyzer
    uint8_t rcode;
    char strbuf[] = "$0802EE\r"; //command 2 (0x02) read all sensors
    rcode = cp210x.SndData(strlen(strbuf), (uint8_t*)strbuf); //send to analyzer
    Serial.print("Sent: ");  Serial.print(rcode);
    if (rcode)
      ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
    delay(100);
    //read from analyzer
    uint8_t  buf[64];
    uint16_t rcvd = 64;
    rcode = cp210x.RcvData(&rcvd, buf);
    if (rcode && rcode != hrNAK)
      ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
    if ( rcvd ) { //more than zero bytes received
      Serial.print(" RCVD: ");
      for (uint16_t i = 0; i < rcvd; i++ ) {
        //  Serial.print("RCVD: "); Serial.println((char)buf[i]);
        Serial.print((char)buf[i]);
      }
    }
    delay(100);
    Serial.println("");
  }
}

Serial Output

configuredevice: 0
CP210x Init
init 1: 0
Addr:01
NC:01
Conf.Val: 01
Iface Num: 00
Alt.Set: 00
Conf.Val: 01
Iface Num: 00
Alt.Set: 00
NumEP:03
Conf:01
CP210x configured
configuredevice 2: 0
attempt config: 0
config rcode 1:0
Sent: 0 RCVD: C02CA;0D8000;0E8000;0F8000;10016B;1113;1212;2E8000;7A
$8C82;01CC
Sent: 0 RCVD: $8C82;01C5;0200000000;0300D2;040000;050000;060000;070000;088000;
Sent: 0 RCVD: 09FFF7;0A02EB;0B8000;0C02CA;0D8000;0E8000;0F8000;10016B;1113;121
Sent: 0 RCVD: 2;2E8000;7A
$8C82;01C5;0200000000;0300D2;040000;050000;060000;07
Sent: 0 RCVD: 0000;088000;09FFF7;0A02EB;0B8000;0C02CA;0D8000;0E8000;0F8000;100
Sent: 0 RCVD: 16B;1113;1212;2E8000;7A
$8C82;01C5;0200000000;0300D2;040000;0500
Sent: 0 RCVD: 00;060000;070000;088000;09FFF7;0A02EB;0B8000;0C02CA;0D8000;0E800
Sent: 0 RCVD: 0;0F8000;10016B;1113;1212;2E8000;7A
$8C82;01C5;0200000000;0300D2
Sent: 0 RCVD: ;040000;050000;060000;070000;088000;09FFF7;0A02EB;0B8000;0C02CA;

Data Structure (from attached PDF in first post)

3) Data structure 
Data will be received or send in HEX. The different values are separated by semicolon. 
The first byte of one value is the index of the data, the following bytes are the data in different length. 
For example see command 5. 
Index Description Bytes 
0 0x00 Answer J2K 1 , Byte 
1 0x01 Status 1 analyzer 1 , Byte , see description 
2 0x02 Errorstatus 4 , Long-Word , see description 
3 0x03 O2 in x.x% 2 , Word (0x8000=nc) 
4 0x04 CO in ppm 2 , Word (0x8000=nc) 
5 0x05 NO in ppm (X.X low NOx) 2 , Word (0x8000=nc) 
6 0x06 NO2 in ppm (X.X low NOx) 2 , Word (0x8000=nc) 
7 0x07 SO2 in ppm 2 , Word (0x8000=nc) 
8 0x08 Mica (CxHy) in ppm 2 , Word (0x8000=nc) 
9 0x09 draft x.xx (or Pa) 2 , Integer 
10 0x0A Temp. air X.X °C/°F 2 , Integer (0x8000=nc) 
11 0x0B Temp. gas X.X °C/°F 2 , Integer (0x8000=nc) 
12 0x0C Temp. sensor X.X °C/°F 2 , Integer (0x8000=nc)

I don't think those delays are doing you any favors - they may well explain why you're losing data.