Proyecto fin de curso. Estaci贸n Meteorol贸gica Arduino

La fuerza de Arduino como dise帽ador radica en el hecho de que absolutamente para cualquier pieza de hardware puede encontrar en Google una descripci贸n, una biblioteca, un diagrama de cableado y un ejemplo de trabajo: un kit completamente listo para integrar en su proyecto. Como colof贸n a este curso de b谩sico de Arduino realizaremos un proyecto medianamente serio, una estaci贸n meteorol贸gica funcional.

! Volvamos a nuestro reloj meteorol贸gico e intentemos 芦ensamblar禄 tal proyecto a partir de bocetos de ejemplo, 隆porque para eso se necesitan ejemplos! Nosotros necesitamos:

  • Arduino NANO.
  • Display. Como LCD1602 con adaptador i2c.
  • M贸dulo reloj en tiempo real, tomemos DS3231.
  • Term贸metro ds18b20.

Paso 1, recopilar informaci贸n.

La mayor parte del proyecto esta ya resuelto a 芦grosso modo, resuelto por m铆禄 pero cada lector deber谩 esforzarse en dar a su proyecto su toque personal.

Comenzamos a buscar en Google informaci贸n sobre la conexi贸n y el ejemplo de cada m贸dulo o pieza de hardware:

De las b煤squedas de ejemplos de Google, aprendemos informaci贸n tan importante como los diagramas de conexi贸n: la pantalla y el reloj est谩n conectados al bus i2c, y el sensor ds18b20 se puede conectar a cualquier otro pin.聽Nuestro diagrama de proyecto arduino queda as铆:

Diagrama del proyecto arduino
Diagrama del proyecto arduino.

Descargue las bibliotecas para nuestros m贸dulos e聽inst谩lelas.聽La biblioteca de visualizaci贸n se nos proporciona directamente en el art铆culo:聽https://iarduino.ru/file/134.html, la biblioteca para el reloj, por mi propia experiencia, recomiendo聽RTClib聽(la que est谩 en el art铆culo del ejemplo no es muy buena).聽En el art铆culo sobre el sensor de temperatura, nos dijeron sobre la biblioteca聽DallasTemperature.h, no dieron un enlace.聽Bueno, busquemos 鈥淒allasTemperature.h鈥 nosotros mismos, lo encontraremos聽en este enlace.聽Tambi茅n necesita la biblioteca OneWire, se proporcion贸 un聽enlace聽en el art铆culo sobre el term贸metro.聽En total, debemos tener instaladas 4 bibliotecas.

Ahora nuestro objetivo es encontrar ejemplos que funcionen para cada pieza de hardware, para asegurarnos de que funcionen y asignarnos el conjunto m铆nimo de c贸digo para controlar el m贸dulo, puede ser dif铆cil: suele haber errores en los art铆culos y a veces copiar y pegar simplemente no funciona. C贸digo: estos art铆culos a menudo se copian y pegan de personas alejadas de los temas, que no los dominan a fondo. Tom茅 un ejemplo de trabajo con una pantalla del art铆culo, pero tuve que mirar para el reloj y el term贸metro en los ejemplos de la biblioteca. Hagamos un poco de combinaci贸n de ejemplos, dejemos solo las funciones para obtener los valores o resultados que necesitamos, voy dejando todo lo que necesito en:


Paso 2, seleccionar y probar.

void setup():

C贸digo inicial para la pantalla de visualizaci贸n LCD1602.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // Configurar la pantalla
// la direcci贸n puede ser 0x27 o 0x3f
void setup() {
  lcd.init();
  lcd.backlight();  // Enciende la luz de fondo de la pantalla
   // Coloca el cursor en la segunda l铆nea y el car谩cter nulo.
  lcd.setCursor(0, 1);
  lcd.print("Hello!");  // hola
}
void loop() {
}

C贸digo inicial para el reloj en tiempo real DS3231.

#include "RTClib.h"
RTC_DS3231 rtc;
void setup () {
  Serial.begin(9600);
 // verifica si el m贸dulo est谩 conectado
  if (! rtc.begin()) {
    Serial.println("No se pudo encontrar RTC");
    while (1);
  }
  // establecer el tiempo para compilar la hora
  // 隆si el m贸dulo tuvo un reinicio!
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
 // mostrar valores de Hora
  DateTime now = rtc.now();
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
}
void loop () {
}

C贸digo inicial para el term贸metro ds18b20.

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
  Serial.begin(9600);
  sensors.begin();
  sensors.requestTemperatures(); // solicitud de temperatura
  float tempC = sensors.getTempCByIndex(0);  // lo cogemos
  Serial.println(tempC);  // se muestra
}
void loop() {
}

Entonces, los ejemplos los hemos adaptado y verificado, todos los m贸dulos funcionan correctamente.聽隆Comencemos a combinar todo en un proyecto!聽Este bloque de lecciones Arduino, es b谩sico, por lo que escribiremos este proyecto en el estilo de 芦boceto禄; colocaremos todo el c贸digo en un archivo y rezaremos para que todo funcione y no haya conflictos de nombres.聽En un siguiente bloque de lecciones en el curso avanzado, en la聽lecci贸n sobre la creaci贸n de grandes proyectos, volveremos a este ejemplo y lo haremos con un enfoque m谩s serio, sin variables globales y con un desglose en archivos de subrutinas independientes.


Paso 3, unificar.

En primer lugar, al comienzo del boceto, conectamos todas las bibliotecas, objetos declarados, tipos de datos y variables. Para mayor belleza y claridad, ordenamos: primero la configuraci贸n (#define), luego las bibliotecas conectadas y al final los datos:

// AJUSTES
#define ONE_WIRE_BUS 2   // pin ds18b20
// Bibliotecas
#include "RTClib.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// OBJETOS Y VARIABLES
// la direcci贸n puede ser 0x27 o 0x3f
LiquidCrystal_I2C lcd(0x3f, 16, 2); // Configurar la pantalla
RTC_DS3231 rtc;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
}
void loop() {
}

A continuaci贸n, pasamos a la inicializaci贸n de setup():

