Author Archives: chrisbaume

Dual-booting Arch Linux on a Macbook with encryption

This was a tricky one to work out, but here’s how I got there with my MacbookPro 11,1. This may not be the best way, but it’s the only one I could get working.

Firstly, use Disk Utility on OS/X to reduce it’s partition size, allowing enough free space to install Arch. Download the Archboot ISO, put it on a USB key and turn the Macbook on while holding down Alt to boot from it.

Use the Archboot GUI to prepare the storage disk. Don’t let the script do it automatically; use the partitioning program to add the following:

  • EFI partition (128M, type af00)
  • Boot partition (128M, type 8300)
  • System partition (rest of space, type 8e00)

Exit the Archboot GUI, then follow these instructions up to the mkinitcpio part. This will create a LUKS container in the system partition and install LVM partitions. Once that’s done, reboot back into the Archboot GUI.

Set up your key mapping, date/time and network. In the storage disk preparation menu, mount the boot and encrypted system partitions. Use Archboot to select and install all of the base, dev and support packages and configure the system. Exit the GUI before you install the bootloader.

Use this command to log into your new system:

arch-chroot /install /bin/bash

Configure mkinitcpio by adding ‘encrypt’ and ‘lvm2’ to the HOOKS property in /etc/mkinitcpio.conf, and run the following commands:

mkinitcpio -p linux-lts
mkinitcpio -p linux

Edit /etc/default/grub and update the following lines:

GRUB_CMDLINE_LINUX_DEFAULT="quiet rootflags=data=writeback libata.force=noncq"
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sdaX:MyStorage root=/dev/mapper/MyStorage-rootvol"

To generate an EFI bootloader, use the following commands (taken from here)

grub-mkconfig -o /boot/grub/grub.cfg
grub-mkstandalone -o boot.efi -d /usr/lib/grub/x86_64-efi -O x86_64-efi /boot/grub/grub.cfg

Insert a USB key, mount it and copy the boot.efi file.

mount /dev/sdX1 /mnt
cp boot.efi /mnt

In OS/X use Disk Utility to format (‘erase’) the 128MB EFI partition, move the boot.efi file into System/Library/CoreServices/ and create a file in the same directory called SystemVersion.plist, with the following contents:

<?xml version="1.0" encoding="utf-8"?>
  <plist version="1.0">
  <dict>
    <key>ProductBuildVersion</key>
    <string></string>
    <key>ProductName</key>
    <string>Linux</string>
    <key>ProductVersion</key>
    <string>Arch Linux</string>
  </dict>
</plist>

If you’re lucky, you should now be able to boot into Arch by holding down the Alt key while booting. If not, here are some resource which should help you out. Good hunting!

Advertisements

Beer monitoring with my Raspberry Pi

Best Raspberry Pi ProjectsThe secret to brewing great beer at home is making sure that you keep it at the right temperature. This can be tricky when your house doesn’t have a thermostat and you’re not in the house for most of the day. However, by using a cheap and cheerful sensor with a raspberry pi, you can record a log of the temperature and check it over the internet to make sure your beer is brewing nicely.

Hardware

The sensor I used is the DHT11 which, at the time of writing, you can order on eBay for £1.12 delivered. It has a digital interface, so you don’t need to do any calibration or digital conversion as you would with a thermistor. To connect the sensor to the RPi, all you need is a 10k resistor to pull-up the data signal and to make the following connections (see pic).

RPi VCC (pin 1) -> DHT11 pin 1
RPi GPIO4 (pin 7) -> DHT11 pin 2
RPi GND (pin 6) -> DHT11 pin 4

DHT11 wiring diagram

Interfacing

The DHT11 uses its own serial interface, which can be interrogated using the wiringPi C library. To install and compile the library, use the following commands:

sudo apt-get install git-core build-essential
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

This blog post details the code necessary to read the sensor data. The code below has been modified to return only the current temperature and to repeat the request if there is an error. Place the following into a file named dht11.c.

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5
int dht11_val[5]={0,0,0,0,0};

int dht11_read_val()
{
  uint8_t lststate=HIGH;
  uint8_t counter=0;
  uint8_t j=0,i;
  for(i=0;i<5;i++)
     dht11_val[i]=0;
  pinMode(DHT11PIN,OUTPUT);
  digitalWrite(DHT11PIN,LOW);
  delay(18);
  digitalWrite(DHT11PIN,HIGH);
  delayMicroseconds(40);
  pinMode(DHT11PIN,INPUT);
  for(i=0;i<MAX_TIME;i++)   {     counter=0;     while(digitalRead(DHT11PIN)==lststate){       counter++;       delayMicroseconds(1);       if(counter==255)         break;     }     lststate=digitalRead(DHT11PIN);     if(counter==255)        break;     // top 3 transistions are ignored     if((i>=4)&&(i%2==0)){
      dht11_val[j/8]<<=1;       if(counter>16)
        dht11_val[j/8]|=1;
      j++;
    }
  }
  // verify checksum and print the verified data
  if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))
  {
    printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);
    return 1;
  }
  else
    return 0;
}

