Skip to content

CANbus

STEP2에는 RS485/CAN으로 명시된 9핀 커넥터를 통해서 한 개의 CAN 포트를 사용할 수 있습니다. SERCAN이라고 불리는 serial-to-can 어댑터를 이용하며, SERCAN의 드라이버는 SocketCAN 소프트웨어로는 작동하지 않기 때문에 뉴로메카 자체 API 함수를 제공합니다.

SERCAN 유틸리티

기본적으로 STEP2에는 여러 개의 CAN 유틸리티가 설치되어 있습니다. 사용자는 다음과 같은 명령어로 설치된 유틸리티를 확인할 수 있습니다.

1
$ ls -l /usr/bin/*SERCAN*


STEP의 CAN 유틸리티

1. SERCAN_setBitrate

SERCAN Module의 비트레이트를 설정하는 툴로써 현재의 비트레이트을 읽거나 새로운 비트레이트을 설정하는 데 사용할 수 있습니다. 아래 터미널 입력을 통해 현재 Module의 비트레이트을 읽을 수 있습니다.

1
$ sudo SERCAN_setBitrate

SERCAN Module의 기본 비트레이트는 1000000 bps (1Mbps)이며 새로운 비트레이트를 다음과 같은 방법으로 설정할 수 있습니다.

1
$ sudo SERCAN_setBitrate 500K


새로운 CAN 비트 속도 업데이트

파라미터가 유효하고 현재 비트레이트 값이 아닌 경우 그림과 같이 업데이트되어 출력됩니다. 유효한 비트레이트 파라미터에는 "1M, 500K, 250K, 125K, 50K, 20K, 10K, 5K" 가 있습니다.

2. SERCAN_send

단일 CAN 프레임을 SERCAN 포트를 통해 전송하는 데 사용할 수 있는 CAN 송신 툴입니다.

아래 명령어는 ID가 123(십진수)이고 데이터가 5바이트(0x01, 0x23, 0x45, 0x67, 0x89)인 CAN 프레임을 SERCAN 포트를 통해 전송합니다 (한 CAN 프레임의 최대 바이트 수는 8바이트라는 점에 유의하십시오).

1
$ SERCAN_send sercan0 123#0123456789

3. SERCAN_dump

SERCAN_dump는 CAN 수신 도구로써 SERCAN 포트에 데이터가 들어오기를 기다렸다가 터미널로 출력합니다.

1
$ SERCAN_dump sercan0


SERCAN_dump를 사용하여 SERCAN 포트에서 CAN 프레임 읽기

4. RTSERCAN_send, RTSERCAN_dump

RTSERCAN_send와 RTSERCAN_dump는 실시간 드라이버를 사용하는 경우 사용되며 SERCAN_send, SERCAN_dump 와 동일한 기능을 가지고 있습니다.

SERCAN API

SERCAN API는 SERCAN Module을 프로그래밍하고 제어하는데 사용됩니다. SERCAN API의 함수 프로토타입은 neuromeka/NRMKFoundation/helper/include/hw/ 의 NRMKsercan.h 파일에서 찾을 수 있습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
//bit rate
int SERCAN_SetBitRate(int fd, char *strBitrate);
int32_t SERCAN_GetBitRate(int fd, uint32_t timeOut /* in ms */);

//normal driver
int  SERCAN_open(void);
int  SERCAN_write(int fd, CAN_FRAME TxFrame);
int  SERCAN_read(int fd, CAN_FRAME *lpRxFrame);
void print_CANFrame(CAN_FRAME Rx_Frame);
//----------------------------------------

//rt driver
int  RTSERCAN_open(void);
int  RTSERCAN_write(int fd, CAN_FRAME TxFrame);
int  RTSERCAN_read(int fd, CAN_FRAME *lpRxFrame);
void rt_print_CANFrame(CAN_FRAME Rx_Frame);

SERCAN API는 비트레이트 설정, 일반 CAN 드라이버, 실시간 CAN 드라이버 세 그룹으로 나뉩니다.

Bit rate 설정 함수

