Si hay un sensor simple y fiable ese es el BMP180. Que no te engañe su apariencia, ahí donde lo ves, este diminuto circuito puede proporcionarnos información de temperatura, presión atmosférica y altitud.
El BMP180 es un sensor de Bosch, sí sí, los de Like A Bosch. Pero no se trata de ningún electrodoméstico para freír patatas o calentar el tupper. No es eso.
Y aunque el sensor BMP180 es capaz de medir la temperatura con una precisión de ±1ºC, su punto fuerte es el cálculo de la presión atmosférica. Esta característica le otorga la capacidad de hacer al menos dos cosas bien:
- Es capaz de medir la altura en la que nos encontramos.
- Predecir cambios en el clima como si fuera un pastor de ovejas.
Luego profundizaremos en cómo es capaz de hacer todo esto con un BMP180.
Pero quizás lo más llamativo del sensor es su fácil uso ya que viene precalibrado de fábrica y no requiere de ningún otro componente adicional para funcionar.
Ideal si quieres hacer una estación meteorológica o necesitas un altímetro si complicarte mucho la vida.
Veamos cómo puedes utilizar este sensor con Arduino.
Indice de contenidos
Dónde comprar el sensor BMP180
Si entras en las típicas tiendas de Internet como Amazon o Aliexpress y buscas BMP180 vas a encontrar una gran variedad de productos que incorporan este sensor.
Y esto es debido a que, como veremos más adelante, el sensor lo puede comprar cualquier empresa e integrarlo en una placa.
Esto nos abre un abanico de posibilidades enorme, ya que no hay un único fabricante, hay decenas de ellos que incorporan un BMP180.
Los precios varían al igual que la calidad. Los que yo compro son de AZDelivery y funcionan bien. Vas a encontrar módulos desde 1€ en Aliexpress hasta 4€ en Amazon.
El que yo he comprado es este y por lo menos a mí, me ha funcionado correctamente.
Características del sensor BMP180
Como suele suceder con este tipo de componentes, el módulo debe el nombre al chip que tiene integrado y que es capaz de medir la temperatura y la presión atmosférica. Este chip se llama BMP180 y está fabricado por Bosch.
Para saber cuáles son las características del sensor BMP180 hay que fijarse en la hoja de características o datasheet del chip. Las principales son:
Característica | Mínimo | Máximo | Precisión |
---|---|---|---|
Temperatura | -40ºC | +85ºC | ± 1ºC |
Presión | 300 hPa | 1.100 hPa | ± 1 hPa |
Altitud | 0 m | 9.130 m | ± 1 m |
En cuanto a la alimentación del BMP180, según la hoja de características técnicas la tensión de alimentación debe estar en el rango de 1,8V a 3,6V.
Sin embargo, estos módulos vienen con un regulador de tensión de la serie XC6206 de 3,3V.
Este tipo de reguladores son LDO (siglas en inglés Low Dropout Regulator) tiene las siguientes características técnicas:
Característica | Valor |
---|---|
Tensión de entrada | 1,8 V a 6 V |
Caída de tensión | 350 mV |
Corriente de salida | 200 mA |
Consumo | 3 μA |
El parámetro más importante de un regulador de tensión es la caída de tensión que nos indica cuánta tensión demás hay que suministrar al regulador para obtener a la salida los 3,3 V deseados.
Por ejemplo, el XC6206 de 3,3V nos indica que como mínimo tenemos que tener una tensión de entrada de 3,3V + 0,35 V lo que nos dice que necesitas una tensión de 3,65 V para que el regulador función correctamente.
En realidad, la caída de tensión de 350 mV es un valor máximo. Bajo ciertas circunstancias, el regulador podría funcionar con una tensión de caída de 75 mV lo que supone alimentar el regulador con una tensión de 3,375 V.
Sea como sea, gracias a este regulador de tensión podrás alimentar tu el sensor BMP180 con una tensión de 5 V como las salidas que tienen Arduino UNO o Arduino Nano.
Con respecto al consumo del sensor dependerá del modo de funcionamiento. El BMP180 puede funcionar en 5 modos diferentes para calcular la presión atmosférica. La obtención de temperatura solo admite el modo standard.
Seleccionar un modo u otro afecta al consumo, al tiempo de conversión y a la resolución según la siguiente tabla.
Modo | Resolución | Consumo | Tiempo |
---|---|---|---|
Ultra low power mode | 16-bit | 3 µA | 4,5 ms |
Standard mode | 17-bit | 5 µA | 7,5 ms |
High resolution mode | 18-bit | 7 µA | 13,5 ms |
Ultra high resolution mode | 19-bit | 12 µA | 25,5 ms |
Advanced resolution mode | 19-bit | 32 µA | 76,5 ms |
Durante la conversión se alcanzan picos de 1 mA, es decir, el sensor BMP180 consume 1A el tiempo que tarde en convertir la presión atmosférica. En el peor de los casos estará consumiendo 1A durante 76,5 ms y luego volverá al consumo normal del modo.
Por último, el sensor BMP180 incluye una interfaz I2C que nos permite una conexión muy sencilla con Arduino a través de dos únicos cables. La dirección I2C del módulo es 0x77.
Una vez conocidas las características técnicas hay que ver el pineado del sensor BMP180.
Pines sensor BMP180
Los pines suelen venir sin soldar así que tendrás que sacar el soldador y el estaño y soldar los pines al módulo BMP180.
En el módulo BMP180 vas a encontrar 4 pines diferentes.
Donde:
- VCC: es el pin por donde se alimenta al módulo. Aunque el sensor BMP180 admite una tensión de entre 1,8V y 3,6V, gracias al regulador podrás alimentar el módulo con una tensión entre 3,3V y 5V.
- GND: pin de tierra. Se conecta directamente con GND de Arduino.
- SCL: señal de reloj del protocolo I2C.
- SDA: señal de datos del protocolo I2C.
Luego de repasar el pinout del sensor BMP180 veremos cómo conectarlo a Arduino.
Conexión del sensor BMP180 con Arduino
Conectar el sensor BMP180 con cualquier Arduino es muy sencillo gracias al protocolo I2C. Este protocolo nos permite hacer la conexión utilizando solo dos pines.
En el siguiente esquema puedes ver la conexión con un Arduino Nano.
El pin VCC se conecta con el pin 5V de Arduino y GND con GND.
Los pines del protocolo I2C SCL y SDA del módulo BMP180 se conectan con los pines A5 y A4 de Arduino.
Si utilizas otro Arduino que no es Nano mira la siguiente tabla.
Placa | SDA | SCL |
---|---|---|
Arduino Pro Mini | A4 | A5 |
Arduino MEGA | 20 | 21 |
Arduino DUE | 20 | 21 |
Arduino Leonardo | 2 | 3 |
Arduino Nano | A4 | A5 |
Cómo programar sensor BMP180
Te puedes imaginar lo que supone a nivel matemático calcular la altitud sabiendo la presión atmosférica. Serían unas cuantas horas calculando y diseñando el algoritmo.
Sin embargo, hay una librería que además de hacer todo esto por nosotros, nos proporciona la temperatura. Esta librería es Sparkfun BMP180.
Haciendo unas simples llamadas a ciertas funciones, tendremos toda esta información lista para mostrarla en el monitor serie o para poder mostrarla en alguna pantalla OLED o LCD.
A continuación verás cómo puedes hacerlo con el IDE de Arduino y con PlatformIO.
BMP180 con IDE de Arduino
Lo primero es instalar la librería a través del IDE de Arduino. En este caso hay que hacerlo descargando la librería que nos ofrece Sparkfun, ya que esta empresa ha dejado de comercializar este producto y la librería no está disponible en el gestor de librerías del IDE de Arduino.
Por este motivo hay que instalar la librería de forma manual.
Lo primero, accede al repositorio de la librería Sparkfun BMP180. Una vez dentro hay que descargarla en formato .zip haciendo clic en el botón que Code y luego en el que pone Download ZIP
Una vez descargado hay que importar la librería desde el IDE de Arduino. Entra en Programa>Incluir Librería>Añadir biblioteca .ZIP
Esto abrirá una ventana para que busques el archivo .zip que acabas de descargar. Lo seleccionas y haces clic en el botón aceptar.
Una vez instalada ya tienes acceso a la librería y a los ejemplos.
Veamos ahora cómo hacerlo con PlatformIO.
BMP180 con PlatformIO
Para empezar a utilizar el sensor BMP180 con PlatformIO lo primero es crear un nuevo proyecto al que llamaremos BMP180-ARDUINO-NANO.
Desde el home de PlatformIO haz clic en nuevo proyecto.
Luego rellena los campos seleccionando Arduino Nano y haz clic en el botón Finish.
Si tu placa es original y la has comprado recientemente, selecciona Arduino Nano ATmega328 (new bootloader).
Para añadir la librería abre de nuevo el home de PlatformIO, accede a la opción de Libraries, pon en el campo de búsqueda bmp180 y pulsa la tecla Enter.
Esto mostrará unas cuantas librerías. Selecciona la que pone Sparkfun BMP180.
Una vez dentro, haz clic en el botón que pone Add to Project.
Luego, selecciona el proyecto que acabamos de crear y haz clic en el botón Add.
Esto creará una nueva línea en el archivo platformio.ini donde se incluye la librería que acabamos de importar.
Con esto ya está todo preparado para empezar a trabajar con el sensor BMP180.
Obtener temperatura y presión con sensor BMP180
El siguiente código es válido para el IDE de Arduino como para PlatformIO.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
#include <Arduino.h> #include <Wire.h> #include <SFE_BMP180.h> // Temporizador unsigned long ultimoEnvio = 0; const unsigned long tiempoEnvio = 3000; // 3 segundos // Sensor BMP180 SFE_BMP180 bmp180; // Modo funcionamiento BMP180 const byte modoPresBMP180 = 3; // Altitud actual en metros const double altitudActual = 106; void setup() { Serial.begin(9600); // Esperar hasta que se inicie el monitor serie while (!Serial) ; // Iniciar sensor de temperatura if (bmp180.begin()) { Serial.println(F("BMP180 iniciado correctamente")); } else { Serial.println(F("Error al inicial BMP180")); // No dejar continuar while (1) ; } } void loop() { // Overflow millis if (ultimoEnvio > millis()) { ultimoEnvio = millis(); } // Temporizador if (millis() - ultimoEnvio >= tiempoEnvio) { // Marca de tiempo ultimoEnvio = millis(); // Variables para obtener datos del sensor BMP180 byte status; double temp, pres, altitud; //Inicio de lectura de temperatura status = bmp180.startTemperature(); // Comprobar resultado de la lectura temperatura // Devuelve 0 si hay error // milisegundos que hay que esperar en caso contrario if (status != 0) { // Pausa hasta que finalice la lectura delay(status); // Obtener temperatura // La temperatura se almacena en temp en grados Celsius status = bmp180.getTemperature(temp); // Comprobar resultado de la temperatura // Devuelve 0 si hay error // Devuelve 1 si todo ha ido bien if (status != 0) { Serial.print(F("Temperatura: ")); Serial.print(temp, 2); Serial.println(F(" ºC")); // Inicio lectura de presión status = bmp180.startPressure(modoPresBMP180); // Comprobar resultado de la lectura presión // Devuelve 0 si hay error // milisegundos que hay que esperar en caso contrario if (status != 0) { // Pausa hata que finalice la lectura delay(status); // Obtener presión atomosférica // La prsión se almacena en la variable pres en milibar (mbar) // Esta función requiere la medida de temperatura status = bmp180.getPressure(pres, temp); // Comprobar resultado de la presión // Devuelve 0 si hay error // Devuelve 1 si todo ha ido bien if (status != 0) { Serial.print(F("Presión: ")); Serial.print(pres, 2); Serial.println(F(" mbar")); // Obtener altitud // Paso 1, establecer la presión a la altitud actual para que nos devuelva la presión compensada a nivel del mar double presNivelMar = bmp180.sealevel(pres, altitudActual); Serial.print(F("Presión a nivel del mar: ")); Serial.print(pres, 2); Serial.println(F(" mbar")); // Paso 2, obtener la altitud con las dos presiones altitud = bmp180.altitude(pres, presNivelMar); Serial.print(F("Altitud: ")); Serial.print(altitud, 2); Serial.println(F(" metros")); } } } } } } |
Vamos a ir viendo cada parte del código empezando por las librerías y las variables.
Librería y variables
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <Arduino.h> #include <SFE_BMP180.h> // Temporizador unsigned long ultimoEnvio = 0; const unsigned long tiempoEnvio = 3000; // 3 segundos // Sensor BMP180 SFE_BMP180 bmp180; // Modo funcionamiento BMP180 const byte modoPresBMP180 = 3; // Altitud actual en metros const double altitudActual = 106; |
Comenzamos importando las librerías. La librería Arduino.h no es necesaria salvo que estés trabajando con PlatformIO.
Hay que crear dos variables para hacer el temporizador. Una almacena el tiempo desde el último envío, ultimoEnvio y la otra almacena el tiempo cada cuanto se obtuvo la última medida, tiempoEnvio.
Luego hay que crear un objeto de la clase SFE_BMP180. El constructor no admite ningún parámetro.
La siguiente variable constante, modoPresBMP180, indica el modo en el que quieres que funcione el sensor BMP180. Este sensor, como ya vimos, tiene diferentes modos de funcionamiento.
La correspondencia con los modos es la siguiente:
- 0 -> modo ultra low power
- 1 -> modo standard
- 2 -> modo high resolution
- 3 -> modo ultra high resolution
Ten en cuenta que contra mayor resolución más tiempo para calcular la presión y más consumo.
Por último, creo una variable para almacenar la altitud donde vas a situar el sensor. Esto nos servirá para, posteriormente, poder calcular la altitud en cualquier sitio.
Para obtener la altitud puedes ir a Google Earth y mirar la altura exacta donde vas a colocar el sensor.
Función setup()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void setup() { Serial.begin(9600); // Esperar hasta que se inicie el monitor serie while (!Serial) ; // Iniciar sensor de temperatura if (bmp180.begin()) { Serial.println(F("BMP180 iniciado correctamente")); } else { Serial.println(F("Error al inicial BMP180")); // No dejar continuar while (1) ; } } |
Comenzamos la función setup() iniciando el monitor serie como siempre. El bucle while(1) nos permite parar la ejecución hasta que no se abra el monitor serie en el IDE.
Para iniciar el sensor hay que llamar a la función bmp180.begin(). Esta función devuelve 1 si todo ha ido correcto y 0 si no ha sido así. En caso de error no permitimos continuar.
Función loop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
void loop() { // Overflow millis if (ultimoEnvio > millis()) { ultimoEnvio = millis(); } // Temporizador if (millis() - ultimoEnvio >= tiempoEnvio) { // Marca de tiempo ultimoEnvio = millis(); // Variables para obtener datos del sensor BMP180 byte status; double temp, pres, altitud; //Inicio de lectura de temperatura status = bmp180.startTemperature(); // Comprobar resultado de la lectura temperatura // Devuelve 0 si hay error // milisegundos que hay que esperar en caso contrario if (status != 0) { // Pausa hasta que finalice la lectura delay(status); // Obtener temperatura // La temperatura se almacena en temp en grados Celsius status = bmp180.getTemperature(temp); // Comprobar resultado de la temperatura // Devuelve 0 si hay error // Devuelve 1 si todo ha ido bien if (status != 0) { Serial.print(F("Temperatura: ")); Serial.print(temp, 2); Serial.println(F(" ºC")); // Inicio lectura de presión status = bmp180.startPressure(modoPresBMP180); // Comprobar resultado de la lectura presión // Devuelve 0 si hay error // milisegundos que hay que esperar en caso contrario if (status != 0) { // Pausa hata que finalice la lectura delay(status); // Obtener presión atomosférica // La prsión se almacena en la variable pres en milibar (mbar) // Esta función requiere la medida de temperatura status = bmp180.getPressure(pres, temp); // Comprobar resultado de la presión // Devuelve 0 si hay error // Devuelve 1 si todo ha ido bien if (status != 0) { Serial.print(F("Presión: ")); Serial.print(pres, 2); Serial.println(F(" mbar")); // Obtener altitud // Paso 1, establecer la presión a la altitud actual para que nos devuelva la presión compensada a nivel del mar double presNivelMar = bmp180.sealevel(pres, altitudActual); Serial.print(F("Presión a nivel del mar: ")); Serial.print(pres, 2); Serial.println(F(" mbar")); // Paso 2, obtener la altitud con las dos presiones altitud = bmp180.altitude(pres, presNivelMar); Serial.print(F("Altitud: ")); Serial.print(altitud, 2); Serial.println(F(" metros")); } } } } } } |
En la función loop() es donde está toda la lógica.
Lo primero es implementar el temporizador como siempre. Se controla con la función millis() si ha pasado el tiempo suficiente. En caso afirmativo entra dentro de la condicional if, reinicia el temporizador y obtiene los datos del sensor BMP180.
Para obtener la temperatura, presión y altitud vamos a necesitar cuatro variables.
La variable del tipo byte que se llama status irá recogiendo los diferentes resultados de las llamadas a la función de la clase SFE_BMP180. Luego veremos cómo.
Las otras tres variables del tipo double son temp, pres y altitud. Estas tres variables almacenarán la temperatura, la presión y la altitud respectivamente.
Comenzamos obteniendo la temperatura.
Antes de leer la temperatura hay que decirle al lector que empiece a obtener su valor. Eso se hace llamando a la función bmp180.startTemperature().
Esta función no recibe ningún parámetro y devuelve un valor del tipo byte (aunque si miras dentro del código verás que es del tipo char que es exactamente igual que el tipo byte).
Almacenamos el resultado en la variable status. Si su valor es 0 es que ha habido algún error, en caso contrario nos dirá el tiempo que tardará en obtener la temperatura.
Lo evaluamos con una sentencia condicional if y si es diferente de cero, hacemos un delay por el tiempo indicado.
Ya sé que he dicho muchas veces que los delay() son caca para los microcontroladores, pero en ciertos casos, como este, donde el retardo va a ser de unos pocos milisegundos, no genera ningún problema.
Como todo ha ido bien podemos obtener la temperatura llamando a la función bmp180.getTemperature(temp). Esta función devuelve dos valores.
Por un lado, devuelve un dato del tipo byte que se almacena en la variable status. Si es 1 es que todo ha ido bien y si es 0 es que algo ha fallado (no continuar).
Por otro lado, devuelve la temperatura y eso lo hacemos pasando por referencia la variable temp. Si miras dentro del código de la librería, verás que se recibe el parámetro como double &T.
Esto quiere decir que en realidad estamos pasando la posición de memoria y no el valor de la variable.
Si todo ha ido correctamente mostramos los datos de temperatura por el monitor serie.
Continuamos con la presión con el mismo método.
Primero indicamos al sensor que se prepare para obtener la presión llamando a la función bmp180.startPressure(modoPresBMP180). Esta función admite un único parámetro que es el modo de funcionamiento del sensor de los cuatro posibles.
Es un número del 0 al 3.
Devuelve un valor que indica si ha habido un error, 0, o en caso contrario los milisegundos que va a tardar el calcular la presión.
Si todo ha ido bien hacemos un retardo con la función delay() los milisegundos obtenidos. Luego obtenemos la presión con la función bmp180.getPressure(pres, temp).
Esta función admite dos parámetros. Por un lado, pasamos por referencia la variable press (la dirección de memoria) y, por otro lado, la temperatura.
El algoritmo que se implementa dentro de la librería requiere de la temperatura para obtener la presión.
La función devuelve 0 en caso de error y 1 si todo ha ido bien.
Para finalizar, si se ha obtenido la presión se muestra por el monitor serie y se calcula la altitud.
En primer paso es establecer la presión al nivel del mar. Para ello es necesario saber a qué altitud está el sensor y la presión actual.
Lo hacemos llamando a la función bmp180.sealevel(pres, altitudActual).
Esta función admite dos parámetros necesarios para calcular la presión al nivel del mar, la presión actual que hemos calculado en el punto anterior, pres, y la altitud actual, altitudActual, que es una constante que hemos definido al principio del código.
Recuerda que la altitud la puedes obtener a través de Google Earth.
La función devuelve la presión a nivel del mar.
Otra opción es obtener por otros medios la presión a nivel del mar mirando datos meteorológicos. En ese caso no sería necesario llamar a la función bmp180.sealevel(…).
Por último calculamos la altitud llamando a la función bmp180.altitude(pres, presNivelMar) que admite dos parámetros, la presión actual, pres, y la presión a nivel del mar que hemos obtenido anteriormente, presNivelMar.
Esta función devuelve la altitud donde está situado el sensor en base a la presión atmosférica.
Ahora sí, ya podemos mostrar los datos por el monitor serie.
Solo nos queda una cosa y es cargar el código a la placa.
Obtendrás un resultado parecido a este.
Para el IDE de Arduino.
Con PlatformIO.
Y con esto damos por terminado el artículo sobre el sensor BMP180 para obtener temperatura, presión atmosférica y altitud.
Nos leemos muy pronto.
Gracias a Depositphotos por la cesión de las imágenes.