Arduino + Raspberry Pi + Sending data to the web

Ever since I needed a simple thermocouple data logger at work and found that they cost at least $600, it's been a little bit of a hobby of mine to get small, cheap computers to do useful things. After all, they used the equivalent of about 3 Commodore 64s to fly to the moon, and these things have about the same computing power as a modern day calculator, so why is it so hard/expensive to set up something with similar computing power to simply record data?

The alternative to a \$600 thermocouple data logger? A microcontroller like the Arduino (~$25) connected to a Raspberry Pi (~$40) running a database and webserver. That means I can charge $535 for brain power and still be competitive ;). The Arduino+Raspberry Pi also happens to be an infinitely more powerful system than a thermocouple data logger. You can basically plug in any sensor that you want, program any control scheme that you want and now, communicate with anything that you want by sending data to the internet.

Note: For the specific case outlined in these instructions, you don't actually need an Arduino since you can hook up directly to the GPIO pins on the Raspberry Pi, but this requires some connector cables that I don't have and adding an Arduino is useful for other projects as well.

The Raspberry Pi + Arduino looks like this:

Each component easily fits into the palm of my hand.

So, what's going on here?

The Arduino is plugged into the Raspberry Pi via the USB port. The Raspberry Pi communicates with the Arduino (via the USB port) using serial communication programmed using Python (requiring the module pySerial). The Python program logs the data from the Arduino and saves the data to a file which can then be read by a webserver running on the Raspberry Pi.

Here's how to set everything up:
(Most of this is just directing you to other people's instructions)

What you'll need:

  1. An Arduino Uno (or some other Arduino compatible variant)
  2. A Raspberry Pi with SD Micro card and a 5V/~1A micro USB power supply and (perhaps1) a powered USB hub
  3. An internet connection
  4. For the simple example of a temperature and light intensity logger controlled by the Arduino: i) a 10K thermistor ii) a 10K resistor iii) 10K photocell iv) a LED v) ~240ohm resistor vi) a breadboard. All of these components can be found in any "getting started with Arduino kit".
1The Raspberry Pi is still a relatively new device and there seems to be a couple of uncertainties about how much power can be delivered via the USB ports, what peripherals it can handle and how many. Some USB hubs don't seem to work, some do. If your Raspberry Pi isn't working as you expect, then it could be a power issue.

Update: Aug 30, 2016 - Better instructions for Raspberry Pi setup are now available, such as here
Step 1. Install Debian linux onto the SD Micro card for the Raspberry Pi: http://elinux.org/RPi_Easy_SD_Card_Setup

Step 2. Make sure you can boot into your Raspberry Pi system (default username/password: pi/raspberry)

Step 3. Change default password:

pi@raspberrypi:~$ passwd [enter] [type your new password]

Step 4. Configure your Raspberry Pi by installing:

  1. SSH: http://fusionstrike.com/2012/setting-ssh-ftp-raspberry-pi-debian
  2. Apache web server: http://fusionstrike.com/2012/installing-apache2-raspberry-pi-debian
  3. PHP: http://fusionstrike.com/2012/setting-php-raspberry-pi-debian
  4. MySQL: http://fusionstrike.com/2012/setting-mysql-raspberry-pi-debian
  5. Gnuplot (for making graphs):
    pi@raspberrypi:~$ sudo apt-get install gnuplot
  6. python-serial module (for using python to communicate with the Arduino):
    pi@raspberrypi:~$ sudo apt-get install python-serial
Step 5. If you want, reclaim space on your SD card: https://projects.drogon.net/raspberry-pi/initial-setup1/

Step 6. Upload a program to your Arduino using your normal everyday PC. To help you out, I've made a simple program that logs temperature and light intensity data from a thermistor and a photocell (it records data when it senses that the temperature changes by more than 0.4oC). Just copy/paste into the Arduino IDE and upload to your Arduino device:

/*
By Ben Kenney - July 2012
Use as you will, mileage may vary, don't short circuit your electronics, 
I won't be held responsible for anything you do, etc...
*/

#include <math.h>

const int ledRedDigital = 9;
const int thermistorAnalogIn = 0;
const int LM34AnalogIn = 1;
const int photocellAnalogIn = 2;

float temp_therm = 0.0;
float temp_LM34 = 0.0;
float light_photocell = 0.0;

float temp_therm_old = 0.0;
float temp_LM34_old = 0.0;


