This is a C++ class for a simple NTC thermistor. I used the thermistor included in the cooking-hacks.com starter kit (datasheet) and the cooking-hacks.com Raspebby to Arduino shield, but this sample is easily adaptable for any NTC thermistor or also for Arduino platform. It can be used with another NTC thermistor: simply change the BasicThermistor.h values:
- BETA (o B-Value) : the beta value of thermistor
- THERMISTOR: zero power resistance at 25° C
Some notes:
- This class is designed for a read every 10 seconds.
- Check the real value of 10k resistance with a multimeter! The 10% tollerance changes the value of about ± 1° C!. In my example I use 9840 Ω instead of 10000 Ω
- I use a arithmetic mean over 12 readings (2 minutes) in order to normalize the temperature value and discard read errors
- I use a simple “is_valid_value” function that discard a macroscopic read error. A “digital” read error of ± 20 is converted to an error of ± 14° C ! So if the previous valueis too big or too small, discard the current value
Header file – BasicThermistor.h
/*
* BasicThermistor.h
*
* Created on: 07/ago/2013
* Author: sarbyn
* Website: http://www.sarbyn.com
*/
#ifndef BASICTHERMISTOR_H_
#define BASICTHERMISTOR_H_
#include "arduPi.h"
#include
/**
* Based on cooking-hacks NTC thermistor - datasheet available at
* http://www.cooking-hacks.com/skin/frontend/default/cooking/pdf/159-282-86001.pdf
*/
// The real 10k resistor value
#define TENKRESISTOR 9840.0f
// Thermistor beta value (from datasheet)
#define BETA 3950.0f
// The thermistor value at room temp (25 C)
// the original value was 2800 ohm
#define THERMISTOR 2700.0f
// The room temperature (25 C) in kelvin
#define ROOMTEMPK 298.15f
// Number of readings over which calculate
// the temperature
#define READINGS 12
// Delay (in ms) between Wire operations
#define DELAY_BETWEEN_OPERATION 20
// The digital value readed from ADC
// must be lower than DIGITAL_TOLLERANCE
// Otherwise it is treaded as a read error
#define DIGITAL_TOLLERANCE 20
// If the digital value readed from ADC is wrong for
// more than DIGITAL_TOLLERANCE_COUNTER, it is a correct value
// and so use it. This is used in case of sudden
// temperature change. If the temperature changes suddenly,
// the value is discarded for DIGITAL_TOLLERANCE_COUNTER reads. After that
// the value is accepted
#define DIGITAL_TOLLERANCE_COUNTER 6
#define ADC_I2C_ADDRESS 8
class BasicThermistor {
public:
BasicThermistor(byte i2c_address, boolean debug_flag);
float read_temperature();
private:
byte address;
boolean debug;
int digital_value;
float read_buffer[READINGS];
unsigned int cached_digital_value;
float temperature;
int invalid_read_counter;
int buffer_pointer;
int read_digital_value();
int is_valid_value(int value);
float calc_temperature(int value);
};
#endif /* BASICTHERMISTOR_H_ */
Class file – BasicThermistor.cpp
/*
* BasicThermistor.cpp
*
* Created on: 07/ago/2013
* Author: sarbyn
* Website: http://www.sarbyn.com
*
*/
/**
* Based on cooking-hacks NTC thermistor - datasheet available at
* http://www.cooking-hacks.com/skin/frontend/default/cooking/pdf/159-282-86001.pdf
*/
#include "BasicThermistor.h"
// Costructor
BasicThermistor::BasicThermistor(byte i2c_address, boolean debug_flag) {
address = i2c_address;
debug = debug_flag;
temperature = 0.0;
cached_digital_value = 0;
digital_value = 0;
invalid_read_counter = 0;
buffer_pointer = 0;
for (int i = 0; i < READINGS; i++) {
read_buffer[i] = -1.0f;
}
}
// Read the digital value from ADC using Wire class
int BasicThermistor::read_digital_value() {
unsigned char val_0 = 0;
unsigned char val_1 = 0;
unsigned int digital_value;
Wire.beginTransmission(ADC_I2C_ADDRESS);
Wire.write(address);
// sleep in order to reduce read error
delay(DELAY_BETWEEN_OPERATION);
Wire.requestFrom(ADC_I2C_ADDRESS, 2);
// sleep in order to reduce read error
delay(DELAY_BETWEEN_OPERATION);
val_0 = Wire.read();
// sleep in order to reduce read error
delay(DELAY_BETWEEN_OPERATION);
val_1 = Wire.read();
// sleep in order to reduce read error
delay(DELAY_BETWEEN_OPERATION);
digital_value = int(val_0)*16 + int(val_1>>4);
if (debug) {
printf("[BT] val [%2x,%2x]\n", val_0, val_1);
printf("[BT] Read digital value %d\n", digital_value);
}
return digital_value;
}
// Check if the readed value is valid
int BasicThermistor::is_valid_value(int value) {
if (cached_digital_value == 0) {
cached_digital_value = value;
return 1;
}
// check against DIGITAL_TOLLERANCE
if (abs(cached_digital_value - value) < DIGITAL_TOLLERANCE) {
if (debug) printf("[BT] Valid digital value %d\n", value);
cached_digital_value = value;
invalid_read_counter = 0;
return 1;
}
if (invalid_read_counter > DIGITAL_TOLLERANCE_COUNTER) {
// too many invalid readings ---> this is a valid read
if (debug) printf("[BT] Too many invalid digital value %d..so use it\n", value);
cached_digital_value = value;
invalid_read_counter = 0;
return 1;
}
// throw away invalid reading
invalid_read_counter++;
if (debug) printf("[BT] Invalid digital value %d\n", value);
return 0;
}
// Convert the ADC value to Celsius Temperature
float BasicThermistor::calc_temperature(int value) {
// convert value
float analog_value = value * 1023.0 / 4095.0;
analog_value = (1023 / analog_value) - 1;
analog_value = TENKRESISTOR / analog_value;
analog_value = analog_value / THERMISTOR;
if (debug) printf("[BT] Analog value %f\n", analog_value);
float kelvin = log(analog_value);
kelvin /= BETA;
kelvin += 1.0 / ROOMTEMPK;
kelvin = 1.0 / kelvin;
return kelvin - 273.15;
}
// Main read function: read the current temperature and return it.
// This is designed for a read every 10 seconds: it collects 12 readings
// (READINGS macro value, 2 minutes) and calculate mean over all the values.
// In this way the temperature value does not change suddenly and
// become more stable
float BasicThermistor::read_temperature() {
digital_value = read_digital_value();
float single_temperature;
if (is_valid_value(digital_value)) {
single_temperature = calc_temperature(digital_value);
if (debug) printf("[BT] Single current temperature is %f\n", single_temperature);
} else {
single_temperature = calc_temperature(cached_digital_value);
if (debug) printf("[BT] Invalid temp, using cached value %f\n", single_temperature);
}
if (debug)
printf("[BT] Storing the temp at pointer %d\n", buffer_pointer);
read_buffer[buffer_pointer] = single_temperature;
buffer_pointer++;
if (read_buffer[buffer_pointer] == -1.0f) {
// this is the first reading....init the buffer
for (int i = buffer_pointer; i < READINGS; i++) {
read_buffer[i] = single_temperature;
}
}
// reset the pointer
if (buffer_pointer == READINGS) buffer_pointer = 0;
temperature = 0;
if (debug) {
printf("[BT] Temp. buffer[");
for (int i = 0; i < READINGS; i++) {
printf("%0.1f,", read_buffer[i]);
}
printf("]\n");
}
for (int i = 0; i < READINGS; i++) {
temperature += read_buffer[i];
}
temperature /= READINGS;
return temperature;
}
