Thermometer (using Arduino and RaspberryPi)

IMG_20140302_181134_1

 

Here is a small project I did to play with my RaspberryPi and my Arduino. I bought both a while ago but didn’t get much chance to play with them. The plan was as follows: to capture the temperature in my living room using a temperature sensor using the arduino, make the arduino write to the Serial port to the RaspberryPi, have a Python program running in the RaspberryPi that reads from the Serial port and then stores the info in an AppEngine Server. In the end, you can point your browser to a certain address and get a plot of the temperature in my living room:

living_room

 

Setup

  • arduino and TO-92 (the sensor): here is a guide how to physically connect the sensor to the arduino.
  • raspberrypi and arduino are connected via an USB cable
  • raspberrypi is powered using a power cord, connected to the internet using an Ethernet cable and has an SD card with Raspbian pre-loaded (if the card came with the Raspberry, it might have already the Raspbian or similar distribution pre-loaded).

Logging in the RaspberryPi

If you have a monitor and a keyboard, you can plug them to the Raspberry. If like me, you don’t, the easiest thing to do is to ssh to it. It is really simple. Make sure you are in the same local network and follow the instructions here. Here is quick summary of what is there: do

ifconfig -a

to find out the address from your wlan. If you have a linksys router, then it will be something like 192.168.1.x. If so, then do the following to figure out the IP of the devices connected to your local network:

sudo nmap -sP 192.168.1.0-255

Now, you just try to ssh to all of them. For one of them, the following will work:

ssh pi@192.168.1.105

If it works, it will ask for a password. Typically, the initial password for Raspbian is ‘raspberry’. Then, you will get something like:

pi@raspberrypi ~ $

Ok, now we are logged in the Raspberry. It will be useful to have both python and ino installed. Ino is a tool used to compile and upload it to arduino.

 

Code for arduino

The first step is to use ino init to create a temperature project. You can follow the Ino Quickstart here. Here is the sketch.ino that I wrote to read from the temperature sensor and write to the serial port:

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

void loop() {
  int valT = analogRead(0);
  float mV = (valT / 1024.0) * 5000;
  float temperature = (mV - 500)  / 10;

  Serial.print("T: ");
  Serial.print(temperature);
  Serial.print("\n");

  delay(300000); //5 minutes
}

Note that I am using the analog pin A0 to read from the sensor. Then we do ino build and ino upload (as described in the quickstart). And at that point the arduino should start sending messages with temperature to the Serial port. Notice I added a delay(300000); so that the arduino sends a temperature every 5 min (300000 miliseconds). If you are following this, you can initially start with a smaller interval to make sure everything is working (say a couple of seconds).

 

Reading from the serial port

Code now should be up and running in the arduino and it should be writing to the serial port. Now, let’s read from it. By typing

pi@raspberrypi ~ $ino serial

you can see the output of the serial port and see if it is doing the right thing. You will also see what the serial port actually is. In my case it is /dev/ttyACM0. Now, let’s see how to read from it in python:

from serial import Serial
import re

serial_pattern = r"T: (\d+\.\d*)\n";
serial_port = '/dev/ttyACM0';
serial_bauds = 9600;

def open_serial_port() :
  s = Serial(serial_port, serial_bauds);
  line = s.readline();
  return s

def read_temperature(s):
  line = s.readline();
  m = re.match(serial_pattern, line);
  return float(m.group(1))

 

AppEngine Server

Now we are ready to create a server in the Google AppEngine and start uploading the temperature we read to it. This tutorial will walk you through the main steps in setting up a server. The server we will set up is actually simpler the the one in the example. I did mine in Go, as I was trying to learn the language (check Golang Tour, it is real fun), but you can do the tutorial in Python as well. Let’s stick with Go. You need essentially three files in your server: app.yaml (which is pretty much standard — see the tutorial), index.yaml (which is autogenerated, so no need to worry about this one either) and the go file that actually specifies the server. I called mine hello.go. The file is longer, but you can find it in this link.

I might dicuss it in more details in a further post (for example, how I am using the Google visualization api), but for now, I will just post the python code I am running in the RaspberryPi that is communicating with the appengine server.

from serial import Serial
import re
import urllib

serial_pattern = r"T: (\d+\.\d*)\n";
serial_port = '/dev/ttyACM0';
serial_bauds = 9600;
url = r'http://renatoppl-helloworld.appspot.com/newtemperature'

if __name__ == "__main__":
  print "Opening serial port"
  s = Serial(serial_port, serial_bauds);
  print "Reading first line from port"
  line = s.readline();
  print "Initializing communication"
  while 1:
    line = s.readline()
    m = re.match(serial_pattern, line);
    params0 = {"temperature":m.group(1), "source":"sensor_living_room"}
    params1 = urllib.urlencode(params0)
    print params1
    data = urllib.urlopen(url, params1).read()

 

