The canframe.py tool
We have developed a simple CAN calculator in Python called canframe.py
. It
defines a class CANFrame
that calculates the bitstream for a CAN frame,
and includes a print
method that displays the fields in the CAN frame.
It is available in the
CANHack GitHub repository
in the src
folder.
For example, here is the CAN frame with standard ID of 0x014 and a payload of 0x01:
The output of the calculator shows the stuff bits in red. The CRC for the frame is 0x7753, or 111011101010011. The reason we picked this frame is that it’s the one shown in the Wikipedia page on CAN. This this image is used everywhere, from academic papers to conference papers to blogs:
This image isn’t a real CAN frame trace (the stuff bits have been omitted). But it’s also not a proper CAN frame trace because the CRC is wrong. It’s been there since 2014, so probably it’s now time it was fixed.
We’ve created a new image but Wikipedia won’t let me upload it for some reason. If anyone else wants to take this image and replace the existing broken one then feel free.
The traces in the image were taken from a real CAN system: we used the Digilent Analog Discovery 2 USB scope. This is a great piece of hobbyist kit: it can do a lot more than just be a scope: it also has digital inputs and the software includes a logic analyzer, which has a number of protocol decodes, including for CAN. Here’s what it shows when that’s used:
CAN H and CAN L was measured on our benchtop CAN bus (more about this in another post) and the digital CAN RX trace comes from the RX pin of a Microchip 2562FD CAN transceiver on a PCB produced by Canis Automotive Labs. The CAN frame was transmitted from an STM32F405 microcontroller with the on-chip bxCAN CAN controller.
UPDATE 2020/25/10
We’ve made some changes to the tool: there is some more detail in the
detailed output (giving individual field values) but the big change is that
we’ve added a protocol decoder: feed in a bitstream (a string of ‘0’ and ‘1’
characters) and a CAN frame is
extracted from the bitstream. The static method from_bitseq
returns
a dictionary consisting of the decoded field values and either
a key of 'stuff_error'
and the bit number where the stuff error was
found, or an instance of CANFrame
created from the field values.
This decode feature is useful for creating a protocol decoder. Our next goal is to create a GTKWave filter so that an arbitrary waveform can be decoded (@Matthew Venn has some example code on how to do this).