제가 해본 것이 CAN 뿐이라, CAN 통신으로 한정해서 이야기를 해보겠습니다.
우선 한가지 짚고 넘어갈 사실.
CAN과 OBD-II 의 관계(?)라고나 할까... 처음 study 할때 나역시 무척 삽질했던 내용입니다.
OBD-II는 차량 배기가스 등을 진단하기 위한 약속이고, CAN은 이 진단을 위한 통신규약의 하나일 뿐입니다.
다시 말해, OBD-II를 구현하기 위해 CAN 통신을 이용하는 것일 뿐, 비교대상이 아니라는 말이죠.
저또한 처음에 저 둘을 비교대상으로 잘못 알고 접근했다가 엄청 헤맸었던 기억이 있습니다.
소프트웨어를 개발하는데 C언어나 베이직, 혹은 어셈블리 등 어떤 언어를 사용할지 선택은 프로그래머의 몫이듯, OBD-II를 구현함에 있어 CAN을 사용할건지, PWM이나 ISO방식을 사용할건지는 선택의 문제입니다.
단, 미국에서 의무적으로 CAN을 사용하도록 법령이 바뀐 상태고, 그 영향으로 전세계적으로 CAN이 의무화될 것 같은 분위기인 것은 확실합니다.
CAN 통신 프로토콜을 보면 ID가 있습니다. CAN 통신에서의 ID는 통신의 최종 목적지일 뿐만 아니라, 우선순위 중재 또한 ID를 통해 이루어지기 굉장히 중요합니다.
그런데 OBD-II 스펙을 보면 PID라는게 있습니다. 이것도 일종의 ID인데, CAN의 ID와 OBD-II의 PID간의 관계를 규명하느라 머리 빠지는 줄 알았네요.
CAN 프로토콜에는 ID와 Data field가 있습니다.(물론 다른것도 많지만)
OBD-II의 PID는 그 자체가 차량 진단에 관련되는 내용으로 CAN 프로토콜의 Data field에 OBD-II의 PID가 들어가게 됩니다.
(이거 나혼자만 고민한 건가???)
자 그럼 본론으로 돌아와서,
OBD-II로 무엇을 할 수 있을까요? 사실 OBD 라는 명칭에 이미 그 답이 들어있습니다.
바로 차량의 고장 진단입니다.
인터넷으로 OBD-II 관련 자료를 검색해 보면 아마도 95% 이상은 차량 스캐너에 관한 내용이 검색될 겁니다.
그럼 두 번째 질문. 어떻게?
차량에 고장이 발생하면 MIL(Mal-function Indicator Lamp)이라는 램프에 불이 들어오게 되고, OBD-II 스캐너로 어느 부위에서 고장이 발생했는지 알 수 있습니다.
이 때 사용되는 DTC(Diagnostics Trouble Codes)라는 진단 코드가 있습니다.
차량 제조사마다 내용이 상이해서(물론 공통되는 부분은 있다) 분량이 방대한데, 인터넷 검색해보면 자료는 쉽게 구할수 있을 것입니다.
참조. PID/DTC list
CAN 통신을 통해 OBD-II를 구현하려면 당연한 말이지만 CAN 통신이 먼저 구현되어야 합니다.
CAN은 multi master network이며 CSMA/CD(Carrier Sense Multiple Access/Collision Detection) +
AMP(Arbitration on Message Priority)방식을 사용합니다.
CSMA/CD 는 LAN에서도 사용하는 방식이며, AMP는 충동 발생시 우선 순위에 의해 중재한다는 뜻입니다.
CAN에서 ID가 곧 우선순위이므로 결국은 충돌 발생시 ID에 의해 중재된다고 볼 수 있습니다.
CAN 통신을 위해서는 기본적으로 MicroController와 CAN tranceiver가 필요합니다.
CAN tranceiver를 직접 구현할 수도 있겠지만, 위에서 말한 SCMA/CD + AMP를 직접 구현해야 하는 일인데,
왠만하면 그냥 포기하고 전용 chip 쓰기를 권합니다.
CAN chip으로 대표적인 것이 Atmel사의 AT90CAN128 입니다.
MCU와 tranceiver가 합쳐진 chip인데, 시중에서 쉽게 구할 수 있고 관련 자료들도 인터넷에 널려 있으니 개인적인 목적으로 사용할 분들에게 추천하는 chip입니다.
단점은 좀 비싸다는 건데, 경험상 CAN 개발은 돈이 투자되는 만큼 시간이 절약되더라는 ...
그 외에도 많이 쓰는 칩으로는 CAN뿐만 아니라 PWM, ISO등 모든 통신이 지원되는 ELM327이 있는데, 이놈도 역시 비쌉니다.
우리 회사에서는 이런 비싼 chip을 쓸 수 없어 선택한 것이 Renesas사의 R8C34E.
이놈도 tranceiver가 내장되어 있는데 가격도 쌉니다.
그 대신, ROM 32K/RAM 2.5K 정도로 메모리가 아주 작죠.
사실 Chip만 괜찮은 걸 고르면 CAN 통신 자체는 별거 아닙니다.
레지스터 몇개 세팅해 주면 대부분 통신은 뚫리는데, 중요한 건 Baud rate 입니다.
해당 차량에서 사용하는 Baud rate를 스캔해야 되는데 이게 skill이라면 skill입니다.
(대부분은 125K/250K/500K/1M 넷 중에서 하나는 맞을텐데 아닌 경우도 있을 수 있으니...)
자, 이제 CAN 통신은 뚫렸으니 우리의 원래 목적인 OBD-II로 돌아가 보겠습니다..
OBD-II 통신의 기본은 Request and Response 입니다.
무슨 말인고 하면, 내가 원하는 데이터를 요청하면 그에 대한 응답이 나한테 온다는 것이죠.
그런데 문제가 있네요. CAN으로 데이터를 요청하려면 ID를 알아야 하는데, 어떻게 알지?
위키백과를 찾아보니 이런 내용이 있습니다.
The PID query is sent to the vehicle on the CAN bus at ID 7DFh, using 8 data bytes.
(Part1에 첨부한 PID 자료의 제일 뒷부분에 나옵니다.)
ID 0x7DF로 요청을 보내면 ID 0x7E8 또는 0x7E9로 응답이 옵니다.
필터설정을 통해 위 ID들만 받아들이도록 해놓으면 나머지 ID들은 자동으로 무시하게 됩니다.
또 한가지 문제가 있습니다.
11bit ID일 경우에 대해서는 Request/Response ID가 나와 있는데, 29bit일 경우에는 어떡하나???
고민하던중 ECU Simulator와 CAN Analyser를 구매하게 됐는데, 이걸 쓰니 간단하게 해결이 되네요.
Request는 0x18DAF110, Response는 0x18DB33F1 입니다.
(돈을 투자하는 만큼 시간이 절약된다는 말을 이래서 한 것입니다).
Tool 소개는 나중에 따로 할 기회가 있을테니 생략하도록 합니다.
예를 들어서 RPM을 구하고 싶으면
Request
0x02 0x01 0x0C 0x00 0x00 0x00 0x00 0x00 (total 8 byte)을 Data frame에 넣어서 네트웤으로 쏴주면 됩니다.
첫번째 바이트는 첫 바이트를 제외한 유효 데이터의 바이트 수를 의미합니다.
Request의 경우는 Mode와 PID만 있으면 되므로 거의 0x02로 고정이라고 보면 됩니다. ("항상"은 아니고 "거의" 입니다.)
Response
0x05 0x41 0x0C 0x0A 0x03 0x00 0x00 0x00
첫번째 바이트는 역시 유효 데이터의 바이트 수를 의미합니다.
두번째 바이트는 Mode인데, Request에서 6번(7번째) 비트를 1로 만들어 주면 됩니다.
Request의 Mode가 0x01이었으므로 Response는 0x41이 된다.
PID는 0x0C로 같고, 이후의 두 바이트가 원하는 값이다. 해석은 Part 1에 첨부해 놓은 PID 문서 참조.
RPM의 경우는 (A*256+B)/4 이므로 이 경우에는 (10*256+3)/4 = 640.75 가 되죠.
참고로 문서의 Formula 필드에서 대문자 A,B,C 등은 데이터 바이트의 순서를 나타냅니다.

