A BeagleBone Blue Setup Guide

bbb-board

I spent some time this week dodging the summer heat wave and having a go with the BeagleBone Blue. Based on the amount of frustration I’ve perceived by reading others’ experiences with the board, I was not motivated to try one for myself. However, @geofrancis pointed out the current low price and excellent availability of these boards, which piqued my interest. So, I decided that maybe I could help alleviate some of the community’s frustration.

Much of this text can likely be incorporated into the wiki, but it is a significant departure from the existing guide(s), so it warrants some community/developer feedback before making significant edits there.

Physical Connection Notes

bbb-annotated

bbb-details

The BeagleBone Blue uses JST-SH connectors for most peripherals. These very small 1.0mm pitch connectors ARE NOT compatible with the 1.25mm pitch DF13 connectors on older Pixhawk autopilots nor the 1.25mm pitch JST-GH connectors common on newer autopilot boards.

Servo outputs are standard 0.1" (2.54mm) pitch DuPont headers compatible with most hobby servos and ESCs.

The DSM2 port (UART4) and motor drivers use 1.5mm pitch JST-ZH connectors.

The LiPo battery connector is a 2.5mm pitch JST-XH connector, intended for use with a 2S 7.4 volt LiPo battery.

The barrel jack is a 5.5x2.5mm jack and will accept 9-18VDC for board power and/or LiPo charging.

The 5V and 3v3 outputs on peripheral ports may not be powered when the board is powered via USB. Use a 2S LiPo or the barrel jack to ensure that peripheral devices receive power when you get to the point where you need to configure them.

NOTE: Be sure to carefully turn the antennas outboard from their inboard/as shipped positions, as they will perform significantly better once they are oriented away from the board’s components and ground plane.


Building from Source

ArduPilot firmware building is not covered in this text. Instructions are available in the ArduPilot Wiki. Highly recommend using pre-built binaries, but if custom firmware is a requirement, one should develop and build on a reasonably powerful computer with a cross-compilation environment rather than attempting to build from source directly on the BeagleBone, which will likely prove slow, cumbersome, and possibly very frustrating.


Setup Guides

I used bits and pieces from each of these guides. They are each reasonably complete, but each contains a bit of nuance that the others do not, and they each refer to differing version numbers. I have updated this guide to the latest versions to the best of my ability (as of July 2022).


SD Card Prep

Recommend using a good quality SDHC card (32GB max). I used a SanDisk Ultra A1 32GB card which is almost certainly significant overkill for the storage requirement (4GB would be plenty). I achieved success with a 64GB SDXC card as well, though the extra storage really isn’t necessary.

Download a compatible OS image from this repository. Look for a ~150MB file prefixed bone-debian-xx.xx-console-armhf. I used the March 2022 Buster console image.

NOTE : As of this writing, more recent debian-10.12 builds do not have networking provisioned and will require a USB-serial adapter for initial log in and configuration.

Use Balena Etcher to flash the SD card (or use the dd utility under Linux).

NOTE : Be sure to fully seat the SD card into the BBB. I may have bricked a board by partially seating the card, though that board likely shipped with a corrupt ROM bootloader.


First Boot

Connect to a computer via USB. The board should show up as a network adapter on its own subnet. Wait a few moments and then connect via ssh (password: temppwd):

ssh debian@192.168.7.2

If the board is unreachable at 192.168.7.2, try 192.168.6.2.

NOTE : Be sure that you are using the image from the SD card (which should boot by default). If cat /etc/dogtag does not show the distro you flashed to the SD card, you have probably booted into the onboard eMMC image, which is likely out of date. Double check SD card compatibility and that you have flashed the correct OS image.

Use passwd to change the default password.

If you don’t want to enter your password often during the next steps, eliminate the need for it when using sudo:

echo "debian ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers.d/debian >/dev/null

If USB Networking is Unavailable (debian-10.12):

Rather than proceeding with a USB-serial adapter, recommend trying a different disk image.

If the USB network adapter fails to show up on the client computer, it is still possible to log in via a 3v3 USB-serial adapter (FTDI) connected to UART0. Connect a 4 pin JST-SH connector to TX, RX, and ground, and use a terminal application like minicom, picocom, RealTerm, or Putty. Execute sudo dpkg-reconfigure openssh-server to enable ssh.


Connect to WiFi

Execute this command and copy the output (something like wifi_abc123_321bca_managed_psk).

connmanctl services | grep 'YOUR_SSID' | grep -Po 'wifi_[^ ]+'

Now provide a configuration file for connman.

sudo nano /var/lib/connman/wifi.config

Once in the editor, create this file:

[service_<OUTPUT-FROM-CONNMANCTL-COMMAND>]
Type = wifi
Security = wpa2
Name = YOUR_SSID
Passphrase = YOUR_WIFI_PASSWORD

Ctrl-O then Ctrl-X will save and exit the editor.

If the WiFi network is available, a bright green LED should light up almost immediately, indicating a successful WiFi connection.

You may wish to limit read access to this file:

sudo chmod 0600 /var/lib/connman/wifi.config

To note the IP address for future ssh or telemetry connections, execute the following command and look for the IP address shown under wlan0.

ip addr

The BeagleBone should connect to this network automatically any time it is available.


Update/Install Software

Update your OS and install requisite software packages. Choose a UTF-8 locale (like en_US.UTF-8) unless you specifically require another language codeset.

sudo apt update
sudo apt -y dist-upgrade
sudo apt install -y git cpufrequtils locales lsb-release
sudo dpkg-reconfigure locales
cd /opt/scripts && git pull && cd ~

If /opt/scripts Does Not Exist (debian-10.12):

Some images may not include the /opt/scripts directory. It’s an easy fix.

cd ~
git clone https://github.com/RobertCNelson/boot-scripts.git
sudo mv boot-scripts /opt/scripts

Configure Hardware/Kernel

Configure the board to use a realtime kernel at 1GHz (“performance”) clock speed. Refer to kernel options if you’d like to use a different/newer version. 5.10-LTS is the latest as of this writing.

In some of the guides, there are references to specifying PRU drivers. Recent builds should make these steps obsolete, and I have omitted them.

Using the March 2022 debian-5.11 image, I found that I had to grow the SD card partition prior to updating the kernel to gain enough free space (sudo /opt/scripts/tools/grow_partition.sh followed by rebooting).

sudo sed -i 's/GOVERNOR="ondemand"/GOVERNOR="performance"/g' /etc/init.d/cpufrequtils
sudo /opt/scripts/tools/update_kernel.sh --bone-rt-kernel --lts-5_10
sudo sed -i 's/#dtb=/dtb=am335x-boneblue.dtb/g' /boot/uEnv.txt

NOTE: After updating the kernel, you may find that a warning is presented on the client terminal when attempting to ssh into the board again. Follow the on screen prompt to remove the stored keys. The required command will look something like this:

ssh-keygen -f "/home/user/.ssh/known_hosts" -R "<IP ADDRESS>"

If you wish to continue running the OS and software from the SD card after this initial setup (instead of flashing to eMMC), you may wish to grow the SD card partition to take advantage of full storage size.

sudo /opt/scripts/tools/grow_partition.sh
sudo reboot;exit

Install/Configure ArduPilot

In the following commands, replace ardurover with arducopter, arduplane, etc, as desired.

Create an environment file to define the serial ports in use.

sudo nano /etc/default/ardurover

Paste the following and change <target IP address> to the one for the computer to which telemetry will be connected.

# WiFi Telemetry
SERIAL0="-A udp:<target IP address>:14550"

# Radio Telemetry (UART1 - "UT1")
SERIAL1="-C /dev/ttyS1"

# GPS1 (UART2 - "GPS")
SERIAL3="-B /dev/ttyS2"

Ctrl-O then Ctrl-X to save and exit.

Create a service for ArduPilot.

sudo nano /lib/systemd/system/ardurover.service

Paste the following:

[Unit]
Description=ArduRover Service
BindsTo=sys-subsystem-net-devices-wlan0.device
After=sys-subsystem-net-devices-wlan0.device
StartLimitIntervalSec=0
Conflicts=arducopter.service arduplane.service antennatracker.service

[Service]
EnvironmentFile=/etc/default/ardurover
ExecStart=/usr/bin/ardupilot/ardurover $SERIAL0 $SERIAL1 $SERIAL3
Restart=on-failure
RestartSec=1

[Install]
WantedBy=multi-user.target

Ctrl-O then Ctrl-X to save and exit.

NOTE : This ardurover.service file differs from those in the other guides because I found that it was beneficial to wait for the WiFi device to be available (even if it goes unused) before starting ArduPilot. Using this method, boot time is approximately 40 seconds. By contrast, using After=networking.service slows the entire boot sequence due to the resource heavy initialization of ArduPilot - it can take up to 5 minutes to fully boot, and ethernet/wifi telemetry becomes unstable.

Install the binaries for the ArduPilot version of choice (latest dev version is the example here).

