Skip to content

[WIZnet CAN] QtCanBus 플러그인 만들기

[WIZnet CAN] QtCanBus 플러그인 만들기

eric_g

Published April 21, 2022

43 UCC

22 VAR

Project description

QtCanBus를 플러그인으로 생성을 하면 QT에서 기본으로 제공해주는 CAN Bus 예제와 CANdevStudio 프로그램에서 사용이 가능해 집니다.

?

아래 국내의 블로그 글을 참조해서 작성을 하였습니다.

?

https://blog.naver.com/jkjguy/222534028970

?
[CAN] Candevstudio 플러그인추가 [1]

Window 에서 Candevstudio 를 설치하고 껍데기 플러그인을 설치해보도록 한다. 기존 bootlibrary , Qt ...

blog.naver.com

?
[CAN] Candevstudio 플러그인추가 [2]

qt 에서 제공하는 플러그인과 candevstudio에 있는 플러그인 조합하여 적용해 보고 테스트 해보도록 하겠습...

blog.naver.com

?

CannelloniCanBus 플러그인 프로젝트가 UDP 기반으로 CAN 통신을 하는 플러그인입니다. 그래서 이 플러그인 프로젝트를 기반으로 작업을 하였습니다.

?

https://github.com/tuvok/qtCannelloniCanBus

?
GitHub - tuvok/qtCannelloniCanBus

Contribute to tuvok/qtCannelloniCanBus development by creating an account on GitHub.

github.com

?

파일 이름을 WiznetCan을 포함하도록 변경하였습니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

플러그인의 이름은 plugin.json의 값을 변경하면 됩니다.

?[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

플러그인 연결 창에서 Interface의 기본 이름을 추가하기 위해서 interfaces()를 추가하였습니다. 인터페이스 추가를 위해서는 QtSiznetCanBusPlugin.cpp에서 QCanBusFactory를 QCanBusFactoryV2로 변경해야 합니다.

?[WIZnet CAN] QtCanBus 플러그인 만들기

QtWiznetCanBusPlugin.cpp

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

WiznetCanBackend.cpp

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

플러그인 프로젝트에 UDP로 보낼 CAN 메세지 처리를 위한 cmd_can 모듈 코드를 추가하였습니다. 이 코드는 향후에 펌웨어에서 그대로 사용할 예정입니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

cmd_can 모듈은 아래의 CAN 명령 처리를 위한 패킷을 송신하게 됩니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

이 패킷에서 type과 cmd는 패킷의 역할과 데이터의 유형을 알 수 있도록 합니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

패킷의 구성은 아래 그림과 같습니다. UDP 패킷에 cmd_can 패킷이 있고 이 패킷안에 실제로 CAN 데이터 패킷이 포함되는 형태입니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

QT Creator에서 CMake 프로젝트로 Open을 해서 빌드를 하게 됩니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

CMakeLists.txt 파일은 변경한 파일명과 추가한 파일들을 코드를 추가하고, cmd_can 모듈은 C 코드로 되어 있기 때문에 C 파일도 빌드가 되도록 변경하였습니다.

?

프로젝트 빌드를 하면 lib로 시작하는 dll 파일이 생성이 되고 이 파일을 QT가 설치된 플러그인 폴더에 복사를 해야 합니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

제 PC에 QT가 설치된 폴더의 예입니다. plugins 밑에 canbus 폴더가 있고 이곳에 빌드한 dll 파일을 복사합니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

이제 QT에서 기본으로 제공해 주는 CAN 예제 프로젝트를 가져와서 빌드 후에 실행을 합니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

?

Connect 창이 뜨고 리스트에 wiznet_can이 추가된 것을 볼 수 있습니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

wiznet_can을 선택하면 기본적으로 기본 IP와 포트가 인터페이스 이름으로 출력됩니다. 이 부분은 연결된 장치의 실제 IP와 포트번호를 입력하면 되고, 여기서는 테스트용 PC 프로그램과 통신을 하기 때문에 그대로 사용을 합니다.

[WIZnet CAN] QtCanBus 플러그인 만들기[WIZnet CAN] QtCanBus 플러그인 만들기

?

연결을 하면 아래 그림처럼 해당 IP로 연결되었다는 메세지가 출력됩니다.

?

아직 보드에 펌웨어 구현이 안되어 있기 때문에 PC로 관련 기능을 구현을 하였습니다.

아래 깃허브의 ez_socket의 예제 중에 ez_socket_can을 빌드하고 실행하면 됩니다.

https://github.com/chcbaram/ez_socket

?
GitHub - chcbaram/ez_socket

Contribute to chcbaram/ez_socket development by creating an account on GitHub.

github.com

?

Code

PC의 서버쪽 코드입니다. 1초마다 CAN 메세지를 송신하고 수신한 CAN 메세지를 출력하도록 되어 있습니다.

int beginServer(void) { ez_err_t err_ret; int ret; err_ret = socketInit(&ez_socket, EZ_SOCKET_SERVER, EZ_SOCKET_UDP); err_ret = socketCreate(&ez_socket); err_ret = socketBind(&ez_socket, NULL, 30000); if (err_ret == EZ_OK) { read_thread = std::thread([=] { uint8_t rx_buf[512]; uint32_t heart_cnt = 0; while(1) { int rx_len; rx_len = socketRead(&ez_socket, (uint8_t *)rx_buf, 512); if (rx_len > 0) { qbufferWrite(&cmd_can_q, rx_buf, rx_len); } if (cmdCanReceivePacket(&cmd_can) == true) { if (cmd_can.rx_packet.type == PKT_TYPE_CMD) { log("Receive Cmd : 0x%02X\n", cmd_can.rx_packet.cmd); switch(cmd_can.rx_packet.cmd) { case PKT_CMD_PING: memcpy(cmd_can.packet.data, &heart_cnt, sizeof(heart_cnt)); cmdCanSendResp(&cmd_can, cmd_can.rx_packet.cmd, cmd_can.packet.data, sizeof(heart_cnt)); heart_cnt++; break; default: break; } } if (cmd_can.rx_packet.type == PKT_TYPE_PING) { log("Receive Type Ping\n"); } if (cmd_can.rx_packet.type == PKT_TYPE_CAN) { can_msg_t can_msg; memcpy(&can_msg, cmd_can.rx_packet.data, sizeof(can_msg)); log("rx can msg id:0x%X, ext:%d dlc:%d, ", can_msg.id, can_msg.id_type, can_msg.length); for (int i=0; i<can_msg.length; i++) { log("0x%02X, ", can_msg.data[i]); } log("\n"); } } } }); uint32_t can_cnt = 0; while(1) { can_msg_t can_msg; can_msg.id = 0x123; can_msg.id_type = CAN_EXT; can_msg.frame_type = CAN_FRAME_TYPE_DATA; can_msg.frame_option = CAN_CLASSIC; can_msg.length = 4; memcpy(can_msg.data, &can_cnt, 4); can_cnt++; cmdCanSendType(&cmd_can, PKT_TYPE_CAN, (uint8_t *)&can_msg, sizeof(can_msg)); ez::delay(1000); } } ret = socketClose(&ez_socket); ret = socketDestroy(&ez_socket); ret = socketDeInit(&ez_socket); printf("exit..\n"); return EZ_OK; }

?

PC프로그램은 main server를 입력하면 실행이 되고 아래 그림처럼 출력됩니다.

[WIZnet CAN] QtCanBus 플러그인 만들기, Code[WIZnet CAN] QtCanBus 플러그인 만들기, Code

?

이제 QT 프로그램에서 Frame ID와 Payload를 입력하고 Send버튼을 누르면 전송이 됩니다.

[WIZnet CAN] QtCanBus 플러그인 만들기, Code[WIZnet CAN] QtCanBus 플러그인 만들기, Code

?

?

PC 서버 프로그램에서 수신한 CAN 패킷을 볼 수 있습니다.

[WIZnet CAN] QtCanBus 플러그인 만들기, Code[WIZnet CAN] QtCanBus 플러그인 만들기, Code

?

?

이제 QT 플로그인을 통한 CAN 패킷 시험을 하였습니다.

펌웨어에 관련 코드를 포팅해서 보드와 통신하는 부분을 진행하면 될 것 같습니다.

Comments

Comments