Saltar al contenido
Nivel intermedio

Agregar la presión atmosférica con un sensor BMP180

Conectar el sensor de presión BMP180

En el nivel inicial armamos una estación que mide temperatura, humedad y presencia de lluvia. Ahora le sumamos un sensor BMP180, que mide la presión atmosférica: la fuerza que ejerce el aire sobre la superficie de la Tierra. La presión se expresa en hectopascales (hPa) (un valor típico ronda los 1013 hPa a nivel del mar).

El BMP180 no se lee por un pin cualquiera: se comunica por el bus I2C, un bus serial que usa solo dos líneas de señal, SDA (datos) y SCL (reloj), más su alimentación.

Esquema de conexión del sistema completo: a la izquierda el LCD Keypad Shield; en la protoboard, el módulo DHT11, el módulo del sensor de lluvia con su placa colectora YL-83 y, a la derecha, el pequeño módulo BMP180. Cables de señal amarillos y grises llevan las líneas SDA y SCL hacia la placa.
El sistema completo del nivel intermedio en la variante Arduino UNO (figura original): al DHT11 y al sensor de lluvia se suma el BMP180 (derecha), conectado por las líneas I2C. En el ESP32, el BMP180 y el LCD I2C comparten el mismo bus.

En el Arduino UNO, el bus I2C está en los pines A4 (SDA) y A5 (SCL). Conectamos ahí las líneas del BMP180, más su alimentación a 5V y GND, como indica el esquema.

En el ESP32, el bus I2C está en GPIO 21 (SDA) y GPIO 22 (SCL): exactamente los mismos pines donde ya conectamos el LCD I2C en el nivel inicial. Y acá viene el punto lindo: el I2C es un bus compartido. El LCD y el BMP180 se cuelgan de los mismos dos cables, y cada uno responde a su propia dirección: el LCD en 0x27 y el BMP180 en 0x77. No hay conflicto, porque cuando la placa «llama» a una dirección, solo contesta ese dispositivo. Conectamos, entonces, SDA y SCL del BMP180 en paralelo con los del LCD, y su alimentación a 3,3 V y GND.

Instalar la librería del BMP180

Como el BMP180 se comunica por I2C, necesitamos una librería que resuelva ese protocolo. Es la misma que usaba el original: la “Adafruit BMP085 Library” (el BMP085 y el BMP180 son compatibles, por eso sirve la misma librería). La instalamos desde el Gestor de bibliotecas del Arduino IDE 2.x: buscamos “Adafruit BMP085” y apretamos Instalar.

En el código, el sensor se declara con Adafruit_BMP085 bmp;, se inicia con bmp.begin() en el setup(), y la presión se lee con bmp.readPressure(). Esa función devuelve la presión en pascales (Pa); como es más habitual expresarla en hectopascales (hPa), el código la divide por 100 antes de mostrarla.

Programar y mostrar la presión en el display

Ahora completamos el programa: al código del nivel inicial le agregamos la lectura del BMP180 y mostramos la presión en el display, identificada con la letra P. El original la ubica junto al estado de la lluvia, en la segunda fila; por ejemplo, P: 1013.

El programa sigue midiendo cada INTERVALO_MEDICION_MS (2 segundos, por el límite del DHT11): en cada ciclo lee la temperatura y la humedad del DHT11, el estado del sensor de lluvia y la presión del BMP180, y vuelca los cuatro datos al LCD.

Ver el código completo · estacion-con-presion.ino
estacion-con-presion.ino Arduino UNO
// Estación meteorológica con presión: además de temperatura y humedad (DHT11)
// y presencia de lluvia (sensor digital), suma un sensor BMP180 que mide la
// presión atmosférica. Todo se muestra en el LCD 16x2. Fila 0: temperatura y
// humedad. Fila 1: estado de lluvia y presión (rótulo "P:").
//
// ¿Por qué importa la presión? El original lo explica: las bajas presiones
// suelen asociarse a tiempo inestable (y a veces lluvia) y las altas, a tiempo
// estable. Sumarla enriquece el pronóstico de la estación.
//
// CONVENCIÓN DEL SENSOR DE LLUVIA (activo-bajo): la salida digital D0 vale
// BAJO cuando DETECTA agua y ALTO cuando está SECO (ver detalle en el sketch
// del nivel inicial). Por eso comparamos contra LOW.
//
// Plataforma: Arduino UNO.
// Conexión (la del esquema original): dato del DHT11 → pin 2; lluvia D0 → pin
// 3; display LCD Keypad Shield paralelo por 8, 9, 4, 5, 6, 7; BMP180 por el bus
// I2C del UNO: SDA → A4, SCL → A5.
//
// Nota del original: en el LCD no usar tildes ni la letra Ñ.
//
// Librerías requeridas (Library Manager): "DHT sensor library" (Adafruit) +
// "Adafruit Unified Sensor", y "Adafruit BMP085 Library" (sirve para BMP085 y
// BMP180, que son compatibles; es la que nombra el original).
//
// Basado en: Fragmento de código del Nivel Intermedio (Paso 3) — Estación
// Meteorológica Automatizada, Saberes Digitales (INET/EDUCAR 2019)
// Modernización: constantes nombradas; DHT de Adafruit con dht.begin();
// pausa de 2 s (el DHT11 no admite más de una lectura por segundo; el original
// no pausaba el loop).

