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

 

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

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