sudo mkdir -p /usr/bin/ardupilot
sudo wget -O /usr/bin/ardupilot/ardurover https://firmware.ardupilot.org/Rover/latest/blue/ardurover
sudo chmod 0755 /usr/bin/ardupilot/ardurover
sudo systemctl enable ardurover.service
sudo reboot;exit

It may take a bit of time to reboot and reconnect to wifi, but as long as you succeeded at using connman above, the green LED should eventually illuminate, and a GCS connection via UDP port 14550 should be possible.


Flash SD Card Image to eMMC

The BeagleBone has its own onboard storage similar to a solid state hard drive. It may be preferable and possibly faster to run the OS from the onboard eMMC rather than from the SD card.

In testing various SD cards, including an A2 class card, it seems the upper limit for SD card I/O on the BeagleBone Blue is about 22 MB/s. My BeagleBone Blue from Embest showed eMMC read/write speeds of 41 and 13 MB/s, respectively, suggesting that it is likely preferable to use eMMC for best performance.

Uncomment the line containing the eMMC flasher script in /boot/uEnv.txt:

sudo sed -i '/init-eMMC-flasher/s/^#//' /boot/uEnv.txt

Flashing takes more power than is typically available from the USB port, so power the board with a 2S LiPo or via the barrel jack and reboot.

sudo reboot;exit

The blue LEDs will blink for a few seconds and then begin a scan pattern. Wait for the scan pattern to stop (about 5 minutes, longer if using an older SD card). Only the power LEDs should remain lit before proceeding.

Remove power, remove the SD card, reapply power, and the board should boot from its internal storage.

NOTE: After flashing to eMMC, you may find that a warning is presented when attempting to ssh into the board again. Follow the on screen prompt to remove stored keys. The required command will look something like this:

ssh-keygen -f "/home/user/.ssh/known_hosts" -R "<IP ADDRESS>"

CAUTION: the SD card used for flashing will still be configured to flash eMMC after the process completes. You may wish to keep it as a backup, but DO NOT insert it into the board again unless you intend to overwrite eMMC with a fresh image!


Enable Lua Scripting

By default, scripts are located in the root directory under /scripts, and you must have root access to edit them. However, you can make a symbolic link to your home directory and place/edit all desired scripts there without invoking root privileges.

cd ~
mkdir scripts
sudo ln -s /home/debian/scripts /scripts

Connect via GCS and set the parameter SCR_ENABLE=1. Reboot, and scripting should work. You may see an error that says Lua: open directory (@ROMFS/scripts) failed, but it appears to be a nuisance warning and does not prevent scripts from loading.


Enable Bluetooth Telemetry

NOTE: This proved more difficult than it probably should have been. I discovered that following any of the guides on the subject resulted in either forcing a failure of the Bluetooth service to start, or a failure of ArduPilot to successfully connect to the virtual serial port prior to its instantiation. There is likely room for improvement to this method, but it does work reliably.

The following instructions are fairly lengthy and more complex than most of the rest of what I’ve written so far. Take care to keep your place as you go to avoid missing steps.

Stop the ArduPilot service, then install pip3 and required packages/modules:

sudo systemctl stop ardurover.service
sudo apt update
sudo apt -y install python3-pip libbluetooth-dev
sudo pip3 install pybluez
sudo pip3 install pyserial

Create a Python script to manage a virtual serial port (/dev/pts/0):

sudo mkdir /usr/bin/bluetooth-serial
sudo nano /usr/bin/bluetooth-serial/bluetooth-serial.py

Paste the following:

import os, pty, serial, time
from bluetooth import *
import threading


def receive(client, master):
    try:
        while True:
            received_data = os.read(master, 1024)
            client.send(received_data)
    except:
        print("cannot receive, connection closed")


def send(client, master):
    try:
        while True:
            data = client.recv(1024) #128
            written = os.write(master, data)
    except:
        print("cannot send, connection closed")


def start_server_and_listen(master):
    service_uuid = "00001101-0000-1000-8000-00805F9B34FB"
    server = BluetoothSocket(RFCOMM)
    server.bind(("", PORT_ANY))
    server.listen(1)
    port = server.getsockname()[1]
    advertise_service(server, "BBBlue-MAVLink", service_id=service_uuid,
                      service_classes=[service_uuid, SERIAL_PORT_CLASS],
                      profiles=[SERIAL_PORT_PROFILE])
    client, client_info = server.accept()
    receive_thread = threading.Thread(target=receive, args=(client, master))
    send_thread = threading.Thread(target=send, args=(client, master))
    receive_thread.start()
    send_thread.start()
    receive_thread.join()
    send_thread.join()
    server.close()
    client.close()


