I have been experimenting with a Raspberry Pi Model B and a Pi camera board, and I wanted to make it slightly more portable. Issue 26 of The MagPi mentioned a new battery-powered UPS with a USB power output, so I decided to give that a try.

My main goals were to power the Pi on battery, and to have the Pi shut down cleanly when the batteries were depleted. If I didn't want to worry about the shutdown signal, almost any USB battery pack (for charging cell phones and other portable electronics) would power the Pi. But I figured it would be better to do a clean shutdown.

Enter the MindSensors.com (formerly OpenElectrons) SmartUPS. It takes three NiMH AA batteries, and it can charge them when hooked up to an external USB power supply. With its I2C control interface, you can query the battery status, and command an early shutdown. A programmable button can also be queried for its status. Similar to ACPI PCs, holding down the button performs a hard power-off.

The SmartUPS documentation claims that the UPS can supply 5V at 1.5A. While I haven't measured the current draw of my Raspberry Pi setup, I have been running it with a 5V/1A USB AC adapter with no issues. But when using the SmartUPS on battery, high CPU load would cause USB devices to disconnect. Since I typically log in with SSH over WiFi, this causes problems.

I contacted OpenElectrons support, and they worked with me to diagnose the problem. They swapped my SmartUPS with a unit set to output a slightly higher voltage, but that didn't completely solve the USB disconnection issues. Often, the devices would reappear on the bus, but not in a way that would allow me to log in again. Eventually, I sent them the Pi, the SmartUPS, and all of the peripherals. They narrowed the issue down to one command that I was running as part of a stress test (building NUT, actually), and the upshot was "don't run that command". Time to set up a cross-compiler on another box, I guess.

At any rate, I wrote a driver for the UPS. If you need a battery backup for your Raspberry Pi, this is IMHO a decent solution. With the NUT driver (similar to the closed-source vendor software), if your USB network devices do disconnect, you can still hold down the SmartUPS power button, which signals upsmon to shut down the Pi.

Commands to grab and build the driver:

apt-get install git
apt-get build-dep nut
apt-get install libi2c-dev   # new dependency for oe_smartups
git clone https://github.com/clepple/nut.git
cd nut
git checkout oe_smartups
./autogen.sh
./configure --with-drivers=oe_smartups,dummyups
make && sudo make install

The ups.conf file should look like this:

[smartups]
    driver = oe_smartups
    port = /dev/i2c-1 # or /dev/i2c-0 if you have an old Raspberry Pi

Cross-Compilation

These notes should be expanded into their own page, but until then:

To get autoconf to see additional libraries or headers, you can put them in the sysroot: arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/arm-linux-gnueabihf/libc (I am sure there is a better way.)

The autoconf invocation looks like this: ./configure --host=arm-linux-gnueabihf (additional info from ffmpeg).

I2C and Device Tree

Although the original I2C spec was designed for a clock speed of 100 kHz, it seems that the SmartUPS cannot keep up at that speed. Symptoms include random bit flips, noticeable on ASCII values such as the SmartUPS firmware version string. (It is unclear whether the BCM2708 I2C master and/or the SmartUPS support I2C clock stretching, which should solve this problem without slowing down transfers to other devices on the bus.)

The January 2015 Raspbian update added Device Tree support, which ignores the previous I2C settings in /etc/modules or /etc/modprobe.d/*. To force the 3.18+ kernel to drop back down to 50 kHz, add the following to /boot/config.txt:

# Force BCM2708 ARM I2C controller to 50 kHz:
dtparam=i2c_arm=on,i2c_arm_baudrate=50000

More details are available on the Raspberry Pi forums or in /boot/overlays/README.

Power Draw

This is also a section in search of a home, but if you are interested in comparing the power consumption of the various members of the Raspberry Pi family, you might be interested in this current draw comparison. Since I typically run with the WiFi dongle enabled, I would not see as much of a savings by moving to a newer unit like the B+, but it's good to know for reference.

TODO

  • Auto-detect RPi I2C port
  • Split NUT I2C detection into kernel and user headers
  • Make I2C address configurable
  • Parse firmware version
  • Map startup options to NUT commands and settings
  • Find an appropriate variable for remaining charge time (including negative values)
  • Expose battery health
  • Add threshold for mapping battery health to RB status