info@naparlinex.com

Hay faltas de ortografía y de expresividad, pero es un código "tal cual". 
Es el que está funcionando en mi arduino UNO.
Espero que se entienda. Si tienes problemas con él, no dudes en mandar un correo y te
atenderemos cumplidamente.


/*
riego11  Ver 1.1  Junio/Julio 2014.

Una vez comprobado el funcionamiento se añade una tarjeta SD para grabar al configuración y un log de cada vez que se riega
Se corrige el bug de ejecutar. No funciona o no lo hace correctamente
Se cambia la secuencia del loop. Hay que conseguir que vaya más rapida la comunicación.
*/


#include <Wire.h> 
#include <DS1307.h>
#include <Shifter.h>
#include <SdFat.h>
#include <stdlib.h>
#include <stdlib.h>


#define SER_Pin 5 // dataPin
#define RCLK_Pin 7 // lacthPin
#define SRCLK_Pin 6 // clockPin
#define NUM_REGISTERS 1

//Pinlluvia se suprime, ahora se configura desde el ini
//#define PIN_LLUVIA 9 // Se pone en la entrada 9 pero puede cambiar

// Aquí se definen cuántos registros de desplazamiento hay en la cadena...
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS); // Se inicializa el registro de desplazamiento usando la librería “Shifter”

DS1307 clock;//el reloj

//El sd y los ficheros
SdFat g_sd;
SdFile g_fichero; //Solo se puyede abrir uno cada vez así que da igual como se llame la variable


//Aqui son todo variables globales (g_ ...), al fin y al cabo no es un PC...

//Variables para la rx del serie
String g_s_cadena_in; // datos que llegan
boolean g_s_inicio_sn; 
boolean g_s_fin_sn; 

//Los tiempos de los reles
struct RELES {
  int r_tiempo;
  int hora_inicio;
  int opcion;
  int ultima_regada;

  boolean activado_sn;
};
RELES g_reles[8];

//Para enviar los estados de cada cosa al monitoreo
char g_estado_reles;
int g_estado_io; 
int g_estado_an[6];

//Los pines digitales pueden ser salida o entrada. Por defecto se ponen todos como salida
//y luiego en el setup se definen quien es quien
boolean g_salida_sn[14];//Ojo es "salida" pero puede ser "entrada" si esto es a false
boolean g_activada_sn[14]; //si la entrada esta activada

boolean g_monitorizar_sn; //si se monitorizan los datos en el PC

boolean g_ejecutar_sn; //Se ejecuta lo que tenga reles[]
int g_ejecutar_rele;
int g_ejecutar_minuto_inicio;

int g_minuto_dia;//Se carga aqui el momento

int g_hoy; //el nº de días transcurridos desde el 2000, o sea hoy

int g_pin_lluvia; //que pin es el detector de lluvia
int g_lluvia_ultima;//Cuando llovió la ultima vez
boolean g_lluvia_grabada; //para grabar sólo una vez


//Archivos de cabecera... por no meterlos en un .h
void vdl_arduino_leer_fechas_log_reles();
void vdl_arduino_transmitir_log_reles();
void vdl_arduino_grabar_log_reles(int rele,boolean manual_sn);
void vdl_arduino_grabar_programacion_reles();
void vdl_arduino_leer_programacion_reles();
void vdl_arduino_leer_ini();
void vdl_arduino_reloj_minuto_dia_hoy();


