Showing posts with label Thermometry. Show all posts
Showing posts with label Thermometry. Show all posts

Thursday, 6 August 2015

Field Mate Part 2 - Open Your Eyes to an Open Sensorium

A few posts past, I addressed the idea of Field Buddy Field Mate - a portable device for capturing environmental data while in the field. Having had a chance to play with a bit of magnetometry (amongst other toys), and finding that I need to build an intelligent thermostat, I have come to the conclusion that there is something lacking in the world of hobby/amateur electronics - and that is a properly integrated set of devices and software for microcontroller use.

I have decided, therefore, that it is time to formalise the Field Mate concept into a more general project.

To this end, I have decided to commence work on what I am calling The Open Sensorium Project.

The aim is to produce a series of software and hardware modules that can be built up and put together in order to build custom instrumentation. Based around Data Capture using sensors (i.e. a sensorium), the modules will provide both sensing, primary processing and export of data via displays, data streaming and data caching (using SD cards).

It will not only provide an open sensorium, in the sense that the data system's "eyes" are wide open, but will also be an open project - open source software, open source hardware (albeit, using a lot of off-the-shelf modules) and free to use and modify.

Given the relatively low cost of microcontrollers, it would be possible for each major module to be separately intelligent.

I hope that there will be a lot of cross-pollination with various other projects, and between the developers using a range of microcontroller systems including, but not limited to, Microchip's PIC, Parallax Propeller, Atmel AVC / Arduino and Raspberry Pi,

As an open project, the material will be released into the wild with few restrictions, and subject to the Gnu General Public Licence.

The rules will be simple - open source may not form a part of a closed source project unless those portions that are open source remain open source. Derivative works are brilliant. Respect and acknowledge the intellectual rights of those whose work you are building upon - and retain any copyright notices that form a part of the source that you are using.

Finally, there will be standards for various parts of the project - standards for quality of product, for quality of documentation and for communication protocols between modules - and to the outside world.


I hope that others will want to get involved in various ways - even if it is only through an eMail saying that you found it useful.

I look forward to hearing from you. I will pass on the web site address once I have settled upon one. I have set up a project page on Sourceforge at: https://sourceforge.net/p/open-sensorium/



For those who care about these things - the font is Neuropolis, the logos were made in MS Word 2013 and either screen-captured or copied to Inkscape.

Saturday, 25 July 2015

Thermistors as thermometers


 

I am taking a break from work of my microscope eyepiece project, and have been playing around with sensors using the Arduino embedded systems.

The device that is the most idiotically complicated to get meaningful information from is the humble thermistor.


Negative Coefficient (NTC) thermistors are used because of their large resistance change with temperature - as the temperature of the device increases, the resistance of the device decreases.

Unfortunately, the relationship between resistance and temperature is far from linear.

Indeed, the Steinhart-Hart Thermistor Equation is the kind of thing that causes nightmares in undergraduate students. Three coefficients of uncertain origin, natural logs of resistances and complicated denominators do not make for a happy user.

Happily, there is a solution.

For the Arduino user, there is a simple circuit to build (right) which is a thermistor analog breakout, and can be made on a thumbnail sized scrap of stripboard. You will need to select a resistor for R2 that matches (approximately, at least) the room-temperature resistance of the thermistor.

The 0V and +5V connections go to the power rails of the microcontroller circuit, and the Vout connection to one of the analog inputs (I use A1 for this).

What you will be doing is measuring the resistance of the thermistor by measuring the voltage drop across R2.


The real work is done in code. I built a simple test program around the code below, and ended up with a thermometer that is both fairly accurate and fairly stable.

Electrical noise throws out a series of fluctuations in the recorded value of Vout  - noise that may be masked by averaging a number of readings, and then using a time-weighted average for the output. This has the effect of making the thermometer slow to react to sudden changes in temperature, but overall, I was happy with the results.

A common mistake with using the Arduino analog ports is due to the nature of the way in which the port reports the voltage - as an integer from zero to 1023. Many users use the formula  -


V = AnalogValue *  Vref  / 1024

This is, of course, incorrect, and should read:


V = AnalogValue *  Vref  / 1023

I have added a pair of calibration constants into the program in order to allow for small shifts in the calibration of the thermistor - slope and offset. The linearity of the output is beyond the average user's facility to correct. The three coefficients in the Steinhart-Hart Equation are represented by three magic numbers that are typical for most modern NTC thermistors - mucking about with these (or using atypical components) will certainly lead to frustration and inevitably to tears before bedtime.



The code, which is probably what you are interested in follows ...


// thermistor.h


// ####################################################################

// ####################################################################

// ##

// ##  thermistor.ino (thermistor.h)

// ##  version 1.00.00

// ##  date    25-Jul-2015

// ##  author  Alysson Rowan (AlyssonR)

// ##

// ##  Copyright (C) 2015, Alysson Rowan

// ##   alyssonrowan @ gmail.com

// ##

// ####################################################################

// ####################################################################

// ##

// ##  This program is provided on an as-is basis without warranty.

// ##  No claim is made as toward operability or fitness for purpose

// ##  whatsoever. No liability can be accepted for any loss or damages

// ##  howsoever caused in respect of this software.

// ##

// ##  This software is made freely available under the terms of the

// ##  GNU General Public License V2. In short, you are allowed to do

// ##  anything with this program except sell it and hide the

// ##  source code.

// ##

// ##  In addition, this program is "postcard ware" – if you find it

// ##  useful then please send me an e-mail and tell me about your

// ##  application.

// ##

// ##  Your comments and suggestions are much appreciated.

// ##

// ####################################################################

// ####################################################################
 




#define thermistorPort A1          // analog input pin assignment

#define thermistorRefR 9630        // resistance of buffer resistor

#define thermistorNRes 10000       // Nominal resistance of thermistor

#define thermistorCorr 1           // Calibration scaling factor

#define thermistorOffs 0           // Calibration offset



// Steinhart-Hart coefficients

// – these magic numbers are fairly close for most modern NTC Thermistors

#define thermistorConA 0.001129148     // coefficient a

#define thermistorConB 0.000234125     // coefficient b

#define thermistorConC 0.0000000876741 // coefficient c



float tempAvge; // Temperature averaged over time







// Temperature Conversions:

//

// To convert Kelvin to Celsius

// Celsius = Kelvin – 273.15;

//

// To convert Celsius to Farenheit

// Farenheit = (Celsius * 1.8000) + 32;



// set up analog thermistor

void analogThermistorEnable()

    {

    analogReference(DEFAULT);

    pinMode(thermistorPort, OUTPUT);

    digitalWrite(thermistorPort, LOW);

    pinMode(thermistorPort, INPUT);

    analogRead(thermistorPort);

    }



// Noise reduction using time-weighted averaging

void thermistorGetTemp(int tempWeight)

  // tempWeight controls the weight that the current  reading has

  // in tempAvge.

  //    tempAvge = 0 produces "current temperature only"

  //    tempAvge = 1 => 50% weighting (standard weighting)

  //    tempAvge = 2 => 33.33% weighting etc.

  // NB: at tempAvge = 4, it takes about 30 readings for the temperature to

  //     stabilise on initialisation and after a sudden change in temperature

  {

  float temperature;

  temperature = (analogTemp(analogThermistorRead())-273.15);

  tempAvge = ((tempAvge * tempWeight) + temperature) / (tempWeight+1);

  }



// read analog thermistor

float analogThermistorRead()

    {

    float thermistorRaw;

    thermistorRaw = analogRead(thermistorPort); 
                   // integer value in range 0 – 1023

    // NB: noise results in periodic variation of reading of up to 0.75 degrees

    // noise is reduced markedly by averaging a number of readings

    for( int count = 1; count < 8; count++)

      {

      thermistorRaw = (thermistorRaw + analogRead(thermistorPort))/2;

      }

    return thermistorRaw;

    }



//  calculate temperature from measured voltage

float analogTemp(float voltageRaw)

    {

    float tempLn; // Natural log of temperature

    float tempKelvin

    tempLn = log(ThermistorRefR * ((1023.0/voltageRaw) - 1); 
             // 1023 intervals not 1024 counts on ADC!!!



    tempKelvin = 1 / (thermistorConA + (thermistorConB * tempLn) + (thermistorConC * tempLn * tempLn * tempLn));

    return tempKelvin;

    }


Note: There is one line that breaks over the width of the column (tempKelvin assignment), so please don't be tempted to put in a line-break. The code is presented as a header file, but it can be as easily copy-pasted into your own code rather than #included