Earth Notes: On Setting Up a Raspberry Pi Off-grid PV-Powered Server (2014)

Updated 2023-03-21.
How I set up a Raspberry Pi (Model B then B+) after the SheevaPlug. ~1.6W consumption typical, 400x less than my original server rack! #RPi #frugal #offGrid
The Raspbery Pi B/B+ took over from my SheevaPlug and was my main Internet server for a couple of years, until I broke it. A good piece of kit with excellent community support!

(The RPi B and B+ have been steps on the road from power-hungry rack of Sun SPARC server boxes to a sun-powered off-grid RPi 2 all-in-one. 512MB memory proved still to be a bit of a squeeze at this stage of the journey, though...)

Having bought a "Raspberry Pi Kit" (R45PI) aka RPi from Maplin, on 2014-06-22 I attempted to get it set up and working with the family TV. (Using the HDMI lead worked just fine.) The keyboard was broken (keys not responding or were sticking) but my local Maplin exchanged it the same day.

(I had, a couple of days before, observed consumption of the Pi, a Model B with 512MB RAM, 2 USB ports and Ethernet, without any keyboard (etc) attached. I measured it to be drawing <3W with just the SD card in and after booting likely finished, so less than the SheevaPlug.)

It booted happily once the keyboard was sorted, and after changing the password, I briefly had my daughter try out "Scratch" which she'd used at school, running under X windows as started with startx.

I set up WiFi which worked immediately, and followed instructions on the printed getting-started sheet to sudo apt-get update and sudo apt-get upgrade, which did not take too long and gets me (uname -a) to:

Linux XXXXX 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l GNU/Linux

I also got the official Oracle Java JDK7 with an sudo apt-get install oracle-java7-jdk. This is not the smaller-footprint 'embedded' version that I'm running on the SheevaPlug, but at least it should not require funny licensing arrangements.

I gave my RasPi a static IP address, changed its name, and added it to my published DNS records so that it could become a server, and enabled incoming ssh (ie sshd) so that I could run it headless and without monopolising the family TV! (Note that as a security matter, in /etc/ssh/sshd_config, PermitRootLogin should be no and indeed the only allowed login should probably be by key ie PasswordAuthentication should be no. I see bad actors attempting to get in regularly, so I make it harder.)

At the comfort of my own desk, and powering the RPi from my off-grid system, I used apt-get to fetch a few more favourite packages such as tcpdump and tcsh.

I won't leave the RPi connected all the time until I have spent some time securing/hardening it, though an initial inspection of the output of netstat -n does not suggest too much insecure junk is running, thankfully.

Initial Plans

RPi in box

Some initial thoughts:

2014-06-24: RTC

The RTC Pi RTC arrived very promptly!

Power consumption was measured before fitting the RTC, with Ethernet connected and the stock 4GB SD card but no USB/keyboard/mouse/TV, via an RS mains adapter 726-3069 and Maplin N67HH power meter, as 3.2W after boot had completed. (Note that the mains adapter data sheet claims typical 71% efficiency, so that 3.2W of power shown may be nearer 2.3W in reality.)

I fitted the RTC board with a battery and then plugged it into the RPi. Steady-state power consumption after boot is still 3.2W.

Setting up the RPi to talk to the RTS over i2c following these generic instructions...

I commented out the 'blacklist' line for the i2c driver in /etc/modprobe.d/raspi-blacklist.conf

#blacklist i2c-bcm2708

(the SPI driver blacklisting is already commented out).

I then added the following to the end of /etc/modules to load modules at boot:

i2c-bcm2708
i2c-dev
rtc-ds1307

and installed i2c-tools:

sudo apt-get install i2c-tools

To verify that the RTC board is detected on my Model B I ran:

sudo i2cdetect -y 1

which output:

           0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
      00:          -- -- -- -- -- -- -- -- -- -- -- -- --
      10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
      40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
      70: -- -- -- -- -- -- -- --

which shows the address '68' which is promising.

As a temporary set up I ran (as root, suitable for my Model B):

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device

and running:

sudo hwclock -r

shows:

Sat 01 Jan 2000 00:01:07 GMT  -0.168507 seconds

which shows that the kernel can see the clock but it is not set yet.

Setting the clock initially with:

sudo hwclock --systohc -D --noadjfile --utc

outputs:

hwclock from util-linux 2.20.1
Using /dev interface to clock.
Assuming hardware clock is kept in UTC time.
Time elapsed since reference time has been 0.394304 seconds.
Delaying further to reach the new time.

Setting Hardware Clock to 18:08:52 = 1403633332 seconds since 1969
ioctl(RTC_SET_TIME) was successful.

which looks good!

Now to have time restored from the hardware RTC in start-up I have added these to the end of /etc/rc.local (before the exit):

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
hwclock -s

It might be better to get this done earlier in the boot sequence, eg before logging starts.

I disabled the default 'fake clock' that stops time going backwards if the network is not connected:

update-rc.d -f fake-hwclock remove

(I reinstated this to help ensure sensible timestamps on files touched during boot before the hwclock is read, eg files in /var/log.)

To power cycle to check that everything works I issue:

sudo halt

and after a short while power consumption drops to 1.0W.

To ensure that the NTP-maintained system clock is periodically saved to the hardware RTC to stop it drifting, I have created in /etc/cron.daily a file called hwRTC:

pi:/etc/cron.daily# cat hwRTC
#!/bin/sh
/sbin/hwclock --systohc -D --noadjfile --utc > /tmp/hwClock.log 2>&1
pi:/etc/cron.daily# ls -al hwRTC
-rwxr-xr-x 1 root root 79 Jun 24 20:17 hwRTC

which should ensure once per day that the RTC time is forced to be correct.

A DS3231 may be a good drop-in replacement for the DS1307 running directly at 3V3 and so not needing level converters for a start, and working with the same software drivers... Also look at DS1338 and DS1337.

2014-06-24: Initial Adventures in Power Reduction

Attempting to turn off the unused HDMI with:

/opt/vc/bin/tvservice -o

actually raised reported consumption to 3.3W, and turning it on again with:

/opt/vc/bin/tvservice -p

apparently drops it back to 3.2W!

When re-measured with my bench supply, /opt/vc/bin/tvservice -o appears in fact to drop consumption by ~20mA ie 100mW. (Putting this in rc.local risks making the system unrecoverable by plugging into the TV. I could possibly start this after a delay to give myself change to kill it manually in such a case.)

The consumption claimed by the mains monitor is not always linearly related to that measured by my bench supply, and the bench supply is likely to be more accurate for a number of reasons.

Various sources on-line suggest that replacing the 3V3 on-board linear regulator which actually supplies most of the board power (5V is for USB mainly) might save 25%+ consumption, maybe as much as 1W, though the USB and Ethernet alone are actually heavy users at ~0.5W and the only power control in software affects both at once.

Replacing the the 3V3 linear regulator with a RECOM R-783.3-0.5 is reported to save ~15%.

The same guide suggests editing /boot/config.txt to insert:

force_turbo=0 #turns on frequency scaling
arm_freq=700 #sets max frequency
arm_freq_min=100 #sets min frequency

installing cpufrequtils with:

sudo apt-get install cpufrequtils
cpufreq-set -g ondemand

but even after a reboot and with the CPU nominally running at 100MHz I'm still seeing 3.2W consumption!

I may want in future to change the threshold for changing CPU frequency from the default 95%* to (say) 60% when battery levels are good to improve responsiveness with:

echo 60 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold

for example. (*Reportedly: seems to default to 70 after reboot on my RPi 20140708.)

Note that in /boot/config.txt I have set (c/o raspi-config):

gpu_mem=16

to minimise GPU memory allocation since I shall be running headless.

$ cat /proc/meminfo | grep Mem
MemTotal:         496764 kB
MemFree:          432672 kB

Note that MemTotal is 513392kB on the SheevaPlug, so I may strain to fit everything in without swap...

Perversely, if I try to waste CPU cycles, eg with:

while true; do true; done

I see consumption apparently drop to 3.0W!

Note that the k8055 board that is used with my SheevaPlug nominally draws 350mW, quite a lot of the gap between the Pi 3.2W and the nominal ~4W minimum of the SheevaPlug, so using some direct ADC/DIO may help with system savings. In fact the idle of the SheevaPlug without a USB hub is nearer ~2.5W, so although the RPi gives a lot of benefits of a supported mainstream distribution, and a less complex and fragile set-up, I may need to work harder to save much juice...

I have ordered a couple of ~80% efficient 3V3 switching regulators and a spare Model B board (and 128GB SD card!) to experiment with, eg replacing the reg and testing other energy-saving mods.

Attempting to get a more accurate power measurement by using my bench supply connected (naughtily) to the appropriate GPIO pins at 5V, shows an idle consumption of 380mA or 1.9W (logged in over ssh), rising to 420mA (2.1W) with a CPU-busy loop (while true; do true; done as above). Compared to the 3.2W reported by the mains power monitor this suggests a mains adapter efficiency of ~60% at this load.

Running a large "find" raised consumption to 440mA (2.2W).

After halting, consumption dropped to 110mA (0.55W).

Later I borrowed some tuning tips from my SheevaPlug set-up, adding these lines to /etc/sysctl.conf:

# DHD20140628: further tweaks to reduce SD card traffic.
vm.dirty_background_ratio=20
vm.dirty_ratio=40
vm.dirty_writeback_centisecs=12011
vm.dirty_expire_centisecs=12101

I am using some prime timings to hope to decouple different activities.

I also adjusted /etc/logrotate.conf to by default compress logs.

I also replaced each commented-out line from /etc/rsyslog.conf below with the uncommented one to try to reduce log traffic a little:

#*.*;auth,authpriv.none         -/var/log/syslog
*.*;auth,authpriv.none,cron.none                -/var/log/syslog

but I can't do this and have fail2ban still work for banning ssh attacks:

#auth,authpriv.*                        /var/log/auth.log
auth,authpriv.notice                 /var/log/auth.log

I also turned off debug logging.

Following the advice to quieten PAM (also this) by adding:

session [success=1 default=ignore] pam_succeed_if.so service in cron quiet use_uid

just above:

session required pam_unix.so

in /etc/pam.d/common-session-noninteractive may also help reduce unwanted chatter/writes.

Note also a simple debugging/monitoring aid in the 'ACT' LED on the RPi board.

echo mmc0 > /sys/class/leds/led0/trigger

(which is the default) will have the LED come on for each SD card access, and:

echo cpu0 > /sys/class/leds/led0/trigger

will have the LED come on with CPU activity for example!

echo none > /sys/class/leds/led0/trigger

turns it off saving a tiny bit of juice, presumably!

The llctl code can be used to (for example) turn off the LAN "100" and "FDX" lights which don't convey a huge amount of information, or use them for other purposes.

lltcl f0 ls d0

leaves the "LNK" LED flickering on activity and turns off "100" and "FDX".

Turning off the "ACT", "FDX", "LNK" and "100" LEDs appears to reduce current draw at 5V on my unmodified Model B from 380mA to 370mA (1.85W), according to my bench supply that reads in units of 10mA so may be less, but suggests that up to 50mW of extra power savings are available this way. This may be worth doing when (very) low on battery. (After halt, current draw now drops to 100mA, cf usual 110mA, with LEDs off.)

This is a sufficiently convincing win that I've moved llctl to /usr/local/bin and I've added this to the end of /etc/rc.local to cut the LAN LEDs by default:

/usr/local/bin/llctl f0 l0 d0

With the LAN LEDs off and:

/opt/vc/bin/tvservice -o

current draw drops to 350mA (1.75W).

To let this happen automatically, though not if anyone is logged in in case they are using TV and keyboard login for example to recover the system, the following is added to /etc/rc.local

# Power down the TV output after a while to save 100mW after warning users.
# Happens after a delay to allow system recovery using TV/keyboard.
# Not done if anyone appears to be logged in.
# COMMENT OUT THE FOLLOWING LINE TO KEEP THE TV OUTPUT RUNNING.
(sleep 180 && if [ "X" = "X`w -h`" ]; then logger -p user.emerg "TV service off
in 2 mins; see /etc/rc.local" && sleep 120 && /opt/vc/bin/tvservice -o; else
logger -p user.emerg "TV service not being turned off; do it manually to save
power"; fi) &

This waits three minutes and if no one appears to be logged in sends a warning and then after a further two minutes and turns off TV service, saving 100mW. If someone does appear to be logged in then the TV service is left on, with a warning to turn it off manually. Thus, a few minutes after a normal unattended boot TV service will be turned off and the extra power savings will be taken.

2014-06-27: Backup and new 128GB Card

As a practice run if nothing else I'm taking a backup of the 4GB SD card with the work done on it so far.

Having halted the RPi and removed the SD card, I can plug the SD card directly into the SD slot of my MacBock Air (running 10.9.3) and the leading FAT partition is mounted automatically.

See here (see also here) the following suggested dd command to make a backup copy from the SD card:

sudo dd bs=1m if=/dev/rdisk1 of=RPi.img

But before doing that I have unmounted the FAT partition to avoid conflicts:

[sudo] umount /dev/disk1s1

The dd command gave the following output:

3765+0 records in
3765+0 records out
3947888640 bytes transferred in 250.045586 secs (15788676 bytes/sec)

suggesting that indeed 4GB had been transferred. Follow with a:

diskutil eject /dev/rdisk1

before physically removing the SD card from the Mac.

I have copied the RPi.img file to 20140627-RPi.img and compressed it with the best-available tool easily available on my Mac to save space, bzip2, since most of the file space is not even used.

sh-3.2# bzip2 -9 20140627-RPi.img
sh-3.2# ls -alrt
...
-rw-r--r--    1 root  staff  3947888640 27 Jun 09:15 RPi.img
-rw-r--r--    1 root  staff  1017288117 27 Jun 09:23 20140627-RPi.img.bz2
...

I will then try cloning that to another 4GB SD card and see if I can boot and run the RPi with that, then to an 8GB card, expanding the partition or creating a new one for data beyond it, then repeat the exercise with the new 128GB card that I have just received.

I shall attempt to clone the 4GB image onto another 4GB card with:

dd bs=1m if=RPi.img of=/dev/rdisk1

having made sure no partitions are being mounted from the card first, in this case requiring:

diskutil unmount /dev/disk1s1

With the destination class 4 card (x150) dd took about 3 minutes.

Success! The RPi boots off the clone card all working as before! Power consumption is apparently as before also.

I am now attempting to dd the 4GB image onto an 8GB card, to see if it bootable and if I can create a new (ext4?) partition beyond the existing ones as data space.

The RPi boots happily from the 8GB card with the 4GB image on it, and with power consumption unchanged.

I ran up parted, and:

(parted) print all
Model: SD SD08G (sd/mmc)
Disk /dev/mmcblk0: 8196MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  62.9MB  58.7MB  primary  fat16        lba
 2      62.9MB  3948MB  3885MB  primary  ext4


(parted) print free
Model: SD SD08G (sd/mmc)
Disk /dev/mmcblk0: 8196MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
        32.3kB  4194kB  4162kB           Free Space
 1      4194kB  62.9MB  58.7MB  primary  fat16        lba
 2      62.9MB  3948MB  3885MB  primary  ext4
        3948MB  8196MB  4248MB           Free Space

(parted) mkpart primary ext3 3948MB  8196MB
(parted) print all
Model: SD SD08G (sd/mmc)
Disk /dev/mmcblk0: 8196MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  62.9MB  58.7MB  primary  fat16        lba
 2      62.9MB  3948MB  3885MB  primary  ext4
 3      3948MB  8196MB  4248MB  primary

Thus creating a new partition filling all the trailing free space.

Inspecting with fdisk shows:

%fdisk -l /dev/mmcblk0

Disk /dev/mmcblk0: 8195 MB, 8195670016 bytes
4 heads, 16 sectors/track, 250112 cylinders, total 16007168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000280b3

Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880     7710719     3793920   83  Linux
/dev/mmcblk0p3         7710720    16007167     4148224   83  Linux

which suggests that this is not particularly laid out to minimise wear and increase write performance.

On the SheevaPlug for the Gallery images partition I used:

mkfs -t ext3 -i 131072 -L galleryDB -O ^resize_inod,dir_index,sparse_super /dev/sda2

That data will be in the new partition, along with a fair amount of other stuff, plus I should probably use ext4 these days. Even though a dir_index,sparse_super are defaults, I'll leave them for clarity, so my command to create a new ext4 filesystem should look something like this for the final create:

mkfs -t ext4 -i 32768 -L data -O ^resize_inode,dir_index,sparse_super /dev/mmcblk0p3

(Note the trailing 'e' on resize_inode that was insisted on by mkfs!)

Here is a test run on the 8GB card:

# mkfs -t ext4 -i 131072 -L data -O ^resize_inode,dir_index,sparse_super /dev/mmcblk0p3
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=data
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
32768 inodes, 1037056 blocks
51852 blocks (5.00%) reserved for the super user
First data block=0
32 block groups
32768 blocks per group, 32768 fragments per group
1024 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736

Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

# mount /dev/mmcblk0p3 /tmp
# df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          3.5G  1.8G  1.6G  53% /
/dev/root       3.5G  1.8G  1.6G  53% /
devtmpfs        239M     0  239M   0% /dev
tmpfs            49M  216K   49M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            98M     0   98M   0% /run/shm
/dev/mmcblk0p1   56M  9.5M   47M  17% /boot
/dev/mmcblk0p3  3.9G   20K  3.7G   1% /tmp

This should give me the ability to back up the OS separately from bulk data, by cloning only the leading part of the SD card if I am feeling brave, for example. It should also help me move data from the SheevaPlug to the RPi later in the transition between them.

So now I repeat for the 128GB card:

  1. Use dd to copy the 4GB clone image on to the 128GB card on the Mac:
    diskutil umount /dev/disk1s1
    time bzip2 -d < 20140627-RPi.img.bz2 | dd bs=1m of=/dev/rdisk1
    diskutil eject disk1
    
    Still takes about 3 minutes (dd line output):
    0+114029 records in
    0+114029 records out
    3947888640 bytes transferred in 171.268633 secs (23050856 bytes/sec)
    
    real    2m51.282s
    user    2m14.160s
    sys     0m8.577s
    
  2. Confirm that the RPi boots from the 128GB SD card and seems sane. (Yes, and power reported at 3.2W by mains meter.)
  3. Use parted to create a new partition using all the free space.
    # parted
    GNU Parted 2.3
    Using /dev/mmcblk0
    Welcome to GNU Parted! Type 'help' to view a list of commands.
    (parted) print free
    Model: SD  (sd/mmc)
    Disk /dev/mmcblk0: 128GB
    Sector size (logical/physical): 512B/512B
    Partition Table: msdos
    
    Number  Start   End     Size    Type     File system  Flags
            32.3kB  4194kB  4162kB           Free Space
     1      4194kB  62.9MB  58.7MB  primary  fat16        lba
     2      62.9MB  3948MB  3885MB  primary  ext4
            3948MB  128GB   124GB            Free Space
    
    (parted) print free
    Model: SD  (sd/mmc)
    Disk /dev/mmcblk0: 128GB
    Sector size (logical/physical): 512B/512B
    Partition Table: msdos
    
    Number  Start   End     Size    Type     File system  Flags
            32.3kB  4194kB  4162kB           Free Space
     1      4194kB  62.9MB  58.7MB  primary  fat16        lba
     2      62.9MB  3948MB  3885MB  primary  ext4
     3      3948MB  128GB   124GB   primary
    
  4. Use mkfs to make the new partition (then add to fstab).
    mkfs -t ext4 -i 32768 -L data -O ^resize_inode,dir_index,sparse_super /dev/mmcblk0p3
    

    Power rose to a peak of about 4.4W (mains), and the output was:

    super /dev/mmcblk0p3
    mke2fs 1.42.5 (29-Jul-2012)
    Filesystem label=data
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    Stride=0 blocks, Stripe width=0 blocks
    3788800 inodes, 30300672 blocks
    1515033 blocks (5.00%) reserved for the super user
    First data block=0
    925 block groups
    32768 blocks per group, 32768 fragments per group
    4096 inodes per group
    Superblock backups stored on blocks:
            32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
            4096000, 7962624, 11239424, 20480000, 23887872
    
    Allocating group tables: done
    Writing inode tables: done
    Creating journal (32768 blocks): done
    Writing superblocks and filesystem accounting information: done
    
  5. Add new partition/line to fstab with sensible mount options.
    /dev/mmcblk0p3  /local          ext4    defaults,noatime,commit=300  0       2
    
    And after a mount -a I can see it, 109GB free:
    # df -h
    Filesystem      Size  Used Avail Use% Mounted on
    rootfs          3.5G  1.8G  1.6G  53% /
    /dev/root       3.5G  1.8G  1.6G  53% /
    devtmpfs        239M     0  239M   0% /dev
    tmpfs            49M  216K   49M   1% /run
    tmpfs           5.0M     0  5.0M   0% /run/lock
    tmpfs            98M     0   98M   0% /run/shm
    /dev/mmcblk0p1   56M  9.5M   47M  17% /boot
    /dev/mmcblk0p3  115G   20K  109G   1% /local
    
    I've adjusted the default commit interval up from the default 5s on / also, to reduce disc traffic, giving a new /etc/fstab as so:
    proc            /proc           proc    defaults          0       0
    /dev/mmcblk0p1  /boot           vfat    defaults          0       2
    /dev/mmcblk0p2  /               ext4    defaults,noatime,commit=120  0       1
    /dev/mmcblk0p3  /local          ext4    defaults,noatime,commit=300  0       2
    # a swapfile is not a swap partition, so no using swapon|off from here on, use dphys-swapfile swap[on|off]  for that
    

I rebooted to check that all the appropriate changes 'stuck' including the new mount options. All seemed well.

Done: backup taken of RPi card as of this morning, and 128GB card cloned to and with new huge data partition!

I have re-enabled the fake-hwclock so that log files written doing boot have more sensible timestamps!

2014-06-28: Analogue Input for Battery Voltage Monitoring

battV

I have ordered an ABElectronics ADC-DAC Pi with two analogue input channels to enable me to monitor battery levels as I do now using the k8055. (I may not use the outputs at all.) Hat-tip for excellent customer service, by the way!

In preparation I downloaded one of their sample code files, compiled with with the gcc C compiler already present on the RPi. I ran it for sheer devilment even though the hardware is not yet here!

wget https://github.com/abelectronicsuk/adcdacpi/raw/master/adc.c
gcc -O adc.c
sudo ./a.out

and the output is:

0.000000
Elapsed time: 8193 milliseconds

which indicates well under 1ms per sample/reading, and that missing results in a 'safe' zero reading rather than (say) a hang.

A very small amount of code should be able to capture the two voltages and make them available to a script just like the k8055 script, though I may take the opportunity to radically revise how that works.

Given that gcc is "built-in" and that running the power management and stats code quickly saves energy, it might indeed be better to move the bulk of the logic into the C code itself. Certainly some of the arithmetic and logical operations would be clearer, and orders of magnitude faster!

One possible disadvantage of this MCP3202-based circuit is that it measures relative to the supply voltage which might easily wobble +/-10% without harm. Whereas I need to measure typically a 0.1V change in ~12V, or <1%. So I may have to switch to a different ADC card with a built-in reference. Though even there, noise/drops in the ground connection would impact accuracy.

2014-06-28: Security Tweaks

I have installed fail3ban as a test:

sudo apt-get install fail2ban

Note that the config is in /etc/fail2ban/jail.conf and I've added some local overrides in the jail.local file, eg like (but not these exact values):

# Local overrides.
[ssh]
maxretry = 5
findtime = 800
bantime  = 900

These make banning a little more aggressive than usual.

Trimming logging output too much may inhibit fail2ban.

I've created a file /etc/network/iptables that contains iptables rules such as:

# Accept anything on loopback.
-A INPUT -i lo -j ACCEPT
# Handle normal inbound traffic not otherwise dealt with so far.
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -j tcp_inbound
-A INPUT -p udp -j udp_inbound
-A INPUT -j DROP
-A tcp_inbound -p tcp -m tcp --dport 123 -j ACCEPT
-A tcp_inbound -p tcp -m tcp --dport 80 -j ACCEPT
-A tcp_inbound -p tcp -m tcp --dport 53 -j ACCEPT
-A tcp_inbound -p tcp -m tcp --dport 25 -j ACCEPT
-A tcp_inbound -p tcp -m tcp --dport 22 -j ACCEPT
-A tcp_inbound -p tcp -j RETURN
-A udp_inbound -p udp -m udp --dport 53 -j ACCEPT
-A udp_inbound -p udp -m udp --dport 123 -j ACCEPT
-A udp_inbound -p udp -j RETURN
COMMIT

to drop any unexpected traffic, ie to ports other than we might wish to answer.

At the end of the section in /etc/network/interfaces for eth0 add:

pre-up iptables-restore < /etc/network/iptables

to start iptables before bringing the (wired) network up.

Since fail2ban will also be using iptables, I have to hope that they play nicely together...

2014-06-29: Java and SVN

I'm starting to test out some of the major components that will need to be shifted from the SheevaPlug, plus many many packages from gnuplot and optipng and svn through to some of my primary Java applications.

I notice that Java is running at about 2/3rds the speed on the SheevaPlug, which would make sense just comparing clock rates, so I could have some of that back if necessary by overclocking.

A small Java application that (re)computes GB grid carbon intensity, updates some Web pages and flag files, and posts to Twitter, works just fine. User time up from about 4s to 6s.

My largest Java application from the SheevaPlug, my Tomcat-hosted WAR, is pretty slow to start up but is possibly more efficient with memory than before (possibly because of latest JDK vs 'embedded' Java 7).

But the point is that things are working as I copy them across to try out.

To try to improve start-up time I'm trying 'modest' overclocking (to 800MHz, all other clocks and voltages unchanged) set by raspi-config and I have initial_turbo set to try to get to the cpufreq governor quickly! 700MHz is the default ARM clock speed (arm_freq).

# Work with CPU speed governor to save some juice...
# Mild overclocking for when we need it.
initial_turbo=60
force_turbo=0 #turns on frequency scaling
arm_freq=800
arm_freq_min=100 #sets min frequency
core_freq=250
sdram_freq=400
over_voltage=0

Time to boot measured from power being supplied to the board up to when all the LAN LEDs are turned off (in rc.local) and ssh login is possible is ~105s (and a little under 20m to settle down into a reasonably steady state) including the large Java Web app starting up.

I am also trying Oracle's Java 8 (oracle-java8-jdk) in the hope that this is more optimised for ARM/RPi, eg to better use hard float. So far it doesn't seem to have broken anything, but I'm not holding out lots of hope! The Java 7 and 8 Oracle packages (nice to have a choice of official JDKs!):

/usr/lib/jvm/jdk-7-oracle-armhf
/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt

At least the is no longer a PermGen in 8, which saves one config headache!

2014-06-30: Performance Again

I don't need X Windows for the Pi (it can be rescued from the text console), so some RAM could be spared at runtime:

update-rc.d lightdm disable

Also I want to try to run without (slow, SD-card-wearing) swap at all, so it can be disabled entirely for now:

sudo update-rc.d dphys-swapfile disable

fail2ban seems to take enough MB of virtual (~27MB) and resident (~6MB) memory that I may turn it off again or run it intermittently. Although it makes me feel good about detecting ssh attackers I'm not sure that it's actually protecting me from much, and it's preventing me turning down logging in the auth.log also! I'll decide when I start bringing up other services that need (virtual) memory.

Here are the top few processes by virtual memory use:

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 2272 root      20   0  272m 145m 9068 S   1.6 30.0   9:55.04 java
 2218 root      20   0 27976 1552 1112 S   0.0  0.3   0:00.06 rsyslogd
 2361 root      20   0 27200 6048 2400 S   0.3  1.2   0:03.97 fail2ban-server
 2590 root      20   0 26528 3688 2620 S   0.0  0.7   0:00.20 console-kit-dae
 2657 root      20   0 23312 2932 2456 S   0.0  0.6   0:00.15 polkitd

console-kit-daemon and polkitd might also be destined for the chop or at least some tuning...

As per this thread, adding one line to the end of /etc/default/fail2ban about halves VIRT usage:

ulimit -s 256

and knocks it down into fifth place:

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 2272 root      20   0  272m 148m 9036 S   2.9 30.5  19:26.93 java
 2218 root      20   0 27976 1552 1112 S   0.0  0.3   0:00.07 rsyslogd
 2590 root      20   0 26528 3700 2620 S   0.0  0.7   0:00.23 console-kit-dae
 2657 root      20   0 23312 2932 2456 S   0.0  0.6   0:00.16 polkitd
 3063 root      20   0 12832 6044 2396 S   0.3  1.2   0:03.66 fail2ban-server

Stack-size reduction is probably going to be needed for Apache (httpd) and others as it was for the SheevaPlug, especially in the absence of zram. I had inserted this in the apache2 init.d script for example:

# NPTL (modern Linux threads) defaults the thread stack size to the setting
# of your stack resource limit. The system-wide default for this is 8MB,
# which is waaay exaggerated when running httpd.
# 512kB should be more than enough (AIX manages on 96kB, Netware on 64kB).
ulimit -s 512

If feeling very bold I could put the following in /etc/security/limits.conf to reduce the default 'soft' stack size from ~8MB as above for all processes, at a significant risk of breaking things...

*                soft    stack           512
root             soft    stack           512
*                hard    stack           2048
root             hard    stack           2048

This may also adjust environment and command-line space. See also Tweaking stack size of Linux processes to reduce swapping. However, as it doesn't seem to work I'll skip that solution!

Inserting high up in /etc/init.d/rsyslog the following:

ulimit -s 512

does make a dramatic change to rsyslog's VIRT:

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 3044 root      20   0  4936 1428 1084 S   0.0  0.3   0:00.02 rsyslogd

down from ~30MB to ~5MB, but I really don't want to hand-edit lots of individual init.d scripts if I can avoid doing so, and it's not even clear what to edit for console-kit-daemon and polkitd. Using /etc/initscript would be a sledgehammer...

I similarly edited /etc/init.d/dbus with an early ulimit, and polkitd too is much improved:

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 2634 root      20   0  6928 2928 2456 S   0.0  0.6   0:00.16 polkitd

Now I'm getting somewhere...

# apt-get remove consolekit
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be REMOVED:
  consolekit lightdm policykit-1
0 upgraded, 0 newly installed, 3 to remove and 4 not upgraded.

which now leaves the top VIRT users as:

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 2266 root      20   0  270m 148m 9012 S  98.6 30.6   8:28.94 java
 2562 root      20   0  9776 3212 2588 S   0.0  0.6   0:00.22 sshd
 2352 root      20   0 11328 6012 2364 S   0.3  1.2   0:03.95 fail2ban-server
 2641 dhd       20   0  6724 3852 1508 S   0.0  0.8   0:01.25 bash
 2667 root      20   0  4752 1824 1452 S   0.0  0.4   0:00.05 bash

which is much better! But fail2ban may still get disabled, and Apache et al may still need individual ulimit treatment when set up.

I have removed some services that I don't need and that may consume resources and represent a mild security hazard:

apt-get remove nfs-common
apt-get remove nfs-kernel-server

A couple of days later I started logging/collecting 5-minute samples of CPU temperature from /sys/class/thermal/thermal_zone0/temp to look for evidence of overheating or patterns, but nothing much is evident from an initial graph of a little over a day. (The big spike around 8am was probably from direct sunlight on the RPi!)

20140708 RPi cputemp
CPU temperature log after a few days.

2014-07-05: GPIO

RPi with IO boards from above

I have built a very simple 'shield' for the RPi with some matrix board and a suitable socket stacks on top of the RTC board.

On that shield I currently have currently placed a pair of screw terminals connected to GND and to GPIO25 (via a 100Ω resistor for a tiny degree of protection, eg against inductance) and an LED via a 4k7 resistor to GPIO25 also so I can see when the line is on.

If not done since boot, or if subsequently 'unexport'ed, the following incantation (as root) makes GPIO25 available in the filesystem, as an output, eg for shell access:

echo 25 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio25/direction

Then turning the output on requires from the shell as root:

echo 1 > /sys/class/gpio/gpio25/value

and off:

echo 0 > /sys/class/gpio/gpio25/value

So here is a simple script to be run as root to turn my desk light on or off:

#!/bin/sh

# Turn on/off the desk light (on GPIO25).
# If $1 is not "on" then turn it off.

# Set up GPIO if required.
if [ ! -e /sys/class/gpio/gpio25/value ]; then
    echo 25 > /sys/class/gpio/export
    echo out > /sys/class/gpio/gpio25/direction
fi

if [ "on" = "$1" ]; then
    echo 1 > /sys/class/gpio/gpio25/value
else
    echo 0 > /sys/class/gpio/gpio25/value
fi

exit 0

I have wired up a 3.5A/24VDC 3V-input SSR (Solid State Relay), part CN024D05 ie RS720-3940, with its input from GPIO25 (via a longish cable run to its own box) and output in series with a nominal 4.5W 12V MR16 LED (and back-EMF fast protection diode) powered at 12V from my off-grid system, and I now have a software-controlled solar-powered desk light!

Note that I did not common the grounds, ie the signal and power are separate, which avoids setting up any ground loops or unwanted flows through the RPi.

Not quite I/O but I just installed access to the RPi's hardware RNG with:

sudo apt-get install rng-tools

and added to /etc/modules

bcm2708-rng

which provides a /dev/hwrng binary readable device, which amongst other things I will use with my EntropyPool Web service in due course.

As an example (root) can dump a single random byte in decimal (0--255), eg for use in a shell script, with:

hexdump -n1 -e '/1 "%u\n"' /dev/hwrng

With /dev/urandom all users will likely be able to run it, and not block.

It would be possible to set up a crude randomised anti-burglar light in summer with entries in root's crontab such as:

1 22 * 4-10 * /usr/local/bin/desklightGPIO/desklight off
*/5 18-21 * 4-10 * if [ `hexdump -n1 -e '/1 "\%u"' /dev/urandom` -gt 50 ]; then /usr/local/bin/desklightGPIO/desklight on; fi

I added early in /etc/init.d/rng-tools

ulimit -s 512

to reduce rngd's use of virtual memory from ~6MB to ~3MB.

ADC

To use ABElectronics' ADC Pi Version 2.x I first have to change its i2c address not to clash with the RTC at 0x68, so I've chosen the 0x6A/0x6B configuration from their datasheet.

This board is based on the MCP3424.

I'm likely to have to do something like:

echo mcp3424 0x6a > /sys/class/i2c-adapter/i2c-1/new_device
echo mcp3424 0x6b > /sys/class/i2c-adapter/i2c-1/new_device

in /etc/rc.local to tell the system that the devices are present, and then maybe C or C++ or Python or i2cget and i2cset from the shell to read and write it.

Having plugged the board in (I now have a triple-decker of RTC, ADC, and my 'shield') I ran:

# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- UU -- 6a 6b -- -- -- --
70: -- -- -- -- -- -- -- --

which confirms the new devices visible at 0x6a and 0x6b.

I then manually ran, and added to /etc/rc.local:

echo mcp3424 0x6a > /sys/class/i2c-adapter/i2c-1/new_device
echo mcp3424 0x6b > /sys/class/i2c-adapter/i2c-1/new_device
# ls -ald /sys/class/i2c-adapter/i2c-1/1-*
drwxr-xr-x 3 root root 0 Jul  5 21:26 /sys/class/i2c-adapter/i2c-1/1-003b
drwxr-xr-x 3 root root 0 Jul  5 21:26 /sys/class/i2c-adapter/i2c-1/1-004c
drwxr-xr-x 4 root root 0 Jul  5 21:12 /sys/class/i2c-adapter/i2c-1/1-0068
drwxr-xr-x 3 root root 0 Jul  5 21:19 /sys/class/i2c-adapter/i2c-1/1-006a
drwxr-xr-x 3 root root 0 Jul  5 21:19 /sys/class/i2c-adapter/i2c-1/1-006b

shows the devices at 0x68 and 0x6b.

As an extremely crude initial detection of ambient light levels I wired a 1M-dark LDR from 5V to input channel 8, with the expectation of getting near 0 output in dark and max in bright light. The i2c... tools are a little crude, but:

i2cset -y 1 0x6b 0xe0; sleep 1; i2cget -y 1 0x6b

Does a one-shot maximum-speed conversion of the input on channel 4 of the ADC on 0x6b, ie channel 8 of the board, and returns the top nybble of the result, eg values ranging from 0x00 to 0x07 at my desktop at the moment by drawing the curtains or opening them. I could probably skip the sleep given the conversion speed! I can get the next 8 bits with i2cget -y 1 0x6b 0 w but the extra data is at this stage probably not needed for, for example, a crude day/night sensor.

Thus the simple anti-burglar cron light might be crudely updated as:

1 22 * 4-10 * /usr/local/bin/desklightGPIO/desklight off
*/5 18-21 * 4-10 * i2cset -y 1 0x6b 0xe0 && if [ `hexdump -n1 -e '/1 "\%u"' /dev/urandom` -gt 50 -a `i2cget -y 1 0x6b` = "0x00" ]; then /usr/local/bin/desklightGPIO/desklight on; fi

See the power management C++ code, intended to be run periodically (ie every few minutes) from crontab, and which contains i2C support for the LDR amongst other things.

Next I shall take feeds from 5V and both nominal 12V battery supplies (though temporarily close to the load near the RPi) via 47kΩ resistors. Given the further 10kΩ to each ADC input, and the 6.8kΩ to ground, and a FSD of 2.048V, the full-scale should now be ~((47+10+6.8)/6.8)*2.048V = ~19.22V ie ~9.382mV/ulp. The 47kΩ resistors at ±1% tolerance, and the tolerance of the on-board 10kΩ and 6.8kΩ is unknown, so I should probably take the 19.22V as a starting point then calibrate against known values if possible for each ADC input. I may also measure the 3.3V rail. I hope to be able to measure the current draw on the 3.3V side from the 5V rail which should be the bulk of the power consumed by the RPi itself, and later into the 5V side with a high-side current-sense amplifier such as MAX4080SAUA+ or TS1101-25EG6T or INA138NA/250. Channel assignments are / may be:

  1. Batt1 (blue wire, red sensor wire, LA), done
  2. 5V supply voltage monitor
  3. 5V supply current sense
  4. Batt2 (purple wire, Li), done
  5. 3.3V supply voltage monitor
  6. 3.3V supply current sense
  7. LDR, done

Note that ADC1 (channels 1--4) and ADC2 (channels 5--8) can be read in parallel if required, doubling throughput.

Having wired up Batt1 and Batt1, initial calibration readings (against a cheap DMM) were:

  • BATT1 1328 raw = 12.48V direct to local busbar (calc 12.46V).
  • BATT2 1359 raw = 12.77V direct to local busbar (calc 12.75V).

The DMM values match very closely with calculated values, so no fudge factor will be applied per channel. (Note that when connecting to the remote sense terminals with additional in-line resistance the multiplier will need to be adjusted.)

Note that these measured voltages are ~0.6V lower than measured at the k8055, (13.0V and 13.4V) which suggests possibly at least that much voltage drop in just the +ve side of the wiring segment from the service cupboard downstairs to the desk busbar, which would be a bit sad, and a motivator to move equipment (eg WiFi and RPi) down to the service cupboard, eliminating that segment for most uses. Measuring at the Li battery (Batt2) in the with the DMM gives 13.00V, and measuring at the same junction board for Batt1 gives 12.50V, which suggests that possibly the wiring is OK and the k8055/SheevaPlug is miscalibrated, and that I've been beating my batteries up more than is wise!

2014-07-11: I have bought a number of high-side current measuring devices to play with, including the digital I2C-based Adafruit INA219 Current Sensor Breakout via oomlout with the aim of continuously and accurately monitoring power draw from the 12V nominal off-grid solar PV battery stores, for normal logging and at a higher rate for performance/consumption tuning. I may have to remove the on-board SCL/SDA 10kΩ pull-up resistors to avoid overloading the i2c bus (there are other pull-ups already).

Seeing how close the shunt inputs are to low-voltage parts of the board is making me nervous. A small slip/short could toast my RPi and everything connected, which would be particularly tiresome if the SD card was destroyed. Hmm, will have a careful think!

Having wired it up I look for signs of it appearing at address 0x40:

# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- UU -- 6a 6b -- -- -- --
70: -- -- -- -- -- -- -- --
# i2cget -y 1 0x40 0 w
0x9f39

and there it is: I can try some measuring once it is all wired up...

Some time later... I now have power monitoring working, currently measuring supply to the SheevaPlug. Here are some monitoring lines (5-second intervals):

AL 30 B1 12597 B2 13026 P 2581
AL 30 B1 12597 B2 13026 P 2584
AL 30 B1 12597 B2 12998 P 4250
AL 30 B1 12597 B2 12988 P 4306

The first two are ~2.5W, and the last two are ~4.3W with the CPU busy. Note that when this measurement was taken all USB devices had been unplugged, so this represents consumption by the SheevaPlug itself.

INA initial read 39 9f.
INA bus voltage read 61 c2 = 12384.
INA shunt voltage read  7 f3 = 0.020350V.
INA current read  f e6 = 0.203500A.
INA power read  9 f2 = 2546mW.

ie that the voltage into the 5V regulator is 12.4V and the current 204mA.

2014-07-11: Moving Services

2014-07-11: NTP: the NTP configuration was updated with some of the features from the SheevaPlug to be more suitable for the free public service that ntp.exnet.com provides, and the two main DNS aliases were moved across in stages to the RPi. All seems satisfactory.

Even without being part of one of the NTP pools (which has proven too burdensome in the past in CPU and bandwidth terms, I think), it is clear that the NTP service is still supporting several hundred clients.

Gallery/PG2K: moved the PG2K master from SheevaPlug to RPi, copying the data from the USB thumbdrive on to the RPi SD card, then (on 2014-07-12) changing the DNS entry (with TTL of ~1d) then bringing down the old master, capturing some logs and config and history, bringing up the new master with the history, and prodding one of the mirrors to connect immediately to the new master (others will need DNS timeouts).

random.hd.org: his was a good moment to move the co-located random.hd.org across also, updating DNS and Tomcat appropriately, and random.hd.org's own config to make use of the new hardware RNG support and local environmental data.

2014-07-12: Apache: starting to set up Apache (2) to bring over the static sites by degrees:

apt-get install apache2

which yielded the error:

[....] Starting web server: apache2(98)Address already in use: make_sock: could
not bind to address 0.0.0.0:80
no listening sockets available, shutting down
Unable to open logs
Action 'start' failed.
The Apache error log may have more information.
 failed!
invoke-rc.d: initscript apache2, action "start" failed.

because Tomcat already has one of the addresses bound. Editing /etc/apache2/ports.conf to listen on appropriate addresses allows Apache to start. There will be plenty of tuning and tweaking to come, starting with some ulimit magic (in envvars) to reduce stack space, and cutting the number of servers/threads/runners to fit this small box!

2014-07-14: displaying the Off-Grid Power page again, this time with added live power consumption and local 12V bus volts, albeit SheevaPlug power draw initially rather than the RPi.

A small experiment indicates that plugging in the Sunny Beam via a 2-way USB hub bumps up consumption by ~1W, thought it is possible that the Sunny Beam battery is charging.

Missing out the hub seems to only cause an additional draw of ~200mW, in line with what was observed before.

Time to get sendmail set up. Always a fun one.

# apt-get install sendmail-bin

It's removed exim (which I installed just to get lockfile, it's creating keys and all sorts of exciting stuff, and it's inviting me to run sendmailconfig later. I will deliver mail to sendmail by tunnelling over SSH as in the old days, as I know how to do it and it's safe.

Apprently the following scary warnings from doing a make are not fatal:

*** ERROR: FEATURE() should be before MAILER()
*** MAILER(`local') must appear after FEATURE(`always_add_domain')*** ERROR:
FEATURE() should be before MAILER()
*** MAILER(`local') must appear after FEATURE(`allmasquerade')*** ERROR:
FEATURE() should be before MAILER()

but I trimmed the offending trailing lines from sendmail.mc anyway without apparent bad results.

And:

# apt-get install sensible-mda

I'm also going to set up a simple secure POP3 daemon, rather than tunnelling a session over SSH. Direct secure access will need a slightly more open firewall and a greater attack surface.

# apt-get install dovecot-pop3d

and I've enabled the dovecot and sasl jails for fail2ban as a precaution.

Dovecot has rather intimidating configuration (and I'm used to sendmail's!). First up is to drastically trim its resource limits for the RPi and more or less my sole usage in /etc/dovecot/conf.d/10-master.conf and enable just pop3s.

2014-07-16: the DNS primary will be BIND:

# apt-get install bind9 bind9-doc

Some tweaking of current usage was necessary, including extra care on file permissions and ownership since the daemon is now running as the user 'bind'.

2014-07-11: Services Moved from SheevaPlug

Services moved, partially moved, or yet-to-be moved:

  • NTP done: 2014-07-11, all aliases pointing at re-configured RPi. Apparently there are several hundred clients...
  • Gallery done: 2014-07-11.
  • SVN: done: 2014-07-12.
  • Apache: done 2014-07-13.
  • SMTP/POP3: done: 2014-07-16.
  • DNS: done: 2014-07-16.
  • Dump-load control done: 2014-08-09.
  • OpenTRV stats monitor done: 2014-08-11.

2014-07-16: Reboot!

As of late evening 2014-07-16 (22:30BST) the SheevaPlug is shutdown and disconnected, and the RPi is providing all services. Boot-up power for the RPi is ~2.7W vs the 2.5W--4.4W draw of the SheevaPlug (without k8055 or USB hub(s)). About 30m after boot (some services take a long time to fully start) power draw is ~2.3W and the RPi is handling 30 network packets per second.

Note that random misuse of (attacks on) exposed public services such as ssh were pushing up system load and power consumption. A bit of tweaking of sshd against attacks (such options as MaxStartups and AllowUsers) kept down load directly and made it possible for fail2ban to notice the attack and shut out the IP addresses automatically with a noticeable drop in load!

Interestingly the overhead of the cron job to run the powermng sampling including power, adds ~200mW to the apparent load! Putting a 5s sleep ahead of the power measurement then logs a correct ~2.3W typical load.

2014-07-17: B+ First Experiment

I now have a RPi Model B+ and an 8GB microSD card. I'm trying to dd the 4GB image saved above onto the 8GB card (using my Mac) to see if the B+ will boot off it (though I don't actually have keyboard or screen easily to hand at this moment) and what power consumption is.

There is a slight risk that the image will not be suitable, and/or that the tweak that I use to turn off the LAN LEDs to save 50mW (not even immediately obvious on the B+ board) may damage something.

A Model B board (no USB or video or Ethernet connection), after being given a couple of minutes to get through boot, runs at ~2.5W reported drawn by my mains power supply.

The equivalent B+ steady draw, assuming that it booted correctly, is ~1.5W. That probably corresponds to ~1W drawn by the board itself, and an mains adapter efficiency of ~60%.

2014-07-19: B+ Live

I tried to dd (on my Mac) my Model B SD card to a new microSD card (SanDisk Ultra SDSDQUA-128G-G46A, Class 10 / UHS-1, ~£70 from MyMemory), both nominally 128GB. It took ~5h and did not quite work:

[79:/Users/dhd/.ssh] dhd# time dd bs=1m if=/dev/rdisk2 of=/dev/rdisk1
54879+0 records in
54878+0 records out
57543753728 bytes transferred in 7923.878570 secs (7262069 bytes/sec)
dd: /dev/rdisk1: short write on character device
dd: /dev/rdisk1: Input/output error
121942+0 records in
121941+1 records out
127864930304 bytes transferred in 17441.687219 secs (7330995 bytes/sec)

because it turns out that the new card is slightly smaller than the old, thus truncating the last/data partition.

So I logged on on TV console, removed the last partition with fdisk (parted just whined and stupidly refused to let me do anything at all), recreated the final partition, put in an ext4 filesystem again with previous parameters, mounted under /lmnt, mounted the old SD on USB and that old partition (/dev/sda3) on /mnt, and prepared to copy the data partition over.

I tried doing cp -a /mnt/* /lmnt but it seemed to hang, so instead I did an rsync, which worked, and took about 8h.

Note that the llctl program still seems to work. Though I can only see two of the three LEDs (moved to the network socket). And indeed of my three stacked GPIO cards (RTC, ADC and my own hand-crafted) all worked exactly as before. Well done RPi Foundation on backwards compatibility!

Power consumption seems to be down to ~1.5W once everything is at steady state, so a reduction of ~0.8W/~30%.

(Note that the power figure includes any losses in the 12V-to-5V PT78HT205V 10W, 5V, 2A switching regulator, and any USB devices plugged in.) Max (stress) consumptions of the various RPi models are reported as Pi1B+/Pi2B/Pi3B 0.35A/0.82A/1.34A circa 2016.

2014-08-11: Power Again

With all services moved over, and a new one or two, some observations:

  • The Sunny Beam monitor permanently plugged into USB to allow continuous monitoring draws ~100mW, in part apparently because it doesn't turn its graphics off, so a USB power-down arrangement might avoid some or all of that, especially at night and in winter when readings are not useful for many hours.
  • The new dump-load relay (modified from the latest OpenTRV boiler control) uses about 250mW when operating/dumping, though is better than the ~1W of the previous arrangement with the 12V relay driven by the k8055. A dimmer LED (1k load resistor?) could save up to about 10% of that. (Note: seems to have stuck 'on' during evening of 2016-10-22.)
  • It's not yet clear how much the RXTX library hurts power consumption; at several hundred (unnecessary) wakeups per second the effect was significant for the SheevaPlug and MacBook Air. Initial observations suggest another 100mW--200mW, possibly from stopping the CPU sleeping properly as expected.

2014-08-18: I tried lowering the network port speed to see if that made any difference to power drain (watching the reported number on my powermng tool looping) because at 10Mbps Ethernet may be able to idle more quietly, trying:

# ethtool -s eth0 autoneg off speed 10

and then:

# ethtool -s eth0 autoneg on

to switch back to a negotiated (100Mbps duplex) rate, and if there was any difference at all it was minor and 10Mbps was higher power.

2015-05-15: Device Tree

2015-05-15: an apt-get update then dist-upgrade brought me into the wonderful world of device tree, signalled by the fact that I no longer open the i2c device that I'd been using.

Following this exposition I ran:

sudo raspi-config

to enable device tree and i2c, which had the effect of adding this to the end of /boot/config.txt:

dtparam=i2c_arm=on

To Do