miércoles, 5 de diciembre de 2018

(ARDUINO) Estación Meteorológica con control de riego

Buenas, hoy os propongo un proyecto muy habitual, pero creo que bastante interesante a la hora de buscar iniciarnos en ARDUINO, el uso combinado de sensores, reloj, display, relé...
una estación para medir diferentes parametros, informando por pantalla y tener el control de un relé que nos activa una bomba de agua para regar nuestras plantas.

Lista de la compra:

  • placa Arduino, en mi caso he utilizado un Arduino Nano
  • Display I2C 20x4
  • Sensor DHT22
  • Sensor de humedad del suelo
  • LDR (Sensor de luminosidad)
  • RTC DS3213
  • 2 resistencias 10k
  • Relé 12v
  • Bomba de agua 12v
  • protoboard
  • cables de conexión
  • Jack hembra
  • para conexión eléctrica
  • Botón pulsador
  • tubo de riego
  • Tuper, para colocar todo
  • tornillos, arandelas y tuercas


Bien, así es como ha quedado


y estas son las vistas del interior




Este es el esquema de componentes y conexiones

Funcionalidad:

  • Mediante el display mostramos los valores de los diferentes sensores.
  • posibilidad de riego manual al pulsar el botón.
  • Mediante "const byte diasRiego = 1; " Controlamos los días entre riegos.
  • Mediante "const byte horaRiego = 21;" // Controlamos la hora en que se realiza el riego.
  • Mediante "const long duracionRiego = 60000;"definimos la duración del riego (en mili segundos 60 segundos).

Comentarios:

  • En la lista de materiales he incluido una bomba de agua de 12v, junto con su adaptador de corriente, es la que yo compre en su momento, pero, no se si por la potencia o por el modelo en concreto, no he conseguido que bombeé agua, el motor si actúa pero el agua no sube por el tubo de riego. Te recomiendo que antes de comprar, tanto la bomba como el relé te asegures de que son funcionales.
  • no olvides que el RTC se debe iniciar la primera vez que se usa, en los ejemplos que carga la librería puedes encontrar un sketch para ello.
  • Puedes observar diferentes variables para la fecha y la hora, esto se debe a que he querido tratar los diferentes dígitos como cadenas para así poder mostrar siempre a dos dígitos.
  • Si observas el sketch, te darás cuenta que los valores de los sensores no actúan en la activación o no del regado, creo que es relativamente sencillo añadir condiciones según el estado de los diferentes sensores ¿te animas?
  • No todo el merito es mio, quiero agradecer a Luis del Valle de programarfacil.com por su aporte al sistema de riego

y este el sketch completo:


// Incluimos librerías
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h> // librería para Display 20x4
#include <SimpleDHT.h>

// Variables pines
const byte pinPulsador = 8;
const byte pinRele = 9;
int pinDHT22 = 7;
SimpleDHT22 dht22;
const int pinSuelo = A3;
const int pinLuz = A2;

// Instancia a la clase RTC_DS3231
RTC_DS3231 rtc;

LiquidCrystal_I2C lcd(0x27, 20, 4); // Definimos dirección para 20 caracteres y 4 lineas

int diaLcd = 0;                //variable visualización en pantalla día
int mesLcd = 0;                //variable visualización en pantalla mes
int horLcd = 0;                //variable visualización en pantalla horas
int minLcd = 0;                //variable visualización en pantalla minutos
int segLcd = 0;                //variable visualización en pantalla segundos
String diaT;
String mesT;
String horT;
String minT;
String segT;

// Parámetros de riego
const byte diasRiego = 1; // con esta variable definimos los días entre riegos
const byte horaRiego = 21; // Con esta variable definimos la hora de riego
byte contadorDias = 0;
boolean centinelaHora = true;

// Tiempo de riego
const long duracionRiego = 60000; // Cuánto tiempo riega en mili segundos 60 segundos
long marcaTiempo; // Marca de tiempo para contar los mili segundos

void setup() {

  // Configuración comunicación serie
  //Serial.begin(9600);

  // SETUP Para LCD
  lcd.init();    // initialize the lcd

  // Modo de los pines
  pinMode(pinPulsador, INPUT);
  pinMode(pinRele, OUTPUT);

  // Iniciamos el rtc
  if (!rtc.begin()) {
    Serial.println("No se ha encontrado el módulo RTC");
    while (1);
  }
}

void loop() {

  // Leer el pulsador
  byte estadoPulsador = digitalRead(pinPulsador);

  // Esperamos para evitar dobles pulsaciones
  delay(300);

  // Comprobamos si se ha pulsado el pulsador
  if (estadoPulsador == HIGH) {
    // Cambiamos de estado el relé
    digitalWrite(pinRele, !digitalRead(pinRele));

    // Comenzamos a contar el tiempo
    marcaTiempo = millis();

  }

  float temperature = 0;
  float humidity = 0;
  int err = SimpleDHTErrSuccess;

  int humedad = analogRead(pinSuelo);
  int humedad_tratada = 0;
  humedad_tratada = map(humedad, 0, 1023, 100, 0);
  int Luz = analogRead(pinLuz);
  int Luz_tratada = 0;
  Luz_tratada = map(Luz, 0, 1023, 0, 100);

  // Obtenemos la fecha
  DateTime tiempoReferencia = rtc.now();
  lcd.backlight();
  lcd.setCursor(0, 0); // posicion 0 de la linea 0

  diaLcd = tiempoReferencia.day();      //conversion del tiempo para debug dia
  mesLcd = tiempoReferencia.month();    //conversion del tiempo para debug mes
  horLcd = tiempoReferencia.hour();     //conversion del tiempo para debug horas
  minLcd = tiempoReferencia.minute();   //conversion del tiempo para debug minutos
  segLcd = tiempoReferencia.second();   //conversion del tiempo para debug segundos

  String diaT = String(diaLcd);           // -- crea variables de cadena de texto utilizando
  String mesT = String(mesLcd);           // -- crea variables de cadena de texto utilizando
  String horT = String(horLcd);           // -- crea variables de cadena de texto utilizando
  String minT = String(minLcd);           //    los valores numéricos de día mes hora minuto y segundos
  String segT = String(segLcd);

  if (diaLcd < 10) diaT = "0" + String(diaLcd); // Comparamos si es día es menor de 10 y añadimos un 0 a la cadena si es cierto
  if (mesLcd < 10) mesT = "0" + String(mesLcd); // Comparamos si es mes es menor de 10 y añadimos un 0 a la cadena si es cierto
  if (horLcd < 10) horT = "0" + String(horLcd); // Comparamos si es hora es menor de 10 y añadimos un 0 a la cadena si es cierto
  if (minLcd < 10) minT = "0" + String(minLcd); // Comparamos si es minuto es menor de 10 y añadimos un 0 a la cadena si es cierto
  if (segLcd < 10) segT = "0" + String(segLcd); // Comparamos si es segundo es menor de 10 y añadimos un 0 a la cadena si es cierto

  lcd.print(horT);
  lcd.print(':');
  lcd.print(minT);
  lcd.print(':');
  lcd.print(segT);
  lcd.setCursor(10, 0); // posición 10 de la linea 0
  lcd.print(diaT);
  lcd.print('/');
  lcd.print(mesT);
  lcd.print('/');
  lcd.print(tiempoReferencia.year(), DEC);

  lcd.setCursor(1, 1); // posición 0 de la linea 1

  if ((err = dht22.read2(pinDHT22, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
    lcd.print("Fallo en DHT22, err="); lcd.print(err);

    //delay(2000);
    return;
  }

  lcd.print((float)temperature);
  lcd.print(" C");
  lcd.setCursor(10, 1);// posición 10 de la linea 1
  lcd.print((float)humidity);
  lcd.print(" %HR");

  lcd.setCursor(3, 2);// posición 3 de la linea 2
  lcd.print("H. Suelo: ");
  lcd.print(humedad_tratada);
  lcd.print("%");

  lcd.setCursor(3, 3);// posición 3 de la linea 3
  lcd.print("Luz Amb.: ");
  lcd.print(Luz_tratada);
  lcd.print("%");

  delay(500);

  // Si es la hora de regar

  if (tiempoReferencia.hour() == horaRiego && centinelaHora) {
    // Marcamos para que no vuelva a entrar
    centinelaHora = false;
    // Sumamos una al contador de días
    contadorDias = contadorDias + 1;
    // Si han pasado los días para regar
    if (contadorDias == diasRiego) {
      // Regamos
      digitalWrite(pinRele, HIGH);
      // Serial.println("Enciende riego automático");
      // Comenzamos a contar el tiempo
      marcaTiempo = millis();

      // Iniciamos el contador de días
      contadorDias = 0;
    }
    // Si es otra hora marcamos para que vuelva a detectar
  } else if (tiempoReferencia.hour() != horaRiego) {
    centinelaHora = true;
  }

  // Si está regando
  if (digitalRead(pinRele)) {
    // Comprobamos si ha pasado el tiempo
    if (millis() - marcaTiempo >= duracionRiego) {
      // Apagamos el riego
      digitalWrite(pinRele, LOW);
      //Serial.println("Apaga riego automático");
    }
  }
}

No hay comentarios:

Publicar un comentario