Notes About Working with Various Arduino & Netduino Microcontroller Boards

Saturday, August 31, 2013

The Sparkfun TMP006 Breakout & the Netduino Plus 2

The Sparkfun TMP006 breakout is a non-contact temperature sensor (mounted on a breakout board) that connects to a microcontroller using I2C.  The Sparkfun page includes links to a couple code examples for using the TMP006 with an Arduino.  Working from the sample code, I have produced the C# code below that works with a Netduino Plus 2.  The code is all in one file for the ease of presentation.  This requires the variables and methods to be flagged as static.  Writing a respectable library will come later...

Connections


TMP006 Breakout   Netduino Plus 2
VCC               3V3
SCL               SCL (w/ 10k Ohm pull-up resistor)
SDA               SDA (w/ 10k Ohm pull-up resistor)
GND               GND

The ADR0 & ADR1 pins can be used to change the I2C device address to something other than the default (0x40).  See p. 7 of the datasheet for details.  

The following code reports the temperature of the sensor and the object "in view" of the temperature sensor by printing the values (in degrees Celsius) to the debug console in Visual Studio. 


Code


using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace TMP006
{
    public class Program
    {
        static ushort DEV_ADDR =0x40; 
        // Constants for calculating object temperature
        static double TMP006_B0 = -0.0000294;
        static double TMP006_B1 = -0.00000057;
        static double TMP006_B2 = 0.00000000463;
        static double TMP006_C2 = 13.4;
        static double TMP006_TREF = 298.15;
        static double TMP006_A2 = -0.00001678;
        static double TMP006_A1 = 0.00175;
        static double TMP006_S0 = 6.4;  // * 10^-14

        // Configuration Settings
        static int TMP006_CFG_RESET = 0x8000;
        static int TMP006_CFG_MODEON = 0x7000;
        static int TMP006_CFG_1SAMPLE = 0x0000;
        static int TMP006_CFG_2SAMPLE = 0x0200;
        static int TMP006_CFG_4SAMPLE = 0x0400;
        static int TMP006_CFG_8SAMPLE = 0x0600;
        static int TMP006_CFG_16SAMPLE = 0x0800;
        static int TMP006_CFG_DRDYEN = 0x0100;
        static int TMP006_CFG_DRDY = 0x0080;

        // Registers to read thermopile voltage and sensor temperature
        static int TMP006_VOBJ = 0x00;
        static int TMP006_TAMB = 0x01;
        static int TMP006_CONFIG = 0x02;

        static I2CDevice tmp006;

        // Read 16 bit int from I2C register reg
        static int read16(int reg)
        {
            int data;
            byte[] regCmd = { (byte) reg };
            byte[] response = { 0, 0 };
            I2CDevice.I2CTransaction[] getData16 = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(regCmd),
                I2CDevice.CreateReadTransaction(response)
            };
            int bytesRead = tmp006.Execute(getData16, 100);
            data = response[0] << 8;
            data |= response[1];

            return data;
        }

        // Write data to I2C register reg
        static void write16(int reg, int data)
        {
            byte msb = (byte)(data >> 8);
            byte lsb = (byte)data;
            byte[] regCmd = { (byte)reg, msb, lsb  };

            I2CDevice.I2CTransaction[] putData16 = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(regCmd)
            };

            int bytesRead = tmp006.Execute(putData16, 100);
        }

        // Configures sensor, use before reading from it
        static void config_TMP006(int samples)
        {
            write16(TMP006_CONFIG, (int)(samples | TMP006_CFG_MODEON));
        }

        // Read raw sensor temperature
        static int readRawDieTemperature()
        {
            int raw = read16(TMP006_TAMB);
            raw >>= 2;
            return raw;
        }

        // Read raw thermopile voltage
        static int readRawVoltage()
        {
            // Voltage encoded as 16-bit 2's complement
            short raw = (short) read16(TMP006_VOBJ);
            if (raw > 32767)
                raw = (short) -(~(raw - 1));
            return raw;
        }

        // Calculate object temperature based on raw sensor temp and thermopile voltage
        static double readObjTempC()
        {
            double Tdie = readRawDieTemperature();
            double Vobj = readRawVoltage();
            Vobj *= 156.25;  // 156.25 nV per LSB
            Vobj /= 1000000000; // nV -> V
            Tdie *= 0.03125; // convert to celsius
            Tdie += 273.15; // convert to kelvin

            // Equations for calculating temperature found in section 5.1 in the user guide
            double tdie_tref = Tdie - TMP006_TREF;
            double S = (1 + TMP006_A1 * tdie_tref + TMP006_A2 * tdie_tref * 
                tdie_tref);
            S *= TMP006_S0;
            S /= 10000000;
            S /= 10000000;

            double Vos = TMP006_B0 + TMP006_B1 * tdie_tref + TMP006_B2 * tdie_tref * 
                tdie_tref;

            double fVobj = (Vobj - Vos) + TMP006_C2 * (Vobj - Vos) * (Vobj - Vos);

            double Tobj = System.Math.Sqrt(System.Math.Sqrt(Tdie * Tdie * Tdie * Tdie + 
                fVobj / S));

            Tobj -= 273.15; // Kelvin -> *C
            return Tobj;
        }

        // Calculate sensor temperature based on raw reading
        static double readDieTempC()
        {
            double Tdie = readRawDieTemperature();
            Tdie *= 0.03125; // convert to celsius
            return Tdie;
        }

        public static void Main()
        {
            tmp006 = new I2CDevice(
                new I2CDevice.Configuration(DEV_ADDR, 100)
            );
            config_TMP006(TMP006_CFG_8SAMPLE | TMP006_CFG_MODEON);
            while (true)
            {
                double object_temp = readObjTempC();
                double sensor_temp = readDieTempC();
                Debug.Print("Object: " + object_temp.ToString() + "°C");
                Debug.Print("Sensor: " + sensor_temp.ToString() + "°C\n");
                Thread.Sleep(2000);
            }
        }
    }
}


No comments:

Post a Comment