Estación Meteorológica Avanzada v2.0: Monitorización en Tiempo Real de Temperatura, Presión, Humedad y Altitud
Construye una estación meteorológica compacta que mide con precisión temperatura, presión, humedad y altitud directamente en tu espacio vital.
Historia
Usando el Adafruit Starter Pack para Windows 10 IoT Core en una Raspberry Pi 2, este proyecto demuestra cómo interconectar un sensor BME280 (o BMP280) para leer datos ambientales y publicarlos en un servicio cloud.
Si tienes un BMP280, sigue la guía Weather Station v1: Weather Station v1.
Hardware
Conecta la Raspberry Pi 2 a una protoboard y cablea el sensor BME280 según el diagrama Fritzing en la sección "Esquemáticos" abajo.
Software
Descarga el código base desde GitHub – ms‑iot/adafruitsample. Te guiaremos añadiendo el código necesario para comunicar con el sensor y publicar lecturas.
Abre Lesson_203v2\StartSolution\lesson_203v2.sln y edita mainpage.xaml.cs.
Una versión completada está en Lesson_203v2\FullSolution\lesson_203v2.sln.
MainPage.xaml.cs
Añade referencia a la clase BME280:
public sealed partial class MainPage : Page {
// Crear nuevo objeto para nuestra clase sensor
BME280 BME280;
Inicializa el sensor en OnNavigatedTo:
// Crear nuevo objeto para nuestra clase sensor BME280 = new BME280Sensor(); // Inicializar el sensor await BME280.Initialize();
Luego, añade código para recopilar y loguear datos:
- Crea variables para temperatura, presión, humedad y altitud, inicializadas a 0.
- Establece constante de presión a nivel del mar (default 1013.25 hPa).
- Lee las cuatro mediciones diez veces y sácalas por consola de depuración.
// Inicialízalas a 0.
float temp = 0;
float pressure = 0;
float altitude = 0;
float humidity = 0;
// Constante para presión a nivel del mar.
const float seaLevelPressure = 1022.00f;
// Leer 10 muestras de datos
for (int i = 0; i < 10; i++){
temp = await BME280.ReadTemperature();
pressure = await BME280.ReadPreasure();
altitude = await BME280.ReadAltitude(seaLevelPressure);
humidity = await BME280.ReadHumidity();
// Escribir valores en consola de depuración
Debug.WriteLine("Temperatura: " + temp.ToString() + " °C");
Debug.WriteLine("Humedad: " + humidity.ToString() + " %");
Debug.WriteLine("Presión: " + pressure.ToString() + " Pa");
Debug.WriteLine("Altitud: " + altitude.ToString() + " m");
Debug.WriteLine("\n");
}
BME280.cs
Abre BME280.cs y añade lo siguiente tras el enum de direcciones de registro:
// String para nombre amigable del bus I2C const string I2CControllerName = "I2C1"; // Crear dispositivo I2C private I2cDevice bme280 = null; // Crear nuevos datos de calibración para el sensor BME280_CalibrationData CalibrationData; // Variable para comprobar si dispositivo está inicializado bool init = false;
Mejora el método Initialize para configurar la conexión I2C:
public async Task Initialize() {
Debug.WriteLine("BME280::Initialize");
try {
I2cConnectionSettings settings = new I2cConnectionSettings(BME280_Address);
settings.BusSpeed = I2cBusSpeed.FastMode;
string aqs = I2cDevice.GetDeviceSelector(I2CControllerName);
DeviceInformationCollection dis = await DeviceInformation.FindAllAsync(aqs);
bme280 = await I2cDevice.FromIdAsync(dis[0].Id, settings);
if (bme280 == null) {
Debug.WriteLine("Dispositivo no encontrado");
}
} catch (Exception e) {
Debug.WriteLine("Excepción: " + e.Message + "\n" + e.StackTrace);
throw;
}
}
Añade la rutina Begin para verificar la firma del sensor y cargar datos de calibración:
private async Task Begin() {
Debug.WriteLine("BME280::Begin");
byte[] WriteBuffer = new byte[] { (byte)eRegisters.BMP280_REGISTER_CHIPID };
byte[] ReadBuffer = new byte[] { 0xFF };
bmp280.WriteRead(WriteBuffer, ReadBuffer);
Debug.WriteLine("Firma BME280: " + ReadBuffer[0].ToString());
if (ReadBuffer[0] != BMP280_Signature) {
Debug.WriteLine("BMP280::Begin Firma Incorrecta.");
return;
}
init = true;
CalibrationData = await ReadCoefficeints();
await WriteControlRegister();
await WriteControlRegisterHumidity();
}
Helpers de registro de control:
private async Task WriteControlRegisterHumidity() {
byte[] WriteBuffer = new byte[] { (byte)eRegisters.BMP280_REGISTER_CONTROLHUMID, 0x03 };
bmp280.Write(WriteBuffer);
await Task.Delay(1);
}
private async Task WriteControlRegister() {
byte[] WriteBuffer = new byte[] { (byte)eRegisters.BMP280_REGISTER_CONTROL, 0x3F };
bmp280.Write(WriteBuffer);
await Task.Delay(1);
}
Funciones utilitarias para leer datos de registro:
private UInt16 ReadUInt16_LittleEndian(byte register) {
UInt16 value = 0;
byte[] writeBuffer = new byte[] { 0x00 };
byte[] readBuffer = new byte[] { 0x00, 0x00 };
writeBuffer[0] = register;
bmp280.WriteRead(writeBuffer, readBuffer);
int h = readBuffer[1] << 8;
int l = readBuffer[0];
value = (UInt16)(h + l);
return value;
}
private byte ReadByte(byte register) {
byte value = 0;
byte[] writeBuffer = new byte[] { 0x00 };
byte[] readBuffer = new byte[] { 0x00 };
writeBuffer[0] = register;
bmp280.WriteRead(writeBuffer, readBuffer);
value = readBuffer[0];
return value;
}
Las funciones de calibración y compensación derivan directamente del datasheet BMP280 y ya vienen proporcionadas.
Implementa ReadTemperature para devolver la temperatura del sensor en °C:
public async TaskReadTemperature() { if (!init) await Begin(); byte tmsb = ReadByte((byte)eRegisters.BMP280_REGISTER_TEMPDATA_MSB); byte tlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_TEMPDATA_LSB); byte txlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_TEMPDATA_XLSB); Int32 t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4); double temp = BMP280_compensate_T_double(t); return (float)temp; }
Completa ReadPreasure (nota el typo original; lo mantenemos por compatibilidad):
public async TaskReadPreasure() { if (!init) await Begin(); if (t_fine == Int32.MinValue) await ReadTemperature(); byte tmsb = ReadByte((byte)eRegisters.BMP280_REGISTER_PRESSUREDATA_MSB); byte tlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_PRESSUREDATA_LSB); byte txlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_PRESSUREDATA_XLSB); Int32 t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4); Int64 pres = BMP280_compensate_P_Int64(t); return ((float)pres) / 256; }
Finalmente, implementa ReadAltitude para calcular altitud usando la fórmula barométrica:
public async TaskReadAltitude(float seaLevel) { if (!init) await Begin(); float pressure = await ReadPreasure(); pressure /= 100; return 44330.0f * (1.0f - (float)Math.Pow((pressure / seaLevel), 0.1903f)); }
¡Tu proyecto ya está listo para desplegar!
Salida Esperada
Temperatura: 24.46189 °C
Humedad: 54.372 %
Presión: 99738.73 Pa
Altitud: 205.1726 m
Fuente: Weather Station V 2.0
Proceso de manufactura
- Estación meteorológica solar DIY con Raspberry Pi
- Construcción de una estación meteorológica exterior con Raspberry Pi 2 y ADS‑WS1
- Construya una estación meteorológica con Raspberry Pi que envíe datos diarios por email
- Monitorización meteorológica remota con Raspberry Pi 3 y PubNub
- Integre su estación meteorológica con CWOP: Guía práctica
- Monitor Meteorológico – Estación Meteorológica DIY con Raspberry Pi y Subida a Dropbox
- Estación meteorológica compacta: Arduino Nano y ESP8266 con sensor BMP280 y pantalla OLED/Nokia LCD
- Estación Meteorológica Portátil Arduino por $10 – Nano, DHT22, BMP180 y LCD
- eDOT: Reloj Preciso y Estación Meteorológica Arduino con Control IR Integrado
- Monitorización Meteorológica en Tiempo Real con Arduino y ThingSpeak IoT
- Estación meteorológica Arduino Nano: Sensores BMP280, DHT11, UV y RTC en OLED 0,96"