Simple Logger

Developer topics relating to software that logs data from ECUs

Moderator: Freon

Simple Logger

Postby Visceral » Sat Jan 08, 2005 6:11 pm

Based on the technical information on the Subaru Select Protocol, I wrote up a very basic application to log a few values:
Image

Development was done in C using Cygwin on Windows. This code is really just "test" quality, and may contain errors.

Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <termios.h>
#include <sys/select.h>
#include <time.h>

#define RESPONSE_MSG_LEN      128

int debug = false;

typedef struct ecu_t
{
  int connected;
  int fd;
} ecu;

int connect(ecu_t *e)
{
  struct termios options;

  e->connected = 0; /* reset in case we fail to connect */

  e->fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
  if (e->fd == -1)
    return 0;
  else
    fcntl(e->fd, F_SETFL, 0);

  tcgetattr(e->fd, &options);

  /* go to 4800 baud */
  cfsetispeed(&options, B4800);
  cfsetospeed(&options, B4800);

  options.c_lflag = 0;  /* No local flags */
  options.c_oflag &= ~OPOST; /* No output processing */
  options.c_iflag &= ~(IXON | IXOFF | INPCK | PARMRK | BRKINT | INLCR | ICRNL |
                      IUCLC | IXANY);
  options.c_iflag |= IGNBRK;  /* Ignore break conditions */
  options.c_cflag |= (CLOCAL | CREAD); /* enable */
  options.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS */
  options.c_cflag &= ~PARENB; /* No parity */
  options.c_cflag &= ~CSTOPB; /* 1 stop bit */
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;     /* 8 bits */

  /* set all of the options */
  tcsetattr(e->fd, TCSANOW, &options);

  tcflush(e->fd, TCIOFLUSH);  /* Added to flush buffer */

  int status;
  ioctl(e->fd, TIOCMGET, &status);
  status |= TIOCM_DTR;       /* Set DTR high */
  status &= ~TIOCM_RTS;      /* Set RTS low  */
  ioctl(e->fd, TIOCMSET, &status);

  e->connected=1;
  return 1;
}

void disconnect(ecu_t *e)
{
  tcflush(e->fd, TCIOFLUSH);
  if (!e->connected)
    return;
  close (e->fd);
}

void printMsg(u_int8_t* msg, int len)
{
  printf("Message: ");
  for (int i = 0; i < len; i++)
    printf("%X ", msg[i]);
  printf("\n");
}

u_int8_t calcChecksum(u_int8_t* msg, int len)
{
  u_int8_t checksum = 0;
  for (int i = 0; i < (len - 1); i++)
    checksum += msg[i];
  return checksum;
}

int sendMsg(ecu_t *e, u_int8_t* msg, int len)
{
  int status;
  int writeLen = 0;

  tcflush(e->fd, TCIOFLUSH);  // Added to flush buffer

  writeLen = write(e->fd, msg, len);
  return writeLen;
}

int recvMsg(ecu_t *e, u_int8_t* msg, int len)
{
  struct termios oldtio, options;
  tcgetattr(e->fd, &oldtio);
   
  tcgetattr(e->fd, &options);
  options.c_lflag = 0;
  options.c_cc[VTIME] = 0;
  options.c_cc[VMIN] = len;
  //tcflush(e->fd, TCIFLUSH);
  tcsetattr(e->fd, TCSANOW, &options);
 
  int readLen = 0;
  readLen = read(e->fd, msg, len);
 
  tcsetattr(e->fd, TCSANOW, &oldtio);
 
  return readLen;
}

int main(int argc, char** argv)
{
  ecu_t e;
  struct timeval hrTime;
  u_int8_t responseMsg[RESPONSE_MSG_LEN];
  int bytesRead;

  if (debug)
    printf("Opening serial port\n");
  if (!connect(&e))
  {
    perror("Could not open port");
    exit(-1);
  }
  else
  {
    if (debug)
      printf("Port opened\n");
  }

  u_int8_t queryMsg[22];
  queryMsg[0] = 0x80;
  queryMsg[1] = 0x10;
  queryMsg[2] = 0xF0;
  queryMsg[3] = 0x11;
  queryMsg[4] = 0xA8;
  queryMsg[5] = 0x00;
  queryMsg[6] = 0x00;
  queryMsg[7] = 0x00;
  queryMsg[8] = 0x0D;  /* MAP */
  queryMsg[9] = 0x00;
  queryMsg[10] = 0x00;
  queryMsg[11] = 0x0E;  /* RPM High */
  queryMsg[12] = 0x00;
  queryMsg[13] = 0x00;
  queryMsg[14] = 0x0F;  /* RPM Low */
  queryMsg[15] = 0x00;
  queryMsg[16] = 0x00;
  queryMsg[17] = 0x11; /* Ignition Timing */
  queryMsg[18] = 0x00;
  queryMsg[19] = 0x00;
  queryMsg[20] = 0x22;
  queryMsg[21] = calcChecksum(queryMsg, 22);

  sleep(1);

  while(1)
  {
    if (debug)
      printMsg(queryMsg, 22);

    if (sendMsg(&e, queryMsg, 22) == -1)
    {
      perror("Could not write");
      exit(-1);
    }

    memset(responseMsg, 0, RESPONSE_MSG_LEN);
    bytesRead = recvMsg(&e, responseMsg, 33);
    if (debug)
      printMsg(responseMsg, 33);
    /* 80 F0 10 05 E8 MAP RPMH RPML IGN KNK CKSUM */
    if (debug)
      printf("MAP: %X, RPMH: %X, RPML: %X, IGN: %X\n", responseMsg[27],
                                                       responseMsg[28],
                                                       responseMsg[29],
                                                       responseMsg[30]);
    float map = (responseMsg[27] * 37)/255;
    unsigned int rpmH = responseMsg[28];
    unsigned int rpmL = responseMsg[29];
    rpmH <<= 8;
    unsigned int rpm = (rpmH + rpmL)/4;
    int ign   = (responseMsg[30] - 128)/2;
    int knk   = (responseMsg[31] - 128)/2;
    gettimeofday(&hrTime, NULL);
    printf("%ld.%ld RPM: %i MAP: %.0f IGN: %i KNK: %i\n", hrTime.tv_sec,
                                                          hrTime.tv_usec/1000,
                                                          rpm,
                                                          map,
                                                          ign,
                                                          knk);
  }

  disconnect(&e);

  return 0;
}
Visceral
 
Posts: 23
Joined: Thu Dec 30, 2004 10:21 am

Postby cdvma » Sun Jan 09, 2005 10:05 am

Interesting, but without looking at the code itself, you get a knock count of 3 and that doesn't seem right.
cdvma
 
Posts: 86
Joined: Tue Jan 04, 2005 9:18 pm
Location: Roch. Inst. of Tech.

Postby Visceral » Sun Jan 09, 2005 10:22 am

cdvma,

I added "KNK" last, and forgot to comment it. That value (0x22) is knock correction, not the reading from the knock sensor.

The RPM and IGN values are dead on. It idles at ~17 degrees advance, which matches the factory service manual. I haven't verified the MAP values.

Column at the left is time. I'm reading ~12 samples per second. Each additional parameter is 7 additional bytes to transfer per sample (3 bytes for the address, 3 bytes for the echo of the address, and 1 byte for the value).

If anyone is interested, I can add some additional parameters. I was also thinking of considering paramaterizing it so that you can select which values are logged.

Thank you to mumbles, and the member which forwarded him the reference info on the SSM protocol.
Visceral
 
Posts: 23
Joined: Thu Dec 30, 2004 10:21 am

Postby stanton » Sun Jan 09, 2005 10:32 am

Great progress. Yeah, I was concerned about the KNKs too.

During the ~0.08 seconds per sample, at 1000 RPM, there should be 2.7 ignition firings. So the count of 3 made sense. But, yeah, it would have meant you're knocking on all cylinders during that little blip of the throttle if that was knock count.

I definitely think a "user configureable" selection of logged values is very useful.
stanton
 
Posts: 9
Joined: Wed Jan 05, 2005 5:28 pm
Location: NJ

Postby mumbles » Tue Jan 11, 2005 4:58 pm

Very good news Visceral, please post some more screenshots and code as you start to be able to log more information.

-B
mumbles
 
Posts: 18
Joined: Thu Dec 30, 2004 1:08 am
Location: Boston

Postby stanton » Thu Jan 13, 2005 5:02 am

After DaveImpreza's post, I followed a few links. There's open-source OBD scanning software at http://www.scantool.net/software/scanto ... index.shtm
It (or some modules of it) might be useful here. I haven't looked at it...don't even know what language it's in.
stanton
 
Posts: 9
Joined: Wed Jan 05, 2005 5:28 pm
Location: NJ

Postby Nemis » Thu Jan 13, 2005 8:28 am

stanton wrote:After DaveImpreza's post, I followed a few links. There's open-source OBD scanning software at http://www.scantool.net/software/scanto ... index.shtm
It (or some modules of it) might be useful here. I haven't looked at it...don't even know what language it's in.


The program was written in C and it use odb protocol not SSM.
so it's more simple write new soft from zero
(but might be useful when we make and prog that run under windows :-) )
thank you
Nemis
 
Posts: 66
Joined: Thu Dec 30, 2004 3:58 am
Location: italy

Postby bofh » Thu Jan 13, 2005 4:37 pm

Not really, because the UI blows... I would say go from scratch.
bofh
 
Posts: 50
Joined: Thu Dec 30, 2004 1:59 pm
Location: Houston, TX

Postby crazymikie » Wed Feb 02, 2005 7:33 am

Maybe a stupid question-

I've been playing around with this and I have a [possibly stupid] question.

I've gone through and removed a lot of the magic numbers- I've made it so that when you add a parameter, you just update one variable and all of the message lengths are calculated and everything 'just works.' I've also added the logic to poll the ECU to see which parameters it supports (I don't do anything with the data, I just print it at this point).

In any case, I was trying to read EGTs (0x106), however, 0x106 = 262 = 100000110 > u_int8. What is the proper way to fix this? I tried using u_int16 arrays and then things got garbled.

I apologize if I'm missing something obvious. If I can get a few more things working, we can start polling some of the undocumented parameters the ECU supports (there are a few), and then we can try and figure out what they are.

Thanks!
Mike
crazymikie
 
Posts: 105
Joined: Mon Jan 03, 2005 6:45 pm
Location: Watertown, MA

Postby WolfPlayer » Wed Feb 02, 2005 1:52 pm

crazymikie,

I can't answer your question. I'm actually just trying to get to the point that you are at right now. If I can ask, what hardware are you using? I have an OBDII data cable that came with software I ordered from here: http://www.obd-2.com/

Do you think the above program will work using that data cable or do I need a different one. I'm working with a 2005 Subaru STi.

t
WolfPlayer
 
Posts: 16
Joined: Wed Feb 02, 2005 1:48 pm

Postby crazymikie » Wed Feb 02, 2005 2:26 pm

I think any OBD -> serial cable should work fine. I've used both the cable from my AccessPort and the cable from my DeltaDash.

You can definitely try the cable- I can't see any bad side effects. Worse case is it just dones't work. I assume you got the ISO version, right?

Please let me know if you need help.
crazymikie
 
Posts: 105
Joined: Mon Jan 03, 2005 6:45 pm
Location: Watertown, MA

Postby WolfPlayer » Wed Feb 02, 2005 5:52 pm

crazymikie wrote:I think any OBD -> serial cable should work fine. I've used both the cable from my AccessPort and the cable from my DeltaDash.

You can definitely try the cable- I can't see any bad side effects. Worse case is it just dones't work. I assume you got the ISO version, right?

Please let me know if you need help.


crazymikie,

Thanks. Yes, I have the ISO version. It's been a REALLY long time since I have used C so I'll probably have problems trying to get this app to work. I am seriously tempted to write an application in Visual Basic or .NET. I'm pretty good with user interfaces so if I can wrap my head around the code such that I can write it in Visual Basic then I could put together a user friendly version that others can use that will log to a datafile.

t
WolfPlayer
 
Posts: 16
Joined: Wed Feb 02, 2005 1:48 pm

Postby crazymikie » Wed Feb 02, 2005 7:56 pm

Let's talk. You just need cygwin installed to get this to compile. I can walk you through it if you'd like. I'm a UNIX guy so between the two of us, we can probably get something going.

I think the thing that needs to be done is to gather info on the parameters which aren't labelled so we can try and figure out what they represent, but we can talk and throw some ideas around.

Just let me know what you need. I can show you what I did to the program as well. It's a little easier to add/remove parameters that you want to poll.


Mike
crazymikie
 
Posts: 105
Joined: Mon Jan 03, 2005 6:45 pm
Location: Watertown, MA

Postby mumbles » Thu Feb 03, 2005 12:20 pm

Yeah i'm also a .net guy. We totally should build upon this, as it seems like the proper direction. You can map all his functions and stuff to C#. It's good though for now because writing in C is still cross-platform capable.
mumbles
 
Posts: 18
Joined: Thu Dec 30, 2004 1:08 am
Location: Boston

Postby crazymikie » Fri Feb 04, 2005 12:47 pm

Figured out the answer to my question. Once again, just overlooking the obvious :)

We got EGTs!


Mike
crazymikie
 
Posts: 105
Joined: Mon Jan 03, 2005 6:45 pm
Location: Watertown, MA

Next

Return to Data Logging Software

Who is online

Users browsing this forum: No registered users and 7 guests

cron