Temperature plot

And finally, you can check the temperature here or the tables here.

 

Final comments

One last comment: there are probably easier (and more elegant ways) of doing those things — for example, it is possible to read sensor data directly from the RaspberryPi without using the Arduino. This small project came out of me trying to learn all those things (Arduino, RaspberryPi and Go) at the same time. One advice that I got once was that the best way to learn something is to come up with a small project that uses all those things and implement it.

13 thoughts on “Thermometer (using Arduino and RaspberryPi)

  1. Stan says:

    HI,
    When I tried serial communication between Rpi and arduino it
    works for sometime but after that arduino stops sending data.
    My python code:
    import serial
    import time

    ser = serial.Serial(‘/dev/ttyAMA0’,115200,timeout =10)

    print ( “connected to: ” + ser.portstr )

    while True:
    try:
    val = ser.read()
    print (str(val))

    except:
    print “Wating for Device”
    ser.close()

  2. renatoppl says:

    Which pattern do you output from the Arduino ? One issue that I had is that when using ‘\n’, the Arduino was not flushing the stdout (I am not sure actually if it was a problem with Arduino, or python. But somehow, it needed some special character like \n so that read() would return.

  3. Aitor says:

    Hey, I’ve been trying to install the serial module. I tried to paste the module directly to the app folder but then I got these error:

    No module named fcntl

    I’ve found that google app engine does not support fcntl in python 2.5. I was wondering how’ve done it to make it work.

    Thanks a lot!

  4. renatoppl says:

    I didn’t need Serial in AppEngine. I have a python program continuously running in the RPi uploading things to AppEngine. Then AppEngine is just recording those and displaying. i did the AppEngine part in go. This link for the code: http://renatoppl.com/blog/wp-content/uploads/2014/03/renatoppl-helloworld.zip

  5. Tamnguyen says:

    my don’t know why, my data input to serial error, my use raspberry pi read data to serial port and print data. code error inwaiting and input ……
    please help me.
    code:
    import serial
    import time

    ser=serial.serial(“/dev/ttyACM0”, 9600,timeout = 0.5);
    ser.open();
    while True:
    bufer = ser.inwaiting();
    if bufer>0:
    val = ser.read(6);
    print(ord(val[0]),ord(val[1]),ord(val[2]),ord(val[3]),ord(val[4]),ord(val[5]))
    else:
    ser.flushInput();
    ser.close();
    time.sleep(0.5);
    ser.open();

    • renatoppl says:

      I think the first two things to check is if the arduino’s output is what you expect. You can do it by running ino serial from the raspian shell. This will also tell you if the arduino is in /dev/ttyACM0 or somewhere else.

      So, if all those are right, then there might be something with your code. I unfortunately don’t understand what inwaiting or read do. Did you try using line = ser.readline() like in the example in the post ?

      One last issue to check: what you output from the arduino should finish with \n so that readline returns.

    • g says:

      serial.Serial(dev……….ect)

      pretty sure that needs to be uppercase!

  6. Alex says:

    I had two quick questions. The first is are there any google app engine files actually on the pi or is it all just sent to the server?
    The second question was where to save the python file that you mentioned. Does this need to be put anywhere to start automatically on reboot?
    Sorry to bother and thank you for the help,
    Alex

  7. Mohamad Alhaddad says:

    Can you make a video tutorial on it please, because i need to know how to communicate between arduino and rapberry pi urgently and i tried to install arduino IDE on rasb and tried to install processing on it…but …
    So please can you make a tutorial about how do you make a connection

  8. ian says:

    Hey I saw your one`s well

    SO… if i type ‘$ino serial’ on pi that i can save a data(from arduino serial monitor) at Raspberry pi right?

  9. Seungjai says:

    I am working on communication between Arduino and raspberry pi.

    If one direction communication (Arduino –> raspberry pi or raspberry pi –> arduino), it works.

    However, When I tried echo (raspberry pi send any random value to arduino, and arduino send back to raspberry pi same value), it did not work.

    Below code is my code. I just send ‘3’ to arduino, and get ‘3’ value from arduino. and print it on python. However, it did not work.

    Arduino code:
    void setup(){
    Serial.begin(9600);
    }
    void loop(){
    num = Serial.read();
    if(num>0){
    Serial.print(num);
    Serial.print(“\n”);
    delay(1000);
    }else{
    delay(1000);
    }
    }

    Raspberry pi code:
    import serial
    import re
    import random
    import time

    s=serial.Serial(‘/dev/ttyACM0’, 9600)
    motion_agent=random.randint(1,3)
    s.write(‘3’)

    while 1:
    s.write(‘3’)
    line = s.readlin()
    print line
    time.sleep(1)

Leave a Reply

Your email address will not be published. Required fields are marked *