Skip to content

Mobile Platform Sensing CAN

dazory edited this page Jul 1, 2021 · 6 revisions

Prerequisite

  1. SocketCAN : CAN 센서 데이터를 처리하기 위한 라이브러리
  2. DBC파일 : raw CAN bus data를 physical value로 디코딩하기 위한 정보

SocketCAN 사용법

Example C SocketCAN Code를 참고하여 코드를 작성할 수 있다. 해당 링크를 통해 <소켓에 연결하는 방법>, <CAN frame의 구조>, <Reading&Storing> 방법을 참고할 수 있다. 만일 CAN sensor없이 테스트를 하고싶다면 을 사용하면 된다. 해당 내용 역시 위 링크에서 참고할 수 있다.

craigpeacock/CAN-Examples은 간단한 CAN data를 주고받는 프로그램 코드를 포함한다.


DBC파일 분석하는 방법

1. DBC2TXT
먼저 DBC파일을 파싱하여 읽을 수 있는 text형태로 바꿔주는 과정이 필요하다. downtimes/can-dbcparser을 설치하여 DBC파일을 text형태로 바꿀 수 있다.

해당 코드를 수정하여 분석하기 쉽게 만든 코드를 diva2/test/can_dbcparser에서 확인할 수 있다.

2. Decoding
DBC파일을 파싱하여 읽을 수 있는 text형태로 바꿔주었다면 CAN DBC File Explained - A Simple Intro [+Editor Playground]을 참고하여 DBC파일 physical value로 해석할 수 있다. 예를 들어, Handle Angle을 해석하는 방법은 아래와 같다.

아래와 같이 DBC파일을 text형태로 파싱한 결과에서 "SAS_Angle(Name)" 중 "SAS"는 Speed Assistant System(속도 어시스턴트 시스템)을 의미한다. 이를 통해 해당 데이터가 차량의 핸들 각도 정보를 담고있음을 예상할 수 있다.

BO_ 688 SAS1: 8 XXX
    SG_ SAS_Angle : 0|16@1+ (0.1,0) [-3276.8|3276.7] "Deg" XXX
    SG_ SAS_Speed : 16|8@1+ (4,0) [0|1016] "" XXX
    SG_ SAS_Stat : 24|8@1+ (1,0) [0|255] "" XXX
    SG_ MsgCount : 32|4@1+ (1,0) [0|15] "" XXX
    SG_ CheckSum : 36|4@1+ (1,0) [0|15] "" XXX

위 정보를 보기 쉽게 정리한 결과는 아래와 같다.

Message Syntax		: BO_
CAN ID (3+29bit)	: 688
NAME			: SAS1
Length(#Data Bytes)	: 8
Sender			: XXX
/
Signal syntax		: SG_
Name			: SAS_Angle
Bit start | length	: 0|16
Little endian(unsigned)	: @1+
(scale, offset)		: (0.1, 0)
[min | max]		: [-3276.8 | 3276.7]
"unit"			: "Deg"
Receiver		: XXX

위 정보를 통해 CAN ID=688일 때, 0비트부터 16비트만큼은 핸들 각도를 의미하며 scale값(=0.1)과 offset(=0)을 이용하여 physical value를 계산할 수 있다.

** 3. Simple Example **
CAN sensor로부터 데이터를 읽어서 핸들 각도 정보를 physical value로 변환하는 가장 단순한 예제 코드는 다음과 같다.

// [Read 255bytes from CAN]
int nbytes;
nbytes = read(s, &frame, sizeof(struct can_frame));

// [Extract a CAN_ID from the frame]
int fid = frame.can_id;
switch (fid)
{
case 688: // HANDLE_ANGLE = 688
{
   // [The information by DBC]
   int bit_start = 0;
   int bit_length = 16;
   float scale = 0.1;
   float offset = 0;

   // [Extract a data from the frame]
   char data[frame.can_dlc];
   for (int i = 0; i < frame.can_dlc; i++)
   {
      data[i] = frame.data[i];
      printf("%02X ", data[i]);
   }

   // [decoding from raw CAN bus data to physical value]
   int dec = fromBytesToDec(data, bit_start, bit_length);
   handleAngle = offset + scale * (float)dec;
   printf("Handle Angle=%fDeg\n", offset + scale * (float)dec);
   }
}