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
- 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 toUART1_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
(pinsP9.21
andP9.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
andIRQ
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
andAIN5
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 UART
s 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'sdevice-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 |