#include "DHT.h"
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <LiquidCrystal.h>

// Pin de datos del sensor y tipo de sensor (DHT11).
const int PIN_DHT = 2;
#define DHTTYPE DHT11

// Salida digital D0 del sensor de lluvia.
const int PIN_LLUVIA = 3;

// Nivel de la salida del sensor cuando HAY lluvia (activo-bajo).
const int LLUVIA_DETECTADA_NIVEL = LOW;

// El DHT11 no admite más de una lectura por segundo; medimos cada 2 s.
const unsigned long INTERVALO_MEDICION_MS = 2000;

// Objetos de sensores y display. El BMP180 habla por I2C (A4/A5 en el UNO).
DHT dht(PIN_DHT, DHTTYPE);
Adafruit_BMP085 bmp;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup() {
  pinMode(PIN_LLUVIA, INPUT);
  dht.begin();
  bmp.begin(); // inicializa el sensor de presión por I2C
  lcd.begin(16, 2);
  lcd.clear();
}

void loop() {
  float temperatura = dht.readTemperature();      // grados Celsius
  float humedad     = dht.readHumidity();         // humedad relativa en %
  // readPressure() devuelve pascales (Pa); dividimos por 100 para tener
  // hectopascales (hPa), la unidad habitual del "1013 hPa" del clima.
  float presion     = bmp.readPressure() / 100.0;

  // Fila 0: temperatura (col 0) y humedad (col 8). Sin tildes ni Ñ.
  lcd.setCursor(0, 0);
  lcd.print("T:");
  lcd.print(temperatura);
  lcd.setCursor(8, 0);
  lcd.print("H:");
  lcd.print(humedad);

  // Fila 1: estado de la lluvia (col 0) y presión (col 10).
  lcd.setCursor(0, 1);
  if (digitalRead(PIN_LLUVIA) == LLUVIA_DETECTADA_NIVEL) {
    lcd.print("Lluvia:SI");
  } else {
    lcd.print("Lluvia:NO");
  }
  lcd.setCursor(10, 1);
  lcd.print("P:");
  lcd.print(presion);

  delay(INTERVALO_MEDICION_MS);
}
estacion-con-presion.ino ESP32
// Estación meteorológica con presión: además de temperatura y humedad (DHT11)
// y presencia de lluvia (sensor digital), suma un sensor BMP180 que mide la
// presión atmosférica. Todo se muestra en el LCD 16x2. Fila 0: temperatura y
// humedad. Fila 1: estado de lluvia y presión (rótulo "P:").
//
// ¿Por qué importa la presión? El original lo explica: las bajas presiones
// suelen asociarse a tiempo inestable (y a veces lluvia) y las altas, a tiempo
// estable.
//
// BUS I2C COMPARTIDO (¡buen punto didáctico!): en el ESP32, TANTO el LCD como
// el BMP180 se conectan al MISMO bus I2C (SDA GPIO 21, SCL GPIO 22). El I2C es
// un bus compartido: varios dispositivos conviven en los mismos dos cables
// porque cada uno tiene una DIRECCIÓN distinta. El LCD responde en 0x27 y el
// BMP180 en 0x77, así que no hay conflicto. Ambos cuelgan en paralelo de
// SDA/SCL.
//
// CONVENCIÓN DEL SENSOR DE LLUVIA (activo-bajo): la salida D0 vale BAJO cuando
// DETECTA agua y ALTO cuando está SECO (ver detalle en el nivel inicial).
//
// Plataforma: ESP32 (DevKit v1).
// Conexión: DHT11 → GPIO 4; lluvia D0 → GPIO 14; LCD y BMP180 al bus I2C
// (SDA GPIO 21, SCL GPIO 22).
//
// ADAPTACIÓN DE PLATAFORMA (ver README): el original usa un LCD Keypad Shield
// paralelo que no entra en un ESP32; acá el LCD es 1602 I2C (LiquidCrystal_I2C,
// 0x27; probá 0x3F si no muestra nada).
// Nota eléctrica: el ESP32 trabaja a 3,3 V; DHT11, BMP180 y LCD I2C andan a 3,3 V.
//
// Nota del original: en el LCD no usar tildes ni la letra Ñ.
//
// Librerías requeridas (Library Manager): "DHT sensor library" (Adafruit) +
// "Adafruit Unified Sensor", "Adafruit BMP085 Library" (BMP085/BMP180) y
// "LiquidCrystal_I2C".
//
// Basado en: Fragmento de código del Nivel Intermedio (Paso 3) — Estación
// Meteorológica Automatizada, Saberes Digitales (INET/EDUCAR 2019)
// Modernización: constantes nombradas; portado a ESP32; DHT de Adafruit con
// dht.begin(); LCD adaptado a I2C (comparte bus con el BMP180); pausa de 2 s.

