2 ELM 327

orginalny vs podrobione
https://www.elektroda.pl/rtvforum/topic3214509.html

dobre:
W miarę sprawdzony jest STN1110 (zwany przez nich ELM327 v2) od Viaken


Na Beagle Bone Black  obsugiwany przez RS

na BBB pdf

obsuga RS232 w linux C

http://xanthium.in/Serial-Port-Programming-on-Linux



sprawdzanie który tty to RS:
$ dmesg | grep tty


ELM

ELM327 instaluje się w Linuksie jako RS323

/dev/ttyUSB#

Emulacja podłączonego ELM w linuxie

$ apt-get install obdgpslogger

uruchom:
$ obdsim


mozna to odczytać:

$ screen /dev/ttyUSB# 38400   (albo bez prędkości)
$ screen /dev/pts/1                    (dla emulacji obdsim)

instalacja screen

sudo apt install screen

polecenia po nawiązaniu komunikacji:

>AT L1 # enable line feed
OK
> AT I # information
ELM327 v1.4
>AT @1 # device description
OBDII to RS232 Interpreter
> AT DP # current protocol
AUTO
> AT RV # car is obviously not connected, no voltage on OBDII port
0.0V


lista polecen AT:
https://www.elmelectronics.com/wp-content/uploads/2016/07/AT_Command_Table.pdf

http://www.obdtester.com/elm-usb-commands


>0100
41 FF ...
lista polecen OBDII PIDS
https://en.wikipedia.org/wiki/OBD-II_PIDs
https://python-obd.readthedocs.io/en/latest/Command%20Tables/


Kod
Działający przykład oparty o komunikację z RS232, odczytujący z emulowanego OBD
przeliczający zwrocone wartosci hex na int.

#include <stdio.h>
#include <fcntl.h>   /* File Control Definitions           */
#include <termios.h> /* POSIX Terminal Control Definitions */
#include <unistd.h>  /* UNIX Standard Definitions     */
#include <errno.h>   /* ERROR Number Definitions           */
#include <stdlib.h>  //strtol do zamiany char na hex

void main(void)
{

         /*------------------------------- Ask for data to write to serial port ------------------*/

printf("Podaj kod PID 4 cyfry np 0100: ");
char tempp[6];
fgets(tempp,6,stdin);
printf("\n");
tempp[4]='\n';
tempp[5]='\0';


 
 
int fd;/*File Descriptor*/

printf("\n +----------------------------------+");
printf("\n |        Serial Port read & write  |");
printf("\n +----------------------------------+");

/*------------------------------- Opening the Serial Port -------------------------------*/

/* Change /dev/ttyUSB0 to the one corresponding to your system */

fd = open("/dev/pts/1",O_RDWR | O_NOCTTY | O_SYNC); 
/* ttyUSB0 is the FT232 based USB2SERIAL Converter   */
/* O_RDWR   - Read/Write access to serial port       */
/* O_NOCTTY - No terminal will control the process   */

/* bez 3 parametru (read) - Open in blocking mode,read will wait              */

//write  dodany 3 parametr(o_sync byl probnie dodany przezemnie)
/* O_NDELAY -Non Blocking Mode,Does not care about-  */
/* -the status of DCD line,Open() returns immediatly */



        if(fd == -1)      /* Error Checking */
           printf("\n  Error! in Opening tty  ");
        else
           printf("\n  tty Opened Successfully ");


/*---------- Setting the Attributes of the serial port using termios structure --------- */

struct termios SerialPortSettings; /* Create the structure                          */

tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */

/* Setting the Baud rate */
cfsetispeed(&SerialPortSettings,B38400); /* Set Read  Speed                       */
cfsetospeed(&SerialPortSettings,B38400); /* Set Write Speed                        */

/* 8N1 Mode */
SerialPortSettings.c_cflag &= ~PARENB;   /* Disables the Parity Enable bit(PARENB),So No Parity   */
SerialPortSettings.c_cflag &= ~CSTOPB;   /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE;  /* Clears the mask for setting the data size             */
SerialPortSettings.c_cflag |=  CS8;      /* Set the data bits = 8                                 */

SerialPortSettings.c_cflag &= ~CRTSCTS;       /* No Hardware flow Control                         */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines       */


SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);          /* Disable XON/XOFF flow control both i/p and o/p */
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Non Cannonical mode                            */

SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/

       /* Setting Time outs no Blocking for writing*/
 SerialPortSettings.c_cc[VMIN] = 1; /*  nr signs to  Read  */
 SerialPortSettings.c_cc[VTIME] = 1; // 0.1 seconds read timeout

if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
 printf("\n  ERROR ! in Setting attributes");
else
 printf("\n  BaudRate = 38400 \n  StopBits = 1 \n  Parity   = none");




         /*------------------------------- Write data to serial port -----------------------------*/

char write_buffer[6];
for(int i=0;i<6;i++)      //="0100\n"; /* Buffer containing characters to write into port      */
 write_buffer[i]=tempp[i];

int  bytes_written  = 0;   /* Value for storing the number of bytes written to the port */

bytes_written = write(fd,write_buffer,sizeof(write_buffer)-1);/* use write() to send data to port                                            */

  printf("\n  %s written to tty",write_buffer);
  printf("\n  %d Bytes written to tty", bytes_written);
  printf("\n +----------------------------------+\n\n");


//usleep (1);             // sleep enough to transmit the 4 plus
                                     // receive 15:  approx 100 uS per char transmit
tcdrain(fd);                         //delay for output
        /*------------------------------- Read data from serial port -----------------------------*/

        /* Setting Time outs - Blocking for reading*/
// SerialPortSettings.c_cc[VMIN] = 10; // Read at least 10 characters 
// SerialPortSettings.c_cc[VTIME] = 0; // Wait indefinetly   