double Thermister(int RawADC) {
 //convert voltage into a temperature
 double Temp;
 Temp = log(((10240000/RawADC) - 10000));
 Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
 Temp = Temp - 273.15;            // Convert Kelvin to Celcius
 return Temp;
}

void setup() {
 Serial.begin(9600);
 pinMode(ledRedDigital,OUTPUT);
}

void loop() {
  temp_therm = Thermister(analogRead(thermistorAnalogIn)); // thermistor temp
  temp_LM34 = (analogRead(LM34AnalogIn)*5.0*100.0)/1024.0; // LM34 temp (F)
  temp_LM34 = (temp_LM34-32.0)*5.0/9.0; // LM34 temp (C)
  light_photocell = analogRead(photocellAnalogIn); // photocell value
   
  // record data only if thermistor temperature changes by more than 0.4 deg C 
  if ( abs(temp_therm-temp_therm_old) > 0.4 ) {
    
    Serial.print(light_photocell);Serial.print(",");
    Serial.print(temp_LM34);Serial.print(",");
    Serial.println(temp_therm);
    digitalWrite(ledRedDigital,HIGH); //blink LED if we make a measurement
    delay(500);
  } 
  digitalWrite(ledRedDigital,LOW);
  temp_therm_old = temp_therm;
  //temp_LM34_old = temp_LM34;
  
 delay(1000*3); // wait 3 seconds and start loop over again
}

Step 7. Hook up the thermistor/photocell to your breadboard and Arduino:

Step 8. Hook up the Arduino to the Raspberry Pi via USB

Step 9. On the Raspberry Pi, make a python program that uses the serial module to read data coming out of the Arduino. The program should then write this data to disk. Something like this should work (name it something like dataLogger.py):

#!/usr/bin/python

'''
by Ben Kenney - July 2012
This program reads data coming from the serial port and saves that data to a text file. It expects data in the format:
"photocell_reading,thermistor_reading"

It assumes that the Arduino shows up in /dev/ttyACM0 on the Raspberry Pi which should happen if you're using Debian.
'''


import serial
from time import strftime
from datetime import datetime, time

ser = serial.Serial('/dev/ttyACM0',9600)

startTime = datetime.now()
try:
	while 1:
		line=ser.readline().rstrip()
		light,temp2=line.split(",")
		now = datetime.now()
		elapsedTime = now-startTime
		elapsedSeconds = (elapsedTime.microseconds+(elapsedTime.days*24*3600+elapsedTime.seconds)*10**6)/10**6
		print("%s,%s,%s,%s"%(now.strftime("%Y-%m-%d %H:%M:%S"),elapsedSeconds,light,temp2))
		f=open('tempLog.dat','a')
		print >>f,("%s,%s,%s,%s"%(now.strftime("%Y-%m-%d %H:%M:%S"),elapsedSeconds,light,temp2))
		f.close()
except KeyboardInterrupt:
	print "\ndone"

This program saves the data being collected by the Arduino into a file called tempLog.dat.

Step 10. Run the python program to log data (note: I suggest you run this program within screen so that you can do other things with your Raspberry Pi while it's collecting data):

pi@raspberrypi:~$ sudo apt-get install screen
pi@raspberrypi:~$ screen -S collectData -d -m python dataLogger.py

Step 11. Use Gnuplot (which was installed in step 4.5) to make a graph of the data. To do this, make a small gnuplot script (call it something like plotData.plt):

reset
set datafile separator ","
set term png
set xdata time
set timefmt "%Y-%m-%d %H:%M:%S"
set format x "%b %d %H:%M"
set xtics rotate by -45
set xlabel ""
set ylabel "Temperature (C)"
set y2label "Light Intensity (%)"
set ytics nomirror
set y2tics
set output "data.png"
set key left

plot "tempLog.dat" using 1:4 title "Thermistor" with lines axes x1y1, \
"tempLog.dat" using 1:($3/1024*100.0) title "Photocell" with lines axes x1y2

and make the graph using:

pi@raspberrypi:~$ gnuplot plotData.plt

This will make the file "data.png".

Step 12. Move the file data.png into your web server directory, which defaults to /var/www/

pi@raspberrypi:~$ cp data.png /var/www

This can be set up in a shell script and run automatically using cron.

The end
Finally, the end result: temperature and light coming through my living room window and showing up on the internet via my Raspberry Pi web server:

It does get hot in direct sunlight in Ottawa.

After typing all of this out, it seems like a lot of work, but if you know your way around linux, it's not too bad.