Usage¶
Technical background¶
CAN bus (Controller Area Network) is a bus frequently used in the automotive industry. Packets with up to eight bytes of data are sent. Each frame (packet) has a frame ID, which pretty much is a ‘from’ address. Typical speeds are 100 to 500 kbit/s.
In Linux the CAN protocol is implemented in SocketCan. It is modelled after network sockets, and in order to use a CAN interface a socket is opened to the Linux kernel. The CAN interface is often named something like ‘can0’.
Each of the CAN frames contains a number of signals. In order to specify a signal, at least this must be known:
- signal type (signed/unsigned integer, etc)
- number of bits
- startbit
- bit numbering scheme
- endianness: little endian or big endian
For more details, see CanSignalDefinition
.
Minimal examples¶
To use can4python in a project with the 'vcan0'
CAN interface, and reading the CAN signal definitions
from a KCD file:
import can4python as can
bus = can.CanBus.from_kcd_file('documentation_example.kcd', 'vcan0', ego_node_ids=["1"])
bus.send_signals({'testsignal2': 3}) # Signal value = 3
The sent CAN frame is viewed using the ‘candump’ command line utility (described in a later section):
$ candump vcan0
vcan0 007 [8] 03 00 00 00 00 00 00 00
As our script will send out frames from the node “1”, it will consider frame ID 7 (which holds testsignal2) as an outgoing frame. That is seen in the corresponding KCD file:
<?xml version="1.0" ?>
<NetworkDefinition xmlns="http://kayak.2codeornot2code.org/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Definition.xsd">
<Document/>
<Bus name="Mainbus">
<Message id="0x007" length="8" name="testmessage">
<Signal name="testsignal1" offset="56"/>
<Signal name="testsignal2" offset="0" length="16" endianess="little"/>
<Signal name="testsignal3" offset="24" length="16" />
<Signal name="testsignal4" offset="59" length="4" endianess="big">
<Value type="signed"/>
</Signal>
<Producer>
<NodeRef id="1"/>
</Producer>
</Message>
</Bus>
</NetworkDefinition>
To receive CAN signals:
import can4python as can
bus = can.CanBus.from_kcd_file('documentation_example.kcd', 'vcan0', ego_node_ids=["2"])
received_signalvalues = bus.recv_next_signals()
print(received_signalvalues)
The bus.recv_next_signals()
will recive one CAN frame, and unpack its signals. The received_signalvalues
is a
dictionary with the signal values (numerical), having the signal names (str) as keys.
If a timeout is defined and no frame is received, a CanTimeoutException
is raised.
Test it by sending a CAN frame using the ‘cansend’ command line utility:
$ cansend vcan0 007#0F0000FF000000F1
The Python script will print:
{'testsignal1': 1.0, 'testsignal3': 255.0, 'testsignal2': 15.0, 'testsignal4': -2.0}
Alternatively, you can also set the CAN frame definitions and CAN signal definitions in your source code (instead of in a KCD file):
import can4python as can
frame_def = can.CanFrameDefinition(7, name='testmessage')
frame_def.producer_ids = ["1"]
signal_def = can.CanSignalDefinition("testsignal2", 0, 16)
frame_def.signaldefinitions.append(signal_def)
config = can.Configuration({7: frame_def}, ego_node_ids=["1"])
bus = can.CanBus(config, 'vcan0')
bus.send_signals({'testsignal2': 3}) # Signal value = 3
Broadcast Manager (BCM) usage example¶
The Broadcast Manager (BCM) can automatically do periodic CAN frame transmission, and it can filter incoming CAN frame on data changes. Periodic transmission is done like this:
import time
import can4python as can
frame_def = can.CanFrameDefinition(7, name='testmessage')
frame_def.producer_ids = ["1"]
frame_def.cycletime = 250 # milliseconds
signal_def = can.CanSignalDefinition("testsignal2", 0, 16)
frame_def.signaldefinitions.append(signal_def)
config = can.Configuration({7: frame_def}, ego_node_ids=["1"])
bus = can.CanBus(config, 'vcan0', use_bcm=True)
bus.send_signals({'testsignal2': 5}) # Signal value = 5. Start periodic transmission.
time.sleep(10)
The output resulting CAN frames are:
$ candump vcan0
vcan0 007 [8] 05 00 00 00 00 00 00 00
vcan0 007 [8] 05 00 00 00 00 00 00 00
vcan0 007 [8] 05 00 00 00 00 00 00 00
vcan0 007 [8] 05 00 00 00 00 00 00 00
vcan0 007 [8] 05 00 00 00 00 00 00 00
vcan0 007 [8] 05 00 00 00 00 00 00 00
vcan0 007 [8] 05 00 00 00 00 00 00 00
(truncated)
Usage recommendations¶
This CAN library is designed for experiments on sending and receiving CAN messages, and extracting the signals within. It main use case is to read a limited number of CAN messages from a CAN bus, and send a few messages now and then.
When running on embedded Linux hardware (for example the BeagleBone), the speed is sufficient to unpack around 500 CAN frames per second. As the can4python library will instruct the Linux kernel to filter incoming messages according to the available message IDs in the KCD configuration file (or corresponding settings made from code), it is recommended to edit your KDC file to only include the messages and signals you are interested in.
Show an overview of settings¶
To have an overview of the messages and signals on the bus:
print(bus.get_descriptive_ascii_art())
It will print something like:
CAN bus 'Mainbus' on CAN interface: vcan0, having 1 frameIDs defined. Protocol RAW
CAN configuration object. Busname 'Mainbus', having 1 frameIDs defined. Enacts these node IDs: 1
Frame definitions:
CAN frame definition. ID=7 (0x007, standard) 'testmessage', DLC=8, cycletime None ms, producers: ['1'], no throttling, contains 4 signals
Signal details:
---------------
Signal 'testsignal1' Startbit 56, bits 1 (min DLC 8) little endian, unsigned, scalingfactor 1, unit:
valoffset 0.0 (range 0 to 1) min None, max None, default 0.0.
Startbit normal bit numbering, least significant bit: 56
Startbit normal bit numbering, most significant bit: 56
Startbit backward bit numbering, least significant bit: 0
111111 22221111 33222222 33333333 44444444 55555544 66665555
76543210 54321098 32109876 10987654 98765432 76543210 54321098 32109876
Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
L
66665555 55555544 44444444 33333333 33222222 22221111 111111
32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210
Signal 'testsignal2' Startbit 0, bits 16 (min DLC 2) little endian, unsigned, scalingfactor 1, unit:
valoffset 0.0 (range 0 to 7e+04) min None, max None, default 0.0.
Startbit normal bit numbering, least significant bit: 0
Startbit normal bit numbering, most significant bit: 15
Startbit backward bit numbering, least significant bit: 56
111111 22221111 33222222 33333333 44444444 55555544 66665555
76543210 54321098 32109876 10987654 98765432 76543210 54321098 32109876
Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
XXXXXXXL MXXXXXXX
66665555 55555544 44444444 33333333 33222222 22221111 111111
32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210
Signal 'testsignal3' Startbit 24, bits 16 (min DLC 5) little endian, unsigned, scalingfactor 1, unit:
valoffset 0.0 (range 0 to 7e+04) min None, max None, default 0.0.
Startbit normal bit numbering, least significant bit: 24
Startbit normal bit numbering, most significant bit: 39
Startbit backward bit numbering, least significant bit: 32
111111 22221111 33222222 33333333 44444444 55555544 66665555
76543210 54321098 32109876 10987654 98765432 76543210 54321098 32109876
Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
XXXXXXXL MXXXXXXX
66665555 55555544 44444444 33333333 33222222 22221111 111111
32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210
Signal 'testsignal4' Startbit 59, bits 4 (min DLC 8) big endian, signed, scalingfactor 1, unit:
valoffset 0.0 (range -8 to 7) min None, max None, default 0.0.
Startbit normal bit numbering, least significant bit: 59
Startbit normal bit numbering, most significant bit: 62
Startbit backward bit numbering, least significant bit: 3
111111 22221111 33222222 33333333 44444444 55555544 66665555
76543210 54321098 32109876 10987654 98765432 76543210 54321098 32109876
Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
MXXL
66665555 55555544 44444444 33333333 33222222 22221111 111111
32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210
The numbers above “Byte0 Byte1 ” etc are the bit numbers using the normal numbering scheme. The letters ‘ML’ indicate the most and least significant bits in the signal, respectively. The numbers at the bottom is the bit numbering in the backward numbering scheme.
Configuration file¶
This CAN library uses the KCD file format for defining CAN signals and CAN messages. It is an open-source file format for describing CAN bus relationships. See https://github.com/julietkilo/kcd for details on the format, and example files.
This can4python CAN library implements a subset of the KCD file format. For example ‘multiplex’ signals are not supported.
One common file format for CAN information is the proprietary DBC file format. The CAN Babel is a tool for converting DBC files to KCD files. See https://github.com/julietkilo/CANBabel
Configurations made in source code using can4python can be written to a KCD file:
mycanbus.write_configuration('outputfile.kcd')
Show the contents of a .KCD configuration file (possibly converted from a .DBC file)¶
It is easy to print an overview of a configuration file:
import can4python
config = can4python.FilehandlerKcd.read("tests/testfile_input.kcd")
print(config.get_descriptive_ascii_art())
It will print:
CAN configuration object. Busname 'Mainbus', having 2 frameIDs defined. Enacts these node IDs:
Frame definitions:
CAN frame definition. ID=1 (0x001, standard) 'testframedef1', DLC=8, cycletime None ms, producers: ['17'], no throttling, contains 4 signals
Signal details:
---------------
Signal 'testsignal11' Startbit 56, bits 1 (min DLC 8) little endian, unsigned, scalingfactor 1, unit:
valoffset 0.0 (range 0 to 1) min None, max None, default 0.0.
Startbit normal bit numbering, least significant bit: 56
Startbit normal bit numbering, most significant bit: 56
Startbit backward bit numbering, least significant bit: 0
111111 22221111 33222222 33333333 44444444 55555544 66665555
76543210 54321098 32109876 10987654 98765432 76543210 54321098 32109876
Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
L
66665555 55555544 44444444 33333333 33222222 22221111 111111
32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210
Signal 'testsignal12' Startbit 8, bits 16 (min DLC 3) little endian, unsigned, scalingfactor 1, unit: m/s
valoffset 0.0 (range 0 to 7e+04) min 0.0, max 100.0, default 0.0.
Test signal number 2
Startbit normal bit numbering, least significant bit: 8
(truncated)
Show filtering of incoming frames¶
To see the CAN frame receive filters (for RAW interface) that are applied (in Ubuntu):
cat /proc/net/can/rcv*
Running tests¶
In order ro run the tests:
sudo make test
The tests are possible to run on a desktop Linux PC, as well as embedded Linux hardware.
Virtual (simulated) CAN interfaces for testing¶
The can4python library uses socketCAN type of CAN interface, for use under Linux. The CAN interfaces are typically named ‘can0’, ‘can1’ etc. It is also possible to setup virtual (simulated) CAN interfaces for testing purposes, and they act as loopback interfaces.
To enable the ‘vcan0’ virtual CAN interface on your desktop Ubuntu Linux machine:
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
To see what is sent on the virtual CAN interface, use the ‘candump’ tool:
candump vcan0
Advanced usage¶
You can for example directly manipulate the CAN interface instance. If using the BCM CAN interface:
mycanbus.caninterface.stop_periodic_send(103)
Architectural overview¶
We define these object types:
- CanBus
- See
CanBus
. Abstraction of the CAN bus, and uses aSocketCanRawInterface
or aSocketCanBcmnterface
. This is the main API object that developers will use. - SocketCanRawInterface
- See
SocketCanRawInterface
. Abstraction of the SocketCAN interface hardware (or simulated=virtual hardware), using the RAW protocol to communicate with the Linux kernel. Requires Python 3.3 or later. - SocketCanBcmInterface
- See
SocketCanBcmInterface
. Abstraction of the SocketCAN interface hardware (or simulated=virtual hardware), using the Broadcast Manager in the Linux kernel. Requires Python 3.4 or later. - CanFrame
- See
CanFrame
. A (physical) package with data sent on the CanBus. - Configuration
- See
Configuration
. An object holding configuration information about what is sent on the CAN bus. Has typically severalCanFrameDefinition
(each having a number ofCanSignalDefinition
). - CanFrameDefinition
- See
CanFrameDefinition
. Describes which signals that are sent in a frame with a specific ID. Has typically severalCanSignalDefinition
objects. Note that aCanFrameDefinition
is a description of the different parts of the Can frame, but theCanFrameDefinition
itself does not hold any data. - CanSignalDefinition
- See
CanSignalDefinition
. Defines where in a message this signal is located, how it is scaled etc. - FilehandlerKcd
- See
FilehandlerKcd
. Reads and writes configurations to file, in the KCD file format.
Either SocketCanRawInterface
or SocketCanBcmInterface
is used, not both simultaneously. You
select which to use in the constructor of the CanBus
.
It is possible to use only parts of the library. The architecture is such that it should be easy to write another CanInterface object.