Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

En este tutorial aprenderemos a hacer una estación meteorológica inalámbrica basada en Arduino. Puede ver el siguiente video o leer el tutorial escrito a continuación.

Resumen

La temperatura y humedad exterior se miden con el sensor DHT22 y estos datos se envían inalámbricamente a la unidad interior usando módulos transceptores NRF24L01. En la unidad interior hay otro DHT22 para medir temperatura y humedad interior, así como un módulo RTC DS3231 que mantiene la hora incluso si el Arduino pierde alimentación. Todos estos datos se muestran en una pantalla OLED de 0,96".

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Diagrama de Circuito de la Estación Meteorológica Inalámbrica Arduino

Veamos el diagrama de circuito y cómo funciona este proyecto. Nota: ya tengo tutoriales detallados de cada módulo: Tutorial NRF24L01, Tutorial DHT22, Tutorial DS3231.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Componentes necesarios:

Tanto el módulo RTC como la pantalla OLED usan protocolo I2C (pines analógicos 4 y 5 en Arduino Nano). Junto al NRF24L01 hay un condensador para estabilizar su alimentación. También hay una resistencia pull-up en el pin de datos del DHT22 para su correcto funcionamiento.

Para alimentación usé adaptador 12V CC en la unidad interior, y en la exterior dos baterías Li-ion de ~7,5V. Con esta configuración la unidad exterior funciona ~10 días antes de descargarse, porque transmitimos datos periódicamente y ponemos el Arduino en modo sleep (consumo ~7 mA).

PCB de Diseño Personalizado

Para mantener los componentes organizados, diseñé un PCB personalizado según el esquema usando EasyEDA (software gratuito de diseño de circuitos online). El mismo PCB sirve para ambas unidades; solo cambia la programación del Arduino.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Terminado el diseño, exportamos el archivo Gerber para fabricación. Puede ver los archivos del proyecto EasyEDA aquí.

Pedimos el PCB a JLCPCB (patrocinador del video).

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Subimos el Gerber, revisamos en el visor, seleccionamos propiedades y pedimos a precio razonable. Nota: si es su primer pedido en JLCPCB, puede conseguir hasta 10 PCBs por solo $2.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Tras unos días llegaron los PCBs. La calidad es excelente y todo coincide con el diseño.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Empecé soldando pines header en el PCB para conectar/desconectar componentes fácilmente.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Luego soldé el condensador y la resistencia pull-up. Los dos divisores de tensión para el contraste del LCD: 1k en R1 y 220 ohm en R2. El tercero es pull-up para el botón.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Ahora solo queda montar los componentes en los headers del PCB.

Construcción de las Carcasas

Para las carcasas usé tablero MDF de 8 mm y sierra circular para cortar todas las piezas a medida.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Para mediciones precisas de temperatura/humedad, los laterales deben permitir entrada de aire. Con taladro y lima hice varias ranuras en paneles laterales de ambas unidades.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

También hice hueco para la pantalla OLED en el panel frontal, y corté una pieza de aluminio a medida para decoración frontal.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Para ensamblar usé cola de madera, sargentos y tornillos.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

Pinté con spray: blanco para exterior, negro para interior. Tras secar, inserté los PCBs.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

En la parte trasera de la unidad interior puse conector de alimentación e interruptor; en la exterior usé un jumper como interruptor.

Construya una Estación Meteorológica Inalámbrica Fiable Basada en Arduino

¡La estación meteorológica inalámbrica Arduino ya funciona! Queda ver cómo funciona el programa.

Código de la Estación Meteorológica Inalámbrica Arduino

Código Unidad Exterior (Transmisor)

/* Arduino Wireless Communication Tutorial
   Outdoor unit - Transmitter
   by Dejan Nedelkovski, www.HowToMechatronics.com
   Libraries: NRF24L01 - TMRh20/RF24, https://github.com/tmrh20/RF24/
              DHT22 - DHTlib, https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib
              LowPower - https://github.com/rocketscream/Low-Power */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <LowPower.h>

