Domotiza tu casa – Día 7. Programador de riego Parte I

Bueno, bueno, bueno, ya estamos aquí otro día más.

Hacia tiempo que queria publicar el programador de riego, y alguno que otro direis ¿lo podrías haber publicado antes de vacaciones, no?

Pues no, porque imaginaros que por lo que sea al volver de las vacaciones os encontrais las plantas muertas, o peor aún, habeis utilizado el programador para regar un cuenco y dar agua al gato. Es demasiada responsabilidad, y cualquier fallo podría provocar mucho reencor hacia mi persona. Así que una vez pasadas las vacaciones empezamos con el tutorial del programador de riego.

Este tutorial constará de varias partes.

La primera, la de hoy, en que haremos el código básico para el funcionamiento del riego.

La segunda, donde montaremos el riego y probaremos el funcionamiento de lo que hemos hecho.

Y una tercera con mejoras que tengo previstas, mas las que podeis vosotros a partir de los comentarios sugerir.

Empecemos por lo primero. El código de hoy es sencillo, sin mucha complicación, breve, e interesante.

Constará de las siguientes partes importantes:

– En el setup, osease, lo que se ejecuta una única vez al iniciar arduino, vamos a sincronizar el reloj interno de arduino con la hora, y definiremos cada cuanto se ha de recalibrar el reloj.

– En el loop, o rutina que ejecutará infinitamente, comprobaremos si es hora de regar o no, y le pondremos un retardo de 10 segundos. Esta comprobación la realizará llamando a una función que nos dirá si es hora de regar o no.

– La función de riego que compara las horas de riego que tiene definidas con la hora actual y nos devuelve “true” o “verdadero” si es hora de regar, y “false” o “falso” si no es momento de regar.

– La función que obtiene la hora la ponemos también en una función aparte

Siempre tenemos que programar de la manera más limpia posible, separando en funciones, clases, etc… de esta manera nos quedará un codigo fácil de entender y de mantener.

 

El código sería el siguiente:

//Inclusión de librerías

#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>

// MAC e IP de Arduino
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
192,168,1,40 };

unsigned int localPort = 8888;      // Puerto para escuchar los paquetes UDP

byte timeServer[] = {
192, 43, 244, 18}; // time.nist.gov el servidor NTP

const int NTP_PACKET_SIZE= 48; // Cuando el servidor nos devuelve la hora en el paquete UDP, La hora viene en los primeros 48 bytes del paquete

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer para almacenar los paquetes entrantes y salientes

void setup()
{
// Inicializamos el Ethernet, el UDP y el Serial
Ethernet.begin(mac,ip);
Udp.begin(localPort);
Serial.begin(9600);

//función importante del dia. “setSyncProvider” selecciona cual es la función que utilizaremos para sincronizar la hora, y “setSyncInterval” define, en segundos, cada cuanto queremos sincronizar la hora.
setSyncProvider(getNtpTime);
//Hacemos que cada hora se sincronice la hora.
setSyncInterval(3600);

//almaceno la hora en la variable timestamp llamando a la función getNtpTime()
unsigned long timestamp = getNtpTime();
Serial.print(“Hora establecida Time:”);
Serial.println(timestamp);
//segunda función importante del día. setTime, asigna al reloj interno de arduino la hora que le indiquemos en la variable.
setTime(timestamp);

}

void loop()
{
//Muestro por el puerto serie la hora
Serial.print(“Son las: “);
Serial.println(String(hour()) + “:” + String(minute()));
//comprobamos si es la hora del riego
if(esHoraRiego()){
//Si es la hora del riego, mostramos un mensaje indicándolo por el puerto serie
Serial.println(“Es hora riego!!”);
} else {
//Si no es la hora del riego, mostramos un mensaje indicándolo por el puerto serie también
Serial.println(“No es hora riego”);
}
delay(10000);

}

boolean esHoraRiego(){
//Defino horas de riego Inicio a las 19:39 y termina a las 19:40 (poned las horas a las que hagais las pruebas)
byte horaInicio = 19;
byte minutoInicio = 39;
byte horaFin = 19;
byte minutoFin = 40;

//Para hacer las comparaciones de cuando empezar y cuando terminar, lo paso todo a minutos. Por eso la hora de inicio serian las (19 x 60) + 39 = 1.179 y la de fin 1.180. Esto lo hago porque el código de intentar comparar horas con horas es algo más complejo, y yo amo la simplicidad.

int momentoInicio = (horaInicio * 60) + minutoInicio;
int momentoFin = (horaFin * 60) + minutoFin;
int momentoAhora = (hour() * 60) + minute();

//Esto es que si hemos pasado o estamos en el momento de inicio , pero antes del momento del fin…
if((momentoInicio<=momentoAhora) && (momentoAhora<momentoFin)){
//devolver “Cierto” en esta función “esHoraRiego”
return true;
} else {
//devolver “Falso” en esta función “esHoraRiego”
return false;
}
}

