Introducción

Un termistor es un tipo de resistor cuya resistencia depende de los cambios de temperatura. Un termistor se puede clasificar en dos grupos:

  • PTC (positive temperature coefficient). La resistencia aumenta con el incremento de la temperatura.
  • NTC (negative temperature coefficient). La resistencia disminuye al aumentar la temperatura.

Thermistor_RT

 

La relación entre la resistencia y la temperatura se puede aproximar así:

R = R_{Ref}\cdot e^{\beta \left ( \frac{1}{T} - \frac{1}{T_{Ref}} \right ) }

Donde R es la resistencia del termistor a una temperatura T(en Kelvin), R_{Ref}es la resistencia del material a una temperatura T_{Ref}, y \betaes una constante específica del material.

Despejando la temperatura:

\frac{1}{T} = A + B\cdot ln(R) + C [ln (R) ]^3

Los parámetros A, B y C son proporcionados por el fabricante. En el caso del termistor Keynes KY-013, dichos valores son:

  • A = 0.001129148
  • B = 0.000234125
  • C = 0.0000000876741

 

Conexión del sensor

El termistor tiene tres puertos, de izquierda a derecha:

  • (S). La salida analógica. Lo conectamos a cualquier puerto analógico del Arduino, por ejemplo A0.
  • (+). Entrada de 5V.
  • (-). Conexión a tierra.

Al conectarlo y probarlo con el programa del siguiente apartado nos damos cuenta de que la salida decrece al aumentar la temperatura y viceversa, por lo que hay que intercambiar los pines 2 y 3 (5V y GND), para que funcione correctamente.

ky013_bb

 

Programa para el Arduino

El fabricante nos proporciona un pequeño programa para probar el sensor, aplicando la fórmula anterior:

#include 

void setup() {
  Serial.begin(9600);
}

void loop() {
  double temperature;
  temperature = Thermister(analogRead(0));
  Serial.print(temperature);
  Serial.println(" C");
  delay(500);
}

