encounters with electron•ics / by flabbergast

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.

{More pics to appear…}

Design notes

  • The atmega328p runs on 3.3V from BBB, with 16MHz crystal (yes, out of spec).
  • The atmega328p is connected to BBB via serial (on UART1, with mega’s RESET wired to UART1_RTSn).
  • The atmega328p can be programmed also using the standard 2x3 AVR ICSP header (once RFM69 is soldered, make sure to use 3.3V for supply and lines both!).
  • The atmega328p, DS3231 RTC and an optional ATSHA204 (or other ATMEL SOIC-8 EEPROM) are all wired together to BBB’s I2C2 (pins P9.21 and P9.22). The I2C lines are brought out to THT pads as well. With solder jumpers, the I2C pads can be connected only to atmega328p, or only to BBB, or to both. The jumpers can be also used to separate the atmega328p from BBB+DS3231.
  • The RFM69 is supplied BBB’s 3.3V and connected to atmega328p’s SPI (with CS and IRQ connected as on Moteino or Jeenode or Anarduino).
  • The RFM69’s antenna can be either a wire whip, or a real antenna attached to onboard u.FL connector.
  • Finally, BBB’s AGND and AIN5 are brought out to THT pads. The original idea was to wire a TMP35 or TMP36 temperature sensor.

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

  • dtbs are in /boot/dtbs/....
  • install dtc - on debian it’s device-tree-compiler package
  • decompile the default overlay dtc -I dtb -O dts /boot/3.8.13-bone70/am335x-boneblack.dtb -o ~/am335x-boneblack.dts
  • edit the dts file (diff for the I2C2 pins below)
  • online tool to figure out the numbers is here
  • compile back and move to /boot/...

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

  • check which pins are muxed where: looks at files in /sys/kernel/debug/pinctrl/44e10800.pinmux
  • map numbers from pinmux-pins from that dir: table here
  • explanation for uart5 here

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

Part Type Value Package Note
C1 Capacitor 0.1uF 1206  
C2 Capacitor 0.1uF 1206  
C3 Capacitor 10uF 1206  
C4 Capacitor 18pF 0805 w/crystal
C5 Capacitor 18pF 0805 w/crystal
Y1 Crystal 16MHz TXC-7A optional
R1 Resistor 10kR 1206 m328 RESET pull-up
R2 Resistor 4.7kR 1206 I2C pull-up
R3 Resistor 4.7kR 1206 I2C pull-up
R4 Resistor 1kR 1206 optional
D1 LED   1206 optional; PB1
IC1 DS3231   SOIC-16wide  
IC2 atmega328p   TQFP-32  
IC3 ATSHA204 or ATMEL EEPROM   SOIC-8narrow optional
J1 male headers   18x2 2.54mm pitch
J2 u.FL SMT connector     optional
U1 RFM69W     also -HW
BAT1 SMT coin cell socket   12mm