//---------------------------------------------------------------------
// Cuando se resetea con el boton del arduino o cuando carga un programa 
// o cuando se conecta el programa de monitorización, pasa por aqui salvo
// que este pulsado el boton de No setup
//---------------------------------------------------------------------
void setup()
{
int a;

Serial.begin(115200); // abre el puerto serie, y le asigna la velocidad de 115200 bps

g_monitorizar_sn = true; //Por defecto se monitoriza 

//Hace falta hacer la ejecución dentro del loop por que sino parece que se vuelve loco el arduino  
g_ejecutar_sn = false; 
g_ejecutar_rele = 0;
g_ejecutar_minuto_inicio = 0;

g_s_cadena_in = ""; // datos que llegan
g_s_inicio_sn = false; 
g_s_fin_sn = false; 

g_s_cadena_in.reserve(128); //la cadena de entrada del serie

g_minuto_dia = 0; //Para el envio de la fecha y hora
g_hoy = 0; //a fecha de hoy cuantos dias pasan del 2000
g_lluvia_ultima = 0;  //Para el control de la lluvia
g_pin_lluvia = 9; //Un por defecto
g_lluvia_grabada = false;

// Para el envio del estado de todo el arduino
g_estado_reles = 0x00; //reles (8)
g_estado_io = 0x0000; //14 e o s
for(a=0;a < 6;a++) g_estado_an[a] = 0; //6 analogicas 

//Se inicia el reloj
Wire.begin(); //Hace falta par el DS1307 (el reloj)
clock.begin(); 
vdl_arduino_reloj_minuto_dia_hoy();

//Los pines que no estan aqui es por que estan reservados para E/S y reles  
//0 y 1 son para el puerto serie
//5 6 y 7 son para los reles
//La tarjeta SD reserva 10,11,12 y 13 para ella
//el 2,3 8,9 son las entradas optoacopladas del relay shield (INPUT)
for(a=0;a < 14; a++) 
   {
   g_salida_sn[a] = true; //por defecto todas salidas
   g_activada_sn[a] = false; //al arrancar todas la IN sin activar
   }

//La config por defecto
pinMode(2, INPUT); //2,3,8,9 -> Optoacopladas de la relay shield
g_salida_sn[2] = false; 
pinMode(3, INPUT); 
g_salida_sn[3] = false; 

pinMode(4, OUTPUT); //Libre (es la única????)

pinMode(8, INPUT); 
g_salida_sn[8] = false;
pinMode(9, INPUT); 
g_salida_sn[9] = false;


//Inicializa el SD
if (!g_sd.begin(SS, SPI_HALF_SPEED)) g_sd.initErrorHalt();

vdl_arduino_leer_ini(); //carga config.ini

//La programacion del riego. Por defecto se ponen estos valores que luego se cambian desde el programa de monitoreo
for(a=0;a < 8; a++) 
   {
   g_reles[a].r_tiempo = 15; //Minutos 
   g_reles[a].activado_sn = false; 
   g_reles[a].opcion = 1; //por defecto diario (ojo que las opciones empiezan en 1
   g_reles[a].ultima_regada = 0; //el nº de dia del ultimo dia que se rego
   }
g_reles[0].hora_inicio = 1080;
g_reles[1].hora_inicio = 1090;
g_reles[2].hora_inicio = 1100;
g_reles[3].hora_inicio = 1110;
g_reles[4].hora_inicio = 1120;
g_reles[5].hora_inicio = 1130;
g_reles[6].hora_inicio = 1140;
g_reles[7].hora_inicio = 1160;

vdl_arduino_leer_programacion_reles(); //Ahora se lee la programacion del ficherito reles.cfg
vdl_arduino_leer_fechas_log_reles(); //Y ahora carga la fecha de la ultimas regadas
}
//
// Y ahora ya las funciones mias 
//
//---------------------------------------------------------------------
// Lee el log los reles y se queda con la fecha más alta
//---------------------------------------------------------------------
void vdl_arduino_leer_fechas_log_reles()
{
int a,leer,tamano,offset,ff,rr;
unsigned char dato;
char cadena[64];
char rele_n[2];
char lit[5];
int fechas[8];

for(a=0;a < 8;a++) fechas[a] = 0;

if(!g_fichero.open("reles.log", O_READ)) 
  {
  Serial.println("{error reles log en fechas}");
  delay(100);
  }
else {
     tamano= g_fichero.fileSize();

     leer=0;
     cadena[0] = 0x00;
     offset = 0;
     while(leer < tamano)
          {
          dato = g_fichero.read();
          leer++;
          if(dato == 0x0d || dato == 0x0a) 
            {
            //si es 0d o 0a el siguiente será o 0d o 0a así que paso de él
            dato = g_fichero.read();
            leer++;
            cadena[offset] = 0x00;
       
            //Puede haber al final del fichero algun 0x0d o 0x0a
            if(cadena[0] != 0x00) 
              {
              rele_n[0] = cadena[0];
              rele_n[1] = 0x00;
              lit[0] = cadena[1];
              lit[1] = cadena[2];
              lit[2] = cadena[3];
              lit[3] = cadena[4];
              lit[4] = 0x00;
              
              rr = atoi(rele_n);
              ff = atoi(lit);
              if(ff > fechas[rr]) fechas[rr] = ff;
              
              }
       
            for(a=0;a < offset;a++) cadena[a] = 0x00;
            offset = 0;
       
            }
          else cadena[offset++] = dato;
          } //fin while
     
     g_fichero.close();
     }
//Y ahora se supone que tengo las fechas de la ultima regada
for(a=0;a < 8; a++) g_reles[a].ultima_regada = fechas[a]; 
}
//---------------------------------------------------------------------
// Lee el log los reles y lo manda por el serie
//---------------------------------------------------------------------
void vdl_arduino_transmitir_log_reles()
{
int a,leer,tamano,offset;
unsigned char dato;
char cadena[64],envio[64];

if(!g_fichero.open("reles.log", O_READ)) 
  {
  Serial.println("{error reles log en TX}");
  delay(100);
  }
else {
     tamano= g_fichero.fileSize();
     //Serial.print("tamano: ");
     //Serial.println(tamano,DEC);

     leer=0;
     cadena[0] = 0x00;
     offset = 0;
     while(leer < tamano)
          {
          dato = g_fichero.read();
          leer++;
          if(dato == 0x0d || dato == 0x0a) 
            {
            //si es 0d o 0a el siguiente será o 0d o 0a así que paso de él
            dato = g_fichero.read();
            leer++;
            cadena[offset] = 0x00;
       
            //Puede haber al final del fichero algun 0x0d o 0x0a
            if(cadena[0] != 0x00) 
              {
         
              sprintf(envio,"{L%s}",cadena);
              Serial.write(envio);
              delay(100);
              }
       
            for(a=0;a < offset;a++) cadena[a] = 0x00;
            offset = 0;
       
            }
          else cadena[offset++] = dato;
          } //fin while
     
     g_fichero.close();
     }

}
//---------------------------------------------------------------------
// Graba un registro de cada vez que se activa un rele
// Si el rele == 9 es le de lluvia. OJO! que no es el pin 9 (puede ser 
// cualquier pin el de lluvia, a pesar de que coincide que es el 9 en 
// este montaje) es el inexistente rele 9  
//---------------------------------------------------------------------
void vdl_arduino_grabar_log_reles(int rele,boolean manual_sn)
{
//int horas,minutos;
char cadena[32];

if(!g_fichero.open("reles.log", O_RDWR | O_CREAT | O_APPEND)) 
  {
  Serial.println("{falla abriendo reles.log para grabar}");
  delay(100);
  }
else {
     
     //Grabo la fecha en ascii por que me da igual grabar 4 caracteres que dos int y luego se puede leer
     if(rele != 9) //el rele 9 NO EXISTE ES LOG DE LLUVIA
       { 
       if(manual_sn) sprintf(cadena,"%d%d manual",rele,g_hoy);
       else sprintf(cadena,"%d%d",rele,g_hoy);
       }
     else {
     //si manual_sn es que se ha activa y sino es que se ha descativado
          if(manual_sn) sprintf(cadena,"%d%d on",rele,g_hoy);
          else sprintf(cadena,"%d%d off",rele,g_hoy);
          }  
     
     g_fichero.println(cadena);

     g_fichero.close();
     }
}
//---------------------------------------------------------------------
// Borra el registro de cada vez que se activa un rele
//---------------------------------------------------------------------
void vdl_arduino_borrar_log_reles()
{
if(!g_sd.remove("reles.log"))
  {
  Serial.println("{falla borrando reles.log}");
  delay(100);
  }
}
//---------------------------------------------------------------------
// Graba el archivo de la progamacion de los reles 
//---------------------------------------------------------------------
void vdl_arduino_grabar_programacion_reles()
{
int a,rele,horas,minutos;
char cadena[32];

if(!g_fichero.open("reles.cfg", O_RDWR | O_CREAT | O_TRUNC)) 
  {
  Serial.println("{falla abriendo reles.cfg para grabar}");
  delay(100);
  }
else {
     for(rele=0;rele < 8;rele++)
        {
        for(a=0;a < 11;a++) cadena[a] = 0x00;
   
        horas = g_reles[rele].hora_inicio/60;
        minutos = g_reles[rele].hora_inicio - (horas*60);
   
        sprintf(cadena,"%d%02d:%02d%03d%d",rele,horas,minutos,g_reles[rele].r_tiempo,g_reles[rele].opcion);
   
        g_fichero.println(cadena);
   
        }

     g_fichero.close();
     }
}
//---------------------------------------------------------------------
// Lee el archivo de la progamacion de los reles 
//---------------------------------------------------------------------
void vdl_arduino_leer_programacion_reles()
{
int a,leer,tamano,offset;
unsigned char dato;
char cadena[16];
char rele_num[2],hh[3],mm[3],r_tiempo[4],r_opcion[2];

if(!g_fichero.open("reles.cfg", O_READ)) 
  {
  Serial.println("{No puede leer reles.cfg}");
  delay(100);
  }
else {
     tamano= g_fichero.fileSize();
     //Serial.print("tamano: ");
     //Serial.println(tamano,DEC);

     leer=0;
     cadena[0] = 0x00;
     offset = 0;
     while(leer < tamano)
          {
          dato = g_fichero.read();
          leer++;
          if(dato == 0x0d || dato == 0x0a) 
            {
            //si es 0d o 0a el siguiente será o 0d o 0a así que paso de él
            dato = g_fichero.read();
            leer++;
            cadena[offset] = 0x00;
       
            //Puede haber al final del fichero algun 0x0d o 0x0a
            if(cadena[0] != 0x00) 
              {
              rele_num[0] = cadena[0];
              rele_num[1] = 0x00;
       
              hh[0] = cadena[1];
              hh[1] = cadena[2];
              hh[2] = 0x00;
              //se pasa de los dos puntos :
              mm[0] = cadena[4];
              mm[1] = cadena[5];
              mm[2] = 0x00;
       
              r_tiempo[0] = cadena[6];
              r_tiempo[1] = cadena[7];
              r_tiempo[2] = cadena[8];
              r_tiempo[3] = 0x00;
       
              r_opcion[0] = cadena[9];
              r_opcion[1] = 0x00;
       
              g_reles[atoi(rele_num)].hora_inicio = atoi(hh)*60+atoi(mm);
              g_reles[atoi(rele_num)].r_tiempo = atoi(r_tiempo);
              g_reles[atoi(rele_num)].opcion = atoi(r_opcion);
         
              }
       
            for(a=0;a < offset;a++) cadena[a] = 0x00;
            offset = 0;
       
            }
          else cadena[offset++] = dato;
          } //fin while
     
     g_fichero.close();
     }
}
//---------------------------------------------------------------------
// Lee el archivo de configuracion inicial config.ini 
//---------------------------------------------------------------------
void vdl_arduino_leer_ini()
{
int a,leer,tamano,offset;
unsigned char dato;
char cadena[16],cual[4],num[3];

//Ahora se lee la configuración del ficherito .ini
if(!g_fichero.open("config.ini", O_READ)) 
  {
  Serial.println("{No puede leer config.ini}");
  delay(100);
  }
else {
     tamano= g_fichero.fileSize();

     leer=0;
     cadena[0] = 0x00;
     offset = 0;
     while(leer < tamano)
          {
          dato = g_fichero.read();
          leer++;
          if(dato == 0x0d || dato == 0x0a) 
            {
            //si es 0d o 0a el siguiente será o 0d o 0a así que paso de él
            dato = g_fichero.read();
            leer++;
            cadena[offset] = 0x00;
       
            strncpy(cual,cadena,3);
            cual[3] = 0x00;
       
            if(strlen(cadena) == 5) 
              {
              num[0] = cadena[4];
              num[1] = 0x00;
              }
            else {
                 num[0] = cadena[4];
                 num[1] = cadena[5];
                 num[2] = cadena[6];
                 }
       
            if(strcmp(cual,"MON") == 0) 
              {
              if(strcmp(num,"1") == 0) g_monitorizar_sn = true; 
              else g_monitorizar_sn = false; 
              }
       
            if(strcmp(cual,"RES") == 0); //NO se hace nada, ya se encargan las librarias de cada cosa
       
            if(strcmp(cual,"ENT") == 0)
              {
              pinMode(atoi(num),INPUT); 
              g_salida_sn[atoi(num)] = false; 
              } 
       
            if(strcmp(cual,"SAL") == 0) pinMode(atoi(num),OUTPUT); 
       
            if(strcmp(cual,"LLU") == 0) g_pin_lluvia = atoi(num); 
       
            for(a=0;a < offset;a++) cadena[a] = 0x00;
            offset = 0;
       
            }
          else cadena[offset++] = dato;
          } //fin while

     g_fichero.close();
     }
}
//---------------------------------------------------------------------
// Devuelve el nº de dias desde el 2000
// Ver 1.1:
// clock.year es el nº de año - 2000 siempre así que se puede devolver un int
//---------------------------------------------------------------------
int  vdl_arduino_dias_transcurridos(int dia,int mes,int anno)
{
int dias; 
int dias_mes[12] = {0,31,59,90,120,151,181,212,243,273,304,334};

if(anno%4 == 0) dias_mes[2] = 60; //bisiesto
dias = (anno*365) + (anno/4) + dias_mes[mes-1] + dia;

return dias;
}
//---------------------------------------------------------------------
// Lee el reloj y actualiza el minuto de dia 
//---------------------------------------------------------------------
void vdl_arduino_reloj_minuto_dia_hoy()
{
boolean error_sn = false;

clock.getTime();
//Tengo la sospecha de que esto a veces arroja valores raros, así que le hago un pequeño control
if(clock.minute < 0 || clock.minute > 59) {clock.minute = 0; error_sn = true;}
if(clock.hour < 0 || clock.hour > 23) {clock.hour = 0; error_sn = true;}
if(!error_sn)
  {
  g_minuto_dia = clock.minute + (clock.hour*60);
  g_hoy = vdl_arduino_dias_transcurridos(clock.dayOfMonth,clock.month,clock.year);
  }
}
//---------------------------------------------------------------------
// Envia los datos de monitoreo 
//---------------------------------------------------------------------
void vdl_arduino_monitoreo()
{
int a;

Serial.print("{T");

Serial.write(clock.hour);
Serial.write(clock.minute);
Serial.write(clock.second);
Serial.write(clock.dayOfMonth);
Serial.write(clock.month);
Serial.write(highByte(clock.year));
Serial.write(lowByte(clock.year));
Serial.write(clock.dayOfWeek);

Serial.write(g_estado_reles);
Serial.write(highByte(g_estado_io));
Serial.write(lowByte(g_estado_io));
  
for(a=0;a < 8;a++) 
   {
   Serial.write(highByte(g_reles[a].ultima_regada));
   Serial.write(lowByte(g_reles[a].ultima_regada));
   }
  
for(a=0;a < 6;a++) 
   {
   Serial.write(highByte(g_estado_an[a]));
   Serial.write(lowByte(g_estado_an[a]));
   }

Serial.println("}");

/*
Serial.print(highByte(g_estado_io),HEX);
Serial.print("-");
Serial.println(lowByte(g_estado_io),HEX);
*/
}


