Category Archives: Raspberry Pi

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

Advertisements

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!