Notes About Working with Various Arduino & Netduino Microcontroller Boards

Saturday, December 21, 2013

Recording 1-Wire Temperature Data to a CSV File on an Arduino Yún

The following example shows how to record temperature data from multiple DS18B20 sensors and write the data to a CSV file on an SD card.  This code uses the Bridge library for the Yún and its Process class to pass the sensor data to a Python script that writes the data to the file.

The 1-Wire (OneWire) library for the Arduino is available here.

The output to the CSV file looks like this:

28 10 76 18 04 00 00 0E,23375,2013-12-21 19:09:47
28 06 06 7A 03 00 00 67,23062,2013-12-21 19:09:49
28 99 D1 49 03 00 00 3D,23250,2013-12-21 19:09:51
28 07 AC 18 04 00 00 33,23250,2013-12-21 19:09:52
28 10 76 18 04 00 00 0E,23437,2013-12-21 19:09:54

Connections


In my application, the sensors aren't more than a few feet apart, so parasitic power mode works nicely.

Looking at the flat side of the head of the sensor, connect the left pin of each sensor to its right pin.  Connect the right pin of each sensor to the left pin of the next sensor in the series. Connect the center pin of each sensor to the center pin of the next.  Connect digital pin 10 of the Arduino to the center pin of the 1st sensor with a 4.7k Ohm pull-up resistor to 3.3 volts.  Except for the 1st sensor, connect the ground (left pin) of each sensor to the Arduino's ground.


Arduino Sketch


Because I have run into problems trying to pass a float or double through the Arduino Yún's Bridge to the Python script on the Linux "side," this code takes the Celsius temperature reported by each sensor and multiplies it by 1000.  After each sensor is read, the Arduino code uses the Process class to run the Python script (below).  The sensor's ID and temperature data are passed as command parameters to the Python script.  

#include <Bridge.h>
#include <Process.h>
#include <OneWire.h>

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
Process p;
String cmd = "/usr/bin/python";        // Linux Path to Python 
String script = "/mnt/sda1/w1temp.py"; // Path to Python script to run

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

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  double celsius;
  
  if (!ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }

  char id[16];
  // Format sensor's ID as 8 bytex in hex
  char format[] = "%02X %02X %02X %02X %02X %02X %02X %02X";
  sprintf(id, format, addr[0], addr[1], addr[2], 
      addr[3], addr[4], addr[5], addr[6], addr[7]);
  // If reading not valid, just skip and continue    
  if(OneWire::crc8(addr, 7) != addr[7]) { return; }
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);   // start conversion, with parasite power on
  delay(750); 
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);             // Read Scratchpad
  for ( i = 0; i < 9; i++) {  // we need 9 bytes
    data[i] = ds.read();
  }
  // Convert the data to actual temperature
  int16_t raw = (data[1] << 8) | data[0];
  celsius = (float)raw / 16.0;
  char tempData[6];
  // Due to problems with passing a float, multiply temperature by 1000
  // then remove decimal by casting as int 
  sprintf(tempData, "%d", (int)(celsius * 1000));
  p.begin(cmd);
  p.addParameter(script);
  p.addParameter(id);       // Pass sensor ID
  p.addParameter(tempData); // Pass temp C * 1000
  p.run();
}


Python Script


The following Python script (saved as /mnt/sda1/w1temp.py) opens the CSV file in append mode, writes the data, and appends the current date and time.  

import sys
import time

file = open("/mnt/sda1/datafile.txt", "a")
file.write(sys.argv[1])
file.write(",")
file.write(sys.argv[2])
file.write(",")
file.write(time.strftime("%Y-%m-%d %H:%M:%S"))
file.write("\n")
file.close()

It is also possible to save the readings to a Sqlite database.  See this post for notes on installing and working with Sqlite on the Arduino Yún.