Even though this is not a direct answer to the question, this amount of code
does not fit in the comment section.
I use these functions to initialize the serial lines:
#include <stdio.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
struct baud_map {
int baud;
speed_t speed;
};
struct baud_map baudmap[] = {
{ 50 , B50 },
{ 75 , B75 },
{ 110 , B110 },
{ 134 , B134 },
{ 150 , B150 },
{ 200 , B200 },
{ 300 , B300 },
{ 600 , B600 },
{ 1200 , B1200 },
{ 1800 , B1800 },
{ 2400 , B2400 },
{ 4800 , B4800 },
{ 9600 , B9600 },
{ 19200 , B19200 },
{ 38400 , B38400 },
{ 57600 , B57600 },
{ 115200 , B115200 },
{ 230400 , B230400 },
{ 0, 0 }
};
int dbits_map[] = { 0, 0, 0, 0, 0, CS5, CS6, CS7, CS8 };
enum parity_t {
PARITY_NO_PARITY,
PARITY_ODD,
PARITY_EVEN
};
int baud_to_speed(int baud, speed_t *speed)
{
if(speed == NULL)
return 0;
struct baud_map *map = baudmap;
while(map->baud)
{
if(map->baud == baud)
{
*speed = map->speed;
return 1;
}
map++;
}
return 0;
}
/*
* tty: "/dev/ttyUSB0"
* baud: baudrate, for example 9600
* parity: see enum parity_t
* stop_bits: 1 or 2
* data_bits: [5-8]
*
* return the fd on success, -1 on failure
*/
int openSerial_long(const char *tty, int baud, enum parity_t parity, int stop_bits, int data_bits)
{
int fd;
speed_t speed;
if(baud_to_speed(baud, &speed) == 0)
{
fprintf(stderr, "Invalid baudrate %d\n", baud);
return 0;
}
fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(fd == -1)
{
fprintf(stderr, "Could not open %s as a tty: %s\n", tty, strerror(errno));
return -1;
}
struct termios termios;
if(tcgetattr(fd, &termios) == -1)
{
fprintf(stderr, "Could not get tty attributes from %s: %s\n", tty, strerror(errno));
close(fd);
return -1;
}
// setting common values
termios.c_iflag &= ~ICRNL; // do not translate \r into \n
termios.c_oflag &= ~OPOST; // do not map \n to \r\n
termios.c_cflag |= (CREAD | CLOCAL); // enable receiver & ignore model ctrl lines
termios.c_lflag |= (ISIG | ICANON); // enable signals and noncanonical mode
termios.c_lflag &= ~ECHO; // disable echo
cfsetispeed(&termios, speed);
cfsetospeed(&termios, speed);
switch(parity)
{
case PARITY_NO_PARITY:
termios.c_cflag &= ~PARENB;
break;
case PARITY_ODD:
termios.c_cflag |= PARENB;
termios.c_cflag |= PARODD;
break;
case PARITY_EVEN:
termios.c_cflag |= PARENB;
termios.c_cflag &= ~PARODD;
break;
default:
fprintf(stderr, "invalid parity\n");
break;
}
if(stop_bits == 1)
termios.c_cflag &= ~CSTOPB;
else if(stop_bits == 2)
termios.c_cflag |= CSTOPB;
else
fprintf(stderr, "Invalid stop bit\n");
int bits;
switch(data_bits)
{
case 5:
case 6:
case 7:
case 8:
bits = dbits_map[data_bits];
break;
default:
bits = -1;
}
if(bits != -1)
{
termios.c_cflag &= ~CSIZE;
termios.c_cflag |= bits;
} else
fprintf(stderr, "Invalid data size\n");
if(tcsetattr(fd, TCSANOW, &termios) == -1)
{
fprintf(stderr, "Could not get tty attributes from %s: %s\n", tty, strerror(errno));
close(fd);
return -1;
}
return fd;
}
/**
* tty: "/dev/ttyUSB0"
* baud: baudrate, for example 9600
* mode: a string like 8N1 where
* the first character is the number of data bits (range from 5-8)
* the second character is N (no parity), O (odd), E (even)
* the third character is the number of stop bits (1 or 2)
*/
int openSerial(const char *tty, int baud, const char *mode)
{
if(tty == NULL || mode == NULL)
return -1;
if(strlen(mode) != 3)
{
fprintf(stderr, "invalid mode\n");
return -1;
}
int stop_bits = mode[2];
if(stop_bits != '1' && stop_bits != '2')
{
fprintf(stderr, "Invalid stop bits\n");
return -1;
}
stop_bits -= '0';
enum parity_t parity;
switch(mode[1])
{
case 'n':
case 'N':
parity = PARITY_NO_PARITY;
break;
case 'o':
case 'O':
parity = PARITY_ODD;
break;
case 'e':
case 'E':
parity = PARITY_EVEN;
break;
default:
fprintf(stderr, "Invalid parity\n");
return -1;
}
int data_bits = mode[0] - '0';
if(data_bits < 5 || data_bits > 8)
{
fprintf(stderr, "invalid data bits\n");
return -1;
}
return openSerial_long(tty, baud, parity, stop_bits, data_bits);
}
The most common mode is "8N1"
(8 bit data, no parity, 1 stop bit) and I open
the serial line with
int fd = open("/dev/ttyUSB0", 9600, "8N1");
if(fd == -1)
{
fprintf(stderr, "Error, could not initialize serial line\n");
exit(EXIT_FAILURE);
}
I have no idea which serial settings you have to use, look it up in the manual.
Also be aware that stuff like this
n = write(fd, "AT I\r\n", 10);
is wrong, it's undefined behvaiour because write
is reading beyon the bound
of the string literal. It would be better to do:
const char *cmd = "AT I\r\n";
n = write(fd, cmd, strlen(cmd));
then you would write the correct amount of data.
Like I said in the comments, I've made a google search on ISO 9141-2 and I could
not find any reliable information on whether it uses AT commands. So please
check the manual of the OBDII chip you are trying to read.
Wikipedia says
ISO 9141-2. This protocol has an asynchronous serial data rate of 10.4 kbit/s. It is somewhat similar to RS-232; however, the signal levels are different, and communications happens on a single, bidirectional line without additional handshake signals. ISO 9141-2 is primarily used in Chrysler, European, and Asian vehicles.
It seems to me that this protocol is only similar to RS232, perhaps you need
another converter (other than FT232R) which supports this baudrate.
This page also states that the baudrate is 10400 bits/s, which is not
supported by default. I've found this post which also suggests that you
should use two converters, one for the communication between OBD2 and converter
at 10.4 kbit/s and one between the converter and your PC at a standard baudrate
like 19.2 kbits/s.
Alternatively you could try to set a custom baudrate as explained here and
here. I've never had to use custom baudrates, so I don't know if this
works.