void setup() {
  // monitor
  lcd.init();
  lcd.backlight();  // Enciende la luz de fondo de la pantalla
  // term贸metro
  sensors.begin();
  // reloj
  rtc.begin();
  // establecer el tiempo para compilar el tiempo
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

隆Excelente! Ahora lo m谩s dif铆cil: debes pensar en la l贸gica del programa. Vamos a dividirlo en pasos simples:

  • 1 vez por segundo: visualizaci贸n del reloj (HH: MM: SS) y el valor actual del sensor.
  • 2 veces por segundo – LED parpadeante en la placa.
  • 5 veces por segundo: medici贸n y promediado de temperatura.

As铆 es va quedando nuestro loop():

void loop() {
  // 2 veces por segundo
  if (millis() - myTimer1 >= 500) {
    myTimer1 = millis();// reiniciar el temporizador
    toggleLED();
  }
  // 5 veces por segundo
  if (millis() - myTimer2 >= 200) {
    myTimer2 = millis(); // reiniciar el temporizador
    getTemp();
  }
  // cada segundo
  if (millis() - myTimer3 >= 1000) {
    myTimer3 = millis(); // reiniciar el temporizador
    redrawDisplay();
  }
}

Crearemos y completaremos las funciones basadas en el temporizador, las siguientes- toggleLED() getTemp() redrawDisplay().

void toggleLED() {
  digitalWrite(13, LEDflag);  // encendido apagado
  LEDflag = !LEDflag; // bandera invertida
}
void getTemp() {
  // suma la temperatura en una variable com煤n
  tempSum += sensors.getTempCByIndex(0);
  sensors.requestTemperatures();
  // contador de medidas
  tempCounter++;
  if (tempCounter >= 5) { // si m谩s de 5  
    tempCounter = 0;  // si 0
    temp = tempSum / 5; //promedio
    tempSum = 0;  // si 0
  }
}
void redrawDisplay() {
  // hora
  DateTime now = rtc.now(); // coge la hora
  lcd.setCursor(0, 0);      // hora en 0,0
  lcd.print(now.hour());    // hora
  lcd.print(':');
   // el primer cero es para decoracion
  if (now.minute() < 10) lcd.print(0);
  lcd.print(now.minute());
  lcd.print(':');
  // el primer cero es para decoracion
  if (now.second() < 10) lcd.print(0);
  lcd.print(now.second());
  // Temperatura
  lcd.setCursor(11, 0);    // cursor en 11.0
  lcd.print("Temp:");
  lcd.setCursor(11, 1);    // cursor en 11,1
  lcd.print(tempcursor
  // fecha
  lcd.setCursor(0, 1);      // cursor en 0,1
  // el primer cero es para decoracion
  if (now.day() < 10) lcd.print(0);
  lcd.print(now.day());
  lcd.print('.');
  // el primer cero es para decoracion
  if (now.month() < 10) lcd.print(0);
  lcd.print(now.month());
  lcd.print('.');
  lcd.print(now.year());
}

Para el funcionamiento de los temporizadores y el conteo de temperatura, tambi茅n necesit谩bamos variables globales, escrib谩moslas en setup ():

uint32_t myTimer1, myTimer2, myTimer3;
boolean LEDflag = false;
float tempSum = 0, temp;
byte tempCounter;

Paso 4, ajustar, probar (y rezar)

Y en general, 隆nuestro proyecto est谩 terminado! Durante el montaje, con el term贸metro, se hizo evidente una caracter铆stica interesante: la lectura del c贸digo se ralentiza mucho, el comando requestTemperatures() espera una respuesta del sensor y bloquea la ejecuci贸n del c贸digo, raz贸n por la cual el reloj no tiene tiempo para ejecutarse 1 vez por segundo. Examinando los ejemplos, encontr茅 un sondeo asincr贸nico del sensor: se agreg贸 una l铆nea a la configuraci贸n del sensor. sensors.setWaitForConversion(false);. En consecuencia, aqu铆 est谩 el c贸digo completo del proyecto, el archivo se llama meteoClock.ino:

// AJUSTES
#define ONE_WIRE_BUS 2  // pin ds18b20
// BIBLIOTECAS
#include "RTClib.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// OBJETOS Y VARIABLES
// la direcci贸n puede ser 0x27 o 0x3f
LiquidCrystal_I2C lcd(0x3f, 16, 2);// Configurar la pantalla
RTC_DS3231 rtc;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
uint32_t myTimer1, myTimer2, myTimer3;
boolean LEDflag = false;
float tempSum = 0, temp;
byte tempCounter;
void setup() {
  Serial.begin(9600); //para depurar
  pinMode(13, 1);
  // monitor
  lcd.init();
  lcd.backlight();  // Enciende la luz de fondo de la pantalla
  // term贸metro
  sensors.begin();
  sensors.setWaitForConversion(false); // obtener datos de forma asincrona
  // reloj
  rtc.begin();
  // establecer el tiempo para compilar la hora
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}
void loop() {
  // 2 veces por segundo
  if (millis() - myTimer1 >= 500) {
    myTimer1 = millis(); // reiniciar el temporizador
    toggleLED();
  }
  // 5 veces por segundo
  if (millis() - myTimer2 >= 200) {
    myTimer2 = millis(); // reiniciar el temporizador
    getTemp();
  }
  // cada segundo
  if (millis() - myTimer3 >= 1000) {
    myTimer3 = millis(); // reiniciar el temporizador
    redrawDisplay();
  }
}
void toggleLED() {
  digitalWrite(13, LEDflag);     // encendido apagado
  LEDflag = !LEDflag;      // bandera invertida
}
void getTemp() {
  // suma la temperatura en una variable com煤n
  tempSum += sensors.getTempCByIndex(0);
  sensors.requestTemperatures();
  // contador de medidas
  tempCounter++;
  if (tempCounter >= 5) { // mas de 5
    tempCounter = 0;  // si 0
    temp = tempSum / 5; // promedio
    tempSum = 0;  // si 0
  }
}
void redrawDisplay() {
  // hora
  DateTime now = rtc.now(); // pilla tiempo
  lcd.setCursor(0, 0);      //cursor en 0,0
  lcd.print(now.hour());    // reloj
  lcd.print(':');
  // el primer cero es decoracion
  if (now.minute() < 10) lcd.print(0);
  lcd.print(now.minute());
  lcd.print(':');
  // el primer cero es decoracion
  if (now.second() < 10) lcd.print(0);
  lcd.print(now.second());
  // TEMP
  lcd.setCursor(11, 0);    // cursor en 11,0
  lcd.print("Temp:");
  lcd.setCursor(11, 1);    //  cursor en 11,1
  lcd.print(temp);
  // HORA
  lcd.setCursor(0, 1);      // cursor en 0,1
  // el primer cero es decoracion
  if (now.day() < 10) lcd.print(0);
  lcd.print(now.day());
  lcd.print('.');
  // el primer cero es decoracion
  if (now.month() < 10) lcd.print(0);
  lcd.print(now.month());
  lcd.print('.');
  lcd.print(now.year());
}

Y as铆 es como se ve nuestro proyecto en la vida real =)

Proyecto fin de curso terminado
Proyecto fin de curso terminado

Deja un comentario