Canbus Python Debian 8.x

General

This is a old version of the HowTo! Is is olny working with old Debian 8.x. A new version for Debian 9.x can be found here.



The BeagleBoneBlack has two internal CAN-Bus controller which are called DCAN0 and DCAN1. In this HowTo the DCAN1-interface will be used because the DCAN0 interface shares the IO-Pins with the I2C-Bus for the cape-identification. The pins of the DCAN1-interface are multiplexed to the connector P9 pin 24 (CAN_RX) & 26 (CAN_TX).

Electrical Interfacing to the CAN-Bus:

In the BeagleBone processor is only the CANBus-control logic integrated. So a driver circuit is needed for the physical connection to the bus. A simple driver circuit can be build around the SN65HVD231D from TI. This driver is working with +3.3V supply voltage and can be directly connected to the beagle bone pins.

CAN Driver with SN65HVD231

This simple can driver circuit is NOT isolated. That means that short circuit and overvoltage can destroy the driver circuit and the connected beagle bone!

Below you can see a test setup with a SN65HVD231 CAN-driver and a LPC1769 AOAA-Board as a CAN-Node.

CAN Communication Test setup

When you want to protect your beagle bone when your are doing experiments with the CAN-Bus you can use an isolated CANBus-driver for example the ADM3052BRWZ from Analog Devices. This driver needs two supply voltages: +3.3V for the beagle bone side and a +12 to +24V supply for the CANBus-side. The ground is not connected between the both supplies, so the beagle bone is isolated from the bus.

CAN Driver with ADM3052

Enable the CAN Bus on the BeagleBone:

This description is based on the Debian Jessie Release (2016-05-13). At others releases there may be differences because the DeviceTreeOverlay stuff is constantly changing… By default the debian image doesn’t include canbus*.dtbo overlays to enable the CAN Bus. But ready to use overlays can be downloaded and installed.

To add the bb.org-overlays install the build tools with:

  1. sudo apt-get update

  2. sudo apt-get install build-essential git-core device-tree-compiler

Clone the bb.org-overlays repository:

  1. git clone https://github.com/beagleboard/bb.org-overlays/

  2. cd ./bb.org-overlays/

  3. ./install.sh

After the system is restartet you can now find in the directory /lib/firmware/ the DeviceTreeOverlay for the DCAN1 "BB-CAN1-00A0.dtbo".

To load the DeviceTreeOverlay at boot time I added the following line in the "/boot/uEnv.txt" file
cape_enable=bone_capemgr.enable_partno=BB-CAN1

After a reboot you can check if the overlay is loaded with:
cat /sys/devices/platform/bone_capemgr/slots
and get this output:

0: PF---- -1  
1: PF---- -1  
2: PF---- -1  
3: PF---- -1  
4: P-O-L- 0 Override Board Name,00A0,Override Manuf,BB-CAN1  

Then you can load the kernel drivers for the CAN-Bus:

sudo modprobe can  
sudo modprobe can-dev  
sudo modprobe can-raw`**

To bring up the interface and configure the bus speed to 125kBit/sec enter the following lines:

sudo ip link set can0 up type can bitrate 125000  
sudo ifconfig can0 up

To check that the can interface is up you can use ifconfig and should get this output:

root@beaglebone:~# ifconfig  
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
      UP RUNNING NOARP MTU:16 Metric:1  
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0  
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0  
      RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)  
      Interrupt:191  

To start the CAN interface at system startup the /etc/network/interfaces configuration file can be used by adding the following lines:

allow-hotplug can0  
iface can0 can static  
   bitrate 125000

First communication tests with the CAN Bus:

To test the communication over the CAN Bus you need to connect a second can device to your beagle bone and terminate the bus properly with 120 Ohm on both sides. For the first tests the CANSend and CanDump from the can-utils collection can be used. The building and installation of the can-utils is done by the following lines:

git clone https://github.com/linux-can/can-utils.git  
cd can-utils/  
./autogen.sh  
./configure  
make  

Sending a CAN-message to the adress 0x5a1 with the databyte[0..5]=0,1,2,3,4
./cansend can0 5A1#00.01.02.03.04

To log the messages on the CAN Bus you can use the CAN Dump program:
./candump can0

CANDump

Communicate with Python over the CAN Bus:

From Python >3.3 the CAN Bus can be directly used via socketcan. For Python 2.7 the python-can-lib is used to communicate to the socketcan via the ctypes interface. The respository of the library can be found at https://github.com/hardbyte/python-can . The installation of the python-can lib. (version 1.5 from the 02.08.2016) can be done with the following lines:

**`mkdir python-can  
cd python-can  
wget https://bitbucket.org/hardbyte/python-can/get/6ab1d0eea5ff.zip  
unzip 6ab1d0eea5ff.zip  
cd hardbyte-python-can-6ab1d0eea5ff  
python setup.py install  

In order to use this library a CAN interface needs to be specified by a configuration file or in the python program. For Python 2.7 the ‘socketcan_ctypes’ interface must be used. Here is an example how to send a messages with an extended id to the CAN bus:

sendcan.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/python
 
import can
can.rc['interface'] = 'socketcan_ctypes'
 
from can.interfaces.interface import Bus
from can import Message
 
def main():
   can_interface = 'can0'
   bus = Bus(can_interface)
 
 
   print "Send a message..."
   Message.extended_id = True
   Message.is_remote_frame = False
   Message.id_type = 1
   Message.is_error_frame = False
   Message.arbitration_id = 0x00E07123
   Message.dlc = 1
   Message.data = [ 0x01]
   try:
	   bus.send(Message);
   except:
	   print "Ups something went wrong!"
 
if __name__ == "__main__":
   main()

Here is another simple example how to receive messages from the CAN Bus:

receivecan.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/python
import datetime
import time
import can
 
can.rc['interface'] = 'socketcan_ctypes'
from can.interfaces.interface import Bus
from can import Message
 
def check_rx(id,data):
     now = datetime.datetime.now()
     timeString = now.strftime("%d.%m.%Y %H:%M:%S ")
     print timeString," ID ",id," Data",data
 
 
def main():
        can_interface = 'can0'
        bus = Bus(can_interface)
 
        try:
           while True:
             Message = bus.recv(0.0)
             if Message:
                check_rx(Message.arbitration_id, Message.data[0])
                 
        except  KeyboardInterrupt:
                bus.shutdown()
 
if __name__ == "__main__":
        main()