unsigned long getNtpTime(){
sendNTPpacket(timeServer); // enviar paquete NTP al servidor de la hora

// esperar para ver si hay respuesta
delay(1000);
if ( Udp.available() ) {
Udp.readPacket(packetBuffer,NTP_PACKET_SIZE);  // leer el paquete

//Extraer la hora del paquete (Ya explicado en el tutorial del servidor NTP

unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);

// la hora obtenida son los segundos desde 1 de Enero de 1900
unsigned long secsSince1900 = highWord << 16 | lowWord;

//Convertir la hora recibida al formato en que trabajan las funciones (hora Unix, 1 de enero de 1970), En segundos, son 2208988800:
const unsigned long seventyYears = 2208988800UL;
//restar 70 años
unsigned long epoch = secsSince1900 – seventyYears;
// retornar Unix time: sumando dos horas por la diferencia horaria

return epoch+7200;

}
}

//Función para enviar el paquete NTP
unsigned long sendNTPpacket(byte *address)
{

memset(packetBuffer, 0, NTP_PACKET_SIZE);

packetBuffer[0] = 0b11100011;
packetBuffer[1] = 0;
packetBuffer[2] = 6;
packetBuffer[3] = 0xEC;

packetBuffer[12]  = 49;
packetBuffer[13]  = 0x4E;
packetBuffer[14]  = 49;
packetBuffer[15]  = 52;

Udp.sendPacket( packetBuffer,NTP_PACKET_SIZE,  address, 123);
}

 

Si teneis cualquier problema, adjunto os dejo el archivo.

Domotiza tu casa – Dia 7 – Programador de riego

Si os ha gustado, dadle al Me gusta del facebook o el linkedI!
Espero vuestros comentarios

6 Replies to “Domotiza tu casa – Día 7. Programador de riego Parte I”

  1. Hola, primero queria felicitarte acabo de acceder a tu blog buscando informacion sobre domotica y me he leido de princpio a fin tu proyecto, me añado tu blog como favorito para ir siguiendote, me interesa mucho el tema. Un saludo y felicidades por el trabajo que estas haciendo

  2. Buena lastima que no hayas continuado subiendo proyectos o quizá esta listo interesante el tema de esto… yo estoy trabajando para mi tesis con algunas cosas así y de verdad que siento no haber encontrado la parte del lm35 antes ya que estuve harto rato realizándolo de forma manual. bueno te propongo algunas soluciones que te pueden ayudar a mejorar quiza en algo algunos proyectos q tengas en mente… para llevar algunos controles del tiempo sin tener que hacer los delay que te pausan el arduino puedes usar la funcion millis() q lleva el contro del tiempo en ejecucion desde que se inicio el arduino, por otro lado puedes usar la interfaz del serial para configurarlo y asi ya no quedas limitado a la programacion del arduino te dejo un pedaso de cod para que lo analises haber si te sirve de algo

    #include

    //Globales temperatura
    int tmax=0;
    int tmin=0;

    setup(){
    Serial.begin(9600);
    tmax=readvariable(0);
    tmin=readvariable(2);

    }

    loop(){
    if (Serial.available() > 0) {
    int inByte = Serial.read();
    switch (inByte) {

    //recive variables de temperatura
    case ‘t’:
    tmax = rescataint();
    escribe(0, tmax);
    tmin = rescataint();
    escribe(2, tmin);

    break;
    default:
    Serial.println(“c”);
    }
    }

    int readvariable(int pos){
    int valor;

    valor = EEPROM.read(pos);
    valor = valor * 4;

    int aux = EEPROM.read(pos+1);
    valor = valor + aux;

    return valor;
    }

    //recive pocicion y el valor
    void escribe(int pos, int valor){

    int valores = valor/4;
    int sobra = valor%4;
    EEPROM.write(pos, valores);
    EEPROM.write(pos+1, sobra);

    }

    // rescata int desde el puerto serial
    int rescataint(){
    int valor = 0;
    byte contador = 0;
    char cadena[24];
    while(1){
    if(Serial.available()){
    memset(cadena, 0, sizeof(cadena));
    while (Serial.available()>0){
    delay(5);
    cadena[contador] = Serial.read();
    contador++;
    }
    valor = atoi(cadena);
    Serial.println(valor+1);

    break;
    }
    }
    return valor;
    }

    entonces así puedes enviar t y luego los valores y se guardan en memoria la memoria es de 512 para arduino UNO (según versión) y cada 2 bytes se puede guardar un numero si se pautea bien tienes tu información escrita. la función millis() retorna el valor en mili segundos con un par de divisiones puedes lograr llevar el tiempo y si lo sincronisas con lo tuyo puedes llevar buen reloj dentro del arduino.
    pifia de millis() que se reinicia aprox 50 días según documentación de arduino

    saludos y espero que te sirva y ojala continues el blog con otros proyectos aunque al parecer por ahora esta parado

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *