Ya comentamos algunos protocolos de comunicaciones que puede usar Arduino para comunicarse con diversos dispositivos. Esta vez nos vamos centrar en ilustrar un caso concreto de uso de un sensor analógico. Concretamente usaremos un termistor NTC barato como sensor de temperatura.
Hay que advertir que si bien se trata de una solución muy económica podría no ser la ser la solución óptima dependiendo de nuestras necesidades.
También comenté que en esta serie de artículos más que un trabajo de erudición, se trataba de compartir mis venturas y desventuras en la búsqueda de soluciones a los problemas de desarrollo que se presentaran en este proyecto.
A pesar de ello no publicaré de momento mas que trozos de mi código porque el desarrollo de los diferentes módulos de la aplicación está aún en fase pre-beta.
Indice:
- Sensor de temperatura NTC
- Impermeabilización de una sonda
- Calibración de sensores analógicos
- Interpolación multimap
- Interpolación polinomial por mínimos cuadrados
- Validación del resultado de la función de interpolación
- Sensor de temperatura con termistor PTC
Sensor de temperatura termistor NTC:
Los termistores NTC son un tipo de sensor analógico. Tal como se aprecia en la imagen de la izquierda, pueden venir presentados con diferentes encapsulados. El tratamiento de los sensores analógicos en general puede ser muy similar al que aquí esbocemos para los termistores. Ya hemos hablado algo sobre sensores analógicos. Véase Entradas analógicas
Un termistor NTC es un semiconductor que ofrece una resistencia al paso de la corriente donde esta varía negativamente con la temperatura. Es decir, a mayor temperatura menor resistencia. Son muy comunes y muy económicos. Hay que advertir que la variación de la resistencia con la temperatura no es lineal.
Sabemos que como resultado de estas variaciones no lineales de la resistencia, se obtendrán unas determinadas variaciones de voltaje, pero ni el valor concreto de la resistencia para cada temperatura, ni el correspondiente valor del voltaje en la entrada analógica, serán datos importantes para nosotros. Para nosotros lo importante será el valor que devuelva Arduino. Este estará comprendido entre 0 y 1023 y a cada uno de estos valores se le podrá asociar una temperatura.
En un principio las resistencias NTC me parecieron muy adecuadas pero cuando empecé a hacer pruebas vi que presentan algunos inconvenientes que he podido soslayar solo parcialmente. La longitud del cable desde el sensor NTC hasta el Arduino les afecta de dos maneras. La primera es porque a mayor longitud del cable, mayores son las interferencias electromagnéticas que serán recogidas por el sensor falseando la lectura de la temperatura. Para minimizar el efecto de las interferencias se realizarán una serie de lecturas y se devolverá el valor promedio de todas ellas. La segunda forma en que les afecta el cable es porque este también recoge la temperatura ambiente y la transporta por el conductor metálico hasta la resistencia NTC.
Los termistores NTC presentan distintas características. Una de ellas es la resistencia nominal. Habitualmente se toma como resistencia nominal de un termistor NTC el valor de resistencia que presenta el termistor a 25ºC.
Para usar un termistor en Arduino lo conectaremos junto a otra resistencia formando un divisor de tensión.
En la figura de la izquierda, vemos el divisor de tensión que se usó para la NTC de 1k ohm.
La resistencia fija del divisor de tensión no debe presentar un valor muy diferente al valor nominal de la resistencia del termistor, porque de otro modo se perdería precisión. Nosotros usaremos siempre divisores de tensión cuya suma de ambas resistencias nunca supere el valor de 1k ohm, para no perjudicar el consumo.
Los divisores de tensión podrían usar valores diferentes para ambas resistencias y estar intercambiadas de posición.
Usé cable coaxial para conectar el sensor, así que este deberá ir conectado a masa. Con ello se minimizan las interferencias electromagnéticas.
La elección de la NTC debería hacerse consultando las características. El código de referencia de esta NTC de 1K que yo usé es 238164063102 y su precio estaba en torno a medio euro. No todos los termistores tienen la misma precisión ni las mismas características y como es lógico tampoco tienen el mismo precio. Si compras un termistor no olvides anotar el código de referencia del modelo para poder consultar las características en Internet y para poder comprar exactamente el mismo si fuera necesario.
Yo adquirí una NTC de 1K (porque en la tienda a la que fui no tenían ninguna otra), así que también compré la resistencia fija de 1k ohm para el divisor de tensión tal y como indica la mencionada figura. Seguidamente explico como la usé.
Impermeabilización de una sonda
La sonda de temperatura en un acuario debería ser muy fiable porque la vida de nuestros peces puede depender de ello. Una falta de hermeticidad podría convertir nuestro acuario en sopa de pescado, pero yo para mis pruebas, he recurrido a impermebilizar un termistor NTC de 1k. Si me propusiera usar la sonda en un acuario, la probaría como mínimo durante un mes sin hacer que toda la responsabilidad de la regulación de la temperatura recaiga sobre esa sonda experimental.
Yo soldé el termistor NTC de 1k a un extremo de un cable. Era un cable coaxial como el que podeis ver en la figura siguiente. Esto lo hice así con idea de que la malla externa fuera conectada a masa en el divisor de tensión y sirviera de pantalla contra las interferencias.
Si no vais a construir una sonda sumergible podéis obviar los detalles de construcción que yo ensayé y que detallo a continuación.
- Puse una gota de pegamento araldite rápido para estabilizar los terminales soldados evitando que en algún momento pudieran cortacircuitarse (Araldite rápido es un pegamento tipo resina Epoxi).
- Dejé fraguar el pegamento durante 24 horas, es importante respetar ese tiempo ya que pese a endurecer muy rápido tarda enfraguar totalmente y el pegamento a medio fraguar podría reaccionar con el agua o con la silicona.
- Enfundé el termistor soldado al cable con un tubo de plástico termoretráctil. Se trata de unos tubos de plástico, de venta en tiendas de electrónica, que al ser sometidos al calor (yo uso un mechero para calentarlos) se hacen más estrechos y permiten envolver de forma ajustada cualquier cable desnudo o punto de soldadura haciendo de aislante. Es mucho mejor que la cinta aislante adhesiva.
- Con el termistor NTC en su interior inyecté dentro del tubo termoretractil, abundande sellador de silicona para este que alcanzara en el interior del tubo al termistor y lo envolviera impermeabilizándolo en el interior del tubo.
- Después empecé a calentar el extremo final con un mechero. La silicona empezó a arder. La apagé soplando. Para evitar este susto basta sellar el extremo del tubo con una pincita o un clip.Terminé de caléntar ese extremo hasta que se estrechó completamente y con la punta de unas tenazas apreté el extremo que quedó perfectamente termosellado.
- Seguí calentando el resto del tubo termoretractil que se fue estrechando quedando así completamente ceñido al termistor. Este tubo termoretractil sobrepasa unos centímetros más allá de la cubierta del cable protegiendo del agua todo el final de la sonda incluyendo parte del cable coaxial.
El procedimiento no es perfecto y yo no confiaría la vida de mis peces a un sensor autoconstruido e insuficientemente probado, pero me sirvió para hacer pruebas de calibración y comprobar el software de interpolación del que hablaré seguidamente.
Calibración de sensores analógicos
Vamos a ilustrar la calibración de un sensor analógico exponiendo como se hizo en el caso concreto del termistor NTC de 1 K Ohm que venimos comentando. Además usaremos el mismo divisor de tensión que ya ilustramos en el diagrama anterior (posee una resistencia de 1k ohm conectada a +5V y un termistor NTC de 1 K Ohm conectado a 0V).
Es importante anotar todos los detalles relativos a los componentes y a su conexión y también el código de referencia del modelo de termistor NTC ya que la calibración que hagamos solo servirá para este caso concreto.
Para ello lo que haremos será una serie de lecturas del pin analógico de Arduino . Este estará conectado al sensor que a su vez será sometido a diferentes temperaturas controladas con ayuda de un termómetro.
El procedimiento que yo seguí fue tomar en una jarra agua fría (a 14ºC) y en otra jarra agua bastante caliente (a 42ºC). Las temperaturas las controlé un poco a ojo con ayuda de un termómetro normal.
Dispongo de una función de lectura GetRaw10() que hace varias lecturas sobre el sensor (hay bastante variación entre lecturas por las interferencias recibidas por el cable). La función entregará el valor promedio multiplicado por diez. Es decir en lugar de devolver valores entre 0 y 1023 me devuelve valores entre 0 y 10230. Con ello tengo un dígito más de precisión en ese valor promedio. Preferí no usar float.
// Tomar el valor de la entrada en crudo. Devuelve el (valor promedio) *10 long CAO_AnalogicSensor::_GetRaw10(){ int i; // El resultado intermedio antes de la división final podría // exceder MAX_UNSIGNED_INT long Val; Val=0; for (i=0; i<NUM_ITER; i++){ Val = Val + analogRead(_Pin); delayMicroseconds(MICROSEG); } Val= (Val*10)/NUM_ITER; // 0..10240 (valor multiplicado por 10) return Val; // 0..10230 }
El procedimiento para obtener los datos de calibración tomando datos a distintas temperaturas fue el siguiente:
- Empecé con la jarra fría (a 14.0 ºC) y Arduino me devolvió el valor 6290
- Para la otra jarra (la de 42 ºC) devolvió el valor 3710.
- Después de estas dos lecturas vertí un poco de agua de la jarra fría a la jarra de agua caliente, la removí para igualar temperaturas en el agua y obtuve una temperatura de 39 ºC que me entregaba un valor de 3900.
- Seguidamente, en la jarra de agua fría vertí agua de la jarra caliente, removí y esta vez obtuve una temperatura de 14.5 ºC que me devolvió el valor 6180.
- Continué jarreando de un lado a otro, midiendo y anotando resultados. Con ello obtuve una tabla de valores de temperatura y sus correspondientes valores entregados por Arduino.
El método es un poco rudimentario. Es fácil equivocarse al leer la temperatura o al anotarla, y por ello conviene introducir los datos convenientemente ordenados en algún programa que nos permita obtener alguna gráfica. Yo lo hice con SciDAVIS (un programa usé por primera vez y que apenas conozco). El caso es que ver la gráfica nos va a permitir detectar la presencia de datos demasiado desviados, posiblemente fruto de algún despiste (que son una de mis especialidades).
Eliminados un par de puntos que aparecieron muy fuera de lo esperado, la curva obtenida quedó tal y como podéis apreciar en la figura siguiente. En ella aparece una gráfica ligeramente curvada y eso es porque hemos limitado las lecturas dentro de un rango de temperaturas que nos interesaban. Valores más extremos darían una curva más acentuada.
Estos datos, correspondientes a 22 puntos, se trasladaron al código como datos para inicializar el sensor.
long Inp[]={6290, 6180, 6050, 5880, 5500, 5160, 5060, 4897, 4890, 4830, 4811, 4740, 4707, 4575, 4550, 4470, 4371, 4210, 4102, 4070, 3900, 3710 }; // 0..10230 long Out[]={ 140, 145, 160, 180, 210, 250, 255, 270, 275, 280, 281, 290, 291, 310, 300, 315, 330, 350, 351, 360, 390, 420 }; // Grad.Centig.*10, Sens_Temp_Acu.Ini("NTC1K 238164063102", "+1K", 0, Inp, Out, DataLen, 2); // Interpol.Polinom.Min.Cuadr. Grado=2
Interpolación multimap
Con este tipo de interpolación obtendremos una función que seguirá fielmente la línea quebrada que aparece en la gráfica. Este tipo de interpolación se explica con todo lujo de detalles en la página A multiMap function for Arduino.
El caso es que Debido a las interferencias y a las apreciaciones a la hora de leer el termómetro de control para realizar la calibración, y que no era digital sino de los normalitos, se obtendrán datos bastante imprecisos.
Interpolación polinomial por mínimos cuadrados
Como resultado de las imprecisiones en los datos de lectura para calibrar el sensor, lo que hemos obtenido obtenemos realmente es una nube de puntos. El método de interpolación por mínimos cuadrados es muy bueno para obtener a partir de estos datos una función polinómica que minimice la suma de los cuadrados de las diferencias entre los datos obtenidos y la función polinómica aproximada a esos resultados.
Intentaré explicar todo esto con detalle y usando ejemplos y un lenguaje poco técnico e intuitivo porque es un tema que no domina demasiada gente (yo tampoco lo domino completamente).
Si usamos un polinomio de grado 1 obtendremos una linea recta que se corresponderá lo mejor posible con esos datos, pero en nuestro caso, vemos que la gráfica aparece ligeramente curvada, por ello dará mejores resultados un polinomio de grado 2 que se corresponderá con una curva parabólica. Elevar el grado del polinomio puede minimizar las desviaciones. Para nuestros 22 puntos podríamos obtener un polinomio de grado 21 que pasaría por todos los puntos, pero esto no significará que esa curva sea un fiel reflejo de la realidad. El resultado no solo sería más costoso de calcular sino que sería probablemente bastante malo. Las gráficas de grado 3 presentan una curva en zigzag y esa no es la forma que se intuye en nuestros datos. Lo que se intuye es una única curva muy suave y por eso usaremos un polinomio de grado 2.
Validación del resultado de la función de interpolación
El método que yo he seguido para obtener el polinomio es el método de Gaus, pero esto no pretende ser una clase de cáculo numérico. Baste decir que el polinomio encontrado para estos datos fue el siguiente:
Y = 1017.274658 – 0.198109*X + 0.000009 * X2
Donde Y es la temperatura en grados centígrados multiplicada por diez, y X es el valor entregado por Arduino multiplicado igualmente por diez. (No me gusta usar float salvo que sea imprescindible).
Esa función caracteriza el uso de un termistor NTC de 1K modelo 238164063102 y conectado como divisor de tensión de forma idéntica al diagrama del mismo visto anteriormente.
Podemos poner a prueba la función obtenida usando los mismos valores de X y obteniendo el resultado aplicando la función. Usaremos para ello un programita en lenguaje python.
#! /usr/bin/python def f(X): return 1017.274658 - (0.198109*X) + (0.000009*X*X ) for X in [ 6290, 6180, 6050, 5880, 5500, 5160, 5060, 4897, 4890, 4830, 4811, 4740, 4707, 4575, 4550, 4470, 4371, 4210, 4102, 4070, 3900, 3710 ] : print "%d : %4.2f" % ( X, f(X) )
Con ello se obtiene la siguiente salida.
6290 : 127.25 6180 : 136.69 6050 : 148.14 5880 : 163.56 5500 : 199.93 5160 : 234.66 5060 : 245.28 4897 : 262.96 4890 : 263.73 4830 : 270.37 4811 : 272.48 4740 : 280.45 4707 : 284.18 4575 : 299.30 4550 : 302.20 4470 : 311.56 4371 : 323.29 4210 : 342.75 4102 : 356.07 4070 : 360.06 3900 : 381.54 3710 : 406.17
Con estos datos ahora podemos superponerlos a los datos reales muestreados durante el procedimiento de calibración. La gráfica demuestra que existe cierta aproximación, pero por alguna razón el resultado que yo obtuve no es demasiado perfecto (debería serlo si lo hubiera hecho bien).
Para la función, me basé en un programita en C de interpolación polinomial de mínimos cuadrados que usaba el método de Gauss. A pesar de que estudié todo esto en mi asignatura de cálculo numérico hace ya muchos años, lo cierto es que no puedo ahora precisar la causa de este error aparentemente sutil y que me entrega una gráfica algo más baja y algo más plana de la que sugieren los datos.
Cabe la posibilidad de que el elevado número de operaciones que usa este método de interpolación, produzca por acumulación de los errores de redondeo esta inexactitud pero la forma de salir de dudas sería usar tipos de datos double en lugar de float, por desgracia en la plataforma Arduino no existe esa posibilidad así que nos quedamos con las ganas de hacer esa prueba.
Pese a ello, la función de interpolación obtenida para este termistor es perfectamente utilizable y se puede mejorar incluyendo un parámetro para un ajuste fino general de los resultados que incremente o decremente ligeramente el resultado teórico obtenido por la función en previsión no solo de la posible acumulación de pequeños errores de redondeo en el cálculo de la función, sino también para la corrección de errores debidos al hardware por las variaciones de los valores dentro de los márgenes de tolerancia contemplados por el fabricante. para la NTC de 1K 238164063102 la tolerancia de los valores de la resistencia a 25 ºC es de ±5% y para la otra resistencia del divisor de tensión se usan resistencias habitualmente con una tolerancia del 5%. Ambos errores en el divisor de tensión podrían compensarse o sumarse.
También hay que decir que en acuariofilia un error de ±0.5 ºC no es demasiado importante y con la posibilidad de un posterior ajuste aún menos.
Por todo ello el resultado de usar un simple termistor NTC podría ser mejor de lo que se necesita normalmente en acuariofilia. Yo pretendo usar más de una sonda y de diferente tipo primero para poder compararlas y segundo por si alguna se avería.
En cualquier caso, con este estudio, he tratado de exprimir al máximo las posibilidades de usar un sensor de temperatura extremadamente barato y no demasiado preciso alcanzando a pesar de todo unos resultados parciales que podrían resultar bastante aceptables para muchas aplicaciones.
Para obtener resultados más precisos y con mayores garantías seguramente tendríamos que olvidarnos de todo esto y adquirir una sonda digital sumergible, porque los termistores NTC baratos tienen sus limitaciones y el bricolaje para obtener una sonda sumergible casera también.
La cuestión es poder ofrecer diferentes opciones para que cada uno pueda decidir lo que más le convenga. Todo este proyecto irá en esta línea de ofrecer diferentes alternativas y que sean los futuros usuarios los que decidan.
Sensor de temperatura con termistor PTC
Hablando de alternativas, existen en el mercado otro tipo de termistores que funcionan aumentando su resistencia cuando aumentan la temperatura. Son los PTC. (Yo no los he probado, son menos frecuentes y caros, pero sustituyendo la resistencia no variable en un divisor de tensión por una PTC podría resultar una combinación PTC+NTC interesante. El sensor en este caso sería de tres hilos y tendríamos el divisor de tensión con dos resistencias variables en la punta. La resistencia nominal de ambas debería ser similar y al actuar en sentido inverso la una de la otra, la pendiente de la curva y por lo tanto la precisión del sensor, podría verse beneficiada, pero esto lo planteo solo como idea para el que quiera experimentar con otro tipo de termistores. También recordar que existen termistores de alta precisión.
Carlos
Mi pequeña aportación a tu entrada:
1) Si usas la malla del coaxial como cable de masa, no estás evitando interferencias, probablemente las captes porque el coaxial funciona en este caso como una antena. Como trabajas en continua no deberían preocuparte interferencias como la del filtro (50/100Hz).
2) El coaxial carga una resistencia, que la puedes considerar como 72 ohms. Puede estar afectando la lectura.
3) Puedes evitar la interpolación y obtener una lectura directa empleando un driver un poco más complejo: puente de wheastone+amplificador.
Antonio Castro
Muchísimas gracias por tu aportación.
1) Tengo entendido que si se hace correctamente si que suprime bastante las interferencias. cable blindado
2) 72 ohmios no es tanto comparado con los 1000 Ohmios del NTC o del divisor de tensión. Un cable coaxial bueno no tiene porque ofrecer más resistencia que un cable bifilar. Depende de lo que se use en cada caso.
3) Supongo que te refieres a usar amplificadores diferenciales, pero estos necesitan alimentación simétrica. No cabe duda de que ese circuito sería capaz de sacar el máximo partido a cualquier sensor y de hecho se usar para los sensores de PH y de potencial redox. Necesitaría incorporar un inversor de polaridad como el que se usa en Phduino. (Un interesante proyecto del que hablaré dentro de poco).
Alguna vez monté algún circuito wheastone. Usando trimmers este circuito permite calibrar la máxima sensibilidad de la medida dentro del rango de valores que nos interese.
Aunque sea anticipar cosas, ya que me haces esta aportación te comento algunos planes respecto a la medida de la temperatura. Lo siguiente que voy a hacer es probar un sensor digital ds18b20. Es inmune a interferencias. Usa protocolo 1-wire, cuesta unos 2 dólares y Electan comercializa una sonda sumergible por 7.95 euros. La he recibido hace unos días y no he tenido tiempo de probarla (tenía que comprar una pequeña resistencia).
La DS18B20 tiene muy buena pinta, pero no creo que llegue descartar totalmente la NTC. El tema sigue abierto, y habrá que comparar diferentes opciones.