SERCAN Module의 비트레이트을 얻거나 설정하기 위해 사용됩니다.

  • SERCAN_SetBitRate(int fd, char *strBitrate)

    SERCAN Module의 비트레이트을 업데이트합니다. fd는 이전에 오픈한 SERCAN 기기의 핸들러 (파일 서술자)이며, strBitrate는 문자열 형식의 비트레이트 값 (1M, 500K, 250K, 125K, 50K, 20K, 10K, 5K)입니다.

  • SERCAN_GetBitRate(int fd, uint32_t timeOut)

    현재 비트레이트을 획득합니다.

일반 CAN 드라이버 함수

일반 CAN 드라이버 함수는 Linux 드라이버를 사용하여 SERCAN Module을 제어하며, POSIX 응용 프로그램에서 사용할 것을 권장합니다.

  • SERCAN_open(void)

    SERCAN 장치를 열고 나중에 사용할 수 있도록 Holder를 반환합니다. 음수 또는 0의 리턴 핸들러는 유효하지 않은 핸들러입니다.

  • SERCAN_write(int fd, CAN_FRAME TxFrame)

    CAN 프레임을 SERCAN 포트에 씁니다. fd는 SERCAN_open 함수에서 얻은 SERCAN 핸들러, 0이 아닌 리턴 값은 쓰기 작업이 실패했음을 나타냅니다.

  • SERCAN_read(int fd, CAN_FRAME *lpRxFrame)

    CAN 프레임을 SERCAN 포트에서 읽습니다. 결과는 lpRxFrame 포인터로 저장되며, 0이 아닌 반환 값은 읽기 작업이 실패했음을 나타냅니다.

Real-time CAN 드라이버 함수

RT CAN 드라이버의 모든 함수는 일반 드라이버와 동일한 함수를 가지고 있습니다. 차이점은 Xenomai rtdm 드라이버를 사용하여 구현되므로 실시간 애플리케이션에서 사용하기에 적합하다는 것입니다.


SERCAN 예제

STEP의 설치 패키지에는 SERCAN Module을 제어하는 sercan_testrtsercan_test 의 두 가지 예제가 있습니다. 각 예제는 동일한 작동 원리를 가지고 작동하지만 다른 SERCAN 드라이버를 사용합니다. sercan_test 는 일반 CAN 드라이버를 사용하는 반면 rtsercan_test 는 실시간 CAN 드라이버를 사용합니다. 본 장에서는 sercan_test 예제를 살펴보도록 하겠습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include "NRMKsercan_tp.h"
#include "NRMKhw_tp.h"

int sercan_fd  = -1;
void * write_thread(void* arg);
void * read_thread(void* arg);

void catch_signal(int sig)
{
    if (sercan_fd>0)
    {
        close(sercan_fd);
    }
    exit(1);
}
//writing thread
void * write_thread(void* arg)
{
    int i;
    CAN_FRAME cfame;
    cfame.can_id=0;
    cfame.can_dlc=8;
    for (i=0; i<8; ++i) cfame.data[i]=0;
    cfame.can_id=0x080;
    cfame.can_dlc=0;

    while(1)
    {
        SERCAN_write(sercan_fd, cfame);
        usleep(1e6); //delay 1s
    }
}
//reading thread
void * read_thread(void* arg)
{
    CAN_FRAME RxFrame;
    while(1)
    {
        if (SERCAN_read(sercan_fd, &RxFrame)==0)
        {
            print_CANFrame(RxFrame);
        }
        usleep(1e4);
    }
}
int main(int argc, char* argv[])
{
    signal(SIGTERM, catch_signal);
    signal(SIGINT, catch_signal);

    // open sercan*******************
    sercan_fd=SERCAN_open();
    if (sercan_fd <= 0) return 1;
    //********************************
    usleep(1e5);

    pthread_t tid1,tid2;
    pthread_create(&tid1, NULL, read_thread, NULL);
    pthread_create(&tid2, NULL, write_thread, NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    return 0;
}

sercan_test 예제의 구조는 tpserial example 예제와 상당히 유사합니다.

  • 메인 함수에서 SERCAN_open() 로 SERCAN 포트를 개방 (line 56)

  • 쓰기 및 읽기 CAN 프레임을 처리하기 위해 두 개의 스레드를 생성

  • write_thread 는 매 1초마다 SERCAN 포트에 반복적으로 기록되는 CAN 프레임 (line 21 - 36 까지).

  • read_thread 의 SERCAN 포트는 10ms마다 수신 데이터를 확인 (line 38 - 49). CAN 프레임이 수신되면 화면에 출력