#include "DHT.h"
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <LiquidCrystal_I2C.h>

// Pin de datos del sensor y tipo de sensor (DHT11).
const int PIN_DHT = 4;
#define DHTTYPE DHT11

// Salida digital D0 del sensor de lluvia.
const int PIN_LLUVIA = 14;

// Nivel de la salida del sensor cuando HAY lluvia (activo-bajo).
const int LLUVIA_DETECTADA_NIVEL = LOW;

// Dirección I2C y tamaño del display (16 columnas x 2 filas).
const uint8_t LCD_DIRECCION_I2C = 0x27;
const uint8_t LCD_COLUMNAS      = 16;
const uint8_t LCD_FILAS         = 2;

// El DHT11 no admite más de una lectura por segundo; medimos cada 2 s.
const unsigned long INTERVALO_MEDICION_MS = 2000;

// Objetos de sensores y display. LCD (0x27) y BMP180 (0x77) comparten el bus.
DHT dht(PIN_DHT, DHTTYPE);
Adafruit_BMP085 bmp;
LiquidCrystal_I2C lcd(LCD_DIRECCION_I2C, LCD_COLUMNAS, LCD_FILAS);

void setup() {
  pinMode(PIN_LLUVIA, INPUT);
  dht.begin();
  bmp.begin(); // el BMP180 se inicializa por el mismo bus I2C que el LCD
  lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop() {
  float temperatura = dht.readTemperature();      // grados Celsius
  float humedad     = dht.readHumidity();         // humedad relativa en %
  float presion     = bmp.readPressure() / 100.0; // Pa → hPa

  // Fila 0: temperatura (col 0) y humedad (col 8). Sin tildes ni Ñ.
  lcd.setCursor(0, 0);
  lcd.print("T:");
  lcd.print(temperatura);
  lcd.setCursor(8, 0);
  lcd.print("H:");
  lcd.print(humedad);

  // Fila 1: estado de la lluvia (col 0) y presión (col 10).
  lcd.setCursor(0, 1);
  if (digitalRead(PIN_LLUVIA) == LLUVIA_DETECTADA_NIVEL) {
    lcd.print("Lluvia:SI");
  } else {
    lcd.print("Lluvia:NO");
  }
  lcd.setCursor(10, 1);
  lcd.print("P:");
  lcd.print(presion);

  delay(INTERVALO_MEDICION_MS);
}
Estación con presión: al DHT11 y al sensor de lluvia se suma el BMP180. El LCD muestra T: y H: en la primera fila, y Lluvia: y P: (en hPa) en la segunda. La única diferencia entre plataformas sigue siendo cómo se maneja el display.

Fijate, al comparar las dos plataformas con el selector, que el sensor de presión se lee igual en ambas: la librería resuelve el I2C por debajo. Lo único que cambia entre UNO y ESP32 es, otra vez, la parte del display.

Podés ver el sistema completo —los cuatro datos actualizándose en pantalla— en el simulador:

Simulación del comportamiento

La misma máquina de estados del firmware, portada a TypeScript, maneja el comportamiento del dispositivo. No se ejecuta el binario real: la ejecución del .hex con avr8js está en el roadmap.

Simulación lista. Presioná «Iniciar» para arrancar la secuencia.

Cierre del nivel

Al terminar este nivel, tu estación mide cuatro variables del clima —temperatura, humedad, lluvia y presión atmosférica— y las muestra todas en el display. Además, apareció una idea importante: el bus I2C, donde el BMP180 (y, en el ESP32, también el LCD) conviven en dos cables compartidos gracias a sus direcciones. En el nivel avanzado vamos a poder mirar todos estos datos a distancia: publicaremos la temperatura, la humedad, la presión y el estado de la lluvia por Internet de las Cosas para monitorear la estación desde el celular.

Evidencia de cierre

Al terminar este nivel, esto tiene que estar funcionando:

  • El sensor de presión BMP180 está conectado por el bus I2C: en el UNO por A4 (SDA) y A5 (SCL); en el ESP32 por GPIO 21 (SDA) y GPIO 22 (SCL), compartiendo el bus con el LCD I2C.
  • Instalaste la librería Adafruit BMP085 (compatible con el BMP180) desde el gestor de bibliotecas del Arduino IDE 2.x.
  • El display muestra ahora también la presión atmosférica en hectopascales (hPa), junto a la temperatura, la humedad y el estado de la lluvia.