Objetivos
Material requerido.
Un NodeMCU o ESP32 o incluso cualquier arduino.
|
|
Una Protoboard mas cables. | |
Un convertidor ADC ADS1X15 | |
Un potenciómetro |
Más sobre los ADC ADS1115
En la última sesión vimos que los convertidores Analógico a digital de la familia ADS11x5 pueden conectarse con facilidad a nuestros proyectos cuando necesitemos mas resolución de los que nos dan nuestros muy amados Arduinos, o simplemente cuando quieras usar un ESP8266 que no brilla precisamente por sus convertidores ADC (Aunque en el resto no hay quien le tosa)
Ya vimos que tenían 15 bits de resolución lo que nos da una muy buena opción, pero ¿Eso es todo? ¿No vamos a recibir nada más por nuestros duramente ganados dineros? Pues, me alegra que lo preguntéis porque en efecto, nos dan más.
En primer lugar hemos visto el modo que llamamos Single Ended, o sea, el modelo normal que ya conocíamos con nuestros Arduinos, pero el ADS1115 tiene otros modos. En concreto tenemos:
Iremos viendo estos nuevos modos pero antes, (Siempre hay truco) tengo que soltaros un rollito sobre la resolución de estos convertidores y el valor en voltios de cada bit de la medida. Primero porque nos va a hacer falta un poco más abajo y conviene asegurarnos de que tenemos algunas ideas claras… y segundo porque parece haber bastante confusión al respecto por las páginas de internet con todo este tema y tampoco es para tanto.
¿Qué resolución tiene el ADS1115?
Podéis leer en muchos sitios que el ADS1115 tiene 16 bits de resolución y en otros que son 15, y no parece haber consenso por lo que conviene preguntarnos ¿Quién tiene razón? Y en Prometec con la idiocia que nos caracteriza dictaminamos que… los dos. ¿Qué te parece?
Parece que vamos a tener que explicarnos, pero en realidad no tiene mucho secreto. El ADS1115 entrega un entero de 16, pero es un entero con signo, por eso solo tenemos 15 bits útiles para valores, pero es capaz de darnos valores positivos y negativos con el ultimo bit, y por tanto es de 16 bits.
Fíjate que esto es algo que nuestros Arduinos no pueden hacer. Si la tensión cae bajo cero nuestro convertidor Arduino nos devolverá cero, siempre y cuando no caiga lo suficiente para freír nuestro integrado, que puede pasar. Pero estos convertidores nos permiten diferenciar y medir tensión negativa y positiva dentro de los márgenes de operación normales.
Por tanto es un convertidor de 16 bits, pero solo puede devolvernos valores de 15 bits, ya que el bit restante indica el signo de la medida, y de ahí toda la confusión.
¿Cuál es el valor de fondo de escala del ADS1115 y cuánto vale cada bit en voltios reales?
Otro tema que marea mucho en internet y que si vais a usar estos cacharritos de convertidores os interesa tener claro. En nuestros muy amados Arduinos el valor de fondo de escala viene fijado por la tensión de alimentación nominal, de 5V, mientras no usemos la tensión de comparación exterior con el pin AREF, y no hay más. O comparamos contra los 5V (El 99% de las veces) o usamos una tensión de referencia que siempre va a ser menor de los 5V.
Si usamos la tensión de 5V como fondo de escala en Arduino tenemos 210 partes de 0 a 5V, o lo que es lo mismo:
5/210 = 0,0048828 Voltios por bit, o 4,88 mV por bit.
Pero si conectamos una tensión de referencia de 3,3V, por ejemplo porque nuestro sensor no da más, nos permite mejorar el ratio de voltios por bit. ¿Por qué? ¿Es magia? Pues sencillamente porque ahora tenemos:
3,3/210 = 0.0032 o 3,2 mV por bit,
Es decir podemos mejorar la resolución jugando con la tensión de comparación del convertidor y eso es todo. Pero si vamos a medir tensiones bajas mejoramos la resolución practica de ADC de Arduino.
Pero si llegando aquí ya te dolía la cabeza, verás ahora. EL ADS1115 a diferencia de Arduino tiene un amplificador de ganancia programable integrado o PGA (Programable Gain Amplifier) que es quien de verdad establece el fondo de escala y en su modo por defecto (Es decir si no habéis enredado) el fondo de escala viene programado en el modo 2/3 y el fondo de escala es de ± 6.144V.
Oño, pues genial! O sea que puedo medir hasta 6.144V ¿No? Pues no. Sobre todo si no quieres quemar el convertidor, así que no pases de 5V.
Una cosa es el fondo teórico y otra que tu chip lo aguante. ¿Por qué ese valor entonces? Pues cosas del PGA, pero es importante que entiendas que la resolución del convertidor en este modo es de:
6.144 / 2^15 = 0,0001875 V/bit o 0.1875 mV por bit
Hablar de mV por bit solo significa que si tu convertidor te da una lectura de, digamos, 234, el valor en voltios es de 1.234 * 0.1875 = 231,4 mV o 0,23 Volts ¿Vale? No hay nada esotérico..[/fancy-ul] [/three-fourth]
Ya comentamos en el capítulo anterior que esta resolución es como 25 veces mejor que la normal en Arduino y por eso, todo este rollo, para que puedas calcular voltios de verdad en la lectura que normalmente es lo que sueles querer.
Pero tienes que entender que el fondo de escala depende del PGA y del factor elegido, que puede hacer que el fondo de escala llegue a una fracción de voltio. Es como el truco de Arduino con el AREF pero un poco mas evolucionado.
De igual modo, hay diferentes modelos de la familia ADS1X15 cada uno con sus propias características por lo que todos estos valores pueden bailar si cambias del modelo y por eso os he dado esta paliza calculando. Porque tienes que estar seguro de los valores que manejas en un momento dado y cual es el fondo de escala de tu modelo de ADC (Por menos se han estrellado sondas marcianas)
Comparator mode
Ahora que hemos hablado de resoluciones y bits ya podemos hablar del modo comparador del ADS1115. En realidad la idea es sencillamente que podemos programar una alerta si la tensión que medimos sobrepasa un cierto valor.
El convertidor funciona normalmente midiendo la tensión obedientemente, pero cuando el valor leído sobrepasa un cierto umbral se dispara una alarma en el pin ALERT, que normalmente está en alto pero que al llegar a la condición baja a LOW indicando así que ha disparado la alarma.
Podemos usar esta señal del pin ALERT para disparar una interrupción o simplemente hacer un polling periódico para decidir si se ha alcanzado la condición. Basta con conectar el pin ALERT a una interrupción o quizás un LED y así visualizar la alarma.
Podríamos hacer un circuito como este:
Se supone que sería una alarma un poco extraña porque estaría encendida normalmente y se apagaría al disparar la alarma.
El programa sería muy parecido al de la sesión anterior Prog_319_1. En el setup haríamos:
void setup(void) { Serial.begin(9600); ads.begin(); ads.startComparator_SingleEnded(0, 16000); }
La instrucción clave es por supuesto la última donde la pedimos que arranque el comparador en el canal 0 (El primer parámetro) y a qué valor debe disparar en 16.000. Y es aquí donde entendéis porque de todos los rollos previos, porque 16000 x 0.1875 = 3V
El loop será muy similar:
void loop(void) { int16_t lectura; lectura = ads.readADC_SingleEnded(0); Voltage = (lectura * 0.1875)/1000; Serial.print("AIN0: "); Serial.print(lectura); Serial.print("\tVoltage: "); Serial.println(Voltage, 2); delay(1000); int16_t adc0 = ads.getLastConversionResults(); }
La clave está de nuevo en la última línea, y el flanco de bajada debería producirse justo después de ejecutar la instrucción getLastConversionResults()
Por lo que he leído por ahí, tendremos un flanco de bajada en el pin ALERT al alcanzar los 3V y sobrepasarlos, lo que deberíamos poder usar como alarma.
Lamentablemente en las pruebas que he ido haciendo, no he conseguido que me haga el menor caso. Supongo que se debe a mi incompetencia, pero no he encontrado mucha información al respecto, y en general bastante confusa.
Tal vez haya por ahí un experto que pueda ilustrarme al respecto y estaría muy agradecido si me enviáis un correito comentando el asunto.
También me han quedado varias dudas de su función. El manual dice que la alarma se dispara al sobrepasar la tensión de referencia… ¿Y puede dispararse al caer de un cierto valor? Sería muy útil para saber por ejemplo que mi batería ha bajado de un cierto nivel y que debería recargarla.
Tampoco he conseguido saberlo, porque no parece haber suficiente información por ahí y el manual del fabricante ha conseguido que pierda las ganas de seguir leyendo.
Hablemos del modo differential conversion
La familia del ADS1x15 soporta dos modos básicos de conversión: el normal de toda la vida que llamamos single ended y dispone de 4 entradas para ello del A0-A3, y el modo diferencial que realiza una conversión de voltaje entre los pines A0-A1 y A2-A3, con lo que solo tenemos dos convertidores disponibles.
Bien veamos, así que tengo que elegir entre tener 4 convertidores o solo dos, estee… déjeme pensar, vale … creo que prefiero 4.
Pero no, las cosas nunca suelen ser tan sencillas. Ten en cuenta que en el modo Single Ended solo puedes leer valores positivos no negativos (Ahí está el truco) y por lo tanto solo tengo 15 bits efectivos de resolución.
Además, aunque los convertidores de esta familia son mucho más resistentes a las interferencias electromagnéticas, no son perfectos y cuando usamos el modo diferencial lo normal es que la interferencia sean las mismas en los dos canales lo que en la práctica tiende a anularlas, haciendo que las medidas sean mucho más resistentes.
Otro de los problemas de tener un PGA (O creías que todo eran ventajas) es que al amplificar las señales también amplificas el ruido, lo que puede acabar en desastre, pero si usas el modo diferencial, la cosa mejora bastante.
Al final depende de lo que necesites. Puedes sacrificar precisión y estabilidad a cambio de disponer de 4 puertos de conversión, pero si solo vas a usar un par de los 4 disponibles no parece grave.
Si hacemos un ejemplo de leer una batería la conexión sería más o menos así:
#include <Wire.h> #include <Adafruit_ADS1015.h> Adafruit_ADS1115 ads ; void setup(void) { Serial.begin(9600); ads.begin(); } void loop(void) { int16_t results; results = ads.readADC_Differential_0_1(); float lectura = results * 0.1875 ; // Pasamos lectura a voltios Serial.print("Differential: "); Serial.print(results); Serial.print("("); Serial.print(lectura ); Serial.println("mV)"); delay(1000); }
La línea clave es:
results = ads.readADC_Differential_0_1();
Para medir de modo diferencial entre las puertas A0 y A1, que también podría ser entre las puertas A2 y A3
int16_t readADC_Differential_2_3(void);
He conectado ex profeso la batería de 3.7 V, al revés para obtener valores negativos y demostraros que nos os engañaba cuando os decía que tienen signo los valores. He comprobado con el polímetro que los valores que lee dan 4,125 V, son compatibles con mi voltímetro 4,18 que por cierto no es de los mejores (¡Que queréis que os diga! Soy pobre)