int main(void)
{
  int attempts=ATTEMPTS;
  if(wiringPiSetup()==-1)
    exit(1);
  while(attempts)
  {
    int success = dht11_read_val();
    if (success) {
      break;
    }
    attempts--;
    delay(500);
  }
  return 0;
}

Compile and execute the source code with the following commands:

gcc -o dht11 dht11.c -L/usr/local/lib -lwiringPi -lpthread
sudo ./dht11

The program should return two numbers – one for relative humidity and the other for temperature.

Logging

The simplest method of creating a log of the temp/humidity is to use a cronjob. The program must be run as root, so use the following command to edit the cron config file:

sudo crontab -e

Add the following line to the end. It will save a timestamp and the temp/humidity every minute to temp.log.

* * * * * echo `date +\%Y\%m\%d\%H\%M\%S`,`/home/pi/wiringPi/dht11` >> /home/pi/temp.log

If that doesn’t seem to be working, the system cron may not be running. The following command will start it, and the line after will make sure it starts every time the RPi turns on:

sudo service cron start
sudo update-rc.d cron defaults

Display

Reading a log file isn’t the easiest way to check how the temp/humidity is changing, but we can use a graphing library to read the log file and plot it. For this, I used DyGraph which is a Javascript library for plotting time-based information. Here is the final .html file I used:

<html>
<head>
<script type="text/javascript" src="dygraph-combined.js"></script>
</head>
<body>





<div id="graphdiv" style="width:750px; height:400px;"></div>





<script type="text/javascript">

  function addZero(num)
  {
    var s=num+"";
    if (s.length < 2) s="0"+s;
    return s;
  }

  function dateFormat(indate)
  {
    var hh = addZero(indate.getHours());
    var MM = addZero(indate.getMinutes());
    //var ss = addZero(indate.getSeconds());
    var dd = addZero(indate.getDate());
    var mm = addZero(indate.getMonth()+1);
    var yyyy = addZero(indate.getFullYear());
    return dd+'/'+mm+' '+hh+':'+MM;
  }

  g = new Dygraph(
    document.getElementById("graphdiv"),
    "temp.log",
    {
      xValueParser: function(x) {
        var date = new Date(x.replace(
          /^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/,
          '$4:$5:$6 $2/$3/$1'
        ));
        return date.getTime();
      },
      axes: {
        x: {
          ticker: Dygraph.dateTicker,
          axisLabelFormatter: function(x) {
            return dateFormat(new Date(x));
          },
          valueFormatter: function(x) {
            return dateFormat(new Date(x));
          }
        }
      },
      labelsDivWidth: 310,
      rollPeriod: 30,
      strokeWidth: 2.0,
      labels: ['Date','Humidity (%)','Temp (°C)']
    }
  );
</script>
</body>
</html>

You can set this up on the RPi by installing a web server like Apache, creating a symlink to the log file, downloading dygraph and saving the above html file as /var/www/temp.html.

sudo apt-get install apache2
ln -s /home/pi/temp.log /var/www/temp.log
wget -P /var/www http://dygraphs.com/dygraph-combined.js

Then use your browser to navigate to 192.168.1.2/temp.html, replacing the IP address with that of your RPi. To be able to access the page from the internet, you’ll have to set up NAT on your router.

Here’s what my final system looks like (click for an interactive demo):
Temp/humidity demo

Using aubio and alsaaudio with Python

The code used in this post no longer works. For an up-to-date example, please see demo_alsa.py.

Aubio is an audio analysis library which contains implementations of some useful algorithms, including pitch detection. It can be used with Python (through SWIG), but the documentation is very light and there doesn’t appear to be any Python-specific instructions.

Below is a small program that listens to the default audio input using alsaaudio, finds the pitch and energy of the signal using aubio, and prints the results to stdout. For the program to work, you will need the aubio and alsaaudio Python libraries installed, which can be done in Ubuntu/Debian with the following command:

sudo apt-get install python python-alsaaudio python-aubio

The smpl_t data type referred to in the code can be replaced by Python’s float type, but the fvec_t type must be populated one-by-one using the fvec_write_sample function.

import alsaaudio, struct
from aubio.task import *

# constants
CHANNELS	= 1
INFORMAT	= alsaaudio.PCM_FORMAT_FLOAT_LE
RATE		= 44100
FRAMESIZE	= 1024
PITCHALG	= aubio_pitch_yin
PITCHOUT	= aubio_pitchm_freq

# set up audio input
recorder=alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE)
recorder.setchannels(CHANNELS)
recorder.setrate(RATE)
recorder.setformat(INFORMAT)
recorder.setperiodsize(FRAMESIZE)

