Sistema de riego sencilla: timelapse

Siempre me gustaron los timelapse, en especial cuando se trata de algún proceso natural donde vemos crecer algo, es por ello que decidí capturar imágenes durante el tiempo que tarde en crecer las lechugas.

Una imagen tomada hoy. La cámara esta fuera de fecha.

Para lograr esto voy a utilizar una cámara ip que compre en Aliexpress hace un tiempo, que utiliza un protocolo llamada RTSP para transmitir video en tiempo real.

Hace un tiempo había armado un video de como capturar imagen de la cámara ip utilizando Python, pueden verlo aquí:

El repositorio del código del ejemplo lo pueden encontrar:
https://github.com/gsampallo/ipcam_python

El mayor problema que tuve en esto fue lograr instalar opencv en la raspberry, si bien existen numerosos tutoriales en internet no quería descargar de cero y tener que compilarlo; opté por instalar la versión para python3 (junto con python3) por medio de apt, más adelante hablara más sobre este tema.

Esta es una primer aproximación, donde arme un pequeño script -llamado creativamente camara.py- que toma las imágenes de la cámara y lo guarda en formato png; las imágenes pesan alrededor de 2mb, será necesario más adelante preparar alguna otra tarea para que comprima las imágenes.

Usando cron se dejo programado en la raspberry (donde corre el script) para que ejecute la captura de imágenes cada 20 minutos; también hay un segundo script en bash que copia las imágenes a una carpeta especifica, las sube a un servidor ftp (para liberar espacio en la raspberry) y luego las elimina.

Cuando tenga imágenes de algunos días, voy a armar un pequeño timelapse de como avanza el proyecto, por lo pronto no queda más que esperar.

UPDATE

La página esta online, pueden verla acá:

https://gsampallo.com/riego/

La imagen se actualiza cada 5′, aún no corregí la fecha de la cámara.

Sistema de riego sencillo: el código

En artículos anteriores (Sistema de riego sencillo y el gabinete) fuimos construyendo paso a paso un sistema de riego automatizado para una maceta; en este articulo entraremos en detalle sobre el software utilizado para controlar el hardware.

El software se puede encontrar en el repositorio:
https://github.com/gsampallo/IrrigationSystem

El software se compone de dos partes:

  1. El software que corre en el NodeMCU, que se conecta a un servidor broker, publica cada 5 segundos el valor de la humedad y esta suscrito a un tema, al recibir un valor activa la bomba de agua por unos pocos segundos y al recibir otro valor la apaga.
  2. El software que corre del lado del servidor: lee el valor de la humedad y una vez al dia activa la bomba.

Sobre el software que corre en el nodemcu, solo copio los fragmentos que considero más interesantes:
La función callback (procesa los mensajes que llegan)


1
2
3
4
5
6
7
8
9
10
11
void callback(char* topic, byte* payload, unsigned int length) {

  if (((char)payload[0] == '1')) {
    estadoValvula = true;
    inicioRiego = millis();
  } else if (((char)payload[0] == '2')) {
    Serial.println("Se detiene el riego");
    estadoValvula = false;
    digitalWrite(pinValvula,HIGH);
  }
}

Al recibir el valor 1 en el mensaje cambia el estado a true de la variable global de estadoValvula y asigna a inicioRiego el valor de millis(); esto ultimo es para poder calcular cuanto tiempo estuvo activo el relay que prende la bomba de agua.

Sobre la funcion loop():


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if(estadoValvula) {
    if ((millis() - inicioRiego) < finRiego) {
      digitalWrite(pinValvula,LOW);
      Serial.println("Regando");
    } else {
      digitalWrite(pinValvula,HIGH);
      estadoValvula = false;
      Serial.println("Se detiene el riego");
      client.publish("MACETA","2");
    }
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = millis();
    int humedad = analogRead(A0);
    snprintf (msg, 75, "%ld", humedad);
   
    client.publish("HUMEDAD",msg);  
  }
}

Tenemos el primer bloque de código donde si el cliente esta desconectado del servidor broker, vuelve a conectarlo por medio de la funcion reconnect() y luego procesa los mensajes del servidor broker (client.,loop).

El segundo bloque de código evalúa la variable estadoValvula, si es true, determina si paso o no el tiempo establecido en finRiego (por defecto son 5 segundos), si aún no transcurrieron los 5 segundos mantiene activo el relay, caso contrario apaga el relay, cambia el estado de la variable estadoValvula y publica en el tema «MACETA» el valor 2.

Esto ultimo es para que los dispositivos que están utilizando ese tema para activar la bomba o no, pueda saber que se apago y cambien el estado de su interfaz (útil para la app MQTT Dash).

El ultimo bloque de código es para publicar el valor del sensor de humedad cada 5 segundos.

Más adelante modificare el código para que el tiempo de riego y de publicación sean parámetros que los tome de la nube y el valor de la humedad se vea reflejado en un canal de ThingSpeak.