A Deep Dive into Qt CAN Bus

A03 5.11.2019 14:00 - 15:00

Bookmark and Share

Burkhard Stubert
Burkhard Stubert

Controller Area Networks – CANs, for short – are widely used for the communication in cars, trucks, tractors, harvesters, construction machines and even e-bikes. When the instrument cluster in your car displays the vehicle speed or petrol level, it received CAN messages from other electronic control units (ECUs). When the driver of a harvester changes the cutting height for maize in the terminal’s HMI, the terminal sends CAN messages to the other ECUs over the CAN bus. Despite the popularity of CAN, the Qt CAN bus API leads a reclusive life in the shadow of glamorous Qt modules like QML and 3D. It is time to change this. Qt 5.6 introduced the Qt CAN bus API as part of the QtSerialBus module. Qt CAN bus is a clean and simple API to connect to a CAN bus, and to send and receive CAN frames. We’ll explore what Qt CAN bus offers and how to solve common CAN communication problems. We start with a simple scenario. The terminal requests the value of a parameter (e.g., the cutting height) from an ECU. The ECU receives the request in a CAN frame, reads the parameter value from its persistent storage and sends a response back to the terminal. The terminal decodes the response and displays the value in its HMI. Let us complicate the scenario a little bit. The application requests the values of all 50 parameters in a group. It writes the 50 request frames to the CAN bus in a for loop and waits for the responses. It will receive many responses but not all – and several error messages. The 50 requests made the write buffer of the CAN controller overflow. Increasing the buffer size is only a temporary solution. As every request has a response, the application could send the next request only when it has received the response to the previous request. If there is only one response every 512 requests, we configure the CAN controller to receive its own CAN frames. The application sends the next request, when it receives the frame of its previous request. The application adapts its sending rate dynamically to the load on the CAN bus. A CAN bus load of 800 frames per second is quite normal. By default, the terminal application sees all frames! Processing 200 frames in the GUI thread will already freeze the GUI. We must reduce the number of CAN frames sent from separate CAN threads to the GUI thread. We can configure the CAN controller to reject irrelevant CAN frames. The CAN threads aggregrate the CAN frames and forward a collection of CAN frames to the GUI thread at a slower rate like 4-5 times per second. If several frames with the same ID arrive in a GUI sample interval, only the last frame is taken into account. A harvester easily has more than 1000 different CAN frames. We need a code generator to produce the code for encoding and decoding all these CAN frames. The functions from QtEndian help us to generate very efficient code.