///////////////////////////////////////////////////////////
// //
// PROYECTO ARDUINO ANTONIO RIVEROLA //
// //
///////////////////////////////////////////////////////////
// Librerías
#include <Wire.h> //Libreria de comunicacion I2C
#include <LiquidCrystal_I2C.h> //Libreria para LCD
#include <OneWire.h> //Temperatura
#include <DallasTemperature.h> //Temperatura
#include <Ultrasonic.h> //Sensor distancia ultrasonido
#include <Keypad.h> //Teclado matricial 4x3
///////////////////////////////////////////////////////////
// Definimos las constantes: //
///////////////////////////////////////////////////////////
//Definimos los PINS
#define TEMP 2
#define LUZSUMP 3
#define PIN_D_NIVEL_SUMP 7
#define PIN_D_NIVEL_MAX 8
//Ultrasonido pin 9
//Ultrasonido pin 10
#define NIVEL_SUMP_MAX 13
#define CALENTADOR 22
#define VENTILADOR 24
#define RELE_PERISTALTICAS 26
#define BOMBAS_MOVIM 28
#define SKIMMER 30
#define BOMBA_SUBIDA 32
#define BOMBA_RELLENO_SUMP 34
#define BOMBA_RELLENO 36
#define ONE_WIRE_BUS 2 //temperatura, pin de entrada
#define Reloj 0x68 // Reloj
int pin_peristaltica1 = 14;//PERISTALTICA 1
int pin_peristaltica2 = 15;//PERISTALTICA 2
int pin_peristaltica3 = 16;//PERISTALTICA 3
LiquidCrystal_I2C lcd(0x27,20,4); //Selecciona la dirección 0x27 para el LCD con 4 lineas
//y 20 caracteres
Ultrasonic ultrasonico(9,10); //Declaramos el sensor ultrasonico en los Pines Digitales elegidos
OneWire oneWire(ONE_WIRE_BUS); //temperatura
DallasTemperature sensors(&oneWire); //temperatura
///////////////////////////////////////////////////////////
// Variables del programa //
///////////////////////////////////////////////////////////
char* reef = " RIVEROLA REEF"; //Selecciona el nombre/version del programa
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
int Retraso=5000;
//Definimos las constantes del teclado matricial
const byte ROWS = 4; //cuatro filas
const byte COLS = 3; // tres columnas
// Matriz
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'#','0','*'}
};
//Conexiones ROW0, ROW1, ROW2 and ROW3 y COL0, COL1 y COL2 en los pienes
byte rowPins[ROWS] = {37, 39, 41, 43}; //conexiones de 4 filas del keypad
byte colPins[COLS] = {45, 47, 49}; //conexiones de 3 columnas del keypad
// Creamos el Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
///////////////////////////////////////////////////////////
//Realizamos el setup de todos los componentes //
///////////////////////////////////////////////////////////
void setup()
{
sensors.begin();
Wire.begin();
Serial.begin(9600);
lcd.init(); //Inicia el LCD
lcd.backlight(); //Activa iluminacion LCD
// Pines de entrada digitales
pinMode (PIN_D_NIVEL_SUMP, INPUT); //Sonda nivel relleno sump
pinMode (PIN_D_NIVEL_MAX, INPUT); //Sonda nivel relleno sump, nivel maximo
//Pines de salida del rele
pinMode(NIVEL_SUMP_MAX , OUTPUT); //Indica nivel alto en el sump
pinMode(LUZSUMP , OUTPUT); //Luz Sump
pinMode(CALENTADOR, OUTPUT); //Calentador
pinMode(VENTILADOR, OUTPUT); //Ventilador
pinMode(RELE_PERISTALTICAS, OUTPUT);//Rele del trasnformador de 12V para Peristalticas
//y luz sump
pinMode(BOMBAS_MOVIM, OUTPUT); //Bombas movimiento Urna
pinMode(SKIMMER, OUTPUT); //Bombas del skimmer
pinMode(BOMBA_SUBIDA, OUTPUT); //Bomba subida
pinMode(BOMBA_RELLENO_SUMP, OUTPUT); //Bomba de relleno al sump
pinMode(BOMBA_RELLENO, OUTPUT); //Bomba emergencia por si se queda vacio el deposito
//de relleno (solo vacaciones)
//Pines de salida Peristalticas
pinMode(pin_peristaltica1, OUTPUT);
pinMode(pin_peristaltica2, OUTPUT);
pinMode(pin_peristaltica3, OUTPUT);
if (minute < 2) Retraso=1000;
else if (hour < 5) Retraso=10000;
else Retraso=3000;
//No entiendo como funciona este punto
/* byte n;
for(n=31; n < 46; n = n + 2)
{
digitalWrite( n, HIGH);
} */
//Las bombas y skimmner tienen que estar activados
digitalWrite(BOMBAS_MOVIM ,HIGH);
digitalWrite(SKIMMER,HIGH);
digitalWrite(BOMBA_SUBIDA,HIGH);
/*
// la primera vez debemos poner en hora, activa esta parte y luego vuelve a quitarla
second = 50;
minute = 51;
hour = 19;
dayOfWeek = 4;
dayOfMonth = 11;
month = 7;
year = 13;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
*/
}
///////////////////////////////////////////////////////
// //
// Entramos en el bucle del codigo principal //
// //
///////////////////////////////////////////////////////
void loop()
{
infolcd(); //Envía la información a la pantalla LCD
getDateDs1307
(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //Obtenemos la hora
sensors.requestTemperatures(); //Activa los sensores de temperatura
Temperatura(); //Control de la temperatura
MirarNiveles(minute, hour); //Niveles del sump
Relleno(); //Nivel del deposito de relleno
Peristalticas(second, minute, hour); //Puesta en marcha peristalticas en segundos
Menu(); //Menu
}
/////////////////
// FUNCIONES //
/////////////////
// Convierte números normales decimales a BCD (binario decimal codificado)
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convierte BCD (binario decimal codificado) a números normales decimales
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(Reloj);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(Reloj);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(Reloj, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
//Dibujamos la pantalla fecha y temperaturas
void infolcd(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print(reef);
lcd.setCursor(0,1);
lcd.print(" ");
if (hour<10)
{
lcd.print("0");
lcd.print(hour,DEC);
}
else
{
lcd.print(hour, DEC);
}
lcd.print(":");
if (minute<10)
{
lcd.print("0");
lcd.print(minute,DEC);
}
else
{
lcd.print(minute, DEC);
}
// Esto pone nombre del dia
lcd.print(" ");
switch (dayOfWeek)
{
case 1:
lcd.print(" Lunes");
break;
case 2:
lcd.print(" Martes");
break;
case 3:
lcd.print("Miercoles");
break;
case 4:
lcd.print(" Jueves");
break;
case 5:
lcd.print(" Viernes");
break;
case 6:
lcd.print(" Sabado");
break;
case 7:
lcd.print(" Domingo");
break;
}
lcd.print(" ");
lcd.setCursor(0,2);
lcd.print(" FECHA: ");
if (dayOfMonth < 10) lcd.print("0");
lcd.print(dayOfMonth, DEC);
lcd.print("/");
if (month < 10) lcd.print("0");
lcd.print(month, DEC);
lcd.print("/");
lcd.print("20");
if (year < 10) lcd.print("0");
lcd.print(year, DEC);
lcd.print(" ");
// TEMPERATURAS
lcd.setCursor(0,3);
lcd.print("T1:");
lcd.print(sensors.getTempCByIndex(0)); //Index 0 , es el primer sensor
lcd.print("\337");
lcd.print(" T2:");
lcd.print(sensors.getTempCByIndex(1)); //Index 1 , es el segundo sensor
lcd.print("\337");
p(); // Pausa 3 segundos
}
// Pausa 3 segundos:
void p ()
{
delay (3000);
}
//////////////////////////////////////////////////////////////
// FUNCION MENU //
//////////////////////////////////////////////////////////////
void Menu ()
{
float t0 = 0;
sensors.requestTemperatures();
t0 = sensors.getTempCByIndex(0);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(reef);
lcd.setCursor(0,1);
lcd.print(" ");
if (hour<10)
{
lcd.print("0");
lcd.print(hour,DEC);
}
else
{
lcd.print(hour, DEC);
}
lcd.print(":");
if (minute<10)
{
lcd.print("0");
lcd.print(minute,DEC);
}
else
{
lcd.print(minute, DEC);
}
// Esto pone nombre del dia
lcd.print(" ");
switch (dayOfWeek)
{
case 1:
lcd.print(" Lunes");
break;
case 2:
lcd.print(" Martes");
break;
case 3:
lcd.print("Miercoles");
break;
case 4:
lcd.print(" Jueves");
break;
case 5:
lcd.print(" Viernes");
break;
case 6:
lcd.print(" Sabado");
break;
case 7:
lcd.print(" Domingo");
break;
}
//Teclado matricial 4x3
char key = kpd.getKey();
if(key) // Check for a valid key.
{
switch (key)
{
case '1': // Comida: Paramos bombas de movimiento y de subida
lcd.setCursor(0,2);
lcd.print("PARO PARA DAR COMIDA");
digitalWrite(BOMBAS_MOVIM, LOW);
digitalWrite(BOMBA_SUBIDA, LOW);
delay (600000);
digitalWrite(BOMBAS_MOVIM, HIGH);
digitalWrite(BOMBA_SUBIDA, HIGH);
break;
case '2': //Limpieza skimmer
lcd.setCursor(0,2);
lcd.print("PARO LIMPIAR SKIMMER");
digitalWrite(SKIMMER, LOW);
delay (600000);
digitalWrite(SKIMMER, HIGH);
break;
case '3': //Cambio calcetin sump
lcd.setCursor(0,2);
lcd.print("PARO LIMPIAR BAJANTE");
digitalWrite(BOMBA_SUBIDA, LOW);
delay (600000);
digitalWrite(BOMBA_SUBIDA, HIGH);
break;
case '4': //Limpieza sump
lcd.setCursor(0,2);
lcd.print(" PARO LIMPIEZA SUMP ");
lcd.setCursor(0,3);
lcd.print(" PULSA 5 AL ACABAR ");
digitalWrite(BOMBA_SUBIDA, LOW);
digitalWrite(SKIMMER, LOW);
digitalWrite(CALENTADOR, LOW);
break;
case '5': //Restaurar sump
digitalWrite(BOMBA_SUBIDA, HIGH);
digitalWrite(SKIMMER, HIGH);
if(t0 < 24.70)
{
digitalWrite (CALENTADOR, HIGH);
}
if(t0 > 25.00)
{
digitalWrite (CALENTADOR, LOW);
}
break;
}
}
}
//////////////////////////////////////////////////////////////////
// //
// COMPRUEBA EL NIVEL DE AGUA DEL SUMP Y DEPOSITO DE RELLENO //
// //
//////////////////////////////////////////////////////////////////
void MirarNiveles(int minutos, int horas)
{
int InicioNiveles1 = 600; // 10:00
int FinalNiveles1 = 602; // 10:05
int InicioNiveles2 = 1200; // 20:00
int FinalNiveles2 = 1202; // 20:05
int Tiempo;
Tiempo=(horas*60+minutos); lcd.clear();
lcd.setCursor(0,0);
lcd.print(reef);
if (digitalRead(PIN_D_NIVEL_MAX)==HIGH) // La bolla no esta activa, funcionamiento normal
{
digitalWrite(NIVEL_SUMP_MAX,LOW);
if (digitalRead(PIN_D_NIVEL_SUMP)==HIGH)
{
lcd.setCursor(0,1);
lcd.print(" SUMP BAJO ");
}
else
{
lcd.setCursor(0,1);
lcd.print(" SUMP OK ");
}
if (Tiempo >= InicioNiveles1 && Tiempo <= FinalNiveles1) //Damos la orden de encendido
//y apagado
if (digitalRead(PIN_D_NIVEL_SUMP)==HIGH) // La bolla esta activa y cierra las
//electrovalvulas
{
digitalWrite(BOMBA_RELLENO_SUMP,HIGH);
lcd.setCursor(0,1);
lcd.print(" SUMP BAJO ");
}
else
{
digitalWrite(BOMBA_RELLENO_SUMP,LOW);
lcd.setCursor(0,1);
lcd.print(" SUMP OK ");
}
if (Tiempo == FinalNiveles1)
digitalWrite(BOMBA_RELLENO_SUMP,LOW);
if (Tiempo >= InicioNiveles2 && Tiempo <= FinalNiveles2) //Damos la orden de encendido
//y apagado
if (digitalRead(PIN_D_NIVEL_SUMP)==HIGH) // La bolla esta activa y la bomba llena el sump
{
digitalWrite(BOMBA_RELLENO_SUMP,HIGH);
lcd.setCursor(0,1);
lcd.print(" SUMP BAJO ");
}
else // El sump esta lleno y cierra la bomba
{
digitalWrite(BOMBA_RELLENO_SUMP,LOW);
lcd.setCursor(0,1);
lcd.print(" SUMP OK ");
}
if (Tiempo == FinalNiveles2)
digitalWrite(BOMBA_RELLENO_SUMP,LOW);
}
else
{
digitalWrite(BOMBA_RELLENO_SUMP,LOW); //Sump demasiado lleno hay que programar la alarma
digitalWrite(NIVEL_SUMP_MAX,HIGH);
lcd.setCursor(0,1);
lcd.print(" ALARMA SUMP ");
}
}
// DEPOSITO DE RELLENO
//Medidas = 42*21*42, 0,88 litros/cm. Total = 37 litros
void Relleno()
{
int Nivel1 = 45; //Hay que ajustar los cm exactos del nivel cuando este puesto en su sitio
int Nivel2 = 15;
int CmAgua;
float Litros;
CmAgua=54-ultrasonico.Ranging(CM);
Litros=CmAgua*0.88;
lcd.setCursor(0,2);
lcd.print("RELLEN");
lcd.print(" ");
lcd.print(Litros); //Indica los litros que quedan en el deposito de relleno
lcd.print("L");
lcd.print(" ");
lcd.print((Litros/37)*100); //Indica el porcentaje del deposito de relleno, cuanto queda
lcd.print("% ");
//lcd.print(ultrasonico.Ranging(CM));
//lcd.print(" cm");
lcd.setCursor(0, 3); //Dibuja una barra de nivel con lo que queda del deposito
lcd.print("MIN "); //Con un minimo y un maximo
if (Litros > 3) lcd.print((char)255);
if (Litros > 6) lcd.print((char)255);
if (Litros > 9) lcd.print((char)255);
if (Litros > 12) lcd.print((char)255);
if (Litros > 15) lcd.print((char)255);
if (Litros > 18) lcd.print((char)255);
if (Litros > 21) lcd.print((char)255);
if (Litros > 24) lcd.print((char)255);
if (Litros > 27) lcd.print((char)255);
if (Litros > 30) lcd.print((char)255);
if (Litros > 33) lcd.print((char)255);
if (Litros > 36) lcd.print((char)255);
lcd.setCursor(17, 3);
lcd.print("MAX");
if (Nivel1 <= ultrasonico.Ranging(CM))// && Tiempo <= FinalNiveles1)
{
digitalWrite(BOMBA_RELLENO,HIGH);
lcd.setCursor(0,2);
lcd.print("RELLEN");
lcd.print(" ");
lcd.print(Litros);
lcd.print("L");
//lcd.print(ultrasonico.Ranging(CM));
//lcd.print(" cm");
}
if (Nivel2 >= ultrasonico.Ranging(CM))// && Tiempo <= FinalNiveles1)
{
digitalWrite(BOMBA_RELLENO,LOW);
lcd.setCursor(0,2);
lcd.print("RELLEN");
lcd.print(" ");
lcd.print(Litros);
lcd.print("L");
//lcd.print(ultrasonico.Ranging(CM));
//lcd.print(" cm");
}
p(); // Pausa 3 segundos
}
/////////////////////////////////////////////////////////
// PERISTALTICAS //
/////////////////////////////////////////////////////////
void Peristalticas(int segundos, int minutos, int horas)
[FONT=Lucida Sans Unicode]//El tiempo se establece en segundos para mayor precisión
//Aun hay que precisar el tiempo necesario para cada peristaltica[/FONT]
{
int InicioPeristaltica1=72000; //72000 = 20:00
int FinPeristaltica1=72060; //72060 = 20:01
int InicioPeristaltica2=72300; //72300 = 20:05
int FinPeristaltica2=72360; //72360 = 20:06
int InicioPeristaltica3=72600; //72600 = 20:10
int FinPeristaltica3=72660; //72660 = 20:11
int Tiempo;
Tiempo=((horas*3600)+(minutos*60)+segundos);
digitalWrite(RELE_PERISTALTICAS, LOW); //PERISTALTICA 1
if (Tiempo >= InicioPeristaltica1 && Tiempo <= FinPeristaltica1)//Damos la orden de encendido
//y apagado
{
digitalWrite(RELE_PERISTALTICAS, HIGH);
digitalWrite(pin_peristaltica1, HIGH);
}
else
{
digitalWrite(pin_peristaltica1, LOW);
digitalWrite(RELE_PERISTALTICAS, LOW);
}
//PERISTALTICA 2
if (Tiempo >= InicioPeristaltica2 && Tiempo <= FinPeristaltica2) //Damos la orden de
//encendido y apagado
{
digitalWrite(RELE_PERISTALTICAS, HIGH);
digitalWrite(pin_peristaltica2, HIGH);
}
else
{
digitalWrite(RELE_PERISTALTICAS, LOW);
digitalWrite(pin_peristaltica2, LOW);
}
//PERISTALTICA 3
if (Tiempo >= InicioPeristaltica3 && Tiempo <= FinPeristaltica3) //Damos la orden de
//encendido y apagado
{
digitalWrite(RELE_PERISTALTICAS, HIGH);
digitalWrite(pin_peristaltica3, HIGH);
}
else
{
digitalWrite(RELE_PERISTALTICAS, LOW);
digitalWrite(pin_peristaltica3, LOW);
}
}
////////////////////////////////////////////////////////////
// CONTROL TEMPERATURAS //
////////////////////////////////////////////////////////////
void Temperatura()
{
float t0 = 0;
float t1 = 0;
sensors.requestTemperatures();
t0 = sensors.getTempCByIndex(0);
t1 = sensors.getTempCByIndex(1);
//Configuracion de la temperatura
if(t0 < 24.70)
{
digitalWrite (CALENTADOR, HIGH);
}
if(t0 > 25.00)
{
digitalWrite (CALENTADOR, LOW);
}
if(t0 > 25.40)
{
digitalWrite (VENTILADOR, HIGH);
}
if(t0 < 25.10)
{
digitalWrite (VENTILADOR, LOW);
}
}