Wednesday, July 16, 2014

C# (Mono) Program to Read an TMP102 Temperature Sensor on a pcDuino 2

Mono is an open source implementation of Microsoft's .NET framework.  It is actually very easy to install Mono on the pcDuino 2 and get up and running with a fairly simple C# program that uses the i2cget utility to read the TMP102 temperature registers, convert it to Celsius and Fahrenheit, and print the results to the console.

For this example, I am using the TMP102 on a breakout board from Sparkfun.

Installing Mono on the pcDuino 2


To install Mono, simply run the following apt-get command as root:

apt-get install mono-complete

It will take a few minutes to download and install, but it isn't any more complicated than that.

You can confirm that your Mono installation is working by checking the version using the mono command:

mono --version

The results should look something like this -

root@ubuntu:~# mono --version
Mono JIT compiler version 2.10.8.1 (Debian 2.10.8.1-1ubuntu2.2)
Copyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com
TLS:           __thread
SIGSEGV:       normal
Notifications: epoll
Architecture:  armel,vfp
Disabled:      none
Misc:          softdebug 
LLVM:          supported, not enabled.
GC:            Included Boehm (with typed GC and Parallel Mark)
root@ubuntu:~# 


The pcDuino Web site also has information on installing smaller Mono configurations.


Installing I2C-Tools


This example uses i2cget to access the TMP102.  This program is part of the i2c-tools package.  You can install it (if you don't have already installed) by running this command as root:

apt-get install i2c-tools

C# Code


Use your favorite text editor to save this code to a file called Tmp102.cs

using System;
using System.Diagnostics;
using System.Threading;

public class Tmp102
{
    private string i2cgetExe = "/usr/sbin/i2cget";
    private string i2cgetCmdArgs = "-y 2 0x48 0 w";
    private string hexString = "";
    private Process p;

    public Tmp102()
    {
        p = new Process();
    }

    public double tempC
    {
        get { return readRawTempData() * 0.0625; }
    }
    public double tempF
    {
        get { return this.tempC * 1.8 + 32; }
    }

    private int readRawTempData()
    {
         // Don't raise event when process exits
         p.EnableRaisingEvents = false;
         // We're using an executable not document, so UseShellExecute false
         p.StartInfo.UseShellExecute = false;
         // Redirect StandardError
         p.StartInfo.RedirectStandardError = true;
         // Redirect StandardOutput so we can capture it
         p.StartInfo.RedirectStandardOutput = true;
         // i2cgetExe has full path to executable
         // Need full path because UseShellExecute is false
         p.StartInfo.FileName = i2cgetExe;
         // Pass arguments as a single string
         p.StartInfo.Arguments = i2cgetCmdArgs;
         // Now run i2cget & wait for it to finish
         p.Start();
         p.WaitForExit();
         // Data returned in format 0xa017
         // Last 2 digits are actually most significant byte (MSB)
         // 2 digits right after 0x are really least significant byte (LSB)
         string data = p.StandardOutput.ReadToEnd();
         // Get LSB & parse as integer
         hexString = data.Substring(2, 2);
         // Redirect StandardOutput so we can capture it
         p.StartInfo.RedirectStandardOutput = true;
         // i2cgetExe has full path to executable
         // Need full path because UseShellExecute is false

         p.StartInfo.FileName = i2cgetExe;
         // Pass arguments as a single string
         p.StartInfo.Arguments = i2cgetCmdArgs;
         // Now run i2cget & wait for it to finish
         p.Start();
         p.WaitForExit();
         // Data returned in format 0xa017
         // Last 2 digits are actually most significant byte (MSB)
         // 2 digits right after 0x are really least significant byte (LSB)
         string data = p.StandardOutput.ReadToEnd();
         // Get LSB & parse as integer
         hexString = data.Substring(2, 2);
     int lsb = Int32.Parse(hexString,
        System.Globalization.NumberStyles.AllowHexSpecifier);
     // Get MSB & parse as integer
     hexString = data.Substring(4, 2);
     int msb = Int32.Parse(hexString,
        System.Globalization.NumberStyles.AllowHexSpecifier);
     // Shift bits as indicated in TMP102 docs & return
     return (((msb << 8) | lsb) >> 4);
    }

    public static void Main()
    {
         Tmp102 t = new Tmp102();
        while(true)
        {
            // Print temp in degrees C and F to console
            Console.WriteLine("{0} C  {1} F", t.tempC , t.tempF);
                     Thread.Sleep(1000);
        }
        }
}

Compiling & Running the Code


To compile the code, run this command:

gmcs Tmp102.cs

This will produce a Tmp102.exe file that you can then run using mono.

mono Tmp102.exe

The program will print the current temperature until you press Ctrl-C to stop it. 


1 comment:

  1. Hi..
    i am working on sending gps data to processor via both uart/usb. do you have the code? i am working on C in Codewarrior.
    Thanks

    ReplyDelete