//---------------------------------------------------------------------
// ON/OFF digital
// Mirar la nota de on_off_rele
//---------------------------------------------------------------------
void vdl_arduino_on_off_digital(int salida,boolean arriba_sn)
{
if(arriba_sn) 
  {
  digitalWrite(salida, HIGH); //LED on 
  g_estado_io = g_estado_io | (0x0001<<salida);    
  }
else {
     digitalWrite(salida, LOW); // turn the LED off    
     g_estado_io = g_estado_io & (~(0x0001<<salida));    
     }
//g_estado_io = g_estado_io ^ (0x0001<<salida);    
}
//---------------------------------------------------------------------
// ON/OFF de un rele
// g_estado_reles = g_estado_reles ^ (0x01<<rele);    
// Como la comunicación serie va como va cabe la posibilidad de pasar
// mas de una vez por aquí con la misma orden, así que no se puede usat el XOR
//---------------------------------------------------------------------
void vdl_arduino_on_off_rele(int rele,boolean salida_sn)
{
if(salida_sn) 
  {
  shifter.setPin(rele, HIGH);
  shifter.write();
  g_estado_reles = g_estado_reles | (0x01<<rele);    
  }
else {
     shifter.setPin(rele, LOW);
     shifter.write();
     g_estado_reles = g_estado_reles & (~(0x01<<rele));    
     }

//Serial.print("rele on_off ");
//Serial.println(g_estado_reles,HEX);
}
//---------------------------------------------------------------------
// Lecturas Entradas digitales
//---------------------------------------------------------------------
void vdl_arduino_lectura_entradas_digitales()
{
int a,lectura;

for(a=0;a < 14;a++) 
   {

   if(!g_salida_sn[a])  //Es una entrada
     {
     lectura = digitalRead(a);
     if(lectura == HIGH) 
       {
       if(!g_activada_sn[a])
         {
         g_activada_sn[a] = true; //para que no este desactivandola todo el rato 
         g_estado_io = g_estado_io ^ (0x0001<<a);    
         } 

       } //si esta arriba
     else { //else esta abajo
          if(g_activada_sn[a]) 
            {
            g_activada_sn[a] = false;
            g_estado_io = g_estado_io ^ (0x0001<<a);    
            }
          }//esta abajo

     } //es entrada 

   }//for
}
//-------------------------------------------------------------------------------------------------------------------
// Si esta activado un rele lo desactiva y si esta desactivado lo activa
//------------------------------------------------------------------------------------------------------------------
void vdl_arduino_programa_rele_on_off(int rele,boolean activar_sn)
{
if(activar_sn)
  {
  if(!g_reles[rele].activado_sn) 
    {
    vdl_arduino_on_off_rele(rele,true);
    g_reles[rele].activado_sn = true; 
    vdl_arduino_grabar_log_reles(rele,false); //log NO manual. 
    } //if no se ha activado
  }
else {
     if(g_reles[rele].activado_sn) 
       {
       vdl_arduino_on_off_rele(rele,false);
       g_reles[rele].activado_sn = false;
       g_reles[rele].ultima_regada = g_hoy;
       } //si estaba activado
     }
}
//-------------------------------------------------------------------------------------------------------------------
// Esto podría estar perfectamente en el loop pero así queda más claro, además da la posibilidad para más adelante
// de activar una bandera que impida la ejecución del programa (un posible boton en el programa del monitoreo
// de "no ejecutar programa")
// Hago un cambio con la rutina anterio; antes se comprobaba que fuera despues de la hora para desactivarlo
// Ahora no: si no esta entre el tiempo de regar se da la orden de desactivar si esta activado.
// Esto se hace por que ha habido veces que me he encontrado reles activos sin tener que estarlo. como no sé
// quien los activa ni por que si no esta entre los minutos de activar se desactiva y ya
//------------------------------------------------------------------------------------------------------------------
void vdl_arduino_programa_reles()
{
int rele;

for(rele=0;rele < 8;rele++) 
   {
   if(g_reles[rele].r_tiempo != 0)
     {
     
     //Primero se comprueba que hoy toca regar (la opcion puede ser desde 1 hasta 4)
     if( (g_hoy - g_reles[rele].ultima_regada) >= g_reles[rele].opcion )
       {
       
       //De seguido se comprueba que sea la hora  
       if(g_minuto_dia >= g_reles[rele].hora_inicio && g_minuto_dia < (g_reles[rele].hora_inicio+g_reles[rele].r_tiempo)) 
         { 
         vdl_arduino_programa_rele_on_off(rele,true); 
         }
       else {
            vdl_arduino_programa_rele_on_off(rele,false); 
            }
       
       } //if g_hoy toca regar
     
     } //si < 0 o > 1440

  } //for rele

}
//-------------------------------------------------------------------------------------------------------------------
// Se puede pedir desde el programa de monitoreo que se ejecute el programa que haya para los reles
// Se ejecuta de manera secuancial lo que haya en g_reles[]
//------------------------------------------------------------------------------------------------------------------
boolean vdl_arduino_ejecutar(boolean ejecutar_sn)
{
if(g_reles[g_ejecutar_rele].r_tiempo != 0)
  {
  if(!g_reles[g_ejecutar_rele].activado_sn) 
    {
    g_reles[g_ejecutar_rele].activado_sn = true;
    g_ejecutar_minuto_inicio = g_minuto_dia;
    vdl_arduino_on_off_rele(g_ejecutar_rele,true);
    vdl_arduino_grabar_log_reles(g_ejecutar_rele,false); //log NO manual. 
    } //if no se ha activado
  //Y si ya ha pasado su tiempo se para y se sigue a por el siguiente
  if(g_minuto_dia >= (g_ejecutar_minuto_inicio+g_reles[g_ejecutar_rele].r_tiempo)) 
    {
    vdl_arduino_on_off_rele(g_ejecutar_rele,false);
    g_reles[g_ejecutar_rele].activado_sn = false;
    g_reles[g_ejecutar_rele].ultima_regada = g_hoy; 
    
    g_ejecutar_minuto_inicio = 1441; //sino hay nada impedirá la ejecución
    g_ejecutar_rele++;
    if(g_ejecutar_rele > 7) ejecutar_sn = false;
    } //if tiempo ytranscurrido
  
  } //si hay definido tiempo que activar
else {
     g_ejecutar_rele++;
     if(g_ejecutar_rele > 7) ejecutar_sn = false;
     }

return ejecutar_sn; //y asi se ponme a false la global
}
//-------------------------------------------------------------------------------------------------------------------
// controla el pin de la lluvia y graba un log cuando se activa y cuado se desactiva
//------------------------------------------------------------------------------------------------------------------
void vdl_arduino_control_lluvia()
{
int rele;

//El detector es normalmente abierto. O sea, esta en alto si NO esta conectado (pero le he cambiado la logica y lo dejo abajo)
if(g_activada_sn[g_pin_lluvia]) 
  {
  if(g_hoy != g_lluvia_ultima) 
    {
    g_lluvia_ultima = g_hoy;
    //si esta activo y hoy todavia no se ha activado se pone el dia de los reles a hoy
    //asi no regara si le toca y se retrasa el proceso del regado en tantos dias como sea necesario
    for(rele=0;rele < 8;rele++) 
       {
       g_reles[rele].ultima_regada = g_hoy; 
       } //for
    } //si hoy != g_lluvia_ultima
  if(!g_lluvia_grabada) 
    {
    vdl_arduino_grabar_log_reles(9,true);
    g_lluvia_grabada = true;
    }
  } //if activada_sn[]
else {

     if(g_lluvia_grabada) 
       {
       vdl_arduino_grabar_log_reles(9,false);
       g_lluvia_grabada = false;
       }
     
     }
}
//---------------------------------------------------------------------
// actua en función de la cadena recibida por el serie
// si recibe una orden de activar una salida o un rele devuelve el nº
// de lo que hay que activar: 0-14 salidas 100-108 reles
//---------------------------------------------------------------------
void vdl_arduino_mensaje_recibido()
{

if(g_s_inicio_sn && g_s_fin_sn) 
  {
  
  //vdl_arduino_on_off_digital(12,true); 
  
  switch(g_s_cadena_in.charAt(0))
        {
        
        case 'M': { //arranca el monitoreo
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  g_monitorizar_sn = true; 
                  } break;
        
        case 'N': { //detiene el monitoreo
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  g_monitorizar_sn = false; 
                  } break;
                  
        case 'H': { //pone la fecha y hora
                  char lit_int[3];
                  int desp,dia,mes,anno,hora,minuto,segundo,dia_semana;  

                  dia=mes=anno=hora=minuto=segundo=dia_semana=0;  

                  for(desp=0;desp < 6;desp++) 
                     {
                     lit_int[0] = g_s_cadena_in.charAt( (desp*2)+1 );
                     lit_int[1] = g_s_cadena_in.charAt( (desp*2)+2 );
                     lit_int[2] = 0x00;

                     switch(desp) 
                           {
                           case 0: dia = atoi(lit_int); break;
                           case 1: mes = atoi(lit_int); break;
                           case 2: anno = atoi(lit_int)+2000; break;
                           case 3: hora = atoi(lit_int); break;
                           case 4: minuto = atoi(lit_int); break;
                           case 5: segundo = atoi(lit_int); break;
                           } //sw

                     } //for desp
                  lit_int[0] = g_s_cadena_in.charAt(13);
                  lit_int[1] = 0x00;
                  lit_int[2] = 0x00;
                  dia_semana = atoi(lit_int);
       
                  clock.fillByYMD(anno,mes,dia);
                  clock.fillByHMS(hora,minuto,segundo);
    
                  switch(dia_semana) 
                        {
                        case 1: clock.fillDayOfWeek(MON); break;
                        case 2: clock.fillDayOfWeek(TUE); break;
                        case 3: clock.fillDayOfWeek(WED); break;
                        case 4: clock.fillDayOfWeek(THU); break;
                        case 5: clock.fillDayOfWeek(FRI); break;
                        case 6: clock.fillDayOfWeek(SAT); break;
                        case 7: clock.fillDayOfWeek(SUN); break;
                        }

                  clock.setTime();
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;
                  
        case 'R': { //La programacion de cada relé
                  char lit[4];
                  int rele,hh,mm;//,tiempo;

                  lit[0] = g_s_cadena_in.charAt(1); 
                  lit[1] = g_s_cadena_in.charAt(2); 
                  lit[2] = 0x00;
                  rele = atoi(lit);

                  lit[0] = g_s_cadena_in.charAt(3); 
                  lit[1] = g_s_cadena_in.charAt(4); 
                  lit[2] = 0x00;
                  hh = atoi(lit);

                  lit[0] = g_s_cadena_in.charAt(6); 
                  lit[1] = g_s_cadena_in.charAt(7); 
                  lit[2] = 0x00;
                  mm = atoi(lit);

                  g_reles[rele].hora_inicio = (hh*60)+mm;

                  lit[0] = g_s_cadena_in.charAt(8); 
                  lit[1] = g_s_cadena_in.charAt(9);
                  lit[2] = g_s_cadena_in.charAt(10);  
                  lit[3] = 0x00;
                  g_reles[rele].r_tiempo = atoi(lit);

                  lit[0] = g_s_cadena_in.charAt(11); 
                  lit[1] = 0x00;
                  g_reles[rele].opcion = atoi(lit);

                  //g_reles[rele].ultima_regada = 0;
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;
        case 'G': { //graba el fichero reles.cf con lo que se ha enviado desde el PC
                  vdl_arduino_grabar_programacion_reles();
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;
        
        case 'C': {//Si pide la configuracion se le envia la config y el estado de cada I/O
                  // OJO! Antes de pedir la config es prudent parar el monitoreo sino puede fallar
                  int desp;
                  
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  //delay(300); 
                  delay(100); 
                  
                  //primero se lee del SD y así de paso se renueva por si acaso se ha modificado a mano
                  vdl_arduino_leer_programacion_reles();
    
                  Serial.flush();
                  Serial.print("{X");
                  for(desp=0;desp < 8;desp++) 
                     {
                     //Serial.write(desp);
                     Serial.write(highByte(g_reles[desp].hora_inicio));
                     Serial.write(lowByte(g_reles[desp].hora_inicio));
                     Serial.write(highByte(g_reles[desp].r_tiempo));
                     Serial.write(lowByte(g_reles[desp].r_tiempo));
                     Serial.write(g_reles[desp].opcion);
                     }
                  Serial.println("}");
                  } break;
        
        case 'L': { //Se envia lo que se lea en el fichero del log
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  delay(100);
                  
                  vdl_arduino_transmitir_log_reles();
                  
                  } break;          
        case 'D': { //graba el fichero reles.cf con lo que se ha enviado desde el PC
                  vdl_arduino_borrar_log_reles();
                  
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;
                  
        case 'A': {//activa o desactiva una salida concreta o rele o e/s digital
                  char lit[4];//001-013 salidas 101-108 reles 
                  int activar = 0;
    
                  lit[0] = g_s_cadena_in.charAt(1); 
                  lit[1] = g_s_cadena_in.charAt(2); 
                  lit[2] = g_s_cadena_in.charAt(3); 
                  lit[3] = 0x00;
                  activar = atoi(lit);
    
                  if(activar > 0) 
                    {
                    if(activar >= 100 && activar < 109) 
                      {
                      vdl_arduino_on_off_rele(activar-100,true); //100 en todos //activar reles
                      vdl_arduino_grabar_log_reles(activar-100,true); //log manual
                      }
                    if(activar >= 600 && activar < 609) vdl_arduino_on_off_rele(activar-600,false);//desactivar reles
                    if(activar >= 1 && activar < 14) vdl_arduino_on_off_digital(activar,true);//activar E/S digital
                    if(activar >= 501 && activar < 514) vdl_arduino_on_off_digital(activar-500,false);//desactivar E/S digital
                    }
                  
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;
        case 'E': { //ejecutar el programa de los reles
                  g_ejecutar_sn = true;
                  g_ejecutar_rele = 0;
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;
        case 'Q': { //Se poen a cero las cecha de ultima regada
                  int rele;
                  
                  for(rele=0;rele < 8;rele++) g_reles[rele].ultima_regada = 0;
                  Serial.flush();
                  Serial.println("{#}"); //qsl
                  } break;          
                  
        } //fin sw
  
  g_s_cadena_in = "";
  g_s_inicio_sn = false;
  g_s_fin_sn = false;
  //vdl_arduino_on_off_digital(12,false); //Apago el 12 
  } //si inicio y fin
}
//---------------------------------------------------------------------
// El main de esto
//---------------------------------------------------------------------
void loop()
{
//g_monitorizar_sn = false;

//PENDIENTE: Cambiar el parpadeo con la función milis (o una interrupcion), de manera que se quite el delay del encencido 
//del pin. Se hace una función parapeo(pin) y ya. 
//Se quita el monitoreo del pin de parpadeo del PC para evitar que esté siempre encendido y en su lugar se pone
//un pulsador que sirva de test. Así si que quiere compobar la comuncación serie, se pulsa el pulsador y se vé si va o no
//Así nos ahorraremos milisegundos (incluso es posible quitar todos los delays del loop
vdl_arduino_on_off_digital(4,true); 
delay(100); //100 milisegundos que tarde desde que se enciende hasta que envia el mensaje al PC 
  
//Se envia el monitoreo. Se hace en dos puntos, al activar el 13 y al desactivarlo, por que si no no se entra de la desactivacion
//ademas as se pueden monitorear los cambios que se producen en el programa.
//Si se quita el parpadeo solo se monitoreara el final del loop() y este habra  que quitar
if(g_monitorizar_sn) vdl_arduino_monitoreo();

vdl_arduino_reloj_minuto_dia_hoy(); //actualizar el minuto de dia (g_minuto_dia) y el nº de dias (g_hoy)

vdl_arduino_lectura_entradas_digitales(); //Si hay un pin digital arriba (y es in) se registra en su variable 

//Los reles se programan por hora a la que empezar, tiempo que debe estar actuando y dias transcurridos desde la ultima activacion
if(!g_ejecutar_sn) vdl_arduino_programa_reles(); //si se ha pedido una ejecucion se pasa del programa

//Si se pide una ejecución desde el programa de monitoreo
if(g_ejecutar_sn) g_ejecutar_sn = vdl_arduino_ejecutar(g_ejecutar_sn);

//Se controla si llueve y se grabar un log si es que si
vdl_arduino_control_lluvia();
  
 
vdl_arduino_on_off_digital(4,false); //Apago el 13 Se acabo la secuencia
delay(100); //segun la demora puede que la pantalla no sea capaz de ir tan rapido
if(g_monitorizar_sn) vdl_arduino_monitoreo();
} // end loop
//------------------------------------------------------------------------
// Este evento ocurre cuando entran nuevos datos al serie.
// Esta funcion corre entre cada vez que el loop se ejecuta, asi que mucho 
// ojo con meter delays aqui por que ralentizara todo el proceso
// Esta funcion es como el loop propiedad del arduino no hay que ponerle otro nombre
//------------------------------------------------------------------------
void serialEvent() 
{

while(Serial.available()) 
     {
     char in_car = (char)Serial.read(); 
     
     //Serial.print(in_car);
     
     if(in_car == '{') g_s_inicio_sn = true;
     else {
          if(in_car == '}') g_s_fin_sn = true;         
          else {
               //ignoro los finales de mensaje estandar
               if(in_car != 0x0d && in_car != 0x0a) g_s_cadena_in += in_car;     
               }
          }  
     
     } //while

//Serial.println(g_s_cadena_in);
vdl_arduino_mensaje_recibido(); //miro si hay mensajes en el serie

} //end serialEvent