<< to CrossControl homepage

Support & Service Center

Accessing the CAN bus from Qt with SocketCAN

Printer-friendly versionPrinter-friendly versionPDF versionPDF version
SocketCan is the standard interface for accessing CAN on Linux and uses normal socket programming to send and receive data on CAN. With SocketCan, several applications can read and write to the same CAN bus at the same time.

Socket CAN commands

To start an interface write the following in the console (do not write the # symbol)
#ifconfig can0 up

To shut down an interface write
#ifconfig can0 down

To set baud rate for an interface
#echo 250000 > /sys/class/net/can0/can_bittiming/bitrate

To get information about an interface
#ifconfig can0

To get statistics
#cat /proc/net/can/stats

To get version
#cat /proc/net/can/version

Bus off

Bus off is handled automatically by the driver. It is possible to recover from bus off manually or automatically.
Manual recovery is performed by:
#sh –c “echo 1 > /sys/class/net/can0/can_restart”

Automatic recovery is performed by:
#ifconfig can0 down
#sh –c “echo 100 > /sys/class/net/can0/can_restart_ms” 
#ifconfig can0 up

It is possible to get a notification when bus-off is detected. See CanWrapper::EnableErrorMessages();

Buffer sizes

CCP XM uses a hardware tx buffer of 64 messages which is usually enough. However, it is possible to increase the additional tx buffer used in the socket layer with the command:
#ifconfig can0 txqueuelen 100

There 100 is the desired size of the queue.
It is also possible to increase the size of the receive buffer. See CanWrapper::SetRecvBufferSize(int size) to see how this is done. Note that it is NOT possible to write something like "ifconfig can0 rxqueuelen 100" because there is no similar receive buffer to configure.

If the TX buffer is full, sending a message will not block but will return an error code.

It is important to continuously read messages from the RX queue, otherwise messages will be lost. Note that if you are losing messages at application level, it will not be seen when writing ifconfig can0 (which shows lost messages) because the lost messages shown here are messages lost in the can controller, not messages lost higher up in the socket layer.

The example application

The example application implements a simple can logger application in Qt. The application has been tested with Qt 4.7.3.
The most important class in the project is the CanWrapper class. This class demonstrates how to open, send and receive data on socket CAN. The CanWrapper class can also be used outside of the Qt environment.
The CAN wrapper class contains the following methods:
bool Init(const char *channelName, int &errorCode);
void Close();
bool SendMsg(struct can_frame msg, bool extended, bool rtr, int &errorCode);
bool GetMsg(struct can_frame &frame, bool &extended, bool &rtr, int &errorCode, struct timeval timeout);
bool SetRecvBufferSize(int size);
void EnableErrorMessages();
  • Init initializes the socket. The name of the can bus (can0, can1…) is taken as parameter.
  • Close closes a previously opened connection. Call this method before opening a new connection.
  • SendMsg is a non-blocking call to send a message. If transmit buffer is full, an error code is returned.
  • GetMsg is a blocking call to receive a message. It is possible to add a timeout value after the call will return even if no message is received.
  • SetRecvBufferSize sets the size of the receive buffer. The standard size is ok in most cases.
  • EnableErrorMessages configures socket-can to report error messages.

The CAN worker thread class is a class run in a separate thread that receives can messages in blocking mode and sends a signal to the GUI when a message is received. A one second timeout is used to be able to detect thread shutdown request.

The MainWindow class sets up the system and take care of button presses and updates of the can message list when a signal is sent from the CAN worker thread.

Using the application:

Select desired can channel with the Channel drop down list.
To send a can message, enter the id in the ID: field and the data bytes (separated by spaces) in the data field. Select “rtr” and “extended” as desired. Press the “Send” button.
To send a burst of messages (100), press the “Send Burst” button. This is used to test what happens when the transmit queue gets full. You probably must increase the TX buffer size to make this work.
Received messages are shown in the list below. Press the “Clear” button to clear the list.
Binary Data SocketCanExample.tar_.gz8.02 KB