-
미니프로그램에서 CAN 신호와 시스템 변수 다루기tip 2025. 1. 10. 01:47
시작하기 전에
미니프로그램을 작성하다보면 CAN 신호와 시스템 변수를 다루게 된다. 아래의 경우들이 있다.
- 미니프로그램에서 CAN 신호를 읽어서 연산에 사용한다.
- 미니프로그램에서 연산한 결과를 CAN 메시지의 신호로 전송한다.
- 신호를 TSMaster의 그래픽, 트레이스, 판넬 창 등에서 사용할 수 있다.
- 메시지는 blf 파일에 저장할 수 있다. (blf 파일을 csv, mat, csv 등으로 변환하여 다른 프로그램에서 읽을 수 있다.)
- 미니프로그램에서 시스템 변수를 읽어서 연산에 사용한다.
- 미니프로그램에서 연산한 결과를 시스템 변수에 저장한다.
- 시스템 변수를 TSMaster의 그래픽, 트레이스, 판넬 창 등에서 사용할 수 있다.
- 시스템 변수를 blf 파일에 저장할 수 있다. (2025-01-10 현재, 시스템 변수를 TSMaster 이외의 프로그램에서 읽을 수는 없다.)
위 방법들을 설명한다.
1. 미니프로그램에서 CAN 신호를 읽는 방법
2. 미니프로그램에서 연산한 결과를 CAN 메시지의 신호로 전송하는 방법
개요
- 아래 순서로 작동하는 미니프로그램을 예제로 설명한다.
- 미니프로그램에서 ESP12 메시지의 YAW_RATE 신호를 읽어서 yaw_rate라는 지역 변수에 저장한다.
- dbc에 yaw_rate를 실어 보낼 메시지와 신호를 만든다.
- 메시지 이름을 calc라고 한다.
- 신호 이름을 yaw_rate_m이라고 한다.
- (변환을 설명하기 위해) yaw_rate_m의 factor와 offset을 YAW_RATE와 다르게 설정한다.
- 미니프로그램에서 yaw_rate_m에 yaw_rate를 저장하고 calc 메시지를 전송한다.
미니프로그램에서 ESP12 메시지의 YAW_RATE 신호를 읽어서 yaw_rate이라는 지역 변수에 저정하기
dbc에 yaw_rate을 실어 보낼 메시지와 신호를 만들기
- 메인 메뉴/ Analysis/ Database 버튼을 클릭한 후 드롭다운 메뉴에서 Show CAN Database를 클릭하여 CAN Database 창을 연다. 편집할 데이터베이스를 선택한 후, CAN Database 창에서 edit the current selected database를 클릭한다. CANdb++ Editor 창이 열린다.
- 미니프로그램의 지역 변수 yaw_rate를 담을 새 신호 yaw_rate_m를 만든다. CANdb++ Editor 창의 왼쪽 영역에서 Signal을 마우스 우클릭한 후 New...을 클릭한다.
- 아래 그림과 같이 새 CAN 신호 yaw_rate_m을 정의한다.
- 참고로 ESP12 메시지의 YAW_RATE 신호의 정의는 아래와 같다. YAW_RATE에 비해 yaw_rate_m은 아래의 차이점들이 있다.
- length: 13 bit vs. 10 bit
- CAN 신호 YAW_RATE와 미니프로그램의 변수 yaw_rate와 CAN 신호 yaw_rate_m는 해상도와 범위가 서로 다르다. 해상도와 범위가 서로 다른 변수들 사이에서 동일한 값이 어떻게 변환되는 지를 데모하기 위한 목적으로 length를 다르게 설정한다.
- 미니프로그램의 변수인 yaw_rate는 floating point (double) 타입이다.
- CAN 신호 YAW_RATE와 yaw_rate_m은 fixed point 타입이다.
- yaw_rate는 YAW_RATE와 yaw_rate_m에 비해 비해 해상도도 높고 범위도 넓다.
- 임베디드 시스템은 메모리와 컴퓨팅 파워를 아끼기 위해서 fixed point 형을 많이 사용한다.
- floating 포인트를 fixed 포인트로 바꾸는 변환 작업이 필요하다. (이 작업을 TSMaster가 한다.)
- factor: 0.01 vs. 0.1
- offset: -40.95 vs -51.15
- 변경된 factor에 따라 offset을 조정하였다.
- Minimun & Maximum:
- [중요] yaw_rate_m의 구간이 YAW_RATE의 구간 보다 크게 설정하였다.
- 그렇지 않으면 yaw_rate_m의 신호가 maximum을 벗어날 때 갑자기 minimum으로 점프하는 현상이 발생한다. minimum을 벗어날 때는 maximum으로 점프한다.
- length: 13 bit vs. 10 bit
- yaw_rate_m 신호를 담을 새 메시지 calc를 만들기 위해서, Message를 마우스 우클릭한 후 New...을 클릭하여 새 메시지 정의창을 띄운다. 이 메시지에 yaw_rate_m 신호를 담을 것이다. 이 메시지를 제어기 (Network node/ ESC)에 연결할 것이다.
- 아래 그림과 같이 새 메시지를 정의한다.
- ID는 다른 메시지들이 사용하지 않는 아이디인 0x222로 임의로 정했다.
- DLC는 8 바이트로 했다. (모든 설정을 완료한 후에 윈도를 캡쳐해서 Transmitter에 ESC가 표시되어 있다.)
- 메시지 정의 창에서 Signals 탭을 선택한다. 아래쪽에 있는 Add... 버튼을 클릭하여 위에서 정의한 yaw_rate_m 신호를 선택한다.
- 메시지 정의 창에서 Layout 탭을 선택한다. 아래 그림처럼 yaw_rate_m 신호가 전체 64 bit 중에서 상위 10 bit를 차지하는 것을 볼 수 있다. 신호의 위치를 변경하고 싶으면 신호를 드래그&드롭할 수 있다.
- 메시지를 제어기와 연결한다. 메시지 정의 창에서 Transmitters 탭을 선택한다. 아래쪽에 있는 Add... 버튼을 클릭하여 ESC를 선택한다. 이 메시지를 ESC가 보내는 것으로 가정했다.
- File/ Save 메뉴를 클릭하여 변경 내용을 저장한다. File/ Exit 메뉴를 클릭하여 CAN db++ Editor를 닫는다. 이 절차를 지키는 것이 중요하다. 이렇게 해야 제대로, TSMaster의 CAN Database에 calc 메시지가 추가되어 있다.
미니프로그램에서 yaw_rate_m에 yaw_rate를 저장하고 calc 메시지를 전송하기
- ESP12 메시지를 수신할 때마다 calc 메시지를 전송하는 것으로 한다.
- 미니프로그램에서 ESP12와 calc 메시지를 사용하기 위해 Global Definition에서 두 메시지를 담을 변수를 정의한다.
- ESP12 메시지를 수신할 때마다 calc 메시지를 전송하기 위해 On CAN Rx에 ESP12 메시지 수신 이벤트를 추가한다.
- Id 드롭다운 메뉴에서 ESP12 메시지를 선택한다. Name에 원하는 이름을 넣은다. 나는 메시지 이름을 주로 사용한다.
- On CAN Rx ESP12 이벤트에 on_can_rx_ESP12(ACAN: RawCAN) 함수를 정의한다.
- 코드는 아래와 같다. 코멘트가 해설로 충분하리라 생각한다.
- calc 메시지를 전송하는 코드는 com.transmit_can_sync(calc_1.FRawCAN, 5) 한 줄이다.
- 5
- timeout 시간이다. 5msec 안에 메시지를 보낸다. 실패하면 전송을 포기한다.
- timeout 시간을 길게 잡으면, 예를 들어 메시지 전송 주기의 수 배로 잡으면, 메시지가 전송되지 않은 대기 상태에서 새 메시지 전송 이벤트가 발생하고, 새 메시지 전송에 대한 대기 상태가 겹치게 된다. 이런 전송 이벤트 발생과 대기 상태의 겹침이 반복되면서 메시지 전송이 안 이뤄진다.
- com.transmit_can_async(calc_1.FRawCAN)을 이용하여 메시지를 전송할 수 있다. sync와 async의 차이는 아래와 같다.
- sync: 메시지 전송까지 다음 코드를 실행하지 않는다. 이벤트 발생 시점에서 timeout 시간 안에 메시지가 전송되거나 아예 전송되지 않는다.
- async: 메시지 전송 코드 실행 후 곧바로 다음 코드를 실행한다. 이벤트 발생 시점에 버퍼에 들어간 메시지는 나중에 전송된다. timeout 설정이 필요없다.
- 5
- CAN 신호를 변수에 저장할 때 fixed 포인트를 floating 포인트로 해상도와 범위 변환은 "yaw_rate = ESP12_1.YAW_RATE" 처럼 "변수 = CAN 신호"로 하면 TSMaster가 알아서 변환을 한다.
- 변수를 CAN 신호에 저장할 때 floating 포인트를 fixed 포인트로 해상도와 범위 변환은 "calc_1.yaw_rate_m = yaw_rate" 처럼 "CAN 신호 = 변수"로 하면 TSMaster가 알아서 변환을 한다. TSMaster가 메시지 데이터 영역 내에 yaw_rate_m의 위치까지 맞춰준다.
# Global Definition에서 정의한 calc_1과 ESP12_1 메시지를 # 사용할 수 있도록 global 변수 선언을 한다. # 로컬 변수와 이름이 겹치지 않으면 선언을 하지 않아도 된다. global calc_1 global ESP12_1 # copy ESP12 message into ESP12_1 ESP12_1.FRawCAN = ACAN # 변환 작동을 보기 위해 yaw_rate라는 로컬 변수를 만든다. # set yaw_rate to ESP12_1. YAW_RATE yaw_rate = ESP12_1.YAW_RATE # 로컬 변수 yaw_rate를 그래픽 창에서 보기 위해 # 시스템 변수 calc.yaw_rate에 복사한다. # update system variable calc.yaw_rate with local variable yaw_rate app.set_system_var_double('calc.yaw_rate', yaw_rate) # calc_1 메시지의 yaw_rate_m 신호에 yaw_rate를 복사한다. calc_1.yaw_rate_m = yaw_rate # tx calc_1 com.transmit_can_sync(calc_1.FRawCAN, 5) # 확인을 위한 print app.log_text('-----', lvlOK) app.log_text(f'CAN signal {ESP12_1.YAW_RATE = }', lvlOK) app.log_text(f'local var {yaw_rate = }', lvlOK) app.log_text(f'CAN signal {calc_1.yaw_rate_m = }', lvlOK) app.log_text(f'{ESP12_1.FRawCAN = }', lvlOK) app.log_text(f'{calc_1.FRawCAN = }', lvlOK)
- ESP12 메시지의 YAW_RATE 신호, 시스템 변수 calc.yaw_rate, calc 메시지의 yaw_rate_m을 한 그래프에 그리면 아래 그림과 같다. 기대한 대로 세 곡선이 해상도가 달라서 생기는 차이만큼을 고려하면 완전히 겹친다.
- 값을 출력해보면 아래와 같다.
- calc_1.yaw_rate_m는 ESP12_1.YAW_RATE와 매우 비슷하나 해상도가 달라 정확히 일치하지 않는다.
- yaw_rate와 ESP12_1.YAW_RATE는 화면에 출력되는 자리수까지는 동일하다. 이는 yaw_rate의 해상도가 YAW_RATE의 해상도 보다 훨씬 높다.
16:10:43.396 CAN signal ESP12_1.YAW_RATE = 1.019999999999996 16:10:43.396 local var yaw_rate = 1.019999999999996 16:10:43.396 CAN signal calc_1.yaw_rate_m = 1.0500000000000043 16:10:43.396 ESP12_1.FRawCAN = {1,0x80,8,0,0x220,128298608,{0x12, 0x24, 0x8C, 0x0, 0x0, 0x65, 0x10, 0xCE}} 16:10:43.396 calc_1.FRawCAN = {0,0x80,8,0,0x222,0,{0xA, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}} 16:10:43.405 ----- 16:10:43.405 CAN signal ESP12_1.YAW_RATE = 0.9899999999999949 16:10:43.405 local var yaw_rate = 0.9899999999999949 16:10:43.405 CAN signal calc_1.yaw_rate_m = 0.9500000000000028 16:10:43.405 ESP12_1.FRawCAN = {1,0x80,8,0,0x220,128308485,{0xC, 0x24, 0x8C, 0x0, 0x0, 0x62, 0x10, 0xD7}} 16:10:43.405 calc_1.FRawCAN = {0,0x80,8,0,0x222,0,{0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}} 16:10:43.416 ----- 16:10:43.416 CAN signal ESP12_1.YAW_RATE = 0.9600000000000009 16:10:43.416 local var yaw_rate = 0.9600000000000009 16:10:43.416 CAN signal calc_1.yaw_rate_m = 0.9500000000000028 16:10:43.416 ESP12_1.FRawCAN = {1,0x80,8,0,0x220,128318631,{0x6, 0x44, 0x8C, 0x0, 0x0, 0x5F, 0x10, 0xEC}} 16:10:43.416 calc_1.FRawCAN = {0,0x80,8,0,0x222,0,{0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}} 16:10:43.426 ----- 16:10:43.426 CAN signal ESP12_1.YAW_RATE = 0.9499999999999957 16:10:43.426 local var yaw_rate = 0.9499999999999957 16:10:43.426 CAN signal calc_1.yaw_rate_m = 0.9500000000000028 16:10:43.426 ESP12_1.FRawCAN = {1,0x80,8,0,0x220,128329404,{0x5, 0x84, 0x8C, 0x0, 0x0, 0x5E, 0x10, 0xFA}} 16:10:43.426 calc_1.FRawCAN = {0,0x80,8,0,0x222,0,{0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}} 16:10:43.435 ----- 16:10:43.435 CAN signal ESP12_1.YAW_RATE = 0.9699999999999989 16:10:43.435 local var yaw_rate = 0.9699999999999989 16:10:43.435 CAN signal calc_1.yaw_rate_m = 0.9500000000000028 16:10:43.435 ESP12_1.FRawCAN = {1,0x80,8,0,0x220,128338211,{0xD, 0xC4, 0x8C, 0x0, 0x0, 0x60, 0x10, 0x4}} 16:10:43.435 calc_1.FRawCAN = {0,0x80,8,0,0x222,0,{0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
3. 미니프로그램에서 시스템 변수를 읽는 방법
- 메인 메뉴/ Simulation/ System Variables 버튼을 클릭하여 System Variable Management 창을 연다.
- 시스템 변수를 정의한다.
- 미니프로그램에서 시스템 변수 calc.yaw_rate_ws를 읽어 x라는 변수에 저장하려면, 아래 코드와 같이 한다.
i, x_str = app.get_system_var_generic('calc.yaw_rate_ws') # 위 함수는 [i, x_str] 형식의 리스트를 반환한다. # i는 인덱스로 보인다. 무엇의 인덱스인지는 모르겠다. # x_str은 calc.yaw_rate_ws의 문자열(str) 값이다. # calc.yaw_rate_ws가 3.14라면 x_str는 '3.14'이다. # calc.yaw_rate_ws를 실수(double) 형식으로 정의했다. # x를 구하려면 x_str를 str에서 float로 변환한다. x = float(x_str) # x는 3.14가 된다.
4. 미니프로그램에서 연산한 결과를 시스템 변수에 저장하는 방법
- 위의 방법으로 시스템 변수를 정의했다고 가정한다.
- 시스템 변수 calc.yaw_rate_ws에 x를 저장하려면, 아래 코드와 같이 한다.
# x를 시스템 변수 calc.yaw_rate_ws에 저장한다. app.set_system_var_double("calc.yaw_rate_ws", x)
'tip' 카테고리의 다른 글
blf 파일에서 m_id, dlc, d_ts 추출하기 (0) 2025.01.19 Python 미니프로그램: 코드에서 CAN 메시지의 신호를 읽는 방법 (0) 2025.01.07 IDS 오감지/ 민감 감지에 관한 고찰 (0) 2025.01.04 침입 판정 기준값 데이터 준비 (0) 2025.01.04 asc 파일을 pandas 데이터프레임으로 변환하기 (0) 2025.01.04