// A partir de la salida del termistor calculamos la temperatura
double Thermister(int voltaje) {
  double Temp;
  Temp = log(((10240000/voltaje) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;
  return Temp;
}</pre>

Como comprobamos leyendo del puerto serial, el sensor funciona correctamente.

temperatura_arduino

 

## Petición y envío por I2C de la temperatura

El siguiente programa tiene como objetivo que la Raspberry Pi realice una petición por I2C de la temperatura enviando la cadena "TEMP" y el Arduino, al recibirla le responda con el valor de la temperatura.

 

### Arduino

En primer lugar, al recibir información por I2C y al tratarse de una cadena de caracteres, utilizamos la librería **** y la clase **String** de Arduino para concatenar los caracteres que se van recibiendo en Bytes. A continuación se compara la cadena con lo que se espera recibir y en caso de coincidencia se lee la temperatura del sensor con la función anterior. A continuación hay que convertir este valor **double** en un **char array** para poder contabilizar los bytes que se envían por I2C. Para ello primero se convierte en un **long int**, previamente habiendo multiplicado la temperatura por 100 para mantener 2 dígitos decimales de precisión, se convierte a continuación en un **String** y se utiliza el método **toCharArray** para realizar la conversión final a **char array**, el cual es enviado por I2C.

#include 
#include 
 
#define SLAVE_ADDRESS 0x04

String TAG_TEMP = "TEMP";
String var;
char c;
int value;
double temperature;
String temp;
char char_array[] = "";
 
// configuracion inicial
void setup() {
  // puerto serie
  Serial.begin(9600);
  
  // inicializamos i2c como esclavo
  Wire.begin(SLAVE_ADDRESS);
  
  // llamadas para la comunicacion
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
}
 
// bucle principal
void loop() {}

// llamada para recibir datos
void receiveData(int byteCount) {
  
  var = "";
  
  while (Wire.available() > 0) {
    c = Wire.read();
    var.concat(c);
  }
    
  if (var == TAG_TEMP) {
    Serial.println("TEMP request received");
    temperature = Thermister(analogRead(0)) *100;
    Serial.println(temperature);
       
    // Convert double to char*
    value = (long int) temperature; 
    temp = (String) value;
    unsigned int temp_length = temp.length()+1;
    ((String)temp).toCharArray(char_array, temp_length);
  }
}
 
// llamada para enviar datos
void sendData() {
  Wire.write(char_array);
  Serial.print("sent: ");
  Serial.println(char_array);
}

double Thermister(int voltaje) {
  double Temp;
  Temp = log(((10240000/voltaje) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;
  return Temp;
}</pre>

 

### Raspberry Pi

Existe una librería llamada **WiringPi** que permite el envío y recepción de datos en la Raspberry Pi con comandos similares a los de la librería **** del Arduino. Sin embargo el comando **int wiringPiI2CWrite (int fd, int data)** solo admite el paso de un entero como parámetro para su envío por I2C, y dado que queremos enviar la cadena de caracteres **TEMP** no nos vale. Por tanto lo realizamos con las llamadas **read** y **write**.

El propósito de programa para poder probar la recepción de la temperatura por I2C realizará una única petición al ejecutarse en forma de script CGI. En las siguientes versiones realizará comprobaciones periódicas con una frecuencia que leerá de un fichero.

El programa establece en primer lugar la conexión a través del puerto **/dev/i2c-0** con los comandos **open** y **ioctl**. A continuación escribe en el puerto la cadena de caracteres "TEMP" y si todos los bytes se han enviado correctamente (4), espera un tiempo y realiza la operación de lectura en un buffer array char. Cuando recibe los 4 bytes de la temperatura, realiza una transformación a entero con el comando **atoi** para a continuación convertirlo en flotante y así recuperar los dos dígitos decimales.

Además resulta conveniente anotar la hora a la que se ha realizado la lectura, por lo tanto se calcula con una función que se ha creado llamada **char * getTime()**, la cual hace uso de la librería ****.

#include 
#include  // exit
#include  // open modo O_RDWR
#include <linux/i2c-dev.h>
#include 

#define ARDUINO_ADDRESS 0x04
#define TI_ADDRESS 0x08


char* getTime();

int main() {
    int fd;
    char TAG_TEMP[] = "TEMP";
    uint nBytesTAG_TEMP = 4;
    uint nBytesTEMP = 4;
    float temperature;
    char buf[4];
    int value;
    
    printf("Content-Type: text/html\n\n");
    printf("");
    printf("");
    
    printf("I2C: Conectando...
"); if ((fd = open("/dev/i2c-0", O_RDWR)) < 0) { printf("I2C: error de acceso"); exit(1); } printf("I2C: Accediendo al Arduino...

"); if (ioctl(fd, I2C_SLAVE, ARDUINO_ADDRESS) < 0) { printf("I2C: error al acceder al esclavo en 0x%x", ARDUINO_ADDRESS); exit(1); } // TEMPERATURE request printf("var enviada: %s
", TAG_TEMP); if (write(fd, TAG_TEMP, nBytesTAG_TEMP) == nBytesTAG_TEMP) { usleep(10000); if (read(fd, &buf, nBytesTEMP) == nBytesTEMP) { value = atoi(buf); printf("valor: %d
", value); temperature = (float) value / (float) 100.00; printf("temperatura: %.2f C
", temperature); printf("%s
", getTime()); } } else printf("envio incorrecto
"); printf("
I2C: Terminando..."); printf(""); close(fd); return (EXIT_SUCCESS); } char* getTime() { time_t current_time; char* c_time_string; /* Obtain current time as seconds elapsed since the Epoch. */ current_time = time(NULL); /* Convert to local time format. */ c_time_string = ctime(&current_time); return c_time_string; }</pre> Probamos el Script: Captura   ## Referencias * [[1]](http://es.aliexpress.com/item/Analog-Temperature-Sensor-Module-For-Arduino-AVR-PIC/1773738744.html?recommendVersion=1) Sensor de temperatura comprado. * [[2]](http://eagerlearning.org/practice/sensors/temperature-sensor/) Información sobre el sensor de temperatura. * [3] Gráfica de la relación entre T y R en un termistor. * [[4]](http://arduino.cc/en/Reference/WireRead) Comando Wire.read de Arduino. * [[5]](http://arduino.cc/en/Tutorial/MasterWriter) Ejemplo de transmisión de datos en Arduino. * [[6]](http://www.arduino.cc/en/Reference/StringObject) Strings en Arduino. * [[7]](http://www.cplusplus.com/reference/ctime/) Librería de C. * [[8]](https://projects.drogon.net/raspberry-pi/wiringpi/i2c-library/) Librería WiringPi. * \[[9]\](http://stackoverflow.com/questions/7383606/converting-an-int-or-string-to-a-char-array- on-arduino) Conversión de entero a char* en Arduino.