#define dataPin 8 // Pin datos DHT22
dht DHT;
RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";
char thChar[32] = "";
String thString = "";

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
  int readData = DHT.read22(dataPin);
  int t = DHT.temperature;
  int h = DHT.humidity;
  thString = String(t) + String(h);
  thString.toCharArray(thChar, 12);
  // Enviar 3 veces para asegurar recepción
  for (int i = 0; i <= 3; i++) {
    radio.write(&thChar, sizeof(thChar));
    delay(50);
  }
  // Sleep 2 min: 15 x 8s = 120s
  for (int sleepCounter = 15; sleepCounter > 0; sleepCounter--) {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}

Descripción: La unidad exterior es el transmisor. Incluimos librerías RF24, DHT y LowPower (para modo sleep). En setup() inicializamos comunicación inalámbrica. En loop() leemos temperatura y humedad del DHT22, convertimos a String, a array char, y enviamos 3 veces con radio.write() para asegurar recepción. Finalmente, ponemos Arduino en sleep 2 minutos para minimizar consumo.

Código Unidad Interior (Receptor)

/* Arduino Wireless Communication Tutorial
   Indoor unit - Receiver
   by Dejan Nedelkovski, www.HowToMechatronics.com
   Libraries: DS3231 - https://www.rinkydinkelectronics.com/library.php?id=73
              U8G2 - https://github.com/olikraus/u8g2 */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <DS3231.h>
#include <U8g2lib.h>
#include <Wire.h>

#define dataPin 8
dht DHT;
DS3231 rtc(SDA, SCL);
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
RF24 radio(10, 9);
const byte address[6] = "00001";
char text[6] = "";
int readDHT22, t, h;
String inTemp, inHum, outTemp, outHum;
String rtcTime, rtcDate;
int draw_state = 0;
unsigned long previousMillis = 0;
long interval = 3000;

// Bitmap icono temperatura (almacenado en Flash con PROGMEM)
#define Temperature_20Icon_width 27
#define Temperature_20Icon_height 47
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00,
  0xc0, 0xe1, 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x79, 0x00,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x8c, 0x79, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00,
  0x70, 0x9e, 0x03, 0x00, 0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00,
  0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0xff, 0x18, 0x00,
  0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00,
  0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00,
  0x0c, 0x7f, 0x1c, 0x00, 0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00,
  0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x00, 0x00,
  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// Bitmap icono humedad
#define Humidity_20Icon_width 27
#define Humidity_20Icon_height 47
static const unsigned char Humidity_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
  0x00, 0x70, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00,
  0x00, 0xdc, 0x01, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x86, 0x03, 0x00,
  0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x07, 0x00, 0x80, 0x03, 0x06, 0x00,
  0x80, 0x01, 0x0c, 0x00, 0xc0, 0x01, 0x1c, 0x00, 0xc0, 0x00, 0x18, 0x00,
  0xe0, 0x00, 0x38, 0x00, 0x60, 0x00, 0x30, 0x00, 0x70, 0x00, 0x70, 0x00,
  0x30, 0x00, 0xe0, 0x00, 0x38, 0x00, 0xc0, 0x00, 0x18, 0x00, 0xc0, 0x01,
  0x1c, 0x00, 0x80, 0x01, 0x0c, 0x00, 0x80, 0x03, 0x0e, 0x00, 0x80, 0x03,
  0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x07,
  0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06,
  0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06,
  0xe3, 0x00, 0x00, 0x06, 0xc7, 0x00, 0x00, 0x06, 0xc6, 0x01, 0x00, 0x07,
  0x86, 0x03, 0x00, 0x03, 0x0e, 0x1f, 0x00, 0x03, 0x0e, 0x1e, 0x80, 0x01,
  0x1c, 0x00, 0xc0, 0x01, 0x38, 0x00, 0xe0, 0x00, 0x78, 0x00, 0x70, 0x00,
  0xf0, 0x00, 0x38, 0x00, 0xe0, 0x07, 0x1f, 0x00, 0x80, 0xff, 0x0f, 0x00,
  0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  u8g2.begin();
  rtc.begin();
}

void loop() {
  if (radio.available()) {
    radio.read(&text, sizeof(text));
    outTemp = String(text[0]) + String(text[1]) + char(176) + "C";
    outHum = String(text[2]) + String(text[3]) + "%";
  }
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    u8g2.firstPage();
    do {
      switch (draw_state) {
        case 0: drawDate(); break;
        case 1: drawInTemperature(); break;
        case 2: drawInHumidity(); break;
        case 3: drawOutTemperature(); break;
        case 4: drawOutHumidity(); break;
      }
    } while ( u8g2.nextPage() );
    draw_state++;
    if (draw_state > 4) draw_state = 0;
  }
}

void drawDate() {
  String dowa = rtc.getDOWStr(); dowa.remove(3);
  rtcDate = dowa + " " + rtc.getDateStr();
  u8g2.setFont(u8g2_font_timB14_tr);
  u8g2.setCursor(0, 15);
  rtcTime = rtc.getTimeStr(); rtcTime.remove(5);
  u8g2.print(rtcDate);
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(8, 58);
  u8g2.print(rtcTime);
}

void drawInTemperature() {
  readDHT22 = DHT.read22(dataPin);
  t = DHT.temperature;
  inTemp = String(t) + char(176) + "C";
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(24, 15); u8g2.print("INDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58); u8g2.print(inTemp);
  u8g2.drawXBMP(0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}

void drawInHumidity() {
  h = DHT.humidity;
  inHum = String(h) + "%";
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(24, 15); u8g2.print("INDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58); u8g2.print(inHum);
  u8g2.drawXBMP(0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}

void drawOutTemperature() {
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(12, 15); u8g2.print("OUTDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58); u8g2.print(outTemp);
  u8g2.drawXBMP(0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}

void drawOutHumidity() {
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(12, 15); u8g2.print("OUTDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58); u8g2.print(outHum);
  u8g2.drawXBMP(0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}

Descripción: En el receptor (unidad interior) incluimos librerías para DS3231 (RTC) y U8G2 (OLED). Definimos instancias, pines, variables y los bitmaps de iconos temperatura/humedad.

Los bitmaps se pueden crear con GIMP (editor open source), dibujar y exportar como .xbm, luego abrir con notepad y copiar el array al código. Usando PROGMEM se guardan en memoria Flash en lugar de SRAM.

En setup() inicializamos radio, OLED y RTC. En loop() comprobamos datos entrantes por NRF24L01; si hay, leemos con radio.read() y guardamos los 2 primeros caracteres en temperatura exterior y los 2 siguientes en humedad exterior.

Usamos millis() (no delay()) para cambiar pantallas cada 3 segundos (variable interval), permitiendo que el resto del código se ejecute y no perdamos datos entrantes. Con firstPage() y nextPage() de U8G2 mostramos 5 pantallas definidas en funciones personalizadas.

drawDate() obtiene fecha/hora del RTC. drawInTemperature() lee temperatura interior y la muestra. Mismo método para las demás pantallas.

¡Eso es todo! Espero que hayan disfrutado este proyecto Arduino y aprendido algo nuevo. Pregunten en los comentarios.

Proceso de manufactura

  1. Estación meteorológica solar DIY con Raspberry Pi
  2. Construcción de una estación meteorológica exterior con Raspberry Pi 2 y ADS‑WS1
  3. Construya una estación meteorológica con Raspberry Pi que envíe datos diarios por email
  4. Estación Meteorológica Avanzada v2.0: Monitorización en Tiempo Real de Temperatura, Presión, Humedad y Altitud
  5. Detector de frecuencia de audio con Arduino – Mide los picos de sonido más intensos
  6. Controlador Inalámbrico Inteligente de Interruptores: Manipulador Remoto Basado en Arduino
  7. Tres en raya con Arduino, matriz LED MAX7219 y carcasa de cartón
  8. Construye un Temporizador Regresivo Fiable con Arduino y Pantalla de 7 Segmentos SparkFun
  9. Estación Meteorológica Portátil Arduino por $10 – Nano, DHT22, BMP180 y LCD
  10. eDOT: Reloj Preciso y Estación Meteorológica Arduino con Control IR Integrado
  11. Monitorización Meteorológica en Tiempo Real con Arduino y ThingSpeak IoT