BeagleBone AI-64 + Servo cape

We recently added Servo Cape Device Tree Overlay for BeagleBone AI-64 and this post will be more like a detailed overview of how to use servo cape with BeagleBone AI-64.

Make sure your system is up to date,

debian@BeagleBone:~$ sudo apt update
debian@BeagleBone:~$ sudo apt upgrade

You can follow the link below for more information on updating BeagleBone AI-64 software
https://docs.beagleboard.io/latest/boards/beaglebone/ai-64/update.html

It’s very likely that by the time you read this post the overlay is already available on you board but, in case it’s now you can get the new device tree overlay from v5.10.x-ti-unified branch of BeagleBoard-DeviceTrees repository and install it on your board,

debian@BeagleBone:~$ cd 
debian@BeagleBone:~$ git clone https://git.beagleboard.org/beagleboard/BeagleBoard-DeviceTrees.git
debian@BeagleBone:~$ cd BeagleBoard-DeviceTrees
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ git branch
* v5.10.x-ti-unified
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ make
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ sudo make install_arm64

After confirming the overlay is in place, update the extlinux.conf to load it,

debian@BeagleBone:~$ ls /boot/firmware/overlays/ | grep SERVO
BBORG_SERVO-00A2.dtbo

debian@BeagleBone:~$ sudo nano /boot/firmware/extlinux/extlinux.conf

After this the nano text editor will open the extlinux.conf file and now you have to add the fdtoverlays /overlays/BBORG_SERVO-00A2.dtbo line as shown below,

label Linux microSD
    kernel /Image
    append console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000 root=/dev/mmcblk1p2 ro rootfstype=ext4 rootwait net.ifnames=0 quiet
    fdtdir /
    fdtoverlays /overlays/BBORG_SERVO-00A2.dtbo
    initrd /initrd.img

Reboot the system and make sure the overlay is loaded correctly,

debian@BeagleBone:~$ sudo reboot

debian@BeagleBone:~$ sudo beagle-version | grep UBOOT
UBOOT: Booted Device-Tree:[k3-j721e-beagleboneai64.dts]
UBOOT: Loaded Overlay:[BBORG_SERVO-00A2]

debian@BeagleBone:~$ ls /proc/device-tree/chosen/overlays/
BBORG_SERVO-00A2  name

The servo cape uses PCA9685 PWM chip which is connected to i2c2 and on BeagleBone Ai-64 we have total 7 i2c buses. The bus number for i2c2 is 5.

debian@BeagleBone:~$ dmesg | grep i2c
[    0.912845] i2c /dev entries driver
[    1.009396] omap_i2c 40b00000.i2c: bus 0 rev0.12 at 100 kHz
[    1.009837] omap_i2c 40b10000.i2c: bus 1 rev0.12 at 100 kHz
[    1.031383] omap_i2c 42120000.i2c: bus 2 rev0.12 at 400 kHz
[    1.031967] omap_i2c 2000000.i2c: bus 3 rev0.12 at 400 kHz
[    1.033025] omap_i2c 2010000.i2c: bus 4 rev0.12 at 400 kHz
[    1.057095] omap_i2c 2020000.i2c: bus 5 rev0.12 at 100 kHz
[    1.057679] omap_i2c 2030000.i2c: bus 6 rev0.12 at 400 kHz
[    1.058172] omap_i2c 2050000.i2c: bus 7 rev0.12 at 400 kHz

Fun fact: The i2c2 bus number (5) is different from i2c number (2) because mcu_i2c and wkup_i2c are initialized before main_i2c. The table below should explain it better,

Bus0 - Bus1 = mcu_i2c
Bus2 = wkup_i2c
Bus3 - Bus7 = main_i2c

With all the information above you know that the bus number is 5 for our device. Now let’s see if we have something on that bus at 0x70 which is the address of PCA9685.

debian@BeagleBone:~$ sudo i2cdetect -y -r 5
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- 54 -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: UU -- -- -- -- -- -- -- 

We indeed have a device at 0x70 and it seems it’s being used by the driver. Let’s check that,

debian@BeagleBone:~$ ls /sys/bus/i2c/drivers/pca9685-pwm
5-0070  bind  uevent  unbind

Now you are all set to control servos with your servo cape but, before going further you may want go through this piece of code from beagle-tester repository to get an idea of what we are doing to control the servos.

By default we have two PWMs exported already i.e pwm0 & pwm1,

debian@BeagleBone:~$ ls /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0
device  export  npwm  power  pwm0  pwm1  subsystem  uevent  unexport

If you want to export 3rd PWM or any other PWM out of 16 available you can use the command below,

debian@BeagleBone:~$ echo 2 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip*/export

debian@BeagleBone:~$ ls /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0
device  export  npwm  power  pwm0  pwm1  pwm2  subsystem  uevent  unexport

Now connect your servo to S1 header pin location on cape and supply 5V via terminal block for the servo. Follow the PWM configuration bits and you should see your servo moving.

Set pwm0 period to 100Hz (10ms)

debian@BeagleBone:~$ echo 10000000 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/period

Set pwm0 duty cycles to 1ms

debian@BeagleBone:~$ echo 1000000 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/duty_cycle

Enable pwm0 PWM output

debian@BeagleBone:~$ echo 1 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/enable

Set pwm0 duty cycles to 2ms

debian@BeagleBone:~$ echo 2000000 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/duty_cycle

Set pwm0 duty cycles to 1ms

debian@BeagleBone:~$ echo 1000000 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/duty_cycle

Disable pwm0 PWM output

debian@BeagleBone:~$ echo 0 > /sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/enable

Congratilation if you got your servo moving. Let me know if you found any issue with the instruction above.

1 Like

To simplify the testing process you can also use the script below.

Create ServoCapeTesting.sh file to store the code,

debian@BeagleBone:~$ cd
debian@BeagleBone:~$ touch ServoCapeTesting.sh
debian@BeagleBone:~$ nano ServoCapeTesting.sh

Now paste the code below in the nano editor that just opened,

#!/bin/bash
servo1=/sys/bus/i2c/drivers/pca9685-pwm/5-0070/pwm/pwmchip0/pwm0/

function disable {
        echo 0 > $servo1/enable
}

function enable {
        echo 1 > $servo1/enable
}

echo "Servo attached to S1 must be running now..."

echo 10000000 > $servo1/period
echo 1000000 > $servo1/duty_cycle
enable

sleep 1
echo 2000000 > $servo1/duty_cycle
sleep 1
echo 1000000 > $servo1/duty_cycle
sleep 1
echo 2000000 > $servo1/duty_cycle
sleep 1
echo 1000000 > $servo1/duty_cycle
disable

Now make the script executable and execute it to move the servo.

debian@BeagleBone:~$ chmod +x ServoCapeTesting.sh
debian@BeagleBone:~$ ./ServoCape_test.sh 
Servo attached to S1 must be running now...

Your servo on S1 header pin location should be moving now…

1 Like

A post was split to a new topic: BBAI64: GPIO numbers