레이블이 can인 게시물을 표시합니다. 모든 게시물 표시
레이블이 can인 게시물을 표시합니다. 모든 게시물 표시

2019년 6월 14일 금요일

ESP32에서 CAN bus 사용하기

CAN버스는 Controller Area Network를 말하는데 이 프로토콜은 주로 자동차에서 널리 이용되고 있다. CAN에 대해 더 자세히 알고 싶으면 다음의 링크들을 참고하면 된다.

- http://www.ni.com/white-paper/2732/en
- http://www.ti.com/lit/an/sloa101b/sloa101b.pdf

ESP32는 CAN 인터페이스를 지원하기 때문에 CAN bus를 쉽게 사용할 수 있다.
이 데모에서는 2개의 ESP32 모듈을 사용해, 첫번째 모듈은 'hellocan' 이라는 메시지를 보내고 두번째 모듈은 받은 메시지의 문자열을 전부 대문자로 바꿔 첫번째 모듈로 돌려보낸다. 그러면 첫번째 모듈은 받은 메시지를 터미널로 출력하게 된다.

ESP32는 CAN controller만을 내장하고 있기 때문에 CAN 버스를 사용하려면 CAN transceiver가 필요하다. 아래 사진의 CAN transceiver를 2개 사용했다.

* aliexpress에서 개당 약 $1 정도로 구입할 수 있다.

ESP32와 CAN transceiver 모듈의 연결은 다음과 같이 해 주면 된다.


CAN library로는 Thomas Barth가 만든 CAN driver를 사용했다.

https://github.com/ThomasBarth/ESP32-CAN-Driver/tree/master/components/can

라이브러리를 다운받아 설치해주면 된다.

첫번째 ESP32 (위의 그림에서 ESP32 (1)에 해당)에는 아래와 같은 코드를 넣어준다.

#include <ESP32CAN.h>
#include <CAN_config.h>

/* the variable name CAN_cfg is fixed, do not change */
CAN_device_t CAN_cfg;

void setup() {
    Serial.begin(115200);
    Serial.println("iotsharing.com CAN demo");
    /* set CAN pins and baudrate */
    CAN_cfg.speed=CAN_SPEED_1000KBPS;
    CAN_cfg.tx_pin_id = GPIO_NUM_5;
    CAN_cfg.rx_pin_id = GPIO_NUM_4;
    /* create a queue for CAN receiving */
    CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t));
    //initialize CAN Module
    ESP32Can.CANInit();
}

void loop() {
    CAN_frame_t rx_frame;
    //receive next CAN frame from queue
    if(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE){

      //do stuff!
      if(rx_frame.FIR.B.FF==CAN_frame_std)
        printf("New standard frame");
      else
        printf("New extended frame");

      if(rx_frame.FIR.B.RTR==CAN_RTR)
        printf(" RTR from 0x%08x, DLC %d\r\n",rx_frame.MsgID,  rx_frame.FIR.B.DLC);
      else{
        printf(" from 0x%08x, DLC %d\n",rx_frame.MsgID,  rx_frame.FIR.B.DLC);
        /* convert to upper case and respond to sender */
        for(int i = 0; i < 8; i++){
          if(rx_frame.data.u8[i] >= 'a' && rx_frame.data.u8[i] <= 'z'){
            rx_frame.data.u8[i] = rx_frame.data.u8[i] - 32;
          }
        }
      }
      //respond to sender
      ESP32Can.CANWriteFrame(&rx_frame);
    }
}

두번째 ESP32 (위의 그림에서 ESP32 (2)에 해당)에는 아래와 같은 코드를 넣어준다.

#include <ESP32CAN.h>
#include <CAN_config.h>

/* the variable name CAN_cfg is fixed, do not change */
CAN_device_t CAN_cfg;

void setup() {
    Serial.begin(115200);
    Serial.println("iotsharing.com CAN demo");
    /* set CAN pins and baudrate */
    CAN_cfg.speed=CAN_SPEED_1000KBPS;
    CAN_cfg.tx_pin_id = GPIO_NUM_5;
    CAN_cfg.rx_pin_id = GPIO_NUM_4;
    /* create a queue for CAN receiving */
    CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t));
    //initialize CAN Module
    ESP32Can.CANInit();
}

void loop() {
    CAN_frame_t rx_frame;
    //receive next CAN frame from queue
    if(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE){

      //do stuff!
      if(rx_frame.FIR.B.FF==CAN_frame_std)
        printf("New standard frame");
      else
        printf("New extended frame");

      if(rx_frame.FIR.B.RTR==CAN_RTR)
        printf(" RTR from 0x%08x, DLC %d\r\n",rx_frame.MsgID,  rx_frame.FIR.B.DLC);
      else{
        printf(" from 0x%08x, DLC %d\n",rx_frame.MsgID,  rx_frame.FIR.B.DLC);
        for(int i = 0; i < 8; i++){
          printf("%c\t", (char)rx_frame.data.u8[i]);
        }
        printf("\n");
      }
    }
    else
    {
      rx_frame.FIR.B.FF = CAN_frame_std;
      rx_frame.MsgID = 1;
      rx_frame.FIR.B.DLC = 8;
      rx_frame.data.u8[0] = 'h';
      rx_frame.data.u8[1] = 'e';
      rx_frame.data.u8[2] = 'l';
      rx_frame.data.u8[3] = 'l';
      rx_frame.data.u8[4] = 'o';
      rx_frame.data.u8[5] = 'c';
      rx_frame.data.u8[6] = 'a';
      rx_frame.data.u8[7] = 'n';

      
      ESP32Can.CANWriteFrame(&rx_frame);
    }
}