master, slave = pty.openpty()
s_name = os.ttyname(slave)
print(s_name)
ser = serial.Serial(port=s_name, baudrate=57600, stopbits=serial.STOPBITS_TWO)

while 1:
    try:
        start_server_and_listen(master)
    except:
        print("Exception occurred, restarting server...")

client.close()
server.close()

Ctrl-O then Ctrl-X to save and exit.

Modify /etc/bluetooth/main.conf to make the board discoverable at boot:

sudo sed -i -E '/^#? ?DiscoverableTimeout ?=/c\DiscoverableTimeout = 0' /etc/bluetooth/main.conf
sudo sed -i -E '/^#? ?AutoEnable ?=/c\AutoEnable=true' /etc/bluetooth/main.conf

Create an override file for the Bluetooth service to skip an uninstalled plugin and start in compatibility mode:

sudo mkdir  /etc/systemd/system/bluetooth.service.d
sudo nano 01-disable-sap-plugin.conf

Paste the following (the two ExecStart= lines are not a typo):

[Service]
ExecStart=
ExecStart=/usr/lib/bluetooth/bluetoothd -C --noplugin=sap

Ctrl-O then Ctrl-X to save and exit.

Create a service to start the Python script:

sudo nano /lib/systemd/system/bluetooth-serial.service

Paste the following:

[Unit]
Description=Bluetooth Serial Service
After=networking.target
StartLimitIntervalSec=0

[Service]
Type=simple
ExecStartPre=/usr/bin/timeout 1s /bin/bash -c 'bluetoothctl show' | /bin/grep "Discoverable: yes"
ExecStart=/usr/bin/python3 /usr/bin/bluetooth-serial/bluetooth-serial.py
Restart=always
RestartSec=1

[Install]
WantedBy=multi-user.target

Ctrl-O then Ctrl-X to save and exit.

Modify the environment file to use the virtual serial port for telemetry:

sudo nano /etc/default/ardurover

Comment the line for WiFi telemetry (add a # character) and add the lines for Bluetooth telemetry:

# WiFi Telemetry
#SERIAL0="-A udp:xxx.xxx.xxx.xxx:14550"

# Bluetooth Telemetry
VIRTUALPORT="/dev/pts/0"
SERIAL0="-A /dev/pts/0"

# Radio Telemetry (UART1 - "UT1")
SERIAL1="-C /dev/ttyS1"

# GPS1 (UART2 - "GPS")
SERIAL3="-B /dev/ttyS2"

Ctrl-O then Ctrl-X to save and exit.

Modify the ardurover service to start after the bluetooth-serial service:

sudo nano /lib/systemd/system/ardurover.service

You can simply delete everything and paste the following:

[Unit]
Description=ArduRover Service
#BindsTo=sys-subsystem-net-devices-wlan0.device
#After=sys-subsystem-net-devices-wlan0.device
After=bluetooth-serial.service
StartLimitIntervalSec=0
Conflicts=arducopter.service arduplane.service antennatracker.service

[Service]
EnvironmentFile=/etc/default/ardurover
ExecStartPre=/bin/ls $VIRTUALPORT
ExecStart=/usr/bin/ardupilot/ardurover $SERIAL0 $SERIAL1 $SERIAL3
Restart=on-failure
RestartSec=1

[Install]
WantedBy=multi-user.target

Ctrl-O then Ctrl-X to save and exit.

Enable the bluetooth-serial service, reboot, and you should be able to pair your client computer/device to a Bluetooth device named “beaglebone.” A virtual serial (COM) port should appear, and you can use it to connect a GCS like Mission Planner.

sudo systemctl enable bluetooth-serial.service
sudo reboot;exit
7 Likes

Great job on updating the BeagleBone installation process @Yuri_Rage :slight_smile:

Seems that the PRU drivers and configuration into the Directory Tree is working as default, that was a big support issue with previous kernels. As I don’t see a command to start the PRU: something similar to /bin/echo pruecapin_pu >/sys/devices/platform/ocp/ocp:P8_15_pinmux/state then it must be started by default, making each of the PRU decoding RCIN and generating RCOUT signals ?

1 Like

@ppoirier, I have only been bench testing and have not yet connected a radio. In the interest of completeness, I did so today and found that some information I read regarding PRU activation by default was incorrect. I will make an update.

PRU drivers remain a bit of a puzzle for now, but I’m achieving better success with the TI kernel. I still don’t quite have things working properly, but it does appear that some updates have been made. I will work through and edit the original post with my findings.

Seems I’m stuck. I get the expected output from lsmod | grep pru, but there is no device at /sys/devices/platform/ocp/ocp:P8_15_pinmux/state. I’ve tried every permutation of UIO driver I can think of, as well as several kernel versions, and they all lead to this error.

1 Like

I have taken the BLUE out of the “old project” box and here are my configs

/boot/uEnv.txt

uname_r=4.19.27-bone-rt-r27
dtb=am335x-boneblue.dtb
###U-Boot Overlays###
enable_uboot_overlays=1
###Custom Cape
dtb_overlay=/lib/firmware/BB-I2C1-00A0.dtbo
###PRUSS OPTIONS
uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo
###Cape Universal Enable
enable_uboot_cape_universal=1
cmdline=coherent_pool=1M net.ifnames=0 quiet

debian@beaglebone:~$ lsmod | grep uio
uio_pruss 16384 0
uio_pdrv_genirq 16384 0
uio 16384 2 uio_pruss,uio_pdrv_genirq

debian@beaglebone:~$ cat /sys/devices/platform/ocp/ocp:P8_15_pinmux/state
pruecapin_pu

some additional notes… while at it :wink:

ArduPilot is working with the memory mapped PRU aka UIO (not the remoteproc method)
as explained here: Enabling the Beaglebone PRU UIO Driver in Recent Kernels

The memory mapping for the PRU is set while loading the overlay : /lib/firmware/AM335X-PRU-UIO-00A0.dtbo
Looking at this directory tree fragment you can see the memory mapping: pruss@4a300000

That correspond to the memory address of the code running on ArduPilot as showned in this example

1 Like

Thank you, Yuri. You document well the complexities. I also never could quite find a combination of drivers and kernel that fully worked. The robot library seemed to suddenly stop working when I got close. This was back in March/April. It sounds like you are using newer stuff.

I wound up cheating by making a couple of lines change to ArduPilot to get it to accept Sbus on TX4. But I had the additional complexity that the smt quad plug popped off the pcb. Ultimately, the only thing I didn’t test were the ESCs. I don’t know if they’d be affected by the PRUs or not.

2 Likes

Thanks much for taking the time to do that. I recognized that the documentation I read regarding default PRU initialization was probably aimed at more recent versions of librobotcontrol, which uses RPROC. I’ve read through a lot of your back and forth with Robert Nelson on GitHub, and it appears that things have not improved with UIO since you last discussed it with him.

I may roll back to an earlier kernel and possibly even an older OS image to see if that makes a difference. I did find the guide you linked and blacklisted the RPROC drivers. I’m baffled as to why things aren’t working properly, as I can confirm that the UIO drivers are loaded, and lsmod output is identical to yours. But there is no state file present no matter what I do, and the ocp directory lacks any pinmux device.

UPDATE:
I was able to get PRU working with UIO under the 4.19 kernel. I have opened a GitHub issue for 5.10.

2 Likes

If you are interested, it would be interesting to have PR to have real PWM and encoder support ! Those are missing on AP side for the blue

2 Likes

Hi,

I have some experiments with the eQep peripherical + Ardupilot - if you want we can talk about it :slight_smile:

1 Like

I think this would be a great thread to share your experiences with encoders and the Blue.

That was the elegance of the PRU, unfortunately that is a curse as well :frowning:
@juvinski happy you participate

The best thing would have someone rewrite the PRU stuff as remoteproc.
Unfortunately this language is like Klingon and as far as I know @mirkix and @lucasdemarchi were the originators of the code maybe @peterbarker could comment ?

2 Likes

Hi @ppoirier :slight_smile:

I have in my bucket list a DShot implementation for the PRU :smiley:

About the blue, there is - at least I could see 2 main questions.

  1. the ECAP to read the rc input is the same as the EQEP4 - so you could use just 3 EQEP instead 4.
  2. to use 4 EQEP the input reading should be changed - because instead to use ECAP should read a PRU pin - and If I not wrong the blue just support 1 PRU instead 2 of black.

@Yuri_Rage,
In my tests, I use the linux filesystem to read the EQEP and feed the WheelEncoder Backend with the data - I will try to find my branch to see exactly what I made.

2 Likes

I owe the original post an update, which I will accomplish soon. For the time being, follow the portion of imfatant’s guide (linked above) for updating the kernel to 4.19 and enabling UIO, and use his aphw script to enable servo rail power and the PRUs.

1 Like