bshang

Arduino To PI with PI Web API

Blog Post created by bshang Employee on Nov 11, 2015

Motivation

 

Internet of Things is all the craze these days. It's currently at the top of the Gartner hype cycle. It's only appropriate that I blog about it soon .

 

In this post, I will show a simple example that collects temperature data by my desk from a sensor, Arduino Yun, PI Web API, and a PI System. I will also show how something very simple helped us learn some interesting things about temperature behavior in the office.

 

Components

 

The components for a sensor-to-PI System data flow are as follows:

 

Sensor: For the sensor, I chose a simple temperature sensor here. It provides a simple low voltage output linearly proportional to the Celcius temperature.

Development Board: I chose the Arduino Yun because it is natively Ethernet and Wi-Fi capable. This component is the device that runs the code. To learn more about it, I encourage you to read the links shared before.

Gateway device: This is the device that offers Internet connectivity. It can be a home router, a cellular router, or another specialized gateway. In this example, we used a cellular router. The development board and router are connected via ethernet cable although Wi-Fi could do as well (as long as the router includes a Wi-Fi access point).

Cloud endpoint: PI Web API is the cloud endpoint here. Another choice could be Azure Event Hubs. The endpoint should be HTTP-accessible although other protocols could be used if the device supports it.

PI System: The PI System is the persistence layer that stores the temperature data.

 

Here is a picture of the setup:

arduino_setup.JPG

 

As you see, there are some additional components, such as a breadboard and wires. For the electronics setup, I followed the examples provided in the links below:

SIK Experiment Guide for Arduino - V3.2 - learn.sparkfun.com

Arduino - TemperatureWebPanel

 

Code

 

As seen in the diagram, The Arduino Yun actually contains two processors: an ATmega 32U4 and AR9331 Linux. The ATmega 32U4 does not include an operating system and can only support code written in the Arduino programming language (which has flavors of C).  The AR9331 runs a version of Linux that supports a Python interpreter so Python code can be written on it.

 

Analog inputs, such as those from the temperature sensor, can only be read via the ATmega 32U4. However, Ethernet and Wi-Fi are offered only via the AR9331. Therefore, a Bridge abstraction is used to pass data between the two processors so the analog input can be sent over Internet to PI Web API (This Bridge abstraction is actually implemented via custom TCP sockets but the end developer doesn't need to know too much about this, as you'll see later).

 

There are two Bridge libraries, one on each processor. These libraries can be used to pass data as key-value pairs between code running on the ATmega 32U4 and AR9331.

ATmega 32U4 Bridge library

AR9331 Bridge library (Python)

 

ATmega 32U4 code:

arduino-sketch-temperature · GitHub

 

#include <Bridge.h>

const int temperaturePin = 0;

void setup()
{
  Bridge.begin();
}


void loop()
{
  float voltage, degreesC, degreesF;
  voltage = getVoltage(temperaturePin);
  degreesC = (voltage - 0.5) * 100.0;
  degreesF = degreesC * (9.0/5.0) + 32.0;

  Bridge.put("TEMP", String(degreesF));

  delay(5000); // repeat once per 5 seconds (change as you wish!)
}


float getVoltage(int pin)
{
  return (analogRead(pin) * 0.004882814);
}

 

As you can see, analogRead(pinNumber) is all that's needed to reach from the analog input on the Arduino Yun. Bridge.put is used to pass the temperature to the Python code running on the other processor.

 

 

 

AR9331 code:

arduino-python-temperature.py · GitHub

 

#!/usr/bin/python

import sys
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
import urllib2, urllib

import random
from time import gmtime, strftime, sleep

from bridgeclient import BridgeClient as bridgeclient

client = bridgeclient()

print "python script is starting"

url = 'https://<SERVER>/piwebapi/streams/{webId}/value'

password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, url, 'username', 'password')

auth = urllib2.HTTPBasicAuthHandler(password_manager) # create an authentication handler
opener = urllib2.build_opener(auth) # create an opener with the authentication handler
urllib2.install_opener(opener) # install the opener... 

req_headers = {'Content-Type': 'application/json'}

while 1:
    val = client.get('TEMP')

    ts = strftime('%Y-%m-%d %H:%M:%S', gmtime()) + 'Z'

    print ts, val

    #urllib2
    req_data = str({"Timestamp": ts, "Value": val})
    request = urllib2.Request(url, headers = req_headers) 
    request.add_data(req_data)

    try:
        response = urllib2.urlopen(request).read()
    except:
        print "Unexpected error:", sys.exc_info()[0]

    sleep(5)

 

We use the Python bridgeclient class to read the temperature passed from the ATmega. We then use the urllib2 Python library to make the REST call to PI Web API.

 

 

Office Temperature Data

 

Let's look at the temperature data collected over 4 days. Interestingly, there is a clear pattern in temperature throughout the day, although there are some differences between days as well. It gets warmer during the afternoon (just in time for a nap) and for the past two days, the heater was turned on the morning.

 

San Leandro:

blog_temp.PNG

 

We also collected temperature data with a Raspberry Pi in the Philadelphia office and compared office desk temperatures.

 

San Leandro (green) vs. Philadelphia (cyan):

blog_temp_compare.PNG

 

Clearly, there is a large difference in temperature between the two office desks (the Philadelphia sensor is also more accurate). There are also some patterns in temperature behavior in the Philadephia office but they are less pronounced, and the temperature variations are smoother. Such insight likely cannot be gained from temperature data from a building management system, which likely gives a more global or averaged view of temperature. There are likely temperature variations within a building, and even on a single floor, depending on closeness to windows, etc. Here, with small sensors and development boards, we can get finer spatial resolution to understand how temperature behaves locally near distributed office desks.

 

Conclusion

 

We showed how simple IoT devices like Arduinos and basic sensors could be used to bring data into the PI System, via PI Web API. We then showed some interesting insights that could be gained from only a few days worth of data collection from two temperature streams. Much more can probably be learned via data collected at the scale of industrial IoT. This concludes the blog post and I hope you may find it helpful for your research. As always, questions/comments are welcome below.

Outcomes