Thermistor sample code for Arduino – Raspberry

This is a C++ class for a simple NTC thermistor. I used the thermistor included in the starter kit (datasheet) and the 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
BasicThermistor schema
BasicThermistor schema

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:

#include "arduPi.h"

 * Based on cooking-hacks NTC thermistor - datasheet available at

// 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

// The digital value readed from ADC
// must be lower than DIGITAL_TOLLERANCE
// Otherwise it is treaded as a read error
// 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 ADC_I2C_ADDRESS 8

class BasicThermistor {
   BasicThermistor(byte i2c_address, boolean debug_flag);
   float read_temperature();
   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);


Class file – BasicThermistor.cpp

 * BasicThermistor.cpp
 * Created on: 07/ago/2013
 * Author: sarbyn
 * Website:

 * Based on cooking-hacks NTC thermistor - datasheet available at

#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;
  // sleep in order to reduce read error
  Wire.requestFrom(ADC_I2C_ADDRESS, 2);
  // sleep in order to reduce read error
  val_0 =;
  // sleep in order to reduce read error
  val_1 =;
  // sleep in order to reduce read error
  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 use it\n", value);
   cached_digital_value = value;
   invalid_read_counter = 0;
   return 1;

  // throw away invalid reading
  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;

  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]);

  for (int i = 0; i < READINGS; i++) {
    temperature += read_buffer[i];

  temperature /= READINGS;

  return temperature;

A $9 arduino board

Some days ago I found on this campaign:


The goal of the founder is to reach 12.000$ and start the production of the Arduino-like board, and now the campain is over 73.000$! . With 12$ (9$ + shipping), or about 9€, you can start to play with Arduino and electronics. I’ve never tried Arduino boards and yesterday I decided to bought one starter kit from, so in September my little Raspberry Pi will have a new little friend 🙂

LiquidCrystal_i2c for ArduPi

I bought on ebay a simple LCD screen with an i2c controller. My purpose is to add a simple output screen to my project TermoPi (a smart thermostat for my home). I found a ready-to-use CPP library called LiquidCrystal_I2C that helps the developer to connect the LCD screen to an Arduino board. I want to use my raspberry Pi with the “Raspberry to arduino shields” , a connection board that export the arduino input-output pins, using the arduino conventions. A developer can use the Arduino coding style and libraries with his RaspberryPi, using ArduPi CPP library and coocking-hacks shield. But the original LiquidCrystal_I2C library is not compatible with ArduPi compatibility library: this library is similiar to arduino SDK…but it’s not arduino SDK:

  • LiquidCrystal_I2C refers to Arduino “print.cpp” functions, not available on ArduPI
  • ArduPi Wire CPP class implements a different Wire.endTrasmission() function, that close and release the I2C comunication pins (it seems a bug)

After some little changes, LiquidCrystal_I2C is ready to use on RaspberryPi with ArduPI library. You can download the library sources from my Bitbuchet GitHub repository: