BBB-RFM69 (Beaglebone Black radio half-cape)

A BeagleBone Black half-cape featuring: an atmega328p, a RFM69(H)W radio and a DS3231 RTC with battery backup.

I made it to turn my BeagleBone Black into a central wireless node collecting sensor data from my RFM69-based sensors. On top of a BBB, I needed a wireless gateway (and opted to go through an atmega328p instead of directly on BBB, because there's more resources on doing it that way), and a real-time clock in case the internets would be down.

I also wanted the whole setup to fit into a smallish BBB case - which meant a custom PCB and SMT parts.

Design notes

Thoughts

As far as the choice for the RTC goes, I was deciding between DS3231 and DS1307. The latter being cheaper, but requires a crystal and needs to run on 5V (which is not such a problem here, because the I2C lines can be pulled up only to 3.3V and no level translation is needed). The former is more precise (which is not too much of a factor here), but it's more expensive (I wonder where do the chinese get it, since they sell it soldered as ready-made modules for £1 on ebay).

Problems with the current revision (rev1)

Altogether, most of the issues come from the fact that I wanted a no-frills atmega328p's autoreset via avrdude and Arduino bootloader. That meant using UART1 on BBB, since none of the other UARTs have the RTS line on the P9 connector. That implied that I2C2 needs to move from the default pins (P9.19 and P9.20 on BBB) to the other possibility (namely P9.21 and P9.22). I didn't realise at the time that I2C2 is used for identifying BBB capes, so its pins are pretty much hardcoded and changing them requires modifying some system files, and it also means that no capes will work. {This is fine for me, but not really a good design decision...}

One genuine mistake: I did not put a 0.1uF capacitor onto the BBB-UART/RTS -> atmega328p/RESET line, so avrdude did not work out of the box. I fixed this on my board manually by cutting a trace and soldering a through-hole capacitor (see the pics).

In hindsight, it was not worth the trouble - I should have left I2C2 at its place, and just use some other pin for atmega328p's reset, and use a custom one-liner to toggle the pin before calling avrdude. That way I wouldn't even need the "forgotten" capacitor. This is already done so in revision3 of the board (not likely to appear in reality, since this one works for my needs).

Pinmuxing on BBB

The way this half-cape is wired requires two modifications to the default pin assignments on BBB. This is done by Device Tree Overlays (some info for instance here, or just google it).

Moving I2C2 from P9.19 and P9.20 to P9.21 and P9.22

Moving I2C2 from P9.19 and P9.20 to P9.21 and P9.22 / diff:

79c79
<                   pinctrl-single,pins = <0x178 0x73 0x17c 0x73>;
---
>                   pinctrl-single,pins = <0x154 0x72 0x150 0x72>;

Enable UART1 (debian 2015-03-01 release)

Enabling TX and RX is easy, since it's enough to tell the kernel about it as a boot parameter:

Add the following to /boot/uEnv.txt (and reboot)

#UART1
cape_enable=capemgr.enable_partno=BB-UART1

Checking the status of serial ports can be done by

cat /proc/tty/driver/OMAP-SERIAL

Enabling UART1 / RTS signal

Well... eventually I gave up on RTS, didn't find out how to turn it on. So I ended up using the "normal" GPIO on that pin in a custom avrdude wrapper.

Resources

Programming the atmega328p

Since I gave up on the hardware RTS, some scripts around avrdude are needed. I used a slightly modified versions for Cryptocape, on github here. For the record, I'm including the listings here:

enable_pin.sh

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

#gpio0_13 for arduino reset pin, pull high to turn on
#GPIOb_p = b * 32 + p = N

pin=13

#enable the pin
echo $pin > /sys/class/gpio/export
#set for output
echo "out" > /sys/class/gpio/gpio$pin/direction
#set HIGH
echo 1 > /sys/class/gpio/gpio$pin/value

upload_m328p.sh

#!/bin/bash
if [ "$1" == "-h" ]
then
  echo "Usage: $0 [sketch.cpp.hex] [time to sleep]"
  exit 1
fi

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

pin=13
serial=/dev/ttyO1

if [ "$2" == "" ]; then
   tts=.9
else
   tts=$2
fi

upload=""
if [ "$1" != "" ]; then
   upload="-U flash:w:$1"
fi

echo Waiting $tts seconds

(echo 0 > /sys/class/gpio/gpio$pin/value \
    && sleep $tts \
    && echo 1 > \
    /sys/class/gpio/gpio$pin/value) &

avrdude -c arduino -p m328p -b 115200 -P $serial $upload

BOM

PartTypeValuePackageNote
C1Capacitor0.1uF1206
C2Capacitor0.1uF1206
C3Capacitor10uF1206
C4Capacitor18pF0805w/crystal
C5Capacitor18pF0805w/crystal
Y1Crystal16MHzTXC-7Aoptional
R1Resistor10kR1206m328 RESET pull-up
R2Resistor4.7kR1206I2C pull-up
R3Resistor4.7kR1206I2C pull-up
R4Resistor1kR1206optional
D1LED1206optional; PB1
IC1DS3231SOIC-16wide
IC2atmega328pTQFP-32
IC3ATSHA204 or ATMEL EEPROMSOIC-8narrowoptional
J1male headers18x22.54mm pitch
J2u.FL SMT connectoroptional
U1RFM69Walso -HW
BAT1SMT coin cell socket12mm