Wednesday, February 28, 2018

Building a Linux Powered Multi-copter from Scratch

Introduction

I purchased my first quadcopter about 6 years ago, back in the heyday of MultiWii. I flew it a few times, crashed it a few times, and it was fun for a little while, but my model lacked GPS, WiFi, and stabilized video, so it ended up sitting on a basement shelf for a few years.

Fast forward to fall 2017, where two things came together. One, I was able to get my hands on an Intel Aero RTF. This is a very powerful computing package on "wings." And two, the Beaglebone Blue came to my attention. It didn't take me long to come up a burning question...."I wonder if I can get the Beaglebone to do most of the stuff the Aero does?"

Let's find out!

Here is my syllabus for the next few blog posts. I'll try to match my normal development progression: get something working and then tweak it for performance.

  1. Component Details
  2. Initial Board Bring-up
  3. Flight Control Software
  4. Ground Tests
  5. Mavlink Improvements
  6. Boot Time Improvements

Stay tuned for Component Details...coming up after a short break.

Howto: Bluetooth GN/NAP on Beaglebone

This is an old article that I never published, but I'm making it available now, "as-is". Some of the instructions may be outdated, but I hope you find it helpful.

Recently I had the need to create a more secure wireless network connection. Bluetooth NAP came up as a viable solution, for a number of reasons:

  • Short Range
  • Fewer Sniffing/Hacking/War-driving tools
  • Mobile device support (Android/IOS)
I'll detail some of the configuration challenges and pairing procedures to get it up and running.

Prerequisites

  • Linux beaglebone 3.8.13-bone50 #1 SMP Tue May 13 13:24:52 UTC 2014 armv7l GNU/Linux
  • Bluetooth USB Dongle: GBU521 (http://www.iogear.com/product/GBU521/)
  • Powered USB Hub (IO Gear Bluetooth adapter will not work when directly plugged into Beaglebone)

Get Bluetooth up and running

Update servers/folders/file names:
sudo apt-get update

Bring installed packages up-to-date:
sudo apt-get upgrade

Install necessary packages:
sudo apt-get install bluez bluez-tools bridge-utils

Ensure Bluetooth is up and running by listing loaded Kernel modules:
debian@beaglebone:~$ lsmod
Module                  Size  Used by
rfcomm                 26769  10
bnep                    8909  2
g_multi                50407  2
libcomposite           15028  1 g_multi
btusb                  10339  0
bluetooth             159258  24 bnep,btusb,rfcomm
rfkill                 16672  2 bluetooth
mt7601Usta            641118  0

Verify Bluetooth Stack

See if device is up via bluez:
debian@beaglebone:~$ hciconfig -a
hci0:   Type: BR/EDR  Bus: USB
        BD Address: 00:02:72:CC:B8:47  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN
        RX bytes:1351 acl:0 sco:0 events:60 errors:0
        TX bytes:1333 acl:0 sco:0 commands:60 errors:0
        Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
        Link policy: RSWITCH SNIFF
        Link mode: SLAVE ACCEPT
        Name: 'beaglebone-0'
        Class: 0x420100
        Service Classes: Networking, Telephony
        Device Class: Computer, Uncategorized
        HCI Version: 4.0 (0x6)  Revision: 0x1000
        LMP Version: 4.0 (0x6)  Subversion: 0x220e
        Manufacturer: Broadcom Corporation (15)


Pair Beaglebone and Device

NOTE: Make sure you have a discoverable Bluetooth device turned on now... 

Test scanning:
debian@beaglebone:~$ hcitool scan
Scanning ...
        60:A4:4C:00:00:00       CGM Nexus 7

Configure local Bluetooth settings:
debian@beaglebone:~$ bluez-test-adapter name honeypot
debian@beaglebone:~$ bluez-test-adapter pairable on
debian@beaglebone:~$ bluez-test-adapter discoverable on
debian@beaglebone:~$ bluez-test-adapter discoverabletimeout 30

NOTE: After setting discoverable to on, you must scan for the beaglebone before the timeout. If you took too long, simple set discoverable to on again.

Pair the beaglebone to the other device
debian@beaglebone:~$ bluez-simple-agent
Agent registered
RequestConfirmation (/org/bluez/15561/hci0/dev_60_A4_4C_B7_C0_A2, 945453)
Confirm passkey (yes/no): yes

Press CTRL-C to quit simple agent....

Add the other device to the trusted list
debian@beaglebone:~$ bluez-test-device trusted 60:A4:4C:B7:C0:A2 yes

At this point the devices are paired, but no services are running on the Beaglebone.

Configure Services

Add NAP service to Beaglebone by editing bluez-nap-server:
debian@beaglebone:~$ sudo nano /usr/local/bin/bluez-nap-server

#!/usr/bin/python

import sys
import time
import dbus
from optparse import OptionParser, make_option

bus = dbus.SystemBus()

manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager")

option_list = [
      make_option("-i", "--device", action="store", type="string", dest="dev_id"),
      ]
parser = OptionParser(option_list=option_list)

(options, args) = parser.parse_args()

if options.dev_id:
        adapter_path = manager.FindAdapter(options.dev_id)
else:
        adapter_path = manager.DefaultAdapter()

server = dbus.Interface(bus.get_object("org.bluez", adapter_path), "org.bluez.NetworkServer")

service = "nap"

if (len(args) < 1):
        bridge = "tether"
else:
        bridge = args[0]

server.Register(service, bridge)

print "Server for %s registered for %s" % (service, bridge)

while True:
        time.sleep(1000)

Make it an executable file:
debian@beaglebone:~$ sudo chmod a+x /usr/local/bin/bluez-nap-server

Start it at boot by creating/editing a service file:
debian@beaglebone:~$ sudo nano /etc/systemd/system/bluez-nap.service

[Unit]
Description=Bluetooth NAP Server
After=syslog.target

[Service]
Type=simple
ExecStart=/usr/local/bin/bluez-nap-server br0
WorkingDirectory=/home/debian

[Install]
WantedBy=multi-user.target


Enable the service:
debian@beaglebone:~$ sudo systemctl enable bluez-nap.service

Enable DHCP by modifying udhcpd config file:
debian@beaglebone:~$ sudo nano /etc/udhcpd.conf
start      169.254.7.2
end        169.254.7.2
interface  br0
max_leases 1
option subnet 255.255.255.252

Create Bluetooth Bridge interface (add to end of interface file, after usb0 definition):
debian@beaglebone:~$ sudo nano /etc/network/interfaces
# Bluetooth NAP interface
auto br0
iface br0 inet static
address 169.254.7.1
netmask 255.255.255.0
bridge_ports none
bridge_fd 5
bridge_stp no

Reset and restart services
debian@beaglebone:~$ sudo systemctl restart networking.service
debian@beaglebone:~$ sudo systemctl restart udhcpd.service
debian@beaglebone:~$ sudo systemctl restart bluez-nap.service

References

  • http://notes.pitfall.org/ip-over-bluetooth-to-a-raspberry-pi.html
  • http://www.hkepc.com/forum/viewthread.php?tid=1710030
  • http://forum.doozan.com/read.php?2,2698
  • https://viaforensics.com/articles-presentations/bluetooth-packet-capture-android.html
  • https://bbs.archlinux.org/viewtopic.php?pid=1129449
  • http://www.linux.com/learn/tutorials/346552-personal-area-networking-with-bluetooth
  • https://github.com/Douglas6/pinaple
  • http://www.raspberrypi.org/forums/viewtopic.php?t=36889&p=479992h