OBD-II 커넥터는 그림과 같은 핀 배열을 갖고 있습니다.
앞서 OBD-II를 위한 통신 방식이 크게 세가지가 있다고 했는데,
통신 방식에 상관없이 커넥터는 모두 동일합니다. 물론 사용하는 핀은 다르죠.
1. NC (-로 표시)
2. 버스의 양극(+) 라인 (SAE-J1850)
3. NC
4. 배터리 접지 (차대접지, 섀시 접지)
5. 신호접지
6. CAN_H (ISO 15765-4 , SAE-J2234)
7. K 시그널 라인 (ISO 9141-2, ISO 14230-4)
8. NC
9. NC
10. 버스의 음극 라인 (SAE-J1850)
11. NC
12. NC
13. NC
14. CAN_L (ISO 15765-4 , SAE-J2234)
15. L 시그널 라인 (ISO 9141-2, ISO 14230-4)
16. 배터리 양극
16번 배터리 양극과 4번 접지는 공통이며 통신방식에 따라 각 두개씩을 사용하게 됩니다.
CAN 통신의 경우는 6번 CAN_H와 14번 CAN_L를 사용합니다.
참고로, 차량내에서 OBD-II 커넥터의 위치는 제조사마다 약간 다른데 보통 운전석 아래나 기어박스 근처에 있습니다. (현대차는 대부분 운전석 아래)
이 커넥터의 위치 또한 표준에 규정되어 있기 때문에 운전석에 앉아서 손이 닿을 수 있는 위치에 있어야 합니다.
우선 한가지 짚고 넘어갈 사실.
CAN과 OBD-II 의 관계(?)라고나 할까... 처음 study 할때 나역시 무척 삽질했던 내용입니다.
OBD-II는 차량 배기가스 등을 진단하기 위한 약속이고, CAN은 이 진단을 위한 통신규약의 하나일 뿐입니다.
다시 말해, OBD-II를 구현하기 위해 CAN 통신을 이용하는 것일 뿐, 비교대상이 아니라는 말이죠.
저또한 처음에 저 둘을 비교대상으로 잘못 알고 접근했다가 엄청 헤맸었던 기억이 있습니다.
소프트웨어를 개발하는데 C언어나 베이직, 혹은 어셈블리 등 어떤 언어를 사용할지 선택은 프로그래머의 몫이듯, OBD-II를 구현함에 있어 CAN을 사용할건지, PWM이나 ISO방식을 사용할건지는 선택의 문제입니다.
단, 미국에서 의무적으로 CAN을 사용하도록 법령이 바뀐 상태고, 그 영향으로 전세계적으로 CAN이 의무화될 것 같은 분위기인 것은 확실합니다.
CAN 통신 프로토콜을 보면 ID가 있습니다. CAN 통신에서의 ID는 통신의 최종 목적지일 뿐만 아니라, 우선순위 중재 또한 ID를 통해 이루어지기 굉장히 중요합니다.
그런데 OBD-II 스펙을 보면 PID라는게 있습니다. 이것도 일종의 ID인데, CAN의 ID와 OBD-II의 PID간의 관계를 규명하느라 머리 빠지는 줄 알았네요.
CAN 프로토콜에는 ID와 Data field가 있습니다.(물론 다른것도 많지만)
OBD-II의 PID는 그 자체가 차량 진단에 관련되는 내용으로 CAN 프로토콜의 Data field에 OBD-II의 PID가 들어가게 됩니다.
(이거 나혼자만 고민한 건가???)
자 그럼 본론으로 돌아와서,
OBD-II로 무엇을 할 수 있을까요? 사실 OBD 라는 명칭에 이미 그 답이 들어있습니다.
바로 차량의 고장 진단입니다.
인터넷으로 OBD-II 관련 자료를 검색해 보면 아마도 95% 이상은 차량 스캐너에 관한 내용이 검색될 겁니다.
그럼 두 번째 질문. 어떻게?
차량에 고장이 발생하면 MIL(Mal-function Indicator Lamp)이라는 램프에 불이 들어오게 되고, OBD-II 스캐너로 어느 부위에서 고장이 발생했는지 알 수 있습니다.
이 때 사용되는 DTC(Diagnostics Trouble Codes)라는 진단 코드가 있습니다.
차량 제조사마다 내용이 상이해서(물론 공통되는 부분은 있다) 분량이 방대한데, 인터넷 검색해보면 자료는 쉽게 구할수 있을 것입니다.
참조. PID/DTC list
CAN 통신을 통해 OBD-II를 구현하려면 당연한 말이지만 CAN 통신이 먼저 구현되어야 합니다.
CAN은 multi master network이며 CSMA/CD(Carrier Sense Multiple Access/Collision Detection) +
AMP(Arbitration on Message Priority)방식을 사용합니다.
CSMA/CD 는 LAN에서도 사용하는 방식이며, AMP는 충동 발생시 우선 순위에 의해 중재한다는 뜻입니다.
CAN에서 ID가 곧 우선순위이므로 결국은 충돌 발생시 ID에 의해 중재된다고 볼 수 있습니다.
CAN 통신을 위해서는 기본적으로 MicroController와 CAN tranceiver가 필요합니다.
CAN tranceiver를 직접 구현할 수도 있겠지만, 위에서 말한 SCMA/CD + AMP를 직접 구현해야 하는 일인데,
왠만하면 그냥 포기하고 전용 chip 쓰기를 권합니다.
CAN chip으로 대표적인 것이 Atmel사의 AT90CAN128 입니다.
MCU와 tranceiver가 합쳐진 chip인데, 시중에서 쉽게 구할 수 있고 관련 자료들도 인터넷에 널려 있으니 개인적인 목적으로 사용할 분들에게 추천하는 chip입니다.
단점은 좀 비싸다는 건데, 경험상 CAN 개발은 돈이 투자되는 만큼 시간이 절약되더라는 ...
그 외에도 많이 쓰는 칩으로는 CAN뿐만 아니라 PWM, ISO등 모든 통신이 지원되는 ELM327이 있는데, 이놈도 역시 비쌉니다.
우리 회사에서는 이런 비싼 chip을 쓸 수 없어 선택한 것이 Renesas사의 R8C34E.
이놈도 tranceiver가 내장되어 있는데 가격도 쌉니다.
그 대신, ROM 32K/RAM 2.5K 정도로 메모리가 아주 작죠.
사실 Chip만 괜찮은 걸 고르면 CAN 통신 자체는 별거 아닙니다.
레지스터 몇개 세팅해 주면 대부분 통신은 뚫리는데, 중요한 건 Baud rate 입니다.
해당 차량에서 사용하는 Baud rate를 스캔해야 되는데 이게 skill이라면 skill입니다.
(대부분은 125K/250K/500K/1M 넷 중에서 하나는 맞을텐데 아닌 경우도 있을 수 있으니...)
자, 이제 CAN 통신은 뚫렸으니 우리의 원래 목적인 OBD-II로 돌아가 보겠습니다..
OBD-II 통신의 기본은 Request and Response 입니다.
무슨 말인고 하면, 내가 원하는 데이터를 요청하면 그에 대한 응답이 나한테 온다는 것이죠.
그런데 문제가 있네요. CAN으로 데이터를 요청하려면 ID를 알아야 하는데, 어떻게 알지?
위키백과를 찾아보니 이런 내용이 있습니다.
The PID query is sent to the vehicle on the CAN bus at ID 7DFh, using 8 data bytes.
(Part1에 첨부한 PID 자료의 제일 뒷부분에 나옵니다.)
ID 0x7DF로 요청을 보내면 ID 0x7E8 또는 0x7E9로 응답이 옵니다.
필터설정을 통해 위 ID들만 받아들이도록 해놓으면 나머지 ID들은 자동으로 무시하게 됩니다.
또 한가지 문제가 있습니다.
11bit ID일 경우에 대해서는 Request/Response ID가 나와 있는데, 29bit일 경우에는 어떡하나???
고민하던중 ECU Simulator와 CAN Analyser를 구매하게 됐는데, 이걸 쓰니 간단하게 해결이 되네요.
Request는 0x18DAF110, Response는 0x18DB33F1 입니다.
(돈을 투자하는 만큼 시간이 절약된다는 말을 이래서 한 것입니다).
Tool 소개는 나중에 따로 할 기회가 있을테니 생략하도록 합니다.
예를 들어서 RPM을 구하고 싶으면
Request
0x02 0x01 0x0C 0x00 0x00 0x00 0x00 0x00 (total 8 byte)을 Data frame에 넣어서 네트웤으로 쏴주면 됩니다.
첫번째 바이트는 첫 바이트를 제외한 유효 데이터의 바이트 수를 의미합니다.
Request의 경우는 Mode와 PID만 있으면 되므로 거의 0x02로 고정이라고 보면 됩니다. ("항상"은 아니고 "거의" 입니다.)
Response
0x05 0x41 0x0C 0x0A 0x03 0x00 0x00 0x00
첫번째 바이트는 역시 유효 데이터의 바이트 수를 의미합니다.
두번째 바이트는 Mode인데, Request에서 6번(7번째) 비트를 1로 만들어 주면 됩니다.
Request의 Mode가 0x01이었으므로 Response는 0x41이 된다.
PID는 0x0C로 같고, 이후의 두 바이트가 원하는 값이다. 해석은 Part 1에 첨부해 놓은 PID 문서 참조.
RPM의 경우는 (A*256+B)/4 이므로 이 경우에는 (10*256+3)/4 = 640.75 가 되죠.
참고로 문서의 Formula 필드에서 대문자 A,B,C 등은 데이터 바이트의 순서를 나타냅니다.
OBD-II 커넥터는 그림과 같은 핀 배열을 갖고 있습니다.
앞서 OBD-II를 위한 통신 방식이 크게 세가지가 있다고 했는데,
통신 방식에 상관없이 커넥터는 모두 동일합니다. 물론 사용하는 핀은 다르죠.
1. NC (-로 표시)
2. 버스의 양극(+) 라인 (SAE-J1850)
3. NC
4. 배터리 접지 (차대접지, 섀시 접지)
5. 신호접지
6. CAN_H (ISO 15765-4 , SAE-J2234)
7. K 시그널 라인 (ISO 9141-2, ISO 14230-4)
8. NC
9. NC
10. 버스의 음극 라인 (SAE-J1850)
11. NC
12. NC
13. NC
14. CAN_L (ISO 15765-4 , SAE-J2234)
15. L 시그널 라인 (ISO 9141-2, ISO 14230-4)
16. 배터리 양극
16번 배터리 양극과 4번 접지는 공통이며 통신방식에 따라 각 두개씩을 사용하게 됩니다.
CAN 통신의 경우는 6번 CAN_H와 14번 CAN_L를 사용합니다.
참고로, 차량내에서 OBD-II 커넥터의 위치는 제조사마다 약간 다른데 보통 운전석 아래나 기어박스 근처에 있습니다. (현대차는 대부분 운전석 아래)
이 커넥터의 위치 또한 표준에 규정되어 있기 때문에 운전석에 앉아서 손이 닿을 수 있는 위치에 있어야 합니다.