User Tools

Site Tools


oak:tutorials:particle-function

This is an old revision of the document!


In this example, we'll show one way you can make the data sent by the Oak useful with python. You can install python as described in the firmware over serial tutorial. Make sure for the below that you're using python version 2.x (e.g. 2.7), not python v3.

The circuit

This tutorial will utilize a TMP36 analog temperature sensor, but anything that can generate a changing value read by the Oak will work. The circuit is quite simple:

Here's the setup in real life, with the outer TMP36 pins plugged directly into Vcc and ground, and a soldered jumper connecting the middle pin to A0. It's connected to power using a surplus store 4 x AA battery pack.

tmp36-hookup.jpg

Code on the Oak

To read the temperature, we'll convert the analog reading to millivolts and then to degrees Celsius as described in this Adafruit tutorial. The variable will be accessible through the Particle.variable() function, which we'll read with python and then use to email a notification when it falls below a certain level.

Here's the Oak code:

double tempC = 0;
int analog = 0;
double mv;

void setup()
{                

  // the Particle.variable() function takes two arguments:
  // 1) the name of the Particle variable. This is how you interact
  //    with the Particle cloud to access the value
  // 2) the local variable name to be stored in the cloud variable
  Particle.variable("temp", tempC);

  // we'll configure the on-board LED to blink
  // this is handy for simply making sure the Oak is running your sketch
  pinMode(1, OUTPUT);
  digitalWrite(1, LOW);
  pinMode(A0, INPUT);
  
}


void loop()
{

  // with the tmp36, the temperature is found using this formula:
  // temp in C = (millivolts out - 500)/10
  // we're reading an analog value (0-1023) which is proportional
  // to the analog reference voltage, which on the Oak is 3.3v for Vcc.

  // get the analog value
  analog = analogRead(A0);

  // convert to millivolts
  // if your temperature readings are incorrect; adjust the 2700 value below
  // this *should* be 3300 for a 3.3V analog device, however plain and simple
  // the temperature may be incorrect and you can use it to calibrate
  mv = analog * 2700.0 / 1024.0;
    
  // convert from mV to degrees C
  tempC = (mv - 500.0) / 10.0;
 
  // flash the LED
  digitalWrite(1, HIGH);
  delay(100);
  digitalWrite(1, LOW);
  delay(500);
  
}

After uploading this sketch, we can do a test call to the Particle API as described in the Particle.variable() tutorial.

Testing the code

$ curl https://api.particle.io/v1/devices/id_here/temp?access_token=token_here
{
  "cmd": "VarReturn",
  "name": "temp",
  "result": 19.609375,
  "coreInfo": {
    "last_app": "",
    "last_heard": "2016-03-20T17:44:21.275Z",
    "connected": true,
    "last_handshake_at": "2016-03-20T17:43:52.080Z",
    "deviceID": "12345678",
    "product_id": 82
  }

Reading the Particle URL with python

With that working properly, let's go about reading that data from a computer using python. For the utter basics, we need to import urllib and json to get the API response and read it in. We've added some other modules in order to delay a loop (time), get the current time (datetime), and send an email (smtplib and MIMEText). The core of the functionality is simply in getting and parsing the data:

## import what we need
import urllib
import json

## simplify the url a bit
base = "https://api.particle.io/v1/devices/"
device_id = "device_id_here"
token = "token_goes_here"
var = "/temp" ## change this if you used a different Particle.variable() name
option = "?access_token="

## put together the full url to query
url = base + device_id + var + option + token

# opens/reads the URL and then parses the json response
data = urllib.urlopen(url).read()
data_json = json.loads(data)

## gets the json value under the "result" key
temp = round(float(data_json["result"]), 2)

print temp

Each time you run the code above, python will print the value stored in results, which corresponds to our call for the temp variable defined by Particle.variable():

## I have this script saved as temp-get.py
$ python ./temp-get.py
19.84

$ python ./temp-get.py
20.14

Sending an email with python

With that behaving, you can put python to work, checking the temperature with some frequency and doing something in response. We'll imagine you might want to check if something gets down to a certain low temperature and then email you about it. Real life examples might be:

  • letting you know it's near freezing so you can cover your plants and protect from frost
  • an alert about the pipes at a cabin so you can wirelessly turn on the heat
  • a notification that your beer in the freezer is now cold so you don't forget and have it explode in your ice tray…

The algorithm we're looking for, then, is:

  • get the temperature
  • log the current time and temperature in a log file
  • see if it's below a cut off
  • if so, send an email and quit
  • if not, wait a little bit (no sense reading once a second here) and repeat

If we move the code above into a while loop, we can accomplish this flow like so:

## import what we need
## added in time and email requirements
import urllib
import json
import smtplib
import datetime
from time import sleep
from email.mime.text import MIMEText

## simplify the url a bit
base = "https://api.particle.io/v1/devices/"
device_id = "device_id_here"
token = "token_goes_here"
var = "/temp" ## change this if you used a different Particle.variable() name
option = "?access_token="

## put together the full url to query
url = base + device_id + var + option + token

# initialize a variable so we know when to stop the loop
email = 0

# as long as email is 0, run the below again and again
while email == 0:

    # same code as above; get URL data, convert to json and extract temp
    data = urllib.urlopen(url).read()
    data_json = json.loads(data)

    temp = round(float(data_json["result"]), 2)

    # store the current system time for this reading
    now = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M:%S")

    # define some cutoff; if the temperature is below 5C, do this:
    if temp < 5 :
    
        # this composes the message
        msg = MIMEText("The beer is cold; it's " + str(temp) + " C!")
        addy = "your_email_address@here.com"
        msg["Subject"] = "Get to the freezer!"
        msg["From"] = addy
        msg["To"] = addy

        # this will send an email from you, to you, through your smtp server
        # google your email provider and "smtp settings" to find out yours
        print "emailing..."
        smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
        smtpserver.ehlo()
        smtpserver.starttls()
        smtpserver.ehlo()
        smtpserver.login(addy, "your_email_password")
        smtpserver.sendmail(addy, addy, msg.as_string())
        smtpserver.close()

        # now we set email to 1 so the while loop stops
        email = 1

    # each time through, add the time and temperature to a file
    # you may have to create this file if it doesn't exist
    log = open("/path/to/tmp36_data-log.csv", "a")
    log.write(str(temp) + "," + now + "\n")
    log.close()

    # wait 10 seconds and repeat
    sleep(10)

# when all done (email sent), tell us
print "done"

Unfortunately, long wires on the TMP36 thwarted my attempts to record an actual beer's temperature in my freezer, so I simply put the bundle out on my porch (Minnesota). The nice part about storing the data to a local log file is you can plot it easily by importing the csv formatted file into Excel, LibreOffice, etc.

Based on the temperature outside, I adjusted the cutoff to 11C (if temp < 11 above) after I saw it wasn't going to drop below 10C. Here's what I got!

oak/tutorials/particle-function.1458500857.txt.gz · Last modified: 2016/03/20 12:07 by jwhendy