//if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) // Set the attributes to the termios structure
// printf("\n  ERROR ! in Setting attributes");
//else
// printf("\n  BaudRate = 38400 \n  StopBits = 1 \n  Parity   = none");



tcflush(fd, TCIFLUSH);   /* Discards old data in the rx buffer            */

char read_buffer[20];   /* Buffer to store the data received              */
int  bytes_read = 0;    /* Number of bytes read by the read() system call */

int licz=3;
do{

char read_buf[20];   /* Buffer to store the data received              */
int  bytes_r = 0;    /* Number of bytes read by the read() system call */


bytes_r = read(fd,&read_buf,19); /* Read the data                   */

//printf("\n  Bytes Rxed przed pt %d:", bytes_r); /* Print the number of bytes read */


for(int i=0;i<bytes_r;i++)  /*printing only the received characters*/
{
// printf("%c",read_buf[i]);
 read_buffer[i]=read_buf[i];
}
bytes_read=bytes_r;
}while(licz--);





printf("\n  Bytes Rxed za petla %d:\n  ", bytes_read); /* Print the number of bytes read */


for(int i=0;i<bytes_read;i++)  /*printing only the received characters*/
 printf("%c",read_buffer[i]);

read_buffer[bytes_read]='\0';
printf("  ");

char A[3];
A[0]=read_buffer[0];
A[1]=read_buffer[1];
A[2]='\0';
int a=(int)strtol(A,NULL,16);


printf("pierwsza =: %d\n",a);



 printf("\n +----------------------------------+\n\n\n");

 close(fd); /* Close the serial port */


}





korzystanie z libftdi

https://codeseekah.com/2012/02/22/elm327-to-rs232-in-linux/

instalacja biblioteki do kodu
sudo apt-get install libftdi libftdi-dev

sprawdzanie:
apt-cache policy libffi-dev

mozna dodac:
sudo apt-get install build-essential

dokumentacja  dla libftdi
https://www.intra2net.com/en/developer/libftdi/documentation/group__libftdi.html


kod (nie działa):

#include <stdio.h>
#include <ftdi.h>
#include <string.h>

int main(int argc, char * argv[]) {

  struct ftdi_context ftdic; /* FTDI context */
  /* line properties */
  enum ftdi_bits_type bits = BITS_8; // 8 data bits
  enum ftdi_stopbits_type sbit = STOP_BIT_1; // 1 stop bit
  enum ftdi_parity_type parity = NONE; // no parity
  enum ftdi_break_type lineend = BREAK_OFF;

  int ret;
  unsigned short modem_status = 0;
  unsigned char * tx;
  unsigned char * rx;
  int i,j; /* general purpose indices */

  if ((tx = malloc(128)) == NULL || (rx = malloc(128)) == NULL) {
    fprintf(stderr, "Error: could not allocate memory\n");
    return EXIT_FAILURE;
  }

  if (ftdi_init(&ftdic) < 0) {
    fprintf(stderr, "Error: could not initialize FTDI\n");
    return EXIT_FAILURE;
  }

  if ((ret = ftdi_usb_open(&ftdic, 0x0403, 0x6001)) < 0) {
    fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  if ((ret = ftdi_usb_reset(&ftdic)) < 0) {
    fprintf(stderr, "unable to reset ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  if ((ret = ftdi_usb_purge_buffers(&ftdic)) < 0) {
    fprintf(stderr, "unable to purge buffers on ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  if ((ret = ftdi_set_baudrate(&ftdic, 38400)) < 0) {
    fprintf(stderr, "unable to set ftdi device baud rate: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  if ((ret = ftdi_set_line_property2(&ftdic, bits, sbit, parity, lineend)) < 0) {
    fprintf(stderr, "unable to set ftdi device properties: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  ftdi_poll_modem_status(&ftdic, &modem_status);
  printf("R232 status: 0x%x\n", modem_status);

  memcpy(tx, "AT E0\r", 6); /* turn echoing off */
  if (ftdi_write_data(&ftdic, tx, sizeof(unsigned char) * 6) < 0) {
    fprintf(stderr, "unable to send ftdi device data: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  while (1) {
    j = 0;

    while ( ( ret = getchar() ) != 0x0a && j < 128) tx[j++] = ret;
    if (!j) continue;
    tx[j++] = 0x0d; /* end */
    ret = 0;
    ftdi_usb_purge_tx_buffer(&ftdic);
    ftdi_usb_purge_rx_buffer(&ftdic);
    for (i = 0; i < j; i++) {
      ret += ftdi_write_data(&ftdic, tx+i, sizeof(unsigned char) * 1);
    }

    printf("Written %d bytes of data: ", ret);
    for (i = 0; i < ret; i++) printf("0x%x ", tx[i]);

    printf("\n");

    while (1) {
      ret = ftdi_read_data(&ftdic, rx, 128);
      if (ret > 0) {
        printf("Read %d bytes of data\n", ret);
        ret -= 3; /* remove > prompt */
        printf("\tDATA: ");
        for (i = 0; i < ret; i++) printf("0x%x ",rx[i]);
        printf("\n\t(");
        for (i = 0; i < ret; i++) printf("%c",rx[i]);
        printf(")\n");
        break;
      } else if (ret < 0) {
        fprintf(stderr, "unable to read from ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
        return EXIT_FAILURE;
      }
    }
  }

  if ((ret = ftdi_usb_close(&ftdic)) < 0) {
    fprintf(stderr, "unable to close ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
    return EXIT_FAILURE;
  }

  ftdi_deinit(&ftdic);

  free(tx);
  free(rx);

  return EXIT_SUCCESS;
}

kompilowanie:
gcc -Wall -ggdb -lftdi kodelm327toRS.c -o obd