양쪽의 보드를 동작시키고 첫번째 ESP32의 시리얼 터미널의 출력은 다음과 같다.




* Original credit goes to http://www.iotsharing.com/2017/09/how-to-use-arduino-esp32-can-interface.html



2010년 3월 7일 일요일

DIAMEX DXM 명령어 목록

DIAMEX DXM module은 시리얼 포트를 통해 PC와 통신을 하고 AT명령어 셋을 사용하기 때문에 이미 나와있는 대다수의 OBD-II 소프트웨어와 호환된다. 지원하는 AT명령어 목록은 다음과 같다.
--

DIAMEX DXM command list

COMMAND

Explanation

ATZ

Reboot the controller

ATWS

Same as ATZ but faster

ATI

Identification text is reported

ATD

All parameters are stored in the ground state as after a cold or warm state

ATE0/1

Toggle the serial echo on/off

ATL0/1

Toggle the transmission of the linefeed(L/F)

ATM0/1

Toggle the memory function of the final protocol

ATH0/1

Toggle if the OBD2 header answers and checksum byte shall be displayed

ATBD

Causes the display of the OBD2 receive buffer

ATB

Display of the OBD2 reception buffer

ATSRxx

Input of the RX ECU OBD2 filter address for OBD2 responses

ATN

Display of the current protocol used as HEX value F0..F9

  • F0 – no active protocol  

  • F1 – PWM protocl 

  • F2 – VPWM protocol 

  • F3 – ISO9141 protocol 

  • F4 – KWP2000 protocol 

  • F5 – KWP2000 protocol 

  • F6 – CAN 11-bit ID, 500 kBaud 

  • F7 – CAN 29-bit ID, 500 kBaud 

  • F8 – CAN 11-bit ID, 250 kBaud 

  • F9 – CAN 29-bit ID, 250 kBaud 

ATDP

Display of the currently used protocol in plaintext

  • NOT CONNECTED 

  • SAE J1850/PWM 

  • SAE J1850/VPWM 

  • ISO9141-2 

  • ISO14230-4, KWP2000 (5 BAUD Init) 

  • ISO14230-4, KWP2000 (Fast Init) 

  • ISO15765-4, CAN(11/500) 

  • ISO15765-4, CAN(29/500) 

  • ISO15765-4, CAN(11/250) 

  • ISO15765-4, CAN(29/250) 

ATK

Display the current keywords on ISO9141 and KWP2000

ATKW0/1,

For a slow, init keywords are distinguished between protocol 3 (ISO9141) and protocol 4 (KWP2000). This automatic detection can be disabled with ATKW0

ATP[A]x

Manual setting of the current protocol or the automatic protocol search

  • ATP1 – PWM 

  • ATP2 – VPWM 

  • APT3 – ISO9141-2 

  • ATP4 – KWP2000 5 BAUD Init 

  • ATP5 – KWP2000 Fast Init 

  • ATP6 – CAN 11/500 

  • ATP7 – CAN 29/500 

  • ATP8 – CAN 11/250 

  • ATP9 – CAN 29/250 

ATV

Overview of all the modifiable parameters of the DXM1 are displayed

ATSBx

Set baud rate of serial interface

  • ATSB0 – 9600 Baud (Standard) 

  • ATSB1 – 19200 Baud 

  • ATSB2 – 38400 Baud 

  • ATSB3 – 57600 Baud 

  • ATSB4 – 115200 Baud 

  • ATSB5 – 125000 Baud 

  • ATSB6 – 250000 Baud 

ATSHxxyyzz

Manual setting of the header bytes for ISO9141, KWP2000, PWM and VPWM protocol

  • xx = priority/type-byte 

  • yy = target-address 

  • zz = source-address 

ATWMxxyyzzaa[bb][cc]

Manual setting of the wakeup message bytes for ISO9141 and KWP2000

  • xx = priority/type-byte (with length indication in KWP) 

  • yy = target-address 

  • zz = source-address 

  • aa, bb, cc = command bytes 1~3 

ATSWxx

The length of time between automatic wakeup commands in existing ISO9141 and KWP2000 can be set

ATCA0/1

The automatic formatting of the transmitted and received CAN data can be switched on/off

ATCC0/1

Multi-frame answers have to be sent flow control messages from the tester, which indicate the controller, that following packages have to be accepted

ATCDxx

Flow control data packages which has to be sent in multi frame responses, contain beside the status byte (FS), a block size byte (BS) and also a byte for the duration (ST), which have to be added between the following response packages

ATCIxxx/xxxxxxxx

CAN-ID which has to be sent, is set with this command

  • 11-bit ID – 7DF (default) 

  • 29-bit ID – 18 DD 33 F1 (default) 

ATCFxxx/xxxxxxxx

Set CAN RX-filter

  • 11-bit ID – 7E8 (default) 

  • 29-bit ID – 18 DA F1 00 (default) 

ATCMxxx/xxxxxxxx

Set CAN RX-mask

  • 11-bit ID – 7F8 (default) 

  • 29-bit ID – 1F FF FF 00 (default) 

AT!00

Output of the serial number of the DXM controller

AT!01

Output of the controller type and the BIOS version number

AT!10

Mesaurement of 12-volt vehicle power