# set up pitch detect
detect = new_aubio_pitchdetection(FRAMESIZE,FRAMESIZE/2,CHANNELS,
                                  RATE,PITCHALG,PITCHOUT)
buf = new_fvec(FRAMESIZE,CHANNELS)

# main loop
runflag = 1
while runflag:

  # read data from audio input
  [length, data]=recorder.read()

  # convert to an array of floats
  floats = struct.unpack('f'*FRAMESIZE,data)

  # copy floats into structure
  for i in range(len(floats)):
    fvec_write_sample(buf, floats[i], 0, i)

  # find pitch of audio frame
  freq = aubio_pitchdetection(detect,buf)

  # find energy of audio frame
  energy = vec_local_energy(buf)

  print "{:10.4f} {:10.4f}".format(freq,energy)

Top 10 tracks of 2012

It’s been nearly a month since 2012 happened, but here’s a list of 10 tracks (in no particular order) that I enjoyed from last year. I hope that you find something new that you like.









Mexico diving video

Back in November, I went SCUBA diving in Mexico. The first week was spent on the island of Cozumel where my girlfriend and I did ten dives, followed by dives in two cenotes – ‘The Pit’ and ‘Pet Cemetery’. For all of the dives, I wore a head-mounted GoPro which recorded over nine hours of footage. I’ve spent the last couple of weekends going through it all and putting the following video together. Hope you like it!

Raspberry Pi UPnP media player

My immediate thought of what to do with my RPi was to set it up so that I could stream audio to the kitchen. I wanted to be able to listen to my music collection (stored on an XBMC server) and podcasts (from my phone), and be able to control everything from my phone. I achieved this by setting up the RPi as a UPnP media renderer, with XBMC as the UPnP media server and my phone as the UPnP control point (and media server). It runs the very minimal GMediaRender on the RPi Debian image. Below is a little tutorial on how I did it:

Packages

Firstly, install all the required software:

sudo apt-get install alsa-base alsa-tools alsa-utils gstreamer0.10-alsa \
gstreamer0.10-ffmpeg gstreamer0.10-fluendo-mp3 gstreamer0.10-plugins-base \
libgstreamer-plugins-base0.10-0 libgstreamer0.10-0 libgstreamer0.10-dev \
gstreamer0.10-plugins-good gstreamer0.10-tools libupnp-dev automake cvs

ALSA setup

Make sure that the username you’re using has permission to access the sound card:

sudo useradd -G audio <username>

To enable the sound card, you need to add the following line to /etc/modules:

snd_bcm2835

After you do that, reboot the machine so that the module is loaded:

sudo reboot

To make sure that ALSA is working, list the devices:

aplay -l

You should see something like this:

card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]

If you want to use the headphone socket instead of audio over HDMI, you’ll need to change the setting:

sudo amixer cset numid=3 1

Finally – to check the sound is working – run the speaker test:

speaker-test

GMediaRender setup

EDIT: As the GMediaRender project appears to be dormant and have some missing features, Henner Zeller has resurrected it back into life in the form of GMediaRender-resurrect. You’re probably better off using his code instead.

You’ll want to use the very latest version of GMediaRender, which can be downloaded from here using CVS:

cvs -d:pserver:anonymous@cvs.sv.gnu.org:/sources/gmrender co .

Once that downloads, run the following commands to compile and install the program:

cd gmrender
./autogen.sh
./configure
make
sudo make install

Now, for the moment of truth, navigate to your home directory and launch the program:

gmediarender -f "Raspberry Pi"

You should be able to use any UPnP control point (such as BubbleUPnP) to send audio from a UPnP media server (like XBMC) to your RPi.

Launch on boot

I’ve been trying to set it up so that GMediaRender launches on boot so that I don’t have to log in every time. None of the techniques I’ve tried so far (crontab @reboot, /etc/rc.local, .bashrc) have worked, so any suggestions are welcome 🙂

EDIT: @MJFComputerServ has kindly pointed me towards this article which explains how to write a /etc/init.d script to launch a program.

Do do this for GMediaRender, copy the following to /etc/init.d/gmediarender

### BEGIN INIT INFO
# Provides: gmediarender
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start GMediaRender at boot time
# Description: Start GMediaRender at boot time.
### END INIT INFO
#! /bin/sh
# /etc/init.d/gmediarender
USER=root
HOME=/root
export USER HOME
case "$1" in
 start)
 echo "Starting GMediaRender"
 /usr/local/bin/gmediarender -f "Raspberry Pi"
 ;;
stop)
 echo "Stopping GMediaRender"
 killall gmediarender
 ;;
*)
 echo "Usage: /etc/init.d/gmediarender {start|stop}"
 exit 1
 ;;
esac
exit 0

Make the file executable:

sudo chmod 755 /etc/init.d/gmediarender

And configure the system to run it on startup:

sudo update-rc.d gmediarender defaults

Works for me – let me know how you get on!