SlideShare une entreprise Scribd logo
1  sur  68
Diseño Controlador Acuario con Arduino
Un controlador de acuario, donde se irán agregando partes del código hasta completarlo,
constara menú para modificar parámetros luz, Hora, fecha, etc. El LCD para visualizar
información, sensor de temperatura y relés. La idea es tener una base y que cualquiera
pueda realizar su controlador y porque no ampliarlo.
Materiales:
Arduino Puede ser Nano, Uno o Mega
Reloj DS3231
Lcd 20x4 con I2C
Sensor temperatura DS18B20
Encoder rotatorio con pulsador
Resistencia 4,7k - 1/4w =1
Resistencia 1k - 1/4w =4
Led Blanco, Rojo, Azul
Fuente de poder 9v
Reles Arduino 5v 2 canales
Transistor 2N2222
Protoboard
Cables conexión
Diagrama esquemático:
Desarrollo
Procedimiento con el código:
Hola voy a hacer mi aporte:
En esta parte del código:
void loop() {
unsigned long currentMillis = millis();
button.tick();
LeeEncoder(0, 7, 1, 1); // Lee el enconder de 0 a 7, de a 1 paso y con
tope final.
if (currentMillis % 6000 < 5) { // Si el resto de dividir
currentMillis por 6000 da menos que 5...
ImprimeFecha();
ImprimeHora();
ImprimeTemp();
}
}
Se va a cumplir cuando sea por ejemplo 6000, 6001, 6002, 6003, 6004 y en el "mejor de
los casos" pero en el transcurso se cumple y se va a actualizar como 20 veces aquí un
ejemplo de lo que digo:
Ahora así como muestra por serial va actualizar en la pantalla para lo cual presentó algo
que puede ser mejor tendrías que añadir las siguientes líneas y borra en el que tú tienes,
espero se entienda.
#define tiempoPresentarDatos 6000UL // Tiempo al que se quiera realizar
las acciones ejemplo 6s (1000ms = 1s)
unsigned long tiempoActualDatos = 0;
void loop() {
if (millis() - tiempoActualDatos >= tiempoPresentarDatos) { // Si el
tiempo actual menos el tiempo anterior es mayor o igual a 6 segundos
tiempoActualDatos = millis(); // Actualiza el tiempo Actual
//Resto del código que quieras que se cumpla cada 6 segundos
}
}
Ahora también por ejemplo en esta parte utilizas una función y en el cual en una condición
la utilizas para para comprobar si tiene tope o no.
void LeeEncoder(int ROTARYMIN, int ROTARYMAX, int ROTARYSTEPS, int
ROTARYTOPE)
{
encoder.tick(); // Lee el encoder y actualiza el puntero. La librería
lleva la cuenta desde 0.
newPos = encoder.getPosition() * ROTARYSTEPS; // Asigna a newPos el
puntero del encoder multiplicado por los pasos.
if (ROTARYTOPE == 1) { // Si el rotor tiene tope entonces no se pasa
de valor
if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor
Mínimo ->
encoder.setPosition(ROTARYMIN / ROTARYSTEPS); // Se fija el
puntero al valor mínimo por los pasos
newPos = ROTARYMIN;
}
if (newPos > ROTARYMAX) { // Solo si el puntero es mayor a Valor
Máximo ->
encoder.setPosition(ROTARYMAX / ROTARYSTEPS); // Se fija el
puntero al valor mínimo por los pasos
newPos = ROTARYMAX;
}
}
if (ROTARYTOPE == 0) { // Si el rotor SI tiene tope entonces se pasa
del valor máximo al mínimo y viceversa.
if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor
Mínimo ->
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX; // Entonces el puntero saltará del mínimo al
máximo
}
if (newPos > ROTARYMAX) { // Solo si el puntero es mayor al Valor
Máximo ->
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN; // Entonces el puntero saltará del máximo
al mínimo.
}
}
}
Lo que veo un poco innecesario ya que ese no va a cambiar en el transcurso del
funcionamiento si no solo cuando se configura por lo que creo que se podría utilizar de esta
forma como ejemplo
#define encoderTope 1
void loop() {
#if encoderTope == 1
if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor Mínimo
->
encoder.setPosition(ROTARYMIN / ROTARYSTEPS); // Se fija el puntero al
valor mínimo por los pasos
newPos = ROTARYMIN;
}
if (newPos > ROTARYMAX) // Solo si el puntero es mayor a Valor Máximo->
encoder.setPosition(ROTARYMAX / ROTARYSTEPS); // Se fija el puntero al
valor mínimo por los pasos
newPos = ROTARYMAX;
}
#else
if (newPos < ROTARYMIN) { //Solo si el puntero es menor a Valor Mínimo->
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX; // Entonces el puntero saltará del mínimo al máximo
}
if (newPos > ROTARYMAX) {//Solo si el puntero es mayor al Valor Máximo->
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN; // Entonces el puntero saltará del máximo
al mínimo.
}
#endif
}
Ok, funcionando
Aquí en este código muestra con la configuración de RTC de FECHA-HORAS
usando con la librería
void ImprimeFecha() {
DateTime now = rtc.now(); // Consulta al RTC
lcd.setCursor(0,0); // Fija el cursor en la primera línea
lcd.print(DiaDeSemana[now.dayOfTheWeek()]); // Imprime el día de la
semana
lcd.setCursor(10,0);
printDigits(now.day(), DEC); // Imprime el día
lcd.print('/'); // Separador
printDigits(now.month(), DEC); // Imprime el mes
lcd.print('/'); // Separador
lcd.print(now.year(), DEC); // Imprime el año
}
void ImprimeHora() {
DateTime now = rtc.now(); // Consulta el RTC
lcd.setCursor(13,1); // Fija cursor en 13,1
lcd.write(1); // Imprime el gráfico
lcd.print(':');
printDigits(now.hour()); // Imprime hora
lcd.print(':');
printDigits(now.minute()); // Imprime minuto
MinActual = now.hour()*60+now.minute(); // Se actualiza la variable
MinActual que será usada para encender y apagar las luces del acuario. Su
valor va de 0 a 1439.
}
Otra forma que evita el problema de los días/meses/horas/minutos de 1 dígitos es esta.
void ImprimeFecha() {
char buffer[20];
DateTime now = rtc.now(); // Consulta al RTC
lcd.setCursor(0,0); // Fija el cursor en la primera línea
lcd.print(DiaDeSemana[now.dayOfTheWeek()]); // Imprime el día de la
semana
lcd.setCursor(10,0);
sprintf(buffer,"%02d/%02d/%04d", now.day(), now.month(), now.year());
lcd.print(buffer);
}
void ImprimeHora() {
char buffer[20];
DateTime now = rtc.now(); // Consulta el RTC
lcd.setCursor(13,1); // Fija cursor en 13,1
lcd.write(1); // Imprime el gráfico
sprintf(buffer,"%02d:%02d:%02d", now.hout(), now.minute(),
now.second());
lcd.print(buffer);
MinActual = now.hour()*60+now.minute(); // Se actualiza la variable
MinActual que será usada para encender y apagar las luces del acuario. Su
valor va de 0 a 1439.
}
Pruebas con sensor temperatura DS18B20
La actualización de la información de corte de un cable demora aproximadamente 20seg
al desconectar cable rojo muestra información diferente no el de falla
La actualización de la información de temperatura demora aprox. 50 seg ver forma de bajar
tiempo.
Prueba de temperatura de RTC3231
Se toma temperatura ambiente y luego se acerca un cautín.
La actualización de temperatura con demora
El calefactor tiene que estar siempre encendido y trabajar así, si lo seteo a 25 grados se
mantiene si sube se apaga si baja se enciende puede haber una variación de un grado, no
entiendo porque en el día una temperatura, horas que esta encendido, noche otra
temperatura, la idea es tener una temperatura pareja y que no por un cambio de
temperatura los peces se enfermen
Esta es la configuración para prueba donde el calefactor en este horario estará a 25° y el
relé no se activa
Esta es la pantalla principal con la temperatura actual
Estamos realizado la prueba y al conectar la señal del relé a negativo se activa, en ningún
momento se activó ni con 9° ni con 60° que llego en un momento.
es lo mismo que tengo, la única forma que se activa el relé es si no dejo activa esta línea
digitalWrite en el void setup pero no se desactiva el calefactor al pasar de los 26 o 35 o
65°
void setup() {
pinMode(SFetAzul, OUTPUT);
pinMode(SFetRojo, OUTPUT);
pinMode(SFetBlanco, OUTPUT);
pinMode(Relay1, OUTPUT);
// digitalWrite(Relay1, HIGH); // Subimos el pin a HIGH porque el relay
se dispara con LOW
pinMode(Relay2, OUTPUT);
// digitalWrite(Relay2, HIGH); // Subimos el pin a HIGH porque el relay
se dispara con LOW
Pruebas memoria:
Se carga programa para blanquear la memoria luego se carga archivo CADUSA y se
chequean valores guardados en calefactor por defecto correspondiendo a estos día 24°
hora 09:00 a 21:40 noche 20°
en el caso del CO2 datos aparecen como en la imagen no siendo legibles y no activando
relé
Se carga programa para blanquear la memoria luego se carga archivo CADUSA y se
chequean valores
En calefactor valores por defecto correspondiendo a estos día 24° hora 09:00 a 21:40 noche
20°.
En el caso del CO2 valores por defecto hora 09:00 a 21:40. En ambos casos se visualiza
correctamente al resetear y cortar la energía al modificar valor CO2 o Calefactor estos se
guardan sin perderse Todo OK.
CADUSA2 en prueba
Se limpia la eeprom se carga CADUSA2
pantalla inicio OK
pantalla información hora. Fecha, temperaturas OK
menús: calefactor valores por defecto aparecen, funciona relé al activar ON OK
fecha y hora Ok
control CO2 se agrega read_but(); en líneas 482, 513, 531, 548, 566, al faltar solo
mostraba ON OFF y no entrega información en pantalla de valores por defecto, al
seleccionar ON u OFF aparece leyenda Hecho y sale del menú.
Al borrar un símbolo! línea 476
if (!Co2Var.Status == 0)
aparece información por defecto y se activa rele
en cada prueba se limpio eeprom
se adjunta archivo con agregado de lineas faltantes y en estado original linea 476 para
análisis
Ya que estamos mostrado este era mi acuario de agua dulce de 170 cm de largo luego
cambie al actual marino
Actual en proceso
Se limpia la eeprom se carga CADUSA2
pantalla inicio OK
pantalla información hora. Fecha, temperaturas OK
menús:
Reloj y fecha OK
calefactor valores por defecto aparecen, relé se activa después de 1 minutos OK
control CO2 entrega información en pantalla de valores por defecto, al seleccionar ON
activa relé después de 1 minuto.
se mantiene la configuración puesta por usuario al resetear y desconectar energía
Prueba de sobre calentamiento a 72° mensaje Alta temperatura en pantalla y se
reestablece bajo los 50°
en cada prueba se limpió eeprom
Lo otro hay posibilidad de agregar este control de temperatura en la parte del void
overheating(), que se accione con el termómetro del rtc como una acción antes que la
temperatura llegue al sobre calentamiento y mantener una temperatura y si falla pasaría al
modo sobre calentamiento.
El código a modificar para usar el sensor de temperatura del rtc.
#include <Wire.h>
#include <OneWire.h> //libreria temperatura
#include <DallasTemperature.h>
OneWire ourWire(12); // Se establece el pin D12 como bus
OneWire
DallasTemperature sensors(&ourWire); //Se declara una variable u objeto
para nuestro sensor
int PinVent = 5; //puerto digital D11 dodne
conectar el ventildor
int Temperatura; //variable calculo temperatura
int Restriccion_de_Temp; //Variable para mapear la
temperatura
int pwm; //Variable para generar pwm
void setup() {
sensors.begin();
pinMode(5,OUTPUT);
// Serial.begin(9600);
}
void loop() {
/////// Regulador Veloc Ventilador ////////////
sensors.requestTemperatures();
Temperatura = (sensors.getTempCByIndex(0));
Restriccion_de_Temp = constrain(Temperatura, 35, 45);
pwm = map(Restriccion_de_Temp, 35, 45, 0, 255);
analogWrite(PinVent,pwm);
// Serial.println(sensors.getTempCByIndex(0));
// Serial.println (pwm);
delay(1000);
}
Una idea para la iluminación del display has probado con una resistencia de 10K donde
está el jumper del lcd atenúa arto y es visible la información y no es molesto a la vista
y solo ver que se apague la pantalla cuando termine el periodo de luz y seencienda cuando
comience el periodo.
Se ve mejor en vivo que en la foto
Prueba de ventilador activándose a los 50° y desactivando a los 45 ...........OK
prueba de atenuación iluminación y activación iluminación LCD .................OK
en lo personal use resistencia de 10k
Con la resistencia de 10k ilumina justo para que se vea y como dices a gusto del lector y
se probó con un valor bajo y uno alto de resistencia.
Se ve muy genial, esa era la idea, al mover el encoder recobra la iluminación genial.
Lo único diferente indicador de dirección de menú ( > ) al cargar por primera vez, reiniciar
o apagar y prender no aparece asta mover el encoder en la dirección de la flecha.
OK, el cambio ( > ) funciona al cargar, reset y apagado y encendido
la (>) parte al cargar y al entrar a un menú y salir este no vuelve automáticamente
línea 1182 se borra 35; se deja rtc.getTemperatura
Prueba iluminación
se pone horario modo sol finalizando 19:23 se apaga iluminación y modo luna enciende a
las 19:25 según reloj
RTC, demora de 1:59 seg según cronometro en encender, no es inmediato el paso a luna
en modo mantenimiento se encienden solo luz azul y rojas solamente o las blancas igual,
solo se me encienden las azul y rojas
Consulta habría forma de poner en el LCD información del estado en que se está como:
Amanecer, Sol, Atardecer, Noche
Según horario programado
a (>) parte al cargar el programa pero al entrar a un menú y salir esta (>) no vuelve
automáticamente
- Transición a modo Luna
Si el horario sol finaliza a las 17:00 y luego dentro a menu luna y pongo que inicie a las
17:00 y finalice 18:00 salgo e ingreso nuevamente este cambia iniciando a las 17:01
provocando un lapso de casi 2 minutos con las luces apagadas y luego enciende luz azul,
la transición debiese ser continua sin espacio apagado
-----Creo que entendí el espacio sin luz es una transición a la salida de la luna
El termino lo tome de la misma pagina " En el lenguaje común, al orto se le denomina
amanecer, alba o aurora. En ocasiones se diferencia la aurora, que sería el primer
resplandor del cielo, del amanecer, que correspondería a la salida del sol"
mañana veré bien lo de las fases del día justo es este Alba, Luna y Ocaso me estan
dando problemas sino dejare los básicos Noche, Amanecer, Sol, Atardecer y Luna que
son los más significativos
Sigue igual, para que vuelva el signo se tiene que mover (girar) el encoder avanzar y
luego retroceder y aparece
Test faces del día
Noche OK
Amanecer OK
Sol OK
Atardecer OK,
se apagan las luces espera 2min y pasa a Sale luna
Ocaso No aparece
Sale luna OK
Luna OK
si es que modifique mi anterior circuito los 10v eran porque las fuentes MEANWELL
necesitan un voltaje de referencia y las recomendaban, no los uso se quedo hay .
los 8v alimento arduino.
los relés que tengo son de 5v hay los uso.
son Tip141 los tengo en uso en mi pantalla actual y son baratos en comparación al fet,
cuando vi precios no se en estos momentos.
voy a usar tu recomendación del transistor para el ventilador.
la fuente uso 5 de estas soportan hasta 18 led de 3w en serie, claro que estuve
revisando y parece que la descontinuaron.
Esta conversación sobre led es algo para largo algunos ven los watt otros los lumens
otros el par led y nunca están de acuerdo yo opte luego de leer mucho por watt y lumens
donde uso led con temp de color
blanco calido 6000-6500k
blanco frio 10000-15000k
azul 460-470nm
royal blue 445nm
uv 420-425nm
para un marino
esta es mi pantalla cuando la estaba armando hace un año placa de aluminio 5mm de
espesor algo gruesa y lentes de 90°
Dudas:
1- linea 235
es el tiempo de amanecer a sol, es de 30min la duracion definido en (+30)
2- en la linea 238
0,30,0,255 quiere decir que va a subir de 0min a 30min y la luz (pmw) iría
aumentando de 0 a 255 según lo programado claro
if (MinActual < (ModoSol.HoraInicio + 30)) { // Periodo Amanecer
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[1]);
brillo = map((MinActual - ModoSol.HoraInicio),0,30,0,255);
No olvidar para la atenuación de la pantalla después de un minuto una resistencia entre
1k a 10k
Diagrama de bloques
Diagrama de flujo
Código
#include <LiquidCrystal_I2C.h> // libreria para LCD por I2C
#include <EEPROM.h>
#include <RotaryEncoder.h>
#include <OneButton.h>
#include <RTClib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define enc_a A0
#define enc_b A1
#define enc_c A2
#define Relay1 7
#define Relay2 8
#define SFetAzul 9
#define SFetRojo 10
#define SFetBlanco 11
// Variables
volatile byte enc_but;
String Calendario[6] = {"A356o", "Mes", "Dia", "Hora", "Minuto",
"Segundo"};
String NombreMeses[13] = {" ","Enero", "Febrero", "Marzo", "Abril",
"Mayo", "Junio", "Julio", "Agosto",
"Septiembre", "Octubre", "Noviembre","Diciembre"};
String DiaDeSemana[7] = {"Domingo", "Lunes", "Martes", "Miercoles",
"Jueves", "Viernes", "Sabado"};
String Periodo_name[7] = {"Noche", "Amanecer", "Sol", "Atardecer", "Luna"
, "Sale luna", "Ocaso"};
unsigned long previousMillis = 0;
unsigned long backlightMillis = 0;
unsigned long currentMillis;
int lastPos = 1;
int newPos = 0;
int MinActual = 0;
byte brillo = 0;
byte spwm[5];
float Temp; // Sensor DS18B20 para el agua del acuario
float Tlamp; // Sensor interno del RTC para la temperatura del
plafón.
byte OverTemp = 65; // Límite superior de temeperatura para el
artefato
byte UnderTemp = 50; // Temperatura a la cual el artefacto retoma el
funcionamiento.
byte Mod_Menu = 0;
byte arrow_symbol[8] = {B00000, B00100, B01110, B11111, B00100,
B00100, B00100, B00100};
byte reloj_symbol[8] = {B00000, B01110, B10101, B10101, B10011,
B10001, B01110, B00000}; // Símbolo reloj
byte thermometer_symbol[8] = {B00100, B01010, B01010, B01110, B01110,
B11111, B11111, B01110}; // Símbolo termómetro
byte lamp_symbol[8] = {B00100, B10101, B01110, B11011, B01110,
B10101, B00100, B00000}; // Símbolo lámpara
struct MyTermo {
byte Status; // Estado 0 apagado y 1 encendido
byte TempHorario; // temepratura durante el rango de horas fijado
byte TempResto; // temperatura para el horario fuera del rango
int HoraInicio; // Hora inicio del rango
int HoraFin; // Hora fin del rango
};
MyTermo TermoVar;
struct MyCo2 {
byte Status; // Co2 On y Off,
int HoraInicio; // Hora inicio
int HoraFin; // Hora Fin
};
MyCo2 Co2Var;
struct MyModeSun { // Modo Sol
byte Azul; // Nivel salida rojo
byte Rojo; // Nivel salida azul
byte Blanco; // Nivel salida blanco
int HoraInicio; // Hora inicio del rango
int HoraFin; // Hora fin del rango
};
MyModeSun ModoSol;
struct MyModeMoon { // Modo Luna
byte Status; // Estado apagado o encendido del modo luna
byte Azul; // Nivel salida rojo
byte Rojo; // Nivel salida azul
byte Blanco; // Nivel salida blanco
int HoraInicio; // Hora inicio del rango
int HoraFin; // Hora fin del rango
};
MyModeMoon ModoLuna;
LiquidCrystal_I2C lcd (0x27, 20,4); // DIR, E, RW, RS, D4, D5, D6, D7
RTC_DS3231 rtc; // Se declara el reloj en tiempo real
OneButton button(A2, true); // Botón del encoder puesto a la librería
OneButton
RotaryEncoder encoder(A1, A0);
OneWire ourWire(12); //Se establece el pin 12 como bus
OneWire
DallasTemperature sensors(&ourWire); //Se declara una variable u objeto
para nuestro sensor
DeviceAddress outsideThermometer;
void setup() {
lcd.init();
pinMode(SFetAzul, OUTPUT);
pinMode(SFetRojo, OUTPUT);
pinMode(SFetBlanco, OUTPUT);
pinMode(Relay1, OUTPUT);
digitalWrite(Relay1, HIGH); // Subimos el pin a HIGH porque el relay se
dispara con LOW
pinMode(Relay2, OUTPUT);
digitalWrite(Relay2, HIGH); // Subimos el pin a HIGH porque el relay se
dispara con LOW
pinMode(enc_a, INPUT_PULLUP);
pinMode(enc_b, INPUT_PULLUP);
pinMode(enc_c, INPUT_PULLUP);
pinMode(13, OUTPUT); // Pin 13 para controlar el cooler
digitalWrite(13, LOW); // Iniciamos su estado en bajo.
button.attachClick(clickbutton);
button.setDebounceTicks(80);
lcd.backlight();
lcd.createChar(0, arrow_symbol);
lcd.createChar(1, reloj_symbol);
lcd.createChar(2, thermometer_symbol);
lcd.createChar(3, lamp_symbol);
if (EEPROM.read(30)>1) { // Si es la primera vez que se inicia el
programa graba los parámetros por defaul
ModoSol.Azul=127; ModoSol.Rojo=127; ModoSol.Blanco=127;
ModoSol.HoraInicio=540; ModoSol.HoraFin=1080;
// Nivel de azul / Nivel de rojo / Nivel de blanco / HoraInicio a
9:00 hs / HoraFin 18:00 hs
EEPROM.put(0,ModoSol); // guarda modo sol
TermoVar.Status=0; TermoVar.TempHorario=24; TermoVar.TempResto=20;
TermoVar.HoraInicio=540; TermoVar.HoraFin=1300;
// 0 Apagado, 1 Ecendido - 24° Por defecto / 20° por defecto /
540 minutos = 09:00 hs / 1300 minutos = 21:40 hs
EEPROM.put(10, TermoVar); // guarda termostato
ModoLuna.Status=0, ModoLuna.Azul=0; ModoLuna.Rojo=0;
ModoLuna.Blanco=0; ModoLuna.HoraInicio=1140; ModoLuna.HoraFin=1380;
//Apagado o Ecendido/ Nivel de azul/ Nivel de rojo/ Nivel de
blanco/ HoraInicio a 19:00 hs / HoraFin 23:00 hs
EEPROM.put(20,ModoLuna); // guarda modo luna
Co2Var.Status = 0; Co2Var.HoraInicio = 540; Co2Var.HoraFin =
1300;
// 0 Apagado, 1 Ecendido // 540 minutos o 09:00 AM // 1300 minutos
= 21:40 hs
EEPROM.put(30, Co2Var); // guarda control Co2
}
EEPROM.get( 0, ModoSol );
EEPROM.get(10, TermoVar);
EEPROM.get(20, ModoLuna);
EEPROM.get(30, Co2Var );
lcd.setCursor(0, 0);
lcd.print("Control de Acuario");
lcd.setCursor(6, 1);
lcd.print("CADUSA");
lcd.setCursor(0,4);
for( int i=0 ; i < 20 ; i++ ) {
lcd.print(".");
delay(150);
}
// delay(500);
lcd.clear();
}
void loop() {
unsigned long currentMillis = millis();
button.tick();
LeeEncoder(0,7,1,1); // Lee el enconder de 0 a 7, de a 1 paso y con
tope final.
if (currentMillis % 6000 < 5) { // Si el resto de dividir
currentMillis por 6000 da menos que 5...
ImprimeFecha(); ImprimeHora(); ImprimeTemp();
if (currentMillis - backlightMillis > 60000) {
lcd.setBacklight(LOW); } // Apaga el lcd a los 60s de inactividad
}
if (currentMillis % 3000 < 5) {
Termostato();
ControlCo2();
}
if (lastPos != newPos) {
lcd.setCursor(0,3);
switch (newPos) {
case 0:
lcd.print("> ");
break;
case 1:
lcd.print("Modo Sol ");
break;
case 2:
lcd.print("Modo Luna ");
break;
case 3:
lcd.print("Calefactor ");
break;
case 4:
lcd.print("Control Co2 ");
break;
case 5:
lcd.print("Mantener ");
break;
case 6:
lcd.print("Fecha y Hora");
break;
case 7:
lcd.print("< ");
break;
}
lastPos = newPos;
Mod_Menu = newPos;
}
// Aquí el código para el control de la iluminación
if (currentMillis % 7000 < 5) { // Cada 7 segundos
/********* Modo SOL *****************
if (MinActual >= ModoSol.HoraInicio && MinActual <=
ModoSol.HoraFin){ // Este es el rango de hora de Sol
if (MinActual < (ModoSol.HoraInicio + 30)) { // Periodo Amanecer
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[1]);
brillo = map((MinActual - ModoSol.HoraInicio),0,30,0,255);
}
if ((ModoSol.HoraInicio+30) < MinActual and (ModoSol.HoraFin-30) >
MinActual ) { // Periodo pleno sol
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[2]);
if (brillo < 255) { lcd.clear(); lcd.setCursor(6,1);
lcd.print("Subiendo"); newPos=0; lastPos=1;}
while (brillo < 255) {
brillo++; Set_pwmSol(); delay(25);
if(brillo==255) {lcd.clear();}
}
}
if (MinActual >= (ModoSol.HoraFin-30)) { // Periodo Atardecer
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[3]);
brillo = map((ModoSol.HoraFin - MinActual),30,0,255,0) ;
}
Set_pwmSol();
} // Fin rango de hora de Sol
/********* Modo LUNA *****************/
if (ModoLuna.Status == 1){ // Si el modo Luna está activado
if (MinActual > ModoLuna.HoraInicio && MinActual <
ModoLuna.HoraFin){ // Este es el rango de hora de Luna
if (MinActual < (ModoLuna.HoraInicio+30)) { // Saliendo Luna
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[5]);
brillo = map((MinActual - ModoLuna.HoraInicio),0,30,0,255);
}
if (MinActual > (ModoLuna.HoraInicio+31) and MinActual <
(ModoLuna.HoraFin-31)) { // Luna plena
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[4]);
if (brillo < 255) { lcd.clear(); lcd.setCursor(6,1);
lcd.print("Subiendo");}
while (brillo < 255) {
brillo++; Set_pwmLuna(); delay(25);
if(brillo==255) {lcd.clear();}
}
}
if (MinActual > (ModoLuna.HoraFin-30)) { // Ocultando Luna
brillo = map((ModoLuna.HoraFin -
MinActual),30,0,255,0);
}
Set_pwmLuna();
} // Fin rango de hora de Luna
} // Fin si el modo Luna está activado
/********* Periodos de Oscuridad *****************/
if (MinActual > ModoLuna.HoraFin or MinActual < ModoSol.HoraInicio){
// Periodo Noche
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[0]);
if (brillo > 0) { lcd.clear(); lcd.setCursor(6,1);
lcd.print("Apagando"); newPos=0; lastPos=1;}
while (brillo > 0) {
brillo--; Set_pwmNoche(); delay(25);
if(brillo==0) {lcd.clear();}
}
}
if (MinActual > ModoSol.HoraFin && MinActual < ModoLuna.HoraInicio){
// Periodo entre Sol y Luna
lcd.setCursor(0,1); lcd.print(" ");
lcd.setCursor(0,1); lcd.print(Periodo_name[6]);
if (brillo > 0) { lcd.clear(); lcd.setCursor(6,1);
lcd.print("Apagando");}
while (brillo > 0) {
brillo--; Set_pwmNoche(); delay(25);
if(brillo==0) {lcd.clear();}
}
}
delay(5);
}
// Fin del código para el control de la iluminación
} // FIN LOOP
void clickbutton() { // Si se hace click porque en el loop esta:
button.tick();
if (Mod_Menu > 0) {
delay(100);
switch (Mod_Menu) { // Según s hizo clik durante el menú que
aparece en la pantalla principal del loop
case 1:
Set_Modo_Sol(); // Si Mod_Menu vale 1 entonces se ejecuta la
función Set_Modo_Sol() y break detiene.
break;
case 2:
Set_Modo_Luna();
break;
case 3:
Set_Calefactor();
break;
case 4:
Set_Co2();
break;
case 5:
Mantenimiento();
break;
case 6:
setupTime();
break;
}
}
}
void LeeEncoder(int ROTARYMIN, int ROTARYMAX, int ROTARYSTEPS, int
ROTARYTOPE )
{
encoder.tick(); // Lee el encoder y actualiza el puntero. La librería
lleva la cuenta desde 0.
newPos = encoder.getPosition() * ROTARYSTEPS; // Asigna a newPos el
puntero del encoder multiplicado por los pasos.
if (newPos != lastPos) { // Enciende el display al mover el
encoder
lcd.setBacklight(HIGH);
backlightMillis = millis();
}
if (ROTARYTOPE == 1) { // Si el rotor tiene tope entonces no se pasa
de valor
if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor
Mínimo ->
encoder.setPosition(ROTARYMIN / ROTARYSTEPS); // Se fija el
puntero al valor mínimo por los pasos
newPos = ROTARYMIN;
}
if (newPos > ROTARYMAX) { // Solo si el puntero es mayor a Valor
Máximo ->
encoder.setPosition(ROTARYMAX / ROTARYSTEPS); // Se fija el
puntero al valor mínimo por los pasos
newPos = ROTARYMAX;
}
}
if (ROTARYTOPE == 0) { // Si el rotor SI tiene tope entonces se pasa
del valor máximo al mínimo y viceversa.
if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor
Mínimo ->
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX; // Entonces el puntero saltará del mínimo al
máximo
}
if (newPos > ROTARYMAX) { // Solo si el puntero es mayor al Valor
Máximo ->
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN; // Entonces el puntero saltará del máximo al
mínimo.
}
}
}
void read_but() // Función que devuele enc_but = 1 al soltar el botón
del encoder.
{
bool pin_status;
delay(5);
pin_status = digitalRead(enc_c); //Se asigna a pin_status el valor
del botón
if (pin_status == LOW && enc_but != 128) { // Si esta pulsado y enc_but
no vale 128
enc_but = 128; // Ahora enc_but si vale 128
}
if (pin_status == HIGH && enc_but == 128) { // Si enc_but que ahora
vale 128 y se suelta el pulsador
enc_but = 1; // ahora enc_but vale 1;
}
}
void Set_Modo_Sol(){
int salir=1;
int x=0;
int hh1 = ModoSol.HoraInicio/60;
int mm1 = ModoSol.HoraInicio - (hh1*60);
int hh2 = ModoSol.HoraFin/60;
int mm2 = ModoSol.HoraFin - (hh2*60);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("M-Sol");
lcd.setCursor(1,1); printDigits(hh1);lcd.print(":");
printDigits(mm1);lcd.print("hs");
lcd.setCursor(1,3); printDigits(hh2);lcd.print(":");
printDigits(mm2);lcd.print("hs");
lcd.setCursor(3,2); lcd.print("a");
lcd.setCursor(9,0);
lcd.print("Azul :");
lcd.print(map(ModoSol.Azul,255,0,100,0));
lcd.print("%");
lcd.setCursor(9,1);
lcd.print("Rojo :");
lcd.print(map(ModoSol.Rojo,255,0,100,0));
lcd.print("%");
lcd.setCursor(9,2);
lcd.print("Blanco:");
lcd.print(map(ModoSol.Blanco,255,0,100,0));
lcd.print("%");
lcd.setCursor(6,0);
lcd.write(1);
lcd.setCursor(5,0);
lcd.blink();
encoder.setPosition(1);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(0,1,1,0);
if (lastPos != newPos){
lastPos = newPos ; salir = newPos ; lcd.setCursor(6,0);
lcd.write(salir);
lcd.setCursor(5,0);
}
read_but();
}
enc_but=0;
if (salir == 0) {goto setsolout ;}
lcd.setCursor(0,1);
encoder.setPosition(hh1);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(5,(hh2-6),1,1);
if (lastPos != newPos){
lastPos = newPos ; hh1 = newPos ; lcd.setCursor(1,1);
lcd.print(" "); lcd.setCursor(1,1);
printDigits(hh1); lcd.setCursor(0,1);
}
read_but();
}
enc_but=0;
lcd.setCursor(3,1);
encoder.setPosition(mm1);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ; mm1 = newPos ; lcd.setCursor(4,1);
lcd.print(" "); lcd.setCursor(4,1);
printDigits(mm1); lcd.setCursor(3,1);
}
read_but();
}
enc_but=0;
lcd.setCursor(0,3);
encoder.setPosition(hh2);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder((hh1+6),21,1,1);// aca modifico duracion periodo 6hrs ,
horari fin luz 21hrs
if (lastPos != newPos){
lastPos = newPos ; hh2 = newPos ; lcd.setCursor(1,3);
lcd.print(" "); lcd.setCursor(1,3);
printDigits(hh2); lcd.setCursor(0,3);
}
read_but();
}
enc_but=0;
lcd.setCursor(3,3);
encoder.setPosition(mm2);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ; mm2 = newPos ; lcd.setCursor(4,3);
lcd.print(" "); lcd.setCursor(4,4);
printDigits(mm2); lcd.setCursor(3,4);
}
read_but();
}
enc_but=0;
encoder.setPosition(map(ModoSol.Azul,0,256,0,21));
delay(250);
lastPos = newPos ;
lcd.setCursor(15,0);
brillo=255;
Set_pwmSol();
while (enc_but!=1) {
LeeEncoder(0,100,5,1);
if (lastPos != newPos){ lastPos = newPos; ModoSol.Azul =
map(newPos,0,100,0,255);
lcd.setCursor(16,0); lcd.print(" "); lcd.setCursor(16,0);
lcd.print(newPos); lcd.print("%"); lcd.setCursor(15,0);
analogWrite(SFetAzul,ModoSol.Azul);
}
read_but();
}
enc_but=0;
encoder.setPosition(map(ModoSol.Rojo,0,256,0,21));
lastPos = newPos ;
delay(250);
lcd.setCursor(15,1);
while (enc_but!=1) {
LeeEncoder(0,100,5,1);
if (lastPos != newPos){ lastPos = newPos ; ModoSol.Rojo =
map(newPos,0,100,0,255);
lcd.setCursor(16,1); lcd.print(" ");
lcd.setCursor(16,1); lcd.print(newPos); lcd.print("%");
lcd.setCursor(15,1);
analogWrite(SFetRojo,ModoSol.Rojo);
}
read_but();
}
enc_but=0;
encoder.setPosition(map(ModoSol.Blanco,0,256,0,21));
lastPos = newPos ;
delay(250);
lcd.setCursor(15,2);
while (enc_but!=1) {
LeeEncoder(0,100,5,1);
if (lastPos != newPos){ lastPos = newPos ; ModoSol.Blanco =
map(newPos,0,100,0,255);
lcd.setCursor(16,2); lcd.print(" "); lcd.setCursor(16,2);
lcd.print(newPos); lcd.print("%"); lcd.setCursor(15,2);
analogWrite(SFetBlanco,ModoSol.Blanco);
}
read_but();
}
enc_but=0;
ModoSol.HoraInicio = (hh1*60) + mm1;
ModoSol.HoraFin = (hh2*60) + mm2;
EEPROM.put(0, ModoSol);
if (ModoSol.HoraFin > ModoLuna.HoraInicio) {
ModoLuna.HoraInicio = (hh2*60) + mm2 + 1;
EEPROM.put(20, ModoLuna);
}
setsolout:
Hecho();
}
void Set_Modo_Luna(){
int hh1 = ModoLuna.HoraInicio/60;
int mm1 = ModoLuna.HoraInicio - (hh1*60);
int hh2 = ModoLuna.HoraFin/60;
int mm2 = ModoLuna.HoraFin - (hh2*60);
int hh3 = ModoSol.HoraFin/60;
int mm3 = ModoSol.HoraFin - (hh1*60);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Luna");
lcd.setCursor(6,0);
if (ModoLuna.Status == 0) {lcd.print("Off");}
if (ModoLuna.Status == 1) {lcd.print("On ");}
lcd.blink();
lcd.setCursor(5,0);
encoder.setPosition(ModoLuna.Status);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(0,1,1,0);
if (lastPos != newPos){ lastPos = newPos ; ModoLuna.Status =
newPos;
lcd.setCursor(6,0); lcd.print(" ");
lcd.setCursor(6,0);
if (ModoLuna.Status == 0) { lcd.print("Off");}
if (ModoLuna.Status == 1) { lcd.print("On ");}
lcd.setCursor(5,0);
}
read_but();
}
enc_but=0;
if (ModoLuna.Status == 0) { goto setlunaout; } // Si apaga Modo Luna
interrumpe el resto y dirige a grabar
lcd.setCursor(1,1); printDigits(hh1);lcd.print(":");
printDigits(mm1);lcd.print("hs");
lcd.setCursor(1,3); printDigits(hh2);lcd.print(":");
printDigits(mm2);lcd.print("hs");
lcd.setCursor(3,2); lcd.print("a");
lcd.setCursor(9,0);
lcd.print("Azul :");
printDigits(map(ModoLuna.Azul,255,0,100,0));
lcd.print("%");
lcd.setCursor(9,1);
lcd.print("Rojo :");
printDigits(map(ModoLuna.Rojo,255,0,100,0));
lcd.print("%");
lcd.setCursor(9,2);
lcd.print("Blanco:");
printDigits(map(ModoLuna.Blanco,255,0,100,0));
lcd.print("%");
lcd.setCursor(0,1);
lcd.blink();
encoder.setPosition(hh1);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(hh3,23,1,1);
if (lastPos != newPos){
lastPos = newPos ; hh1 = newPos ; lcd.setCursor(1,1);
lcd.print(" "); lcd.setCursor(1,1);
printDigits(hh1); lcd.setCursor(0,1);
}
read_but();
}
enc_but=0;
lcd.setCursor(3,1);
encoder.setPosition(mm1);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ; mm1 = newPos ;
if ((hh1 == hh3) && (mm1 <= mm3)) { mm1 = mm3+1;
encoder.setPosition(mm1);}
lcd.setCursor(4,1);
lcd.print(" "); lcd.setCursor(4,1);
printDigits(mm1); lcd.setCursor(3,1);
}
read_but();
}
enc_but=0;
lcd.setCursor(0,3);
encoder.setPosition(hh2);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder((hh1+2),23,1,1);
if (lastPos != newPos){
lastPos = newPos ; hh2 = newPos ; lcd.setCursor(1,3);
lcd.print(" "); lcd.setCursor(1,3);
printDigits(hh2); lcd.setCursor(0,3);
}
read_but();
}
enc_but=0;
lcd.setCursor(3,3);
encoder.setPosition(mm2);
delay(250);
lastPos = newPos ;
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ; mm2 = newPos ; lcd.setCursor(4,3);
lcd.print(" "); lcd.setCursor(4,4);
printDigits(mm2); lcd.setCursor(3,4);
}
read_but();
}
enc_but=0;
encoder.setPosition(map(ModoLuna.Azul,0,256,0,21));
lastPos = newPos ; delay(250);
lcd.setCursor(15,0);
brillo=255;
Set_pwmLuna();
while (enc_but!=1) {
LeeEncoder(0,50,5,1);
if (lastPos != newPos){ lastPos = newPos; ModoLuna.Azul =
map(newPos,0,100,0,255);
lcd.setCursor(16,0); lcd.print(" "); lcd.setCursor(16,0);
printDigits(newPos);
lcd.print("%"); lcd.setCursor(15,0);
analogWrite(SFetAzul,ModoLuna.Azul);
}
read_but();
}
enc_but=0;
encoder.setPosition(map(ModoLuna.Rojo,0,256,0,21));
lastPos = newPos ; delay(250);
lcd.setCursor(15,1);
while (enc_but!=1) {
LeeEncoder(0,20,5,1);
if (lastPos != newPos){ lastPos = newPos; ModoLuna.Rojo =
map(newPos,0,100,0,255);
lcd.setCursor(16,1); lcd.print(" "); lcd.setCursor(16,1);
printDigits(newPos);
lcd.print("%"); lcd.setCursor(15,1);
analogWrite(SFetRojo,ModoLuna.Rojo);
}
read_but();
}
enc_but=0;
encoder.setPosition(map(ModoLuna.Blanco,0,256,0,21));
delay(250);
lastPos = newPos ;
lcd.setCursor(15,2);
while (enc_but!=1) {
LeeEncoder(0,50,5,1);
if (lastPos != newPos){ lastPos = newPos; ModoLuna.Blanco =
map(newPos,0,100,0,255);
lcd.setCursor(16,2); lcd.print(" "); lcd.setCursor(16,2);
printDigits(newPos);
lcd.print("%"); lcd.setCursor(15,2);
analogWrite(SFetBlanco,ModoLuna.Blanco);
}
read_but();
}
enc_but=0;
setlunaout:
ModoLuna.HoraInicio = (hh1*60) + mm1;
ModoLuna.HoraFin = (hh2*60) + mm2;
EEPROM.put(20, ModoLuna);
Hecho();
}
void Set_Calefactor() { // Creamos 4 variales temporales para horas y
minutos
int hh1 = TermoVar.HoraInicio/60; // Obtener las horas de
TermoVar.HoraInicio
int mm1 = TermoVar.HoraInicio%60; // Obtener los minutos de
TermoVar.HoraInicio
int hh2 = TermoVar.HoraFin/60; // Obterner las horas de
TermoVar.HoraFin
int mm2 = TermoVar.HoraFin%60; // Obetener los minutos de
TermoVar.HoraFin
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Calefactor");
lcd.setCursor(14,0);
if (!TermoVar.Status)
lcd.print("Off");
else
lcd.print("On ");
lcd.setCursor(13,0); lcd.blink();
encoder.setPosition(TermoVar.Status);
lastPos = newPos ; delay(250);
while (enc_but!=1) { // Ciclo ON OFF del termostato
LeeEncoder(0,1,1,1); // Lee el enconder de 0 a 1
if (lastPos != newPos) { // Si se gira el encoder, entonces...
lastPos = newPos ; // Vovemos a igualar lastPos
TermoVar.Status = newPos; // Fijamos TermoVar.Status al nuevo
valor,0 o 1.
lcd.setCursor(14,0);
if (!TermoVar.Status)
lcd.print("Off");
else
lcd.print("On ");
lcd.setCursor(13,0);
}
read_but(); // Lee si opromimos el botón del encoder y enc_but pasa
a valor 1.
} // Fin Ciclo ON OFF del termostato
enc_but=0; // Habiendo opromido el encoder se sale del while y
volvemos a poner a enc_but en valor 0.
if (!TermoVar.Status) { // Si TermoVar.Status quedó en Off interrumpe
el resto y dirige hacia la etiqueta setout
goto setout;
}
lcd.setCursor(0,1);
lcd.print("Dia: ");
lcd.print(TermoVar.TempHorario);lcd.print("337");
lcd.setCursor(3,1);
encoder.setPosition(TermoVar.TempHorario);
lastPos = newPos; delay(250);
while (enc_but!=1) { // Ciclo fija temperatura durante el día
LeeEncoder(10,34,1,1); // Cambiar aquí si se necesita una
temperatura inferior a 10 o superior a 34.
if (lastPos != newPos){
lastPos = newPos ;
TermoVar.TempHorario = newPos;
lcd.setCursor(5,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print(TermoVar.TempHorario);
lcd.print("337");
lcd.setCursor(3,1);
if (TermoVar.TempResto > TermoVar.TempHorario)
TermoVar.TempResto = TermoVar.TempHorario;
}
read_but();
}
enc_but=0; // Fin Ciclo fija temperatura durante el día
lcd.setCursor(0,2);
lcd.print("Hora: ");
printDigits(hh1);
lcd.print(":");
printDigits(mm1);
lcd.print(" a ");
printDigits(hh2);
lcd.print(":");
printDigits(mm2);
lcd.setCursor(5,2);
encoder.setPosition(hh1);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder(0,(hh2-1),1,1);
if (lastPos != newPos) {
lastPos = newPos ;
hh1 = newPos;
lcd.setCursor(6,2);
lcd.print(" ");
lcd.setCursor(6,2);
printDigits(hh1);
lcd.setCursor(5,2);
}
read_but();
}
enc_but=0;
lcd.setCursor(8,2);
encoder.setPosition(mm1);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ;
mm1 = newPos;
lcd.setCursor(9,2);
lcd.print(" ");
lcd.setCursor(9,2);
printDigits(mm1);
lcd.setCursor(8,2);
}
read_but();
}
enc_but=0;
lcd.setCursor(13,2);
encoder.setPosition(hh2);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder((hh1+1),23,1,1);
if (lastPos != newPos) {
lastPos = newPos ;
hh2 = newPos;
lcd.setCursor(14,2);
lcd.print(" ");
lcd.setCursor(14,2);
printDigits(hh2);
lcd.setCursor(13,2);
}
read_but();
}
enc_but=0;
lcd.setCursor(16,2);
encoder.setPosition(mm2);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){ lastPos = newPos ; mm2 = newPos;
lcd.setCursor(17,2); lcd.print(" ");
lcd.setCursor(17,2); printDigits(mm2);lcd.setCursor(16,2);
}
read_but();
}
enc_but=0;
lcd.setCursor(0,3); lcd.print("Noche: ");
lcd.print(TermoVar.TempResto);
lcd.print("337");
lcd.setCursor(5,3);
encoder.setPosition(TermoVar.TempResto);
lastPos = newPos; delay(250);
while (enc_but!=1) {
LeeEncoder(10,TermoVar.TempHorario,1,1);
if (lastPos != newPos){
lastPos = newPos ;
TermoVar.TempResto = newPos;
lcd.setCursor(7,3);
lcd.print(" ");
lcd.setCursor(7,3);
lcd.print(TermoVar.TempResto);
lcd.print("337");
lcd.setCursor(5,3);
}
read_but();
}
enc_but=0;
setout:
TermoVar.HoraInicio = (hh1*60) + mm1;
TermoVar.HoraFin = (hh2*60) + mm2;
EEPROM.put(10, TermoVar);
if (!TermoVar.Status) { digitalWrite(Relay1, HIGH);}
Hecho();
}
void Set_Co2() { // Creamos 4 variales temporales para
horas y minutos
int hh1 = Co2Var.HoraInicio/60; // Obtener las horas de
Co2Var.HoraInicio
int mm1 = Co2Var.HoraInicio%60; // Obtener los minutos de
Co2Var.HoraInicio
int hh2 = Co2Var.HoraFin/60; // Obterner las horas de Co2Var.HoraFin
int mm2 = Co2Var.HoraFin%60; // Obetener los minutos de
Co2Var.HoraFin
lcd.clear();
lcd.setCursor(0,0); lcd.print("Control Co2");
lcd.setCursor(14,0);
if (Co2Var.Status == 0) lcd.print("Off");
if (Co2Var.Status == 1) lcd.print("On ");
lcd.setCursor(13,0); lcd.blink();
encoder.setPosition(Co2Var.Status);
lastPos = newPos ; delay(250);
while (enc_but!=1) { // Ciclo ON OFF del control Co2
LeeEncoder(0,1,1,1);
if (lastPos != newPos) {
lastPos = newPos ;
Co2Var.Status = newPos;
lcd.setCursor(14,0);
if (Co2Var.Status == 0)
lcd.print("Off");
else
lcd.print("On ");
lcd.setCursor(13,0);
}
read_but();
}
enc_but=0; // Fin Ciclo ON OFF del control Co2
if (!Co2Var.Status) { goto set2out; } // Si apaga el Co2 interrumpe el
resto y dirige a grabar
lcd.setCursor(0,2);
lcd.print("Hora: ");
printDigits(hh1);
lcd.print(":");
printDigits(mm1);
lcd.print(" a ");
printDigits(hh2);
lcd.print(":");
printDigits(mm2);
lcd.setCursor(5,2);
encoder.setPosition(hh1);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder(0,(hh2-1),1,1);
if (lastPos != newPos){
lastPos = newPos ;
hh1 = newPos;
lcd.setCursor(6,2);
lcd.print(" ");
lcd.setCursor(6,2);
printDigits(hh1);
lcd.setCursor(5,2);
}
read_but();
}
enc_but=0;
lcd.setCursor(8,2);
encoder.setPosition(mm1);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ;
mm1 = newPos;
lcd.setCursor(9,2);
lcd.print(" ");
lcd.setCursor(9,2);
printDigits(mm1);
lcd.setCursor(8,2);
}
read_but();
} enc_but=0;
lcd.setCursor(13,2);
encoder.setPosition(hh2);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder((hh1+1),23,1,1);
if (lastPos != newPos) {
lastPos = newPos ;
hh2 = newPos;
lcd.setCursor(14,2);
lcd.print(" ");
lcd.setCursor(14,2);
printDigits(hh2);
lcd.setCursor(13,2);
}
read_but();
}
enc_but=0;
lcd.setCursor(16,2);
encoder.setPosition(mm2);
lastPos = newPos ; delay(250);
while (enc_but!=1) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ;
mm2 = newPos;
lcd.setCursor(17,2);
lcd.print(" ");
lcd.setCursor(17,2);
printDigits(mm2);
lcd.setCursor(16,2);
}
read_but();
}
enc_but=0;
set2out:
Co2Var.HoraInicio = (hh1*60) + mm1;
Co2Var.HoraFin = (hh2*60) + mm2;
EEPROM.put(30, Co2Var);
Hecho();
}
void Mantenimiento(){
lcd.clear();
lcd.setCursor(0,0); lcd.print("Mantenimiento");
lcd.setCursor(0,4);
lcd.print("Clic para salir.");
encoder.setPosition(0);
LeeEncoder(0,100,5,0);
delay(250);
lcd.setCursor(5,1);
lcd.print("Luz: ");
while (enc_but!=1) {
LeeEncoder(0,100,5,1);
if (lastPos != newPos){ lastPos = newPos ;
for( int a =1; a<3; a++) { spwm[a] = map(newPos,0,100,0,255); }
lcd.setCursor(10,1); lcd.print(" ");
lcd.setCursor(10,1); printDigits(newPos); lcd.print("%");
Set_pwm();
}
read_but();
}
enc_but=0;
Hecho();
}
void setupTime(){
int set_time[6];
DateTime now = rtc.now();
set_time[0] = now.year() ;
set_time[1] = now.month() ;
set_time[2] = now.day() ;
set_time[3] = now.hour() ;
set_time[4] = now.minute() ;
set_time[5] = now.second() ;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ajuste Fecha / Hora");
for(int i=0;i<6;i++) {
lcd.setCursor(0,2);lcd.print(Calendario[i]);
lcd.setCursor(8,2);lcd.print(" ");
delay(50);
encoder.setPosition(set_time[i]);
lcd.setCursor(8,2); printDigits(set_time[i]);
while(enc_but!=1 && i == 0) {
LeeEncoder(2018,2050,1,0);
if (lastPos != newPos){
lastPos = newPos ; set_time[i] = newPos ;
lcd.setCursor(8, 2);lcd.print(" ");
lcd.setCursor(8, 2);lcd.print(set_time[i]);}
read_but();
}
enc_but=0;
delay(50);
while(enc_but!=1 && i==1) {
LeeEncoder(1,12,1,0);
if (lastPos != newPos){
lastPos = newPos ;set_time[i] = newPos ;
lcd.setCursor(8, 2);lcd.print(" ");
lcd.setCursor(8, 2);lcd.print(NombreMeses[newPos]);
}
read_but();
}
enc_but=0;
delay(50);
while(enc_but!=1 && i==2) {
LeeEncoder(1,31,1,0);
if (lastPos != newPos){
lastPos = newPos ;set_time[i] = newPos ;
lcd.setCursor(8, 2); lcd.print(" ");
lcd.setCursor(8, 2); printDigits(set_time[i]);
}
read_but();
}
enc_but=0;
delay(50);
while(enc_but!=1 && i==3) {
LeeEncoder(0,23,1,0);
if (lastPos != newPos){
lastPos = newPos ;set_time[i] = newPos ;
lcd.setCursor(8, 2);lcd.print(" ");
lcd.setCursor(8, 2);printDigits(set_time[i]);
}
read_but();
}
enc_but=0;
delay(50);
while(enc_but!=1 && i==4) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ;
set_time[i] = newPos ;
lcd.setCursor(8, 2);lcd.print(" ");
lcd.setCursor(8, 2);printDigits(set_time[i]);
}
read_but();
}
enc_but=0;
delay(50);
while(enc_but!=1 && i==5) {
LeeEncoder(0,59,1,0);
if (lastPos != newPos){
lastPos = newPos ;
set_time[i] = newPos ;
lcd.setCursor(8, 2);
lcd.print(" ");
lcd.setCursor(8, 2);
printDigits(set_time[i]);
}
read_but();
}
enc_but=0;
}
rtc.adjust(DateTime(set_time[0],set_time[1],set_time[2],set_time[3]
,set_time[4], set_time[5]));
Hecho();
}
void printDigits(int digits) { // Esta función agrega un cero a dígitos
menores a 10
if(digits < 10){
lcd.print('0');
}
lcd.print(digits);
}
void RefreshLCD() {
ImprimeFecha();
delay(50);
ImprimeHora();
delay(50);
ImprimeTemp();
delay(50);
}
void ImprimeTemp() {
if (sensors.getAddress(outsideThermometer, 0)) { // Si hay
comunicación con el sensor DS18B20
sensors.requestTemperatures(); //Se envía el comando para leer la
temperatura
Temp= sensors.getTempCByIndex(0); //Se obtiene la temperatura en ºC
lcd.setCursor(13,2);
lcd.write(2); // Imprime el símbolo termómetro
lcd.print(":");
if (Temp < 10) {
lcd.print(' ');
} // Si la temperatura es menor de 10 deja un espacio en blanco
lcd.print(Temp,1); // Imprime la temperatura del DS18B20 con un
decimal.
lcd.print("337"); // Imprime °
}
else { // Si no hay comunicación con el sensor porque se ha cortado
el cable, etc.
lcd.setCursor(13,2);
lcd.write(2); // Imprime el símbolo termómetro
lcd.print(":Falla"); // Comunica la falla del sensor
}
Tlamp = rtc.getTemperature(); // Asigna a Tlamp la temperatura del RTC
lcd.setCursor(13,3);
lcd.write(3); // Imprime el símbolo lámpara
lcd.print(":");
if (Tlamp < 10) { lcd.print(' ');} // Si la temperatura es menor de 10
deja un espacio en blanco
lcd.print(Tlamp,1); // Imprime la temperatura del RTC con un decimal.
lcd.print("337"); // Imprime °
if (Tlamp > UnderTemp) { digitalWrite(13, HIGH); } // Activa el cooler
a los 50°
if (Tlamp < UnderTemp-5) { digitalWrite(13, LOW); } // Lo apaga a los
45°
if (Tlamp > OverTemp){
overheating();
} // Si la temperatura es mayor a OverTemp llama a la función
overheating
}
void MideTemperatura() {
sensors.requestTemperatures(); //Se envía el comando para leer la
temperatura
Temp = sensors.getTempCByIndex(0); //Se asigna a la variable Temp,
la temperatura en ºC del sensor ds18B20
Tlamp = rtc.getTemperature(); // Se asigna a la variable Tlamp la
temperatura del RTC
}
void ImprimeFecha() {
DateTime now = rtc.now(); // Consulta al RTC
lcd.setCursor(0,0); // Fija el cursor en la primera línea
lcd.print(DiaDeSemana[now.dayOfTheWeek()]); // Imprime el día de la
semana
lcd.setCursor(10,0);
printDigits(now.day()); // Imprime el día
lcd.print('/'); // Separador
printDigits(now.month()); // Imprime el mes
lcd.print('/'); // Separador
lcd.print(now.year(), DEC); // Imprime el año
}
void ImprimeHora() {
DateTime now = rtc.now(); // Consulta el RTC
lcd.setCursor(13,1); // Fija cursor en 13,1
lcd.write(1); // Imprime el gráfico
lcd.print(':');
printDigits(now.hour()); // Imprime hora
lcd.print(':');
printDigits(now.minute()); // Imprime minuto
MinActual = now.hour()*60+now.minute(); // Se actualiza la variable
MinActual que será usada para encender y apagar las luces del acuario. Su
valor va de 0 a 1439.
}
void Hecho() {
currentMillis = millis();
previousMillis = millis();
lcd.setBacklight(HIGH);
encoder.setPosition(0);
delay(100);
newPos = 0;
Mod_Menu = newPos;
lastPos = 1;
lcd.noBlink();
lcd.clear();
lcd.setCursor(6, 1);
lcd.print("Hecho !!");
delay(2000);
lcd.clear();
RefreshLCD();
}
void overheating() {
analogWrite(SFetAzul,0);
analogWrite(SFetRojo,0);
analogWrite(SFetBlanco,0);
byte cursor=20;
lcd.clear();
lcd.setBacklight(HIGH);
lcd.setCursor(0, 0);
lcd.print("Alta Temperatura!!");
lcd.setCursor(0,3);
lcd.print("3773773773773773773773773773773773773773773773
77377377377377"); // Imprime relleno
while (Tlamp > UnderTemp) { // Entra en un ciclo mientras la
temperatura sea excesiva.
MideTemperatura(); // Mide ambas temperaturas
Termostato(); // Corrobora el termostato para el
calefactor
ControlCo2(); // Comprueba si el Co2 debe estar activo
lcd.setCursor(7, 1);
lcd.print(Tlamp,2);
lcd.print("337"); // Imprime °
delay(1000);
cursor--;
lcd.setCursor(cursor,3);
lcd.print("376"); // Imprime en Blanco
if (cursor ==0) {cursor =20; delay(1000); lcd.setCursor(0,3);
lcd.print("3773773773773773773773773773773773773773773773
77377377377377");
}
} // Sale del ciclo de alta temperatura
lcd.clear(); // Limpia la pantalla
RefreshLCD(); // Actualiza el lcd con los datos normales.
}
void Termostato(){
if (TermoVar.Status) { // Si el termostato esta encendido
if ((MinActual >= TermoVar.HoraInicio) && (MinActual <=
TermoVar.HoraFin)) { // Rango de hora de día
if (Temp < TermoVar.TempHorario) {
digitalWrite(Relay1, LOW);
} else {
digitalWrite(Relay1, HIGH);
}
}
else
if (Temp < TermoVar.TempResto) {
digitalWrite(Relay1, LOW);
} else {
digitalWrite(Relay1, HIGH);
}
}
if (!TermoVar.Status)
digitalWrite(Relay1, HIGH);
delay(5);
}
void ControlCo2(){
if (Co2Var.Status == 1) { // Si el termostato esta encendido
if ((MinActual >= Co2Var.HoraInicio) && (MinActual <=
Co2Var.HoraFin)) { // Rango de hora de día
digitalWrite(Relay2, LOW);
}
else {
digitalWrite(Relay2, HIGH);
} // Apagado para el resto del día
}
if (Co2Var.Status == 0) {
digitalWrite(Relay2, HIGH);
} // Apagado para Co2 Off
delay(5);
}
void Set_pwm(){
analogWrite(SFetAzul, spwm[1]);
analogWrite(SFetRojo, spwm[2]);
analogWrite(SFetBlanco, spwm[3]);
}
void Set_pwmSol(){
spwm[1]= map(ModoSol.Azul , 0, 255, 0, brillo);
spwm[2]= map(ModoSol.Rojo , 0, 255, 0, brillo);
spwm[3]= map(ModoSol.Blanco, 0, 255, 0, brillo);
Set_pwm();
}
void Set_pwmLuna(){
spwm[1]= map(ModoLuna.Azul , 0, 255, 0, brillo);
spwm[2]= map(ModoLuna.Rojo , 0, 255, 0, brillo);
spwm[3]= map(ModoLuna.Blanco, 0, 255, 0, brillo);
Set_pwm();
}
void Set_pwmNoche(){
spwm[1]= map(spwm[1], 0, 255, 0, brillo);
spwm[2]= map(spwm[2], 0, 255, 0, brillo);
spwm[3]= map(spwm[3], 0, 255, 0, brillo);
Set_pwm();
}
Diagrama de flujo
Arduino: Reporte de diseño controlador acuario con Arduino

Contenu connexe

Tendances

Sistemas de Detección de Intrusos (IDS)
Sistemas de Detección de Intrusos (IDS)Sistemas de Detección de Intrusos (IDS)
Sistemas de Detección de Intrusos (IDS)Alberto Mayo Vega
 
Resumen wireless hart
Resumen wireless hartResumen wireless hart
Resumen wireless hartMarcos UC
 
Presentacion Zelio
Presentacion ZelioPresentacion Zelio
Presentacion ZelioPEDROCARRENO
 
Unidad No. 5 - Agentes Inteligentes
Unidad No. 5 - Agentes InteligentesUnidad No. 5 - Agentes Inteligentes
Unidad No. 5 - Agentes InteligentesMilton Klapp
 
sumadores, codificadores, decodificadores,multiplexores, demultiplexores
sumadores, codificadores, decodificadores,multiplexores, demultiplexoressumadores, codificadores, decodificadores,multiplexores, demultiplexores
sumadores, codificadores, decodificadores,multiplexores, demultiplexoresreinardoCoa
 
redes neuronales con Levenberg-Marquardt lmbp
redes neuronales con Levenberg-Marquardt lmbpredes neuronales con Levenberg-Marquardt lmbp
redes neuronales con Levenberg-Marquardt lmbpESCOM
 
Normas isa-5-1-controles-automaticos
Normas isa-5-1-controles-automaticosNormas isa-5-1-controles-automaticos
Normas isa-5-1-controles-automaticosHumberto Omar Fonseca
 
Geometría Computacional: Objetos y problemas básicos
Geometría Computacional: Objetos y problemas básicosGeometría Computacional: Objetos y problemas básicos
Geometría Computacional: Objetos y problemas básicosMiguel Sancho
 
Set de 35 instrucciones para pic16f877A programación en assembler
Set de 35 instrucciones para pic16f877A programación en assembler Set de 35 instrucciones para pic16f877A programación en assembler
Set de 35 instrucciones para pic16f877A programación en assembler Anllel Cardenas Yllanes
 
Analisis semantico
Analisis semanticoAnalisis semantico
Analisis semanticoAreli Gómez
 
Circuito integrado 7486
Circuito integrado 7486Circuito integrado 7486
Circuito integrado 7486maria_amanta
 
GUÍA DE EJERCICIOS RESUELTOS TEMA 3
GUÍA DE EJERCICIOS RESUELTOS TEMA 3GUÍA DE EJERCICIOS RESUELTOS TEMA 3
GUÍA DE EJERCICIOS RESUELTOS TEMA 3Luis Zurita
 
Micro PLC Logo! Comunicación con teléfono Android
Micro PLC Logo! Comunicación con teléfono AndroidMicro PLC Logo! Comunicación con teléfono Android
Micro PLC Logo! Comunicación con teléfono Androidxendika2
 
Configuraciones básica en Router Cisco
Configuraciones básica en Router CiscoConfiguraciones básica en Router Cisco
Configuraciones básica en Router CiscoAXELELIANAMAVIZCA
 

Tendances (20)

Sistemas de Detección de Intrusos (IDS)
Sistemas de Detección de Intrusos (IDS)Sistemas de Detección de Intrusos (IDS)
Sistemas de Detección de Intrusos (IDS)
 
Resumen wireless hart
Resumen wireless hartResumen wireless hart
Resumen wireless hart
 
PROYECTOS CON PIC 16F84
PROYECTOS CON PIC 16F84PROYECTOS CON PIC 16F84
PROYECTOS CON PIC 16F84
 
Presentacion Zelio
Presentacion ZelioPresentacion Zelio
Presentacion Zelio
 
Unidad No. 5 - Agentes Inteligentes
Unidad No. 5 - Agentes InteligentesUnidad No. 5 - Agentes Inteligentes
Unidad No. 5 - Agentes Inteligentes
 
sumadores, codificadores, decodificadores,multiplexores, demultiplexores
sumadores, codificadores, decodificadores,multiplexores, demultiplexoressumadores, codificadores, decodificadores,multiplexores, demultiplexores
sumadores, codificadores, decodificadores,multiplexores, demultiplexores
 
redes neuronales con Levenberg-Marquardt lmbp
redes neuronales con Levenberg-Marquardt lmbpredes neuronales con Levenberg-Marquardt lmbp
redes neuronales con Levenberg-Marquardt lmbp
 
Cisco itn module 1
Cisco itn module 1Cisco itn module 1
Cisco itn module 1
 
Normas isa-5-1-controles-automaticos
Normas isa-5-1-controles-automaticosNormas isa-5-1-controles-automaticos
Normas isa-5-1-controles-automaticos
 
Investigación Enrutamiento
Investigación EnrutamientoInvestigación Enrutamiento
Investigación Enrutamiento
 
Geometría Computacional: Objetos y problemas básicos
Geometría Computacional: Objetos y problemas básicosGeometría Computacional: Objetos y problemas básicos
Geometría Computacional: Objetos y problemas básicos
 
Set de 35 instrucciones para pic16f877A programación en assembler
Set de 35 instrucciones para pic16f877A programación en assembler Set de 35 instrucciones para pic16f877A programación en assembler
Set de 35 instrucciones para pic16f877A programación en assembler
 
Analisis semantico
Analisis semanticoAnalisis semantico
Analisis semantico
 
AAA Servers
AAA ServersAAA Servers
AAA Servers
 
Circuito integrado 7486
Circuito integrado 7486Circuito integrado 7486
Circuito integrado 7486
 
Ejercicios ripv2
Ejercicios ripv2Ejercicios ripv2
Ejercicios ripv2
 
GUÍA DE EJERCICIOS RESUELTOS TEMA 3
GUÍA DE EJERCICIOS RESUELTOS TEMA 3GUÍA DE EJERCICIOS RESUELTOS TEMA 3
GUÍA DE EJERCICIOS RESUELTOS TEMA 3
 
Micro PLC Logo! Comunicación con teléfono Android
Micro PLC Logo! Comunicación con teléfono AndroidMicro PLC Logo! Comunicación con teléfono Android
Micro PLC Logo! Comunicación con teléfono Android
 
Configuraciones básica en Router Cisco
Configuraciones básica en Router CiscoConfiguraciones básica en Router Cisco
Configuraciones básica en Router Cisco
 
RS422 y RS495
RS422 y RS495RS422 y RS495
RS422 y RS495
 

Similaire à Arduino: Reporte de diseño controlador acuario con Arduino

Microprogramacion - Interrupciones y timers
Microprogramacion - Interrupciones y timersMicroprogramacion - Interrupciones y timers
Microprogramacion - Interrupciones y timersmarco calderon layme
 
Tutorial proton part 4
Tutorial proton part 4Tutorial proton part 4
Tutorial proton part 4dar851112
 
Microcontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltosMicrocontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltosmarco calderon layme
 
TIMERS&TEMPORIZADORES EN "C"
TIMERS&TEMPORIZADORES EN "C"TIMERS&TEMPORIZADORES EN "C"
TIMERS&TEMPORIZADORES EN "C"Diego Rojas Ruiz
 
Microcontroladores: Introducción al AVR Studio
Microcontroladores: Introducción al AVR StudioMicrocontroladores: Introducción al AVR Studio
Microcontroladores: Introducción al AVR StudioSANTIAGO PABLO ALBERTO
 
Microcontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladoresMicrocontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladoresSANTIAGO PABLO ALBERTO
 
ARDUINO - LADDER PROYECTO CX3 RESET TEMP EH EN 2 CILINDROS BI MONO...
ARDUINO  - LADDER   PROYECTO  CX3 RESET  TEMP  EH  EN   2  CILINDROS  BI MONO...ARDUINO  - LADDER   PROYECTO  CX3 RESET  TEMP  EH  EN   2  CILINDROS  BI MONO...
ARDUINO - LADDER PROYECTO CX3 RESET TEMP EH EN 2 CILINDROS BI MONO...Jovanny Duque
 
ARDUINO - LADDER - 2 CILINDROS CX3 RESET - IMPLEMENTACIÓN DE LADDER SOB...
ARDUINO - LADDER -  2  CILINDROS   CX3  RESET - IMPLEMENTACIÓN  DE LADDER SOB...ARDUINO - LADDER -  2  CILINDROS   CX3  RESET - IMPLEMENTACIÓN  DE LADDER SOB...
ARDUINO - LADDER - 2 CILINDROS CX3 RESET - IMPLEMENTACIÓN DE LADDER SOB...Jovanny Duque
 
Arquitectura del plc
Arquitectura del plcArquitectura del plc
Arquitectura del plcForrestMamani
 
Lab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdfLab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdfsopitamani1
 
Alarma arduino wavecom programa y esquema numeros borrados 48 pag
Alarma arduino wavecom programa y esquema numeros borrados 48 pagAlarma arduino wavecom programa y esquema numeros borrados 48 pag
Alarma arduino wavecom programa y esquema numeros borrados 48 pagjoaquinin1
 
Informe N°2-Microcontroladores
Informe N°2-MicrocontroladoresInforme N°2-Microcontroladores
Informe N°2-MicrocontroladoresOmar Ruiz
 
Termómetro con arduino uno
Termómetro con arduino unoTermómetro con arduino uno
Termómetro con arduino unoIvan Espinosa
 
Curso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxCurso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxJose Manuel Mansilla Carrasco
 
Curso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxCurso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxfreddymadriz
 
Curso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxCurso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxJose Manuel Mansilla Carrasco
 

Similaire à Arduino: Reporte de diseño controlador acuario con Arduino (20)

Proyecto1
Proyecto1Proyecto1
Proyecto1
 
Microprogramacion - Interrupciones y timers
Microprogramacion - Interrupciones y timersMicroprogramacion - Interrupciones y timers
Microprogramacion - Interrupciones y timers
 
Tutorial proton part 4
Tutorial proton part 4Tutorial proton part 4
Tutorial proton part 4
 
Microcontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltosMicrocontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltos
 
TIMERS&TEMPORIZADORES EN "C"
TIMERS&TEMPORIZADORES EN "C"TIMERS&TEMPORIZADORES EN "C"
TIMERS&TEMPORIZADORES EN "C"
 
Microcontroladores: Introducción al AVR Studio
Microcontroladores: Introducción al AVR StudioMicrocontroladores: Introducción al AVR Studio
Microcontroladores: Introducción al AVR Studio
 
Microcontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladoresMicrocontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladores
 
Analisis para control pid
Analisis para control pidAnalisis para control pid
Analisis para control pid
 
ARDUINO - LADDER PROYECTO CX3 RESET TEMP EH EN 2 CILINDROS BI MONO...
ARDUINO  - LADDER   PROYECTO  CX3 RESET  TEMP  EH  EN   2  CILINDROS  BI MONO...ARDUINO  - LADDER   PROYECTO  CX3 RESET  TEMP  EH  EN   2  CILINDROS  BI MONO...
ARDUINO - LADDER PROYECTO CX3 RESET TEMP EH EN 2 CILINDROS BI MONO...
 
ARDUINO - LADDER - 2 CILINDROS CX3 RESET - IMPLEMENTACIÓN DE LADDER SOB...
ARDUINO - LADDER -  2  CILINDROS   CX3  RESET - IMPLEMENTACIÓN  DE LADDER SOB...ARDUINO - LADDER -  2  CILINDROS   CX3  RESET - IMPLEMENTACIÓN  DE LADDER SOB...
ARDUINO - LADDER - 2 CILINDROS CX3 RESET - IMPLEMENTACIÓN DE LADDER SOB...
 
Arquitectura del plc
Arquitectura del plcArquitectura del plc
Arquitectura del plc
 
Lab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdfLab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdf
 
Micro2 tema 4
Micro2 tema 4Micro2 tema 4
Micro2 tema 4
 
Alarma arduino wavecom programa y esquema numeros borrados 48 pag
Alarma arduino wavecom programa y esquema numeros borrados 48 pagAlarma arduino wavecom programa y esquema numeros borrados 48 pag
Alarma arduino wavecom programa y esquema numeros borrados 48 pag
 
Informe N°2-Microcontroladores
Informe N°2-MicrocontroladoresInforme N°2-Microcontroladores
Informe N°2-Microcontroladores
 
Termómetro con arduino uno
Termómetro con arduino unoTermómetro con arduino uno
Termómetro con arduino uno
 
Curso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxCurso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xx
 
Curso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxCurso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xx
 
Curso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xxCurso de programacion en c++ para microcontroladores pic 16 f87xx
Curso de programacion en c++ para microcontroladores pic 16 f87xx
 
Tutorial ii proyectos en basic proton
Tutorial ii   proyectos en basic protonTutorial ii   proyectos en basic proton
Tutorial ii proyectos en basic proton
 

Plus de SANTIAGO PABLO ALBERTO

Manual de teoría y practica electroneumática avanzada
Manual de teoría y practica electroneumática avanzadaManual de teoría y practica electroneumática avanzada
Manual de teoría y practica electroneumática avanzadaSANTIAGO PABLO ALBERTO
 
Programacion de PLC basado en Rslogix 500 por Roni Domínguez
Programacion de PLC basado en Rslogix 500 por Roni Domínguez Programacion de PLC basado en Rslogix 500 por Roni Domínguez
Programacion de PLC basado en Rslogix 500 por Roni Domínguez SANTIAGO PABLO ALBERTO
 
Programación de microcontroladores PIC en C con Fabio Pereira
Programación de microcontroladores PIC en  C con Fabio PereiraProgramación de microcontroladores PIC en  C con Fabio Pereira
Programación de microcontroladores PIC en C con Fabio PereiraSANTIAGO PABLO ALBERTO
 
Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...
Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...
Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...SANTIAGO PABLO ALBERTO
 
Programación de autómatas PLC OMRON CJ/CP1
Programación de  autómatas PLC OMRON CJ/CP1Programación de  autómatas PLC OMRON CJ/CP1
Programación de autómatas PLC OMRON CJ/CP1SANTIAGO PABLO ALBERTO
 
Manual del sistema del controlador programable S7-200 SMART
Manual del sistema del controlador programable S7-200 SMARTManual del sistema del controlador programable S7-200 SMART
Manual del sistema del controlador programable S7-200 SMARTSANTIAGO PABLO ALBERTO
 
PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...
PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...
PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...SANTIAGO PABLO ALBERTO
 
PLC y Electroneumática: Electricidad y Automatismo eléctrico por Luis Miguel...
PLC y Electroneumática: Electricidad y Automatismo eléctrico por  Luis Miguel...PLC y Electroneumática: Electricidad y Automatismo eléctrico por  Luis Miguel...
PLC y Electroneumática: Electricidad y Automatismo eléctrico por Luis Miguel...SANTIAGO PABLO ALBERTO
 
Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...
Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...
Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...SANTIAGO PABLO ALBERTO
 
PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...
PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...
PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...SANTIAGO PABLO ALBERTO
 
Electrónica digital: Introducción a la Lógica Digital - Teoría, Problemas y ...
Electrónica digital:  Introducción a la Lógica Digital - Teoría, Problemas y ...Electrónica digital:  Introducción a la Lógica Digital - Teoría, Problemas y ...
Electrónica digital: Introducción a la Lógica Digital - Teoría, Problemas y ...SANTIAGO PABLO ALBERTO
 

Plus de SANTIAGO PABLO ALBERTO (20)

secuencia electroneumática parte 1
secuencia electroneumática parte 1secuencia electroneumática parte 1
secuencia electroneumática parte 1
 
secuencia electroneumática parte 2
secuencia electroneumática parte 2secuencia electroneumática parte 2
secuencia electroneumática parte 2
 
Manual de teoría y practica electroneumática avanzada
Manual de teoría y practica electroneumática avanzadaManual de teoría y practica electroneumática avanzada
Manual de teoría y practica electroneumática avanzada
 
Programacion de PLC basado en Rslogix 500 por Roni Domínguez
Programacion de PLC basado en Rslogix 500 por Roni Domínguez Programacion de PLC basado en Rslogix 500 por Roni Domínguez
Programacion de PLC basado en Rslogix 500 por Roni Domínguez
 
Programación de microcontroladores PIC en C con Fabio Pereira
Programación de microcontroladores PIC en  C con Fabio PereiraProgramación de microcontroladores PIC en  C con Fabio Pereira
Programación de microcontroladores PIC en C con Fabio Pereira
 
Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...
Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...
Análisis y Diseño de Sistemas de Control Digital por Ricardo Fernandez del Bu...
 
Arduino: Arduino de cero a experto
Arduino: Arduino de cero a expertoArduino: Arduino de cero a experto
Arduino: Arduino de cero a experto
 
Fisica I
Fisica IFisica I
Fisica I
 
Quimica.pdf
Quimica.pdfQuimica.pdf
Quimica.pdf
 
Manual básico PLC OMRON
Manual básico PLC OMRON Manual básico PLC OMRON
Manual básico PLC OMRON
 
Programación de autómatas PLC OMRON CJ/CP1
Programación de  autómatas PLC OMRON CJ/CP1Programación de  autómatas PLC OMRON CJ/CP1
Programación de autómatas PLC OMRON CJ/CP1
 
Manual del sistema del controlador programable S7-200 SMART
Manual del sistema del controlador programable S7-200 SMARTManual del sistema del controlador programable S7-200 SMART
Manual del sistema del controlador programable S7-200 SMART
 
Catálogo de PLC S7-200 SMART
Catálogo de PLC S7-200 SMART Catálogo de PLC S7-200 SMART
Catálogo de PLC S7-200 SMART
 
PLC: Automatismos industriales
PLC: Automatismos industrialesPLC: Automatismos industriales
PLC: Automatismos industriales
 
PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...
PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...
PLC: Buses industriales y de campo practicas de laboratorio por Jose Miguel R...
 
PLC y Electroneumática: Electricidad y Automatismo eléctrico por Luis Miguel...
PLC y Electroneumática: Electricidad y Automatismo eléctrico por  Luis Miguel...PLC y Electroneumática: Electricidad y Automatismo eléctrico por  Luis Miguel...
PLC y Electroneumática: Electricidad y Automatismo eléctrico por Luis Miguel...
 
Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...
Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...
Electrónica: Diseño y desarrollo de circuitos impresos con Kicad por Miguel P...
 
PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...
PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...
PLC: Diseño, construcción y control de un motor doble Dahlander(cuatro veloci...
 
PLC: Motor Dahlander
PLC: Motor DahlanderPLC: Motor Dahlander
PLC: Motor Dahlander
 
Electrónica digital: Introducción a la Lógica Digital - Teoría, Problemas y ...
Electrónica digital:  Introducción a la Lógica Digital - Teoría, Problemas y ...Electrónica digital:  Introducción a la Lógica Digital - Teoría, Problemas y ...
Electrónica digital: Introducción a la Lógica Digital - Teoría, Problemas y ...
 

Dernier

NOM-002-STPS-2010, combate contra incendio.pptx
NOM-002-STPS-2010, combate contra incendio.pptxNOM-002-STPS-2010, combate contra incendio.pptx
NOM-002-STPS-2010, combate contra incendio.pptxJairReyna1
 
MUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptx
MUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptxMUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptx
MUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptxIcelaMartnezVictorin
 
1. Cap. 4 Carga Axial (1).pdf237374335347
1. Cap. 4 Carga Axial (1).pdf2373743353471. Cap. 4 Carga Axial (1).pdf237374335347
1. Cap. 4 Carga Axial (1).pdf237374335347vd110501
 
Tarea de UTP matematices y soluciones ingenieria
Tarea de UTP matematices y soluciones ingenieriaTarea de UTP matematices y soluciones ingenieria
Tarea de UTP matematices y soluciones ingenieriaSebastianQP1
 
Trabajo en altura de acuerdo a la normativa peruana
Trabajo en altura de acuerdo a la normativa peruanaTrabajo en altura de acuerdo a la normativa peruana
Trabajo en altura de acuerdo a la normativa peruana5extraviado
 
SEMANA 6 MEDIDAS DE TENDENCIA CENTRAL.pdf
SEMANA  6 MEDIDAS DE TENDENCIA CENTRAL.pdfSEMANA  6 MEDIDAS DE TENDENCIA CENTRAL.pdf
SEMANA 6 MEDIDAS DE TENDENCIA CENTRAL.pdffredyflores58
 
Simbología de Soldadura, interpretacion y aplicacion en dibujo tecnico indus...
Simbología de Soldadura,  interpretacion y aplicacion en dibujo tecnico indus...Simbología de Soldadura,  interpretacion y aplicacion en dibujo tecnico indus...
Simbología de Soldadura, interpretacion y aplicacion en dibujo tecnico indus...esandoval7
 
lean manufacturing and its definition for industries
lean manufacturing and its definition for industrieslean manufacturing and its definition for industries
lean manufacturing and its definition for industriesbarom
 
3.3 Tipos de conexiones en los transformadores trifasicos.pdf
3.3 Tipos de conexiones en los transformadores trifasicos.pdf3.3 Tipos de conexiones en los transformadores trifasicos.pdf
3.3 Tipos de conexiones en los transformadores trifasicos.pdfRicardoRomeroUrbano
 
Tema 7 Plantas Industriales (2).pptx ingenieria
Tema 7 Plantas Industriales (2).pptx ingenieriaTema 7 Plantas Industriales (2).pptx ingenieria
Tema 7 Plantas Industriales (2).pptx ingenieriaLissetteMorejonLeon
 
5. MATERIAL COMPLEMENTARIO - PPT de la Sesión 02.pptx
5. MATERIAL COMPLEMENTARIO - PPT  de la Sesión 02.pptx5. MATERIAL COMPLEMENTARIO - PPT  de la Sesión 02.pptx
5. MATERIAL COMPLEMENTARIO - PPT de la Sesión 02.pptxJOSLUISCALLATAENRIQU
 
Topografía 1 Nivelación y Carretera en la Ingenierías
Topografía 1 Nivelación y Carretera en la IngenieríasTopografía 1 Nivelación y Carretera en la Ingenierías
Topografía 1 Nivelación y Carretera en la IngenieríasSegundo Silva Maguiña
 
Electricidad y electronica industrial unidad 1
Electricidad y electronica industrial unidad 1Electricidad y electronica industrial unidad 1
Electricidad y electronica industrial unidad 1victorrodrigues972054
 
La mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacionLa mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacionnewspotify528
 
LIQUIDACION OBRAS PUBLICAS POR CONTRATA.pdf
LIQUIDACION OBRAS PUBLICAS  POR CONTRATA.pdfLIQUIDACION OBRAS PUBLICAS  POR CONTRATA.pdf
LIQUIDACION OBRAS PUBLICAS POR CONTRATA.pdfManuelVillarreal44
 
ESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTO
ESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTOESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTO
ESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTOCamiloSaavedra30
 
trabajos en altura 2024, sistemas de contencion anticaidas
trabajos en altura 2024, sistemas de contencion anticaidastrabajos en altura 2024, sistemas de contencion anticaidas
trabajos en altura 2024, sistemas de contencion anticaidasNelsonQuispeQuispitu
 
Estudio de materiales asfalticos para utilizar en obras viales
Estudio de materiales asfalticos para utilizar en obras vialesEstudio de materiales asfalticos para utilizar en obras viales
Estudio de materiales asfalticos para utilizar en obras vialesRamonCortez4
 
Ley 29783 ALCANCES E INTERPRETACION ----
Ley 29783 ALCANCES E INTERPRETACION ----Ley 29783 ALCANCES E INTERPRETACION ----
Ley 29783 ALCANCES E INTERPRETACION ----AdministracionSSTGru
 
MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...
MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...
MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...Arquitecto Alejandro Gomez cornejo muñoz
 

Dernier (20)

NOM-002-STPS-2010, combate contra incendio.pptx
NOM-002-STPS-2010, combate contra incendio.pptxNOM-002-STPS-2010, combate contra incendio.pptx
NOM-002-STPS-2010, combate contra incendio.pptx
 
MUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptx
MUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptxMUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptx
MUROS Y CONEXIONES NTC 2017 CONCRETO REFORZADO.pptx
 
1. Cap. 4 Carga Axial (1).pdf237374335347
1. Cap. 4 Carga Axial (1).pdf2373743353471. Cap. 4 Carga Axial (1).pdf237374335347
1. Cap. 4 Carga Axial (1).pdf237374335347
 
Tarea de UTP matematices y soluciones ingenieria
Tarea de UTP matematices y soluciones ingenieriaTarea de UTP matematices y soluciones ingenieria
Tarea de UTP matematices y soluciones ingenieria
 
Trabajo en altura de acuerdo a la normativa peruana
Trabajo en altura de acuerdo a la normativa peruanaTrabajo en altura de acuerdo a la normativa peruana
Trabajo en altura de acuerdo a la normativa peruana
 
SEMANA 6 MEDIDAS DE TENDENCIA CENTRAL.pdf
SEMANA  6 MEDIDAS DE TENDENCIA CENTRAL.pdfSEMANA  6 MEDIDAS DE TENDENCIA CENTRAL.pdf
SEMANA 6 MEDIDAS DE TENDENCIA CENTRAL.pdf
 
Simbología de Soldadura, interpretacion y aplicacion en dibujo tecnico indus...
Simbología de Soldadura,  interpretacion y aplicacion en dibujo tecnico indus...Simbología de Soldadura,  interpretacion y aplicacion en dibujo tecnico indus...
Simbología de Soldadura, interpretacion y aplicacion en dibujo tecnico indus...
 
lean manufacturing and its definition for industries
lean manufacturing and its definition for industrieslean manufacturing and its definition for industries
lean manufacturing and its definition for industries
 
3.3 Tipos de conexiones en los transformadores trifasicos.pdf
3.3 Tipos de conexiones en los transformadores trifasicos.pdf3.3 Tipos de conexiones en los transformadores trifasicos.pdf
3.3 Tipos de conexiones en los transformadores trifasicos.pdf
 
Tema 7 Plantas Industriales (2).pptx ingenieria
Tema 7 Plantas Industriales (2).pptx ingenieriaTema 7 Plantas Industriales (2).pptx ingenieria
Tema 7 Plantas Industriales (2).pptx ingenieria
 
5. MATERIAL COMPLEMENTARIO - PPT de la Sesión 02.pptx
5. MATERIAL COMPLEMENTARIO - PPT  de la Sesión 02.pptx5. MATERIAL COMPLEMENTARIO - PPT  de la Sesión 02.pptx
5. MATERIAL COMPLEMENTARIO - PPT de la Sesión 02.pptx
 
Topografía 1 Nivelación y Carretera en la Ingenierías
Topografía 1 Nivelación y Carretera en la IngenieríasTopografía 1 Nivelación y Carretera en la Ingenierías
Topografía 1 Nivelación y Carretera en la Ingenierías
 
Electricidad y electronica industrial unidad 1
Electricidad y electronica industrial unidad 1Electricidad y electronica industrial unidad 1
Electricidad y electronica industrial unidad 1
 
La mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacionLa mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacion
 
LIQUIDACION OBRAS PUBLICAS POR CONTRATA.pdf
LIQUIDACION OBRAS PUBLICAS  POR CONTRATA.pdfLIQUIDACION OBRAS PUBLICAS  POR CONTRATA.pdf
LIQUIDACION OBRAS PUBLICAS POR CONTRATA.pdf
 
ESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTO
ESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTOESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTO
ESTUDIO TÉCNICO DEL PROYECTO DE CREACION DE SOFTWARE PARA MANTENIMIENTO
 
trabajos en altura 2024, sistemas de contencion anticaidas
trabajos en altura 2024, sistemas de contencion anticaidastrabajos en altura 2024, sistemas de contencion anticaidas
trabajos en altura 2024, sistemas de contencion anticaidas
 
Estudio de materiales asfalticos para utilizar en obras viales
Estudio de materiales asfalticos para utilizar en obras vialesEstudio de materiales asfalticos para utilizar en obras viales
Estudio de materiales asfalticos para utilizar en obras viales
 
Ley 29783 ALCANCES E INTERPRETACION ----
Ley 29783 ALCANCES E INTERPRETACION ----Ley 29783 ALCANCES E INTERPRETACION ----
Ley 29783 ALCANCES E INTERPRETACION ----
 
MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...
MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...
MEC. FLUIDOS - Análisis Diferencial del Movimiento de un Fluido -GRUPO5 sergi...
 

Arduino: Reporte de diseño controlador acuario con Arduino

  • 1. Diseño Controlador Acuario con Arduino Un controlador de acuario, donde se irán agregando partes del código hasta completarlo, constara menú para modificar parámetros luz, Hora, fecha, etc. El LCD para visualizar información, sensor de temperatura y relés. La idea es tener una base y que cualquiera pueda realizar su controlador y porque no ampliarlo. Materiales: Arduino Puede ser Nano, Uno o Mega Reloj DS3231 Lcd 20x4 con I2C Sensor temperatura DS18B20 Encoder rotatorio con pulsador Resistencia 4,7k - 1/4w =1 Resistencia 1k - 1/4w =4 Led Blanco, Rojo, Azul Fuente de poder 9v Reles Arduino 5v 2 canales Transistor 2N2222 Protoboard Cables conexión Diagrama esquemático:
  • 2.
  • 3. Desarrollo Procedimiento con el código: Hola voy a hacer mi aporte: En esta parte del código: void loop() { unsigned long currentMillis = millis(); button.tick(); LeeEncoder(0, 7, 1, 1); // Lee el enconder de 0 a 7, de a 1 paso y con tope final. if (currentMillis % 6000 < 5) { // Si el resto de dividir currentMillis por 6000 da menos que 5... ImprimeFecha(); ImprimeHora(); ImprimeTemp(); } } Se va a cumplir cuando sea por ejemplo 6000, 6001, 6002, 6003, 6004 y en el "mejor de los casos" pero en el transcurso se cumple y se va a actualizar como 20 veces aquí un ejemplo de lo que digo: Ahora así como muestra por serial va actualizar en la pantalla para lo cual presentó algo que puede ser mejor tendrías que añadir las siguientes líneas y borra en el que tú tienes, espero se entienda.
  • 4. #define tiempoPresentarDatos 6000UL // Tiempo al que se quiera realizar las acciones ejemplo 6s (1000ms = 1s) unsigned long tiempoActualDatos = 0; void loop() { if (millis() - tiempoActualDatos >= tiempoPresentarDatos) { // Si el tiempo actual menos el tiempo anterior es mayor o igual a 6 segundos tiempoActualDatos = millis(); // Actualiza el tiempo Actual //Resto del código que quieras que se cumpla cada 6 segundos } } Ahora también por ejemplo en esta parte utilizas una función y en el cual en una condición la utilizas para para comprobar si tiene tope o no. void LeeEncoder(int ROTARYMIN, int ROTARYMAX, int ROTARYSTEPS, int ROTARYTOPE) { encoder.tick(); // Lee el encoder y actualiza el puntero. La librería lleva la cuenta desde 0. newPos = encoder.getPosition() * ROTARYSTEPS; // Asigna a newPos el puntero del encoder multiplicado por los pasos. if (ROTARYTOPE == 1) { // Si el rotor tiene tope entonces no se pasa de valor if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor
  • 5. Mínimo -> encoder.setPosition(ROTARYMIN / ROTARYSTEPS); // Se fija el puntero al valor mínimo por los pasos newPos = ROTARYMIN; } if (newPos > ROTARYMAX) { // Solo si el puntero es mayor a Valor Máximo -> encoder.setPosition(ROTARYMAX / ROTARYSTEPS); // Se fija el puntero al valor mínimo por los pasos newPos = ROTARYMAX; } } if (ROTARYTOPE == 0) { // Si el rotor SI tiene tope entonces se pasa del valor máximo al mínimo y viceversa. if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor Mínimo -> encoder.setPosition(ROTARYMAX / ROTARYSTEPS); newPos = ROTARYMAX; // Entonces el puntero saltará del mínimo al máximo } if (newPos > ROTARYMAX) { // Solo si el puntero es mayor al Valor Máximo -> encoder.setPosition(ROTARYMIN / ROTARYSTEPS); newPos = ROTARYMIN; // Entonces el puntero saltará del máximo al mínimo. } } } Lo que veo un poco innecesario ya que ese no va a cambiar en el transcurso del funcionamiento si no solo cuando se configura por lo que creo que se podría utilizar de esta forma como ejemplo #define encoderTope 1 void loop() { #if encoderTope == 1 if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor Mínimo -> encoder.setPosition(ROTARYMIN / ROTARYSTEPS); // Se fija el puntero al valor mínimo por los pasos newPos = ROTARYMIN; } if (newPos > ROTARYMAX) // Solo si el puntero es mayor a Valor Máximo->
  • 6. encoder.setPosition(ROTARYMAX / ROTARYSTEPS); // Se fija el puntero al valor mínimo por los pasos newPos = ROTARYMAX; } #else if (newPos < ROTARYMIN) { //Solo si el puntero es menor a Valor Mínimo-> encoder.setPosition(ROTARYMAX / ROTARYSTEPS); newPos = ROTARYMAX; // Entonces el puntero saltará del mínimo al máximo } if (newPos > ROTARYMAX) {//Solo si el puntero es mayor al Valor Máximo-> encoder.setPosition(ROTARYMIN / ROTARYSTEPS); newPos = ROTARYMIN; // Entonces el puntero saltará del máximo al mínimo. } #endif } Ok, funcionando Aquí en este código muestra con la configuración de RTC de FECHA-HORAS usando con la librería
  • 7. void ImprimeFecha() { DateTime now = rtc.now(); // Consulta al RTC lcd.setCursor(0,0); // Fija el cursor en la primera línea lcd.print(DiaDeSemana[now.dayOfTheWeek()]); // Imprime el día de la semana lcd.setCursor(10,0); printDigits(now.day(), DEC); // Imprime el día lcd.print('/'); // Separador printDigits(now.month(), DEC); // Imprime el mes lcd.print('/'); // Separador lcd.print(now.year(), DEC); // Imprime el año } void ImprimeHora() { DateTime now = rtc.now(); // Consulta el RTC lcd.setCursor(13,1); // Fija cursor en 13,1 lcd.write(1); // Imprime el gráfico lcd.print(':'); printDigits(now.hour()); // Imprime hora lcd.print(':'); printDigits(now.minute()); // Imprime minuto MinActual = now.hour()*60+now.minute(); // Se actualiza la variable MinActual que será usada para encender y apagar las luces del acuario. Su valor va de 0 a 1439. } Otra forma que evita el problema de los días/meses/horas/minutos de 1 dígitos es esta. void ImprimeFecha() { char buffer[20]; DateTime now = rtc.now(); // Consulta al RTC lcd.setCursor(0,0); // Fija el cursor en la primera línea lcd.print(DiaDeSemana[now.dayOfTheWeek()]); // Imprime el día de la semana lcd.setCursor(10,0); sprintf(buffer,"%02d/%02d/%04d", now.day(), now.month(), now.year()); lcd.print(buffer); } void ImprimeHora() { char buffer[20]; DateTime now = rtc.now(); // Consulta el RTC lcd.setCursor(13,1); // Fija cursor en 13,1 lcd.write(1); // Imprime el gráfico sprintf(buffer,"%02d:%02d:%02d", now.hout(), now.minute(), now.second()); lcd.print(buffer);
  • 8. MinActual = now.hour()*60+now.minute(); // Se actualiza la variable MinActual que será usada para encender y apagar las luces del acuario. Su valor va de 0 a 1439. } Pruebas con sensor temperatura DS18B20 La actualización de la información de corte de un cable demora aproximadamente 20seg al desconectar cable rojo muestra información diferente no el de falla La actualización de la información de temperatura demora aprox. 50 seg ver forma de bajar tiempo. Prueba de temperatura de RTC3231
  • 9. Se toma temperatura ambiente y luego se acerca un cautín. La actualización de temperatura con demora El calefactor tiene que estar siempre encendido y trabajar así, si lo seteo a 25 grados se mantiene si sube se apaga si baja se enciende puede haber una variación de un grado, no entiendo porque en el día una temperatura, horas que esta encendido, noche otra temperatura, la idea es tener una temperatura pareja y que no por un cambio de temperatura los peces se enfermen Esta es la configuración para prueba donde el calefactor en este horario estará a 25° y el relé no se activa
  • 10. Esta es la pantalla principal con la temperatura actual Estamos realizado la prueba y al conectar la señal del relé a negativo se activa, en ningún momento se activó ni con 9° ni con 60° que llego en un momento.
  • 11. es lo mismo que tengo, la única forma que se activa el relé es si no dejo activa esta línea digitalWrite en el void setup pero no se desactiva el calefactor al pasar de los 26 o 35 o 65° void setup() { pinMode(SFetAzul, OUTPUT); pinMode(SFetRojo, OUTPUT); pinMode(SFetBlanco, OUTPUT); pinMode(Relay1, OUTPUT); // digitalWrite(Relay1, HIGH); // Subimos el pin a HIGH porque el relay se dispara con LOW pinMode(Relay2, OUTPUT); // digitalWrite(Relay2, HIGH); // Subimos el pin a HIGH porque el relay se dispara con LOW Pruebas memoria:
  • 12. Se carga programa para blanquear la memoria luego se carga archivo CADUSA y se chequean valores guardados en calefactor por defecto correspondiendo a estos día 24° hora 09:00 a 21:40 noche 20° en el caso del CO2 datos aparecen como en la imagen no siendo legibles y no activando relé Se carga programa para blanquear la memoria luego se carga archivo CADUSA y se chequean valores En calefactor valores por defecto correspondiendo a estos día 24° hora 09:00 a 21:40 noche 20°. En el caso del CO2 valores por defecto hora 09:00 a 21:40. En ambos casos se visualiza correctamente al resetear y cortar la energía al modificar valor CO2 o Calefactor estos se guardan sin perderse Todo OK. CADUSA2 en prueba Se limpia la eeprom se carga CADUSA2 pantalla inicio OK pantalla información hora. Fecha, temperaturas OK menús: calefactor valores por defecto aparecen, funciona relé al activar ON OK fecha y hora Ok control CO2 se agrega read_but(); en líneas 482, 513, 531, 548, 566, al faltar solo mostraba ON OFF y no entrega información en pantalla de valores por defecto, al seleccionar ON u OFF aparece leyenda Hecho y sale del menú. Al borrar un símbolo! línea 476 if (!Co2Var.Status == 0)
  • 13. aparece información por defecto y se activa rele en cada prueba se limpio eeprom se adjunta archivo con agregado de lineas faltantes y en estado original linea 476 para análisis Ya que estamos mostrado este era mi acuario de agua dulce de 170 cm de largo luego cambie al actual marino Actual en proceso
  • 14. Se limpia la eeprom se carga CADUSA2 pantalla inicio OK pantalla información hora. Fecha, temperaturas OK menús: Reloj y fecha OK calefactor valores por defecto aparecen, relé se activa después de 1 minutos OK control CO2 entrega información en pantalla de valores por defecto, al seleccionar ON activa relé después de 1 minuto. se mantiene la configuración puesta por usuario al resetear y desconectar energía Prueba de sobre calentamiento a 72° mensaje Alta temperatura en pantalla y se reestablece bajo los 50° en cada prueba se limpió eeprom Lo otro hay posibilidad de agregar este control de temperatura en la parte del void overheating(), que se accione con el termómetro del rtc como una acción antes que la temperatura llegue al sobre calentamiento y mantener una temperatura y si falla pasaría al modo sobre calentamiento. El código a modificar para usar el sensor de temperatura del rtc. #include <Wire.h> #include <OneWire.h> //libreria temperatura #include <DallasTemperature.h> OneWire ourWire(12); // Se establece el pin D12 como bus OneWire DallasTemperature sensors(&ourWire); //Se declara una variable u objeto para nuestro sensor int PinVent = 5; //puerto digital D11 dodne conectar el ventildor int Temperatura; //variable calculo temperatura int Restriccion_de_Temp; //Variable para mapear la temperatura int pwm; //Variable para generar pwm void setup() { sensors.begin(); pinMode(5,OUTPUT); // Serial.begin(9600); } void loop() {
  • 15. /////// Regulador Veloc Ventilador //////////// sensors.requestTemperatures(); Temperatura = (sensors.getTempCByIndex(0)); Restriccion_de_Temp = constrain(Temperatura, 35, 45); pwm = map(Restriccion_de_Temp, 35, 45, 0, 255); analogWrite(PinVent,pwm); // Serial.println(sensors.getTempCByIndex(0)); // Serial.println (pwm); delay(1000); } Una idea para la iluminación del display has probado con una resistencia de 10K donde está el jumper del lcd atenúa arto y es visible la información y no es molesto a la vista y solo ver que se apague la pantalla cuando termine el periodo de luz y seencienda cuando comience el periodo. Se ve mejor en vivo que en la foto Prueba de ventilador activándose a los 50° y desactivando a los 45 ...........OK prueba de atenuación iluminación y activación iluminación LCD .................OK en lo personal use resistencia de 10k Con la resistencia de 10k ilumina justo para que se vea y como dices a gusto del lector y se probó con un valor bajo y uno alto de resistencia. Se ve muy genial, esa era la idea, al mover el encoder recobra la iluminación genial. Lo único diferente indicador de dirección de menú ( > ) al cargar por primera vez, reiniciar o apagar y prender no aparece asta mover el encoder en la dirección de la flecha. OK, el cambio ( > ) funciona al cargar, reset y apagado y encendido
  • 16. la (>) parte al cargar y al entrar a un menú y salir este no vuelve automáticamente línea 1182 se borra 35; se deja rtc.getTemperatura Prueba iluminación se pone horario modo sol finalizando 19:23 se apaga iluminación y modo luna enciende a las 19:25 según reloj RTC, demora de 1:59 seg según cronometro en encender, no es inmediato el paso a luna en modo mantenimiento se encienden solo luz azul y rojas solamente o las blancas igual, solo se me encienden las azul y rojas Consulta habría forma de poner en el LCD información del estado en que se está como: Amanecer, Sol, Atardecer, Noche Según horario programado a (>) parte al cargar el programa pero al entrar a un menú y salir esta (>) no vuelve automáticamente - Transición a modo Luna Si el horario sol finaliza a las 17:00 y luego dentro a menu luna y pongo que inicie a las 17:00 y finalice 18:00 salgo e ingreso nuevamente este cambia iniciando a las 17:01 provocando un lapso de casi 2 minutos con las luces apagadas y luego enciende luz azul, la transición debiese ser continua sin espacio apagado -----Creo que entendí el espacio sin luz es una transición a la salida de la luna El termino lo tome de la misma pagina " En el lenguaje común, al orto se le denomina amanecer, alba o aurora. En ocasiones se diferencia la aurora, que sería el primer resplandor del cielo, del amanecer, que correspondería a la salida del sol" mañana veré bien lo de las fases del día justo es este Alba, Luna y Ocaso me estan dando problemas sino dejare los básicos Noche, Amanecer, Sol, Atardecer y Luna que son los más significativos Sigue igual, para que vuelva el signo se tiene que mover (girar) el encoder avanzar y luego retroceder y aparece Test faces del día Noche OK Amanecer OK Sol OK Atardecer OK, se apagan las luces espera 2min y pasa a Sale luna Ocaso No aparece Sale luna OK Luna OK si es que modifique mi anterior circuito los 10v eran porque las fuentes MEANWELL necesitan un voltaje de referencia y las recomendaban, no los uso se quedo hay . los 8v alimento arduino. los relés que tengo son de 5v hay los uso. son Tip141 los tengo en uso en mi pantalla actual y son baratos en comparación al fet,
  • 17. cuando vi precios no se en estos momentos. voy a usar tu recomendación del transistor para el ventilador. la fuente uso 5 de estas soportan hasta 18 led de 3w en serie, claro que estuve revisando y parece que la descontinuaron. Esta conversación sobre led es algo para largo algunos ven los watt otros los lumens otros el par led y nunca están de acuerdo yo opte luego de leer mucho por watt y lumens donde uso led con temp de color blanco calido 6000-6500k blanco frio 10000-15000k azul 460-470nm royal blue 445nm uv 420-425nm para un marino esta es mi pantalla cuando la estaba armando hace un año placa de aluminio 5mm de espesor algo gruesa y lentes de 90°
  • 18. Dudas: 1- linea 235 es el tiempo de amanecer a sol, es de 30min la duracion definido en (+30) 2- en la linea 238 0,30,0,255 quiere decir que va a subir de 0min a 30min y la luz (pmw) iría aumentando de 0 a 255 según lo programado claro if (MinActual < (ModoSol.HoraInicio + 30)) { // Periodo Amanecer lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[1]); brillo = map((MinActual - ModoSol.HoraInicio),0,30,0,255);
  • 19. No olvidar para la atenuación de la pantalla después de un minuto una resistencia entre 1k a 10k
  • 22. Código #include <LiquidCrystal_I2C.h> // libreria para LCD por I2C #include <EEPROM.h> #include <RotaryEncoder.h> #include <OneButton.h> #include <RTClib.h> #include <OneWire.h> #include <DallasTemperature.h> #define enc_a A0 #define enc_b A1 #define enc_c A2 #define Relay1 7 #define Relay2 8 #define SFetAzul 9 #define SFetRojo 10 #define SFetBlanco 11 // Variables volatile byte enc_but; String Calendario[6] = {"A356o", "Mes", "Dia", "Hora", "Minuto", "Segundo"}; String NombreMeses[13] = {" ","Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre","Diciembre"}; String DiaDeSemana[7] = {"Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado"}; String Periodo_name[7] = {"Noche", "Amanecer", "Sol", "Atardecer", "Luna" , "Sale luna", "Ocaso"}; unsigned long previousMillis = 0; unsigned long backlightMillis = 0; unsigned long currentMillis; int lastPos = 1;
  • 23. int newPos = 0; int MinActual = 0; byte brillo = 0; byte spwm[5]; float Temp; // Sensor DS18B20 para el agua del acuario float Tlamp; // Sensor interno del RTC para la temperatura del plafón. byte OverTemp = 65; // Límite superior de temeperatura para el artefato byte UnderTemp = 50; // Temperatura a la cual el artefacto retoma el funcionamiento. byte Mod_Menu = 0; byte arrow_symbol[8] = {B00000, B00100, B01110, B11111, B00100, B00100, B00100, B00100}; byte reloj_symbol[8] = {B00000, B01110, B10101, B10101, B10011, B10001, B01110, B00000}; // Símbolo reloj byte thermometer_symbol[8] = {B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110}; // Símbolo termómetro byte lamp_symbol[8] = {B00100, B10101, B01110, B11011, B01110, B10101, B00100, B00000}; // Símbolo lámpara struct MyTermo { byte Status; // Estado 0 apagado y 1 encendido byte TempHorario; // temepratura durante el rango de horas fijado byte TempResto; // temperatura para el horario fuera del rango int HoraInicio; // Hora inicio del rango int HoraFin; // Hora fin del rango }; MyTermo TermoVar; struct MyCo2 { byte Status; // Co2 On y Off, int HoraInicio; // Hora inicio int HoraFin; // Hora Fin
  • 24. }; MyCo2 Co2Var; struct MyModeSun { // Modo Sol byte Azul; // Nivel salida rojo byte Rojo; // Nivel salida azul byte Blanco; // Nivel salida blanco int HoraInicio; // Hora inicio del rango int HoraFin; // Hora fin del rango }; MyModeSun ModoSol; struct MyModeMoon { // Modo Luna byte Status; // Estado apagado o encendido del modo luna byte Azul; // Nivel salida rojo byte Rojo; // Nivel salida azul byte Blanco; // Nivel salida blanco int HoraInicio; // Hora inicio del rango int HoraFin; // Hora fin del rango }; MyModeMoon ModoLuna; LiquidCrystal_I2C lcd (0x27, 20,4); // DIR, E, RW, RS, D4, D5, D6, D7 RTC_DS3231 rtc; // Se declara el reloj en tiempo real OneButton button(A2, true); // Botón del encoder puesto a la librería OneButton RotaryEncoder encoder(A1, A0); OneWire ourWire(12); //Se establece el pin 12 como bus OneWire DallasTemperature sensors(&ourWire); //Se declara una variable u objeto para nuestro sensor DeviceAddress outsideThermometer;
  • 25. void setup() { lcd.init(); pinMode(SFetAzul, OUTPUT); pinMode(SFetRojo, OUTPUT); pinMode(SFetBlanco, OUTPUT); pinMode(Relay1, OUTPUT); digitalWrite(Relay1, HIGH); // Subimos el pin a HIGH porque el relay se dispara con LOW pinMode(Relay2, OUTPUT); digitalWrite(Relay2, HIGH); // Subimos el pin a HIGH porque el relay se dispara con LOW pinMode(enc_a, INPUT_PULLUP); pinMode(enc_b, INPUT_PULLUP); pinMode(enc_c, INPUT_PULLUP); pinMode(13, OUTPUT); // Pin 13 para controlar el cooler digitalWrite(13, LOW); // Iniciamos su estado en bajo. button.attachClick(clickbutton); button.setDebounceTicks(80); lcd.backlight(); lcd.createChar(0, arrow_symbol); lcd.createChar(1, reloj_symbol); lcd.createChar(2, thermometer_symbol); lcd.createChar(3, lamp_symbol); if (EEPROM.read(30)>1) { // Si es la primera vez que se inicia el programa graba los parámetros por defaul ModoSol.Azul=127; ModoSol.Rojo=127; ModoSol.Blanco=127; ModoSol.HoraInicio=540; ModoSol.HoraFin=1080; // Nivel de azul / Nivel de rojo / Nivel de blanco / HoraInicio a 9:00 hs / HoraFin 18:00 hs EEPROM.put(0,ModoSol); // guarda modo sol
  • 26. TermoVar.Status=0; TermoVar.TempHorario=24; TermoVar.TempResto=20; TermoVar.HoraInicio=540; TermoVar.HoraFin=1300; // 0 Apagado, 1 Ecendido - 24° Por defecto / 20° por defecto / 540 minutos = 09:00 hs / 1300 minutos = 21:40 hs EEPROM.put(10, TermoVar); // guarda termostato ModoLuna.Status=0, ModoLuna.Azul=0; ModoLuna.Rojo=0; ModoLuna.Blanco=0; ModoLuna.HoraInicio=1140; ModoLuna.HoraFin=1380; //Apagado o Ecendido/ Nivel de azul/ Nivel de rojo/ Nivel de blanco/ HoraInicio a 19:00 hs / HoraFin 23:00 hs EEPROM.put(20,ModoLuna); // guarda modo luna Co2Var.Status = 0; Co2Var.HoraInicio = 540; Co2Var.HoraFin = 1300; // 0 Apagado, 1 Ecendido // 540 minutos o 09:00 AM // 1300 minutos = 21:40 hs EEPROM.put(30, Co2Var); // guarda control Co2 } EEPROM.get( 0, ModoSol ); EEPROM.get(10, TermoVar); EEPROM.get(20, ModoLuna); EEPROM.get(30, Co2Var ); lcd.setCursor(0, 0); lcd.print("Control de Acuario"); lcd.setCursor(6, 1); lcd.print("CADUSA"); lcd.setCursor(0,4); for( int i=0 ; i < 20 ; i++ ) { lcd.print("."); delay(150); } // delay(500); lcd.clear();
  • 27. } void loop() { unsigned long currentMillis = millis(); button.tick(); LeeEncoder(0,7,1,1); // Lee el enconder de 0 a 7, de a 1 paso y con tope final. if (currentMillis % 6000 < 5) { // Si el resto de dividir currentMillis por 6000 da menos que 5... ImprimeFecha(); ImprimeHora(); ImprimeTemp(); if (currentMillis - backlightMillis > 60000) { lcd.setBacklight(LOW); } // Apaga el lcd a los 60s de inactividad } if (currentMillis % 3000 < 5) { Termostato(); ControlCo2(); } if (lastPos != newPos) { lcd.setCursor(0,3); switch (newPos) { case 0: lcd.print("> "); break; case 1: lcd.print("Modo Sol "); break; case 2: lcd.print("Modo Luna "); break; case 3: lcd.print("Calefactor "); break;
  • 28. case 4: lcd.print("Control Co2 "); break; case 5: lcd.print("Mantener "); break; case 6: lcd.print("Fecha y Hora"); break; case 7: lcd.print("< "); break; } lastPos = newPos; Mod_Menu = newPos; } // Aquí el código para el control de la iluminación if (currentMillis % 7000 < 5) { // Cada 7 segundos /********* Modo SOL ***************** if (MinActual >= ModoSol.HoraInicio && MinActual <= ModoSol.HoraFin){ // Este es el rango de hora de Sol if (MinActual < (ModoSol.HoraInicio + 30)) { // Periodo Amanecer lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[1]); brillo = map((MinActual - ModoSol.HoraInicio),0,30,0,255); } if ((ModoSol.HoraInicio+30) < MinActual and (ModoSol.HoraFin-30) > MinActual ) { // Periodo pleno sol lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[2]);
  • 29. if (brillo < 255) { lcd.clear(); lcd.setCursor(6,1); lcd.print("Subiendo"); newPos=0; lastPos=1;} while (brillo < 255) { brillo++; Set_pwmSol(); delay(25); if(brillo==255) {lcd.clear();} } } if (MinActual >= (ModoSol.HoraFin-30)) { // Periodo Atardecer lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[3]); brillo = map((ModoSol.HoraFin - MinActual),30,0,255,0) ; } Set_pwmSol(); } // Fin rango de hora de Sol /********* Modo LUNA *****************/ if (ModoLuna.Status == 1){ // Si el modo Luna está activado if (MinActual > ModoLuna.HoraInicio && MinActual < ModoLuna.HoraFin){ // Este es el rango de hora de Luna if (MinActual < (ModoLuna.HoraInicio+30)) { // Saliendo Luna lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[5]); brillo = map((MinActual - ModoLuna.HoraInicio),0,30,0,255); } if (MinActual > (ModoLuna.HoraInicio+31) and MinActual < (ModoLuna.HoraFin-31)) { // Luna plena lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[4]); if (brillo < 255) { lcd.clear(); lcd.setCursor(6,1); lcd.print("Subiendo");} while (brillo < 255) { brillo++; Set_pwmLuna(); delay(25);
  • 30. if(brillo==255) {lcd.clear();} } } if (MinActual > (ModoLuna.HoraFin-30)) { // Ocultando Luna brillo = map((ModoLuna.HoraFin - MinActual),30,0,255,0); } Set_pwmLuna(); } // Fin rango de hora de Luna } // Fin si el modo Luna está activado /********* Periodos de Oscuridad *****************/ if (MinActual > ModoLuna.HoraFin or MinActual < ModoSol.HoraInicio){ // Periodo Noche lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[0]); if (brillo > 0) { lcd.clear(); lcd.setCursor(6,1); lcd.print("Apagando"); newPos=0; lastPos=1;} while (brillo > 0) { brillo--; Set_pwmNoche(); delay(25); if(brillo==0) {lcd.clear();} } } if (MinActual > ModoSol.HoraFin && MinActual < ModoLuna.HoraInicio){ // Periodo entre Sol y Luna lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(Periodo_name[6]); if (brillo > 0) { lcd.clear(); lcd.setCursor(6,1); lcd.print("Apagando");} while (brillo > 0) { brillo--; Set_pwmNoche(); delay(25); if(brillo==0) {lcd.clear();}
  • 31. } } delay(5); } // Fin del código para el control de la iluminación } // FIN LOOP void clickbutton() { // Si se hace click porque en el loop esta: button.tick(); if (Mod_Menu > 0) { delay(100); switch (Mod_Menu) { // Según s hizo clik durante el menú que aparece en la pantalla principal del loop case 1: Set_Modo_Sol(); // Si Mod_Menu vale 1 entonces se ejecuta la función Set_Modo_Sol() y break detiene. break; case 2: Set_Modo_Luna(); break; case 3: Set_Calefactor(); break; case 4: Set_Co2(); break; case 5: Mantenimiento(); break; case 6:
  • 32. setupTime(); break; } } } void LeeEncoder(int ROTARYMIN, int ROTARYMAX, int ROTARYSTEPS, int ROTARYTOPE ) { encoder.tick(); // Lee el encoder y actualiza el puntero. La librería lleva la cuenta desde 0. newPos = encoder.getPosition() * ROTARYSTEPS; // Asigna a newPos el puntero del encoder multiplicado por los pasos. if (newPos != lastPos) { // Enciende el display al mover el encoder lcd.setBacklight(HIGH); backlightMillis = millis(); } if (ROTARYTOPE == 1) { // Si el rotor tiene tope entonces no se pasa de valor if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor Mínimo -> encoder.setPosition(ROTARYMIN / ROTARYSTEPS); // Se fija el puntero al valor mínimo por los pasos newPos = ROTARYMIN; } if (newPos > ROTARYMAX) { // Solo si el puntero es mayor a Valor Máximo -> encoder.setPosition(ROTARYMAX / ROTARYSTEPS); // Se fija el puntero al valor mínimo por los pasos newPos = ROTARYMAX; } }
  • 33. if (ROTARYTOPE == 0) { // Si el rotor SI tiene tope entonces se pasa del valor máximo al mínimo y viceversa. if (newPos < ROTARYMIN) { // Solo si el puntero es menor a Valor Mínimo -> encoder.setPosition(ROTARYMAX / ROTARYSTEPS); newPos = ROTARYMAX; // Entonces el puntero saltará del mínimo al máximo } if (newPos > ROTARYMAX) { // Solo si el puntero es mayor al Valor Máximo -> encoder.setPosition(ROTARYMIN / ROTARYSTEPS); newPos = ROTARYMIN; // Entonces el puntero saltará del máximo al mínimo. } } } void read_but() // Función que devuele enc_but = 1 al soltar el botón del encoder. { bool pin_status; delay(5); pin_status = digitalRead(enc_c); //Se asigna a pin_status el valor del botón if (pin_status == LOW && enc_but != 128) { // Si esta pulsado y enc_but no vale 128 enc_but = 128; // Ahora enc_but si vale 128 } if (pin_status == HIGH && enc_but == 128) { // Si enc_but que ahora vale 128 y se suelta el pulsador enc_but = 1; // ahora enc_but vale 1; } }
  • 34. void Set_Modo_Sol(){ int salir=1; int x=0; int hh1 = ModoSol.HoraInicio/60; int mm1 = ModoSol.HoraInicio - (hh1*60); int hh2 = ModoSol.HoraFin/60; int mm2 = ModoSol.HoraFin - (hh2*60); lcd.clear(); lcd.setCursor(0,0); lcd.print("M-Sol"); lcd.setCursor(1,1); printDigits(hh1);lcd.print(":"); printDigits(mm1);lcd.print("hs"); lcd.setCursor(1,3); printDigits(hh2);lcd.print(":"); printDigits(mm2);lcd.print("hs"); lcd.setCursor(3,2); lcd.print("a"); lcd.setCursor(9,0); lcd.print("Azul :"); lcd.print(map(ModoSol.Azul,255,0,100,0)); lcd.print("%"); lcd.setCursor(9,1); lcd.print("Rojo :"); lcd.print(map(ModoSol.Rojo,255,0,100,0)); lcd.print("%"); lcd.setCursor(9,2); lcd.print("Blanco:"); lcd.print(map(ModoSol.Blanco,255,0,100,0)); lcd.print("%"); lcd.setCursor(6,0);
  • 35. lcd.write(1); lcd.setCursor(5,0); lcd.blink(); encoder.setPosition(1); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(0,1,1,0); if (lastPos != newPos){ lastPos = newPos ; salir = newPos ; lcd.setCursor(6,0); lcd.write(salir); lcd.setCursor(5,0); } read_but(); } enc_but=0; if (salir == 0) {goto setsolout ;} lcd.setCursor(0,1); encoder.setPosition(hh1); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(5,(hh2-6),1,1); if (lastPos != newPos){ lastPos = newPos ; hh1 = newPos ; lcd.setCursor(1,1); lcd.print(" "); lcd.setCursor(1,1); printDigits(hh1); lcd.setCursor(0,1); }
  • 36. read_but(); } enc_but=0; lcd.setCursor(3,1); encoder.setPosition(mm1); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm1 = newPos ; lcd.setCursor(4,1); lcd.print(" "); lcd.setCursor(4,1); printDigits(mm1); lcd.setCursor(3,1); } read_but(); } enc_but=0; lcd.setCursor(0,3); encoder.setPosition(hh2); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder((hh1+6),21,1,1);// aca modifico duracion periodo 6hrs , horari fin luz 21hrs if (lastPos != newPos){ lastPos = newPos ; hh2 = newPos ; lcd.setCursor(1,3); lcd.print(" "); lcd.setCursor(1,3); printDigits(hh2); lcd.setCursor(0,3);
  • 37. } read_but(); } enc_but=0; lcd.setCursor(3,3); encoder.setPosition(mm2); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm2 = newPos ; lcd.setCursor(4,3); lcd.print(" "); lcd.setCursor(4,4); printDigits(mm2); lcd.setCursor(3,4); } read_but(); } enc_but=0; encoder.setPosition(map(ModoSol.Azul,0,256,0,21)); delay(250); lastPos = newPos ; lcd.setCursor(15,0); brillo=255; Set_pwmSol();
  • 38. while (enc_but!=1) { LeeEncoder(0,100,5,1); if (lastPos != newPos){ lastPos = newPos; ModoSol.Azul = map(newPos,0,100,0,255); lcd.setCursor(16,0); lcd.print(" "); lcd.setCursor(16,0); lcd.print(newPos); lcd.print("%"); lcd.setCursor(15,0); analogWrite(SFetAzul,ModoSol.Azul); } read_but(); } enc_but=0; encoder.setPosition(map(ModoSol.Rojo,0,256,0,21)); lastPos = newPos ; delay(250); lcd.setCursor(15,1); while (enc_but!=1) { LeeEncoder(0,100,5,1); if (lastPos != newPos){ lastPos = newPos ; ModoSol.Rojo = map(newPos,0,100,0,255); lcd.setCursor(16,1); lcd.print(" "); lcd.setCursor(16,1); lcd.print(newPos); lcd.print("%"); lcd.setCursor(15,1); analogWrite(SFetRojo,ModoSol.Rojo); } read_but(); } enc_but=0; encoder.setPosition(map(ModoSol.Blanco,0,256,0,21)); lastPos = newPos ;
  • 39. delay(250); lcd.setCursor(15,2); while (enc_but!=1) { LeeEncoder(0,100,5,1); if (lastPos != newPos){ lastPos = newPos ; ModoSol.Blanco = map(newPos,0,100,0,255); lcd.setCursor(16,2); lcd.print(" "); lcd.setCursor(16,2); lcd.print(newPos); lcd.print("%"); lcd.setCursor(15,2); analogWrite(SFetBlanco,ModoSol.Blanco); } read_but(); } enc_but=0; ModoSol.HoraInicio = (hh1*60) + mm1; ModoSol.HoraFin = (hh2*60) + mm2; EEPROM.put(0, ModoSol); if (ModoSol.HoraFin > ModoLuna.HoraInicio) { ModoLuna.HoraInicio = (hh2*60) + mm2 + 1; EEPROM.put(20, ModoLuna); } setsolout: Hecho(); } void Set_Modo_Luna(){
  • 40. int hh1 = ModoLuna.HoraInicio/60; int mm1 = ModoLuna.HoraInicio - (hh1*60); int hh2 = ModoLuna.HoraFin/60; int mm2 = ModoLuna.HoraFin - (hh2*60); int hh3 = ModoSol.HoraFin/60; int mm3 = ModoSol.HoraFin - (hh1*60); lcd.clear(); lcd.setCursor(0,0); lcd.print("Luna"); lcd.setCursor(6,0); if (ModoLuna.Status == 0) {lcd.print("Off");} if (ModoLuna.Status == 1) {lcd.print("On ");} lcd.blink(); lcd.setCursor(5,0); encoder.setPosition(ModoLuna.Status); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(0,1,1,0); if (lastPos != newPos){ lastPos = newPos ; ModoLuna.Status = newPos; lcd.setCursor(6,0); lcd.print(" "); lcd.setCursor(6,0); if (ModoLuna.Status == 0) { lcd.print("Off");} if (ModoLuna.Status == 1) { lcd.print("On ");} lcd.setCursor(5,0); } read_but();
  • 41. } enc_but=0; if (ModoLuna.Status == 0) { goto setlunaout; } // Si apaga Modo Luna interrumpe el resto y dirige a grabar lcd.setCursor(1,1); printDigits(hh1);lcd.print(":"); printDigits(mm1);lcd.print("hs"); lcd.setCursor(1,3); printDigits(hh2);lcd.print(":"); printDigits(mm2);lcd.print("hs"); lcd.setCursor(3,2); lcd.print("a"); lcd.setCursor(9,0); lcd.print("Azul :"); printDigits(map(ModoLuna.Azul,255,0,100,0)); lcd.print("%"); lcd.setCursor(9,1); lcd.print("Rojo :"); printDigits(map(ModoLuna.Rojo,255,0,100,0)); lcd.print("%"); lcd.setCursor(9,2); lcd.print("Blanco:"); printDigits(map(ModoLuna.Blanco,255,0,100,0)); lcd.print("%"); lcd.setCursor(0,1); lcd.blink(); encoder.setPosition(hh1); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(hh3,23,1,1); if (lastPos != newPos){
  • 42. lastPos = newPos ; hh1 = newPos ; lcd.setCursor(1,1); lcd.print(" "); lcd.setCursor(1,1); printDigits(hh1); lcd.setCursor(0,1); } read_but(); } enc_but=0; lcd.setCursor(3,1); encoder.setPosition(mm1); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm1 = newPos ; if ((hh1 == hh3) && (mm1 <= mm3)) { mm1 = mm3+1; encoder.setPosition(mm1);} lcd.setCursor(4,1); lcd.print(" "); lcd.setCursor(4,1); printDigits(mm1); lcd.setCursor(3,1); } read_but(); } enc_but=0; lcd.setCursor(0,3); encoder.setPosition(hh2); delay(250); lastPos = newPos ;
  • 43. while (enc_but!=1) { LeeEncoder((hh1+2),23,1,1); if (lastPos != newPos){ lastPos = newPos ; hh2 = newPos ; lcd.setCursor(1,3); lcd.print(" "); lcd.setCursor(1,3); printDigits(hh2); lcd.setCursor(0,3); } read_but(); } enc_but=0; lcd.setCursor(3,3); encoder.setPosition(mm2); delay(250); lastPos = newPos ; while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm2 = newPos ; lcd.setCursor(4,3); lcd.print(" "); lcd.setCursor(4,4); printDigits(mm2); lcd.setCursor(3,4); } read_but(); } enc_but=0; encoder.setPosition(map(ModoLuna.Azul,0,256,0,21)); lastPos = newPos ; delay(250); lcd.setCursor(15,0);
  • 44. brillo=255; Set_pwmLuna(); while (enc_but!=1) { LeeEncoder(0,50,5,1); if (lastPos != newPos){ lastPos = newPos; ModoLuna.Azul = map(newPos,0,100,0,255); lcd.setCursor(16,0); lcd.print(" "); lcd.setCursor(16,0); printDigits(newPos); lcd.print("%"); lcd.setCursor(15,0); analogWrite(SFetAzul,ModoLuna.Azul); } read_but(); } enc_but=0; encoder.setPosition(map(ModoLuna.Rojo,0,256,0,21)); lastPos = newPos ; delay(250); lcd.setCursor(15,1); while (enc_but!=1) { LeeEncoder(0,20,5,1); if (lastPos != newPos){ lastPos = newPos; ModoLuna.Rojo = map(newPos,0,100,0,255); lcd.setCursor(16,1); lcd.print(" "); lcd.setCursor(16,1); printDigits(newPos); lcd.print("%"); lcd.setCursor(15,1); analogWrite(SFetRojo,ModoLuna.Rojo); } read_but(); } enc_but=0;
  • 45. encoder.setPosition(map(ModoLuna.Blanco,0,256,0,21)); delay(250); lastPos = newPos ; lcd.setCursor(15,2); while (enc_but!=1) { LeeEncoder(0,50,5,1); if (lastPos != newPos){ lastPos = newPos; ModoLuna.Blanco = map(newPos,0,100,0,255); lcd.setCursor(16,2); lcd.print(" "); lcd.setCursor(16,2); printDigits(newPos); lcd.print("%"); lcd.setCursor(15,2); analogWrite(SFetBlanco,ModoLuna.Blanco); } read_but(); } enc_but=0; setlunaout: ModoLuna.HoraInicio = (hh1*60) + mm1; ModoLuna.HoraFin = (hh2*60) + mm2; EEPROM.put(20, ModoLuna); Hecho(); } void Set_Calefactor() { // Creamos 4 variales temporales para horas y minutos int hh1 = TermoVar.HoraInicio/60; // Obtener las horas de TermoVar.HoraInicio
  • 46. int mm1 = TermoVar.HoraInicio%60; // Obtener los minutos de TermoVar.HoraInicio int hh2 = TermoVar.HoraFin/60; // Obterner las horas de TermoVar.HoraFin int mm2 = TermoVar.HoraFin%60; // Obetener los minutos de TermoVar.HoraFin lcd.clear(); lcd.setCursor(0,0); lcd.print("Calefactor"); lcd.setCursor(14,0); if (!TermoVar.Status) lcd.print("Off"); else lcd.print("On "); lcd.setCursor(13,0); lcd.blink(); encoder.setPosition(TermoVar.Status); lastPos = newPos ; delay(250); while (enc_but!=1) { // Ciclo ON OFF del termostato LeeEncoder(0,1,1,1); // Lee el enconder de 0 a 1 if (lastPos != newPos) { // Si se gira el encoder, entonces... lastPos = newPos ; // Vovemos a igualar lastPos TermoVar.Status = newPos; // Fijamos TermoVar.Status al nuevo valor,0 o 1. lcd.setCursor(14,0); if (!TermoVar.Status) lcd.print("Off"); else lcd.print("On "); lcd.setCursor(13,0); }
  • 47. read_but(); // Lee si opromimos el botón del encoder y enc_but pasa a valor 1. } // Fin Ciclo ON OFF del termostato enc_but=0; // Habiendo opromido el encoder se sale del while y volvemos a poner a enc_but en valor 0. if (!TermoVar.Status) { // Si TermoVar.Status quedó en Off interrumpe el resto y dirige hacia la etiqueta setout goto setout; } lcd.setCursor(0,1); lcd.print("Dia: "); lcd.print(TermoVar.TempHorario);lcd.print("337"); lcd.setCursor(3,1); encoder.setPosition(TermoVar.TempHorario); lastPos = newPos; delay(250); while (enc_but!=1) { // Ciclo fija temperatura durante el día LeeEncoder(10,34,1,1); // Cambiar aquí si se necesita una temperatura inferior a 10 o superior a 34. if (lastPos != newPos){ lastPos = newPos ; TermoVar.TempHorario = newPos; lcd.setCursor(5,1); lcd.print(" "); lcd.setCursor(5,1); lcd.print(TermoVar.TempHorario); lcd.print("337"); lcd.setCursor(3,1); if (TermoVar.TempResto > TermoVar.TempHorario) TermoVar.TempResto = TermoVar.TempHorario;
  • 48. } read_but(); } enc_but=0; // Fin Ciclo fija temperatura durante el día lcd.setCursor(0,2); lcd.print("Hora: "); printDigits(hh1); lcd.print(":"); printDigits(mm1); lcd.print(" a "); printDigits(hh2); lcd.print(":"); printDigits(mm2); lcd.setCursor(5,2); encoder.setPosition(hh1); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder(0,(hh2-1),1,1); if (lastPos != newPos) { lastPos = newPos ; hh1 = newPos; lcd.setCursor(6,2); lcd.print(" "); lcd.setCursor(6,2); printDigits(hh1); lcd.setCursor(5,2); }
  • 49. read_but(); } enc_but=0; lcd.setCursor(8,2); encoder.setPosition(mm1); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm1 = newPos; lcd.setCursor(9,2); lcd.print(" "); lcd.setCursor(9,2); printDigits(mm1); lcd.setCursor(8,2); } read_but(); } enc_but=0; lcd.setCursor(13,2); encoder.setPosition(hh2); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder((hh1+1),23,1,1); if (lastPos != newPos) {
  • 50. lastPos = newPos ; hh2 = newPos; lcd.setCursor(14,2); lcd.print(" "); lcd.setCursor(14,2); printDigits(hh2); lcd.setCursor(13,2); } read_but(); } enc_but=0; lcd.setCursor(16,2); encoder.setPosition(mm2); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm2 = newPos; lcd.setCursor(17,2); lcd.print(" "); lcd.setCursor(17,2); printDigits(mm2);lcd.setCursor(16,2); } read_but(); } enc_but=0; lcd.setCursor(0,3); lcd.print("Noche: "); lcd.print(TermoVar.TempResto); lcd.print("337"); lcd.setCursor(5,3);
  • 51. encoder.setPosition(TermoVar.TempResto); lastPos = newPos; delay(250); while (enc_but!=1) { LeeEncoder(10,TermoVar.TempHorario,1,1); if (lastPos != newPos){ lastPos = newPos ; TermoVar.TempResto = newPos; lcd.setCursor(7,3); lcd.print(" "); lcd.setCursor(7,3); lcd.print(TermoVar.TempResto); lcd.print("337"); lcd.setCursor(5,3); } read_but(); } enc_but=0; setout: TermoVar.HoraInicio = (hh1*60) + mm1; TermoVar.HoraFin = (hh2*60) + mm2; EEPROM.put(10, TermoVar); if (!TermoVar.Status) { digitalWrite(Relay1, HIGH);} Hecho(); }
  • 52. void Set_Co2() { // Creamos 4 variales temporales para horas y minutos int hh1 = Co2Var.HoraInicio/60; // Obtener las horas de Co2Var.HoraInicio int mm1 = Co2Var.HoraInicio%60; // Obtener los minutos de Co2Var.HoraInicio int hh2 = Co2Var.HoraFin/60; // Obterner las horas de Co2Var.HoraFin int mm2 = Co2Var.HoraFin%60; // Obetener los minutos de Co2Var.HoraFin lcd.clear(); lcd.setCursor(0,0); lcd.print("Control Co2"); lcd.setCursor(14,0); if (Co2Var.Status == 0) lcd.print("Off"); if (Co2Var.Status == 1) lcd.print("On "); lcd.setCursor(13,0); lcd.blink(); encoder.setPosition(Co2Var.Status); lastPos = newPos ; delay(250); while (enc_but!=1) { // Ciclo ON OFF del control Co2 LeeEncoder(0,1,1,1); if (lastPos != newPos) { lastPos = newPos ; Co2Var.Status = newPos; lcd.setCursor(14,0); if (Co2Var.Status == 0) lcd.print("Off"); else lcd.print("On "); lcd.setCursor(13,0); } read_but();
  • 53. } enc_but=0; // Fin Ciclo ON OFF del control Co2 if (!Co2Var.Status) { goto set2out; } // Si apaga el Co2 interrumpe el resto y dirige a grabar lcd.setCursor(0,2); lcd.print("Hora: "); printDigits(hh1); lcd.print(":"); printDigits(mm1); lcd.print(" a "); printDigits(hh2); lcd.print(":"); printDigits(mm2); lcd.setCursor(5,2); encoder.setPosition(hh1); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder(0,(hh2-1),1,1); if (lastPos != newPos){ lastPos = newPos ; hh1 = newPos; lcd.setCursor(6,2); lcd.print(" "); lcd.setCursor(6,2); printDigits(hh1); lcd.setCursor(5,2); }
  • 54. read_but(); } enc_but=0; lcd.setCursor(8,2); encoder.setPosition(mm1); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm1 = newPos; lcd.setCursor(9,2); lcd.print(" "); lcd.setCursor(9,2); printDigits(mm1); lcd.setCursor(8,2); } read_but(); } enc_but=0; lcd.setCursor(13,2); encoder.setPosition(hh2); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder((hh1+1),23,1,1); if (lastPos != newPos) { lastPos = newPos ;
  • 55. hh2 = newPos; lcd.setCursor(14,2); lcd.print(" "); lcd.setCursor(14,2); printDigits(hh2); lcd.setCursor(13,2); } read_but(); } enc_but=0; lcd.setCursor(16,2); encoder.setPosition(mm2); lastPos = newPos ; delay(250); while (enc_but!=1) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; mm2 = newPos; lcd.setCursor(17,2); lcd.print(" "); lcd.setCursor(17,2); printDigits(mm2); lcd.setCursor(16,2); } read_but(); } enc_but=0;
  • 56. set2out: Co2Var.HoraInicio = (hh1*60) + mm1; Co2Var.HoraFin = (hh2*60) + mm2; EEPROM.put(30, Co2Var); Hecho(); } void Mantenimiento(){ lcd.clear(); lcd.setCursor(0,0); lcd.print("Mantenimiento"); lcd.setCursor(0,4); lcd.print("Clic para salir."); encoder.setPosition(0); LeeEncoder(0,100,5,0); delay(250); lcd.setCursor(5,1); lcd.print("Luz: "); while (enc_but!=1) { LeeEncoder(0,100,5,1); if (lastPos != newPos){ lastPos = newPos ; for( int a =1; a<3; a++) { spwm[a] = map(newPos,0,100,0,255); } lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); printDigits(newPos); lcd.print("%"); Set_pwm(); } read_but(); } enc_but=0;
  • 57. Hecho(); } void setupTime(){ int set_time[6]; DateTime now = rtc.now(); set_time[0] = now.year() ; set_time[1] = now.month() ; set_time[2] = now.day() ; set_time[3] = now.hour() ; set_time[4] = now.minute() ; set_time[5] = now.second() ; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Ajuste Fecha / Hora"); for(int i=0;i<6;i++) { lcd.setCursor(0,2);lcd.print(Calendario[i]); lcd.setCursor(8,2);lcd.print(" "); delay(50); encoder.setPosition(set_time[i]); lcd.setCursor(8,2); printDigits(set_time[i]); while(enc_but!=1 && i == 0) { LeeEncoder(2018,2050,1,0); if (lastPos != newPos){ lastPos = newPos ; set_time[i] = newPos ; lcd.setCursor(8, 2);lcd.print(" "); lcd.setCursor(8, 2);lcd.print(set_time[i]);}
  • 58. read_but(); } enc_but=0; delay(50); while(enc_but!=1 && i==1) { LeeEncoder(1,12,1,0); if (lastPos != newPos){ lastPos = newPos ;set_time[i] = newPos ; lcd.setCursor(8, 2);lcd.print(" "); lcd.setCursor(8, 2);lcd.print(NombreMeses[newPos]); } read_but(); } enc_but=0; delay(50); while(enc_but!=1 && i==2) { LeeEncoder(1,31,1,0); if (lastPos != newPos){ lastPos = newPos ;set_time[i] = newPos ; lcd.setCursor(8, 2); lcd.print(" "); lcd.setCursor(8, 2); printDigits(set_time[i]); } read_but(); } enc_but=0; delay(50); while(enc_but!=1 && i==3) {
  • 59. LeeEncoder(0,23,1,0); if (lastPos != newPos){ lastPos = newPos ;set_time[i] = newPos ; lcd.setCursor(8, 2);lcd.print(" "); lcd.setCursor(8, 2);printDigits(set_time[i]); } read_but(); } enc_but=0; delay(50); while(enc_but!=1 && i==4) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; set_time[i] = newPos ; lcd.setCursor(8, 2);lcd.print(" "); lcd.setCursor(8, 2);printDigits(set_time[i]); } read_but(); } enc_but=0; delay(50); while(enc_but!=1 && i==5) { LeeEncoder(0,59,1,0); if (lastPos != newPos){ lastPos = newPos ; set_time[i] = newPos ; lcd.setCursor(8, 2);
  • 60. lcd.print(" "); lcd.setCursor(8, 2); printDigits(set_time[i]); } read_but(); } enc_but=0; } rtc.adjust(DateTime(set_time[0],set_time[1],set_time[2],set_time[3] ,set_time[4], set_time[5])); Hecho(); } void printDigits(int digits) { // Esta función agrega un cero a dígitos menores a 10 if(digits < 10){ lcd.print('0'); } lcd.print(digits); } void RefreshLCD() { ImprimeFecha(); delay(50); ImprimeHora(); delay(50); ImprimeTemp(); delay(50); }
  • 61. void ImprimeTemp() { if (sensors.getAddress(outsideThermometer, 0)) { // Si hay comunicación con el sensor DS18B20 sensors.requestTemperatures(); //Se envía el comando para leer la temperatura Temp= sensors.getTempCByIndex(0); //Se obtiene la temperatura en ºC lcd.setCursor(13,2); lcd.write(2); // Imprime el símbolo termómetro lcd.print(":"); if (Temp < 10) { lcd.print(' '); } // Si la temperatura es menor de 10 deja un espacio en blanco lcd.print(Temp,1); // Imprime la temperatura del DS18B20 con un decimal. lcd.print("337"); // Imprime ° } else { // Si no hay comunicación con el sensor porque se ha cortado el cable, etc. lcd.setCursor(13,2); lcd.write(2); // Imprime el símbolo termómetro lcd.print(":Falla"); // Comunica la falla del sensor } Tlamp = rtc.getTemperature(); // Asigna a Tlamp la temperatura del RTC lcd.setCursor(13,3); lcd.write(3); // Imprime el símbolo lámpara lcd.print(":"); if (Tlamp < 10) { lcd.print(' ');} // Si la temperatura es menor de 10 deja un espacio en blanco lcd.print(Tlamp,1); // Imprime la temperatura del RTC con un decimal. lcd.print("337"); // Imprime °
  • 62. if (Tlamp > UnderTemp) { digitalWrite(13, HIGH); } // Activa el cooler a los 50° if (Tlamp < UnderTemp-5) { digitalWrite(13, LOW); } // Lo apaga a los 45° if (Tlamp > OverTemp){ overheating(); } // Si la temperatura es mayor a OverTemp llama a la función overheating } void MideTemperatura() { sensors.requestTemperatures(); //Se envía el comando para leer la temperatura Temp = sensors.getTempCByIndex(0); //Se asigna a la variable Temp, la temperatura en ºC del sensor ds18B20 Tlamp = rtc.getTemperature(); // Se asigna a la variable Tlamp la temperatura del RTC } void ImprimeFecha() { DateTime now = rtc.now(); // Consulta al RTC lcd.setCursor(0,0); // Fija el cursor en la primera línea lcd.print(DiaDeSemana[now.dayOfTheWeek()]); // Imprime el día de la semana lcd.setCursor(10,0); printDigits(now.day()); // Imprime el día lcd.print('/'); // Separador printDigits(now.month()); // Imprime el mes lcd.print('/'); // Separador
  • 63. lcd.print(now.year(), DEC); // Imprime el año } void ImprimeHora() { DateTime now = rtc.now(); // Consulta el RTC lcd.setCursor(13,1); // Fija cursor en 13,1 lcd.write(1); // Imprime el gráfico lcd.print(':'); printDigits(now.hour()); // Imprime hora lcd.print(':'); printDigits(now.minute()); // Imprime minuto MinActual = now.hour()*60+now.minute(); // Se actualiza la variable MinActual que será usada para encender y apagar las luces del acuario. Su valor va de 0 a 1439. } void Hecho() { currentMillis = millis(); previousMillis = millis(); lcd.setBacklight(HIGH); encoder.setPosition(0); delay(100); newPos = 0; Mod_Menu = newPos; lastPos = 1; lcd.noBlink(); lcd.clear(); lcd.setCursor(6, 1); lcd.print("Hecho !!");
  • 64. delay(2000); lcd.clear(); RefreshLCD(); } void overheating() { analogWrite(SFetAzul,0); analogWrite(SFetRojo,0); analogWrite(SFetBlanco,0); byte cursor=20; lcd.clear(); lcd.setBacklight(HIGH); lcd.setCursor(0, 0); lcd.print("Alta Temperatura!!"); lcd.setCursor(0,3); lcd.print("3773773773773773773773773773773773773773773773 77377377377377"); // Imprime relleno while (Tlamp > UnderTemp) { // Entra en un ciclo mientras la temperatura sea excesiva. MideTemperatura(); // Mide ambas temperaturas Termostato(); // Corrobora el termostato para el calefactor ControlCo2(); // Comprueba si el Co2 debe estar activo lcd.setCursor(7, 1); lcd.print(Tlamp,2); lcd.print("337"); // Imprime °
  • 65. delay(1000); cursor--; lcd.setCursor(cursor,3); lcd.print("376"); // Imprime en Blanco if (cursor ==0) {cursor =20; delay(1000); lcd.setCursor(0,3); lcd.print("3773773773773773773773773773773773773773773773 77377377377377"); } } // Sale del ciclo de alta temperatura lcd.clear(); // Limpia la pantalla RefreshLCD(); // Actualiza el lcd con los datos normales. } void Termostato(){ if (TermoVar.Status) { // Si el termostato esta encendido if ((MinActual >= TermoVar.HoraInicio) && (MinActual <= TermoVar.HoraFin)) { // Rango de hora de día if (Temp < TermoVar.TempHorario) { digitalWrite(Relay1, LOW); } else { digitalWrite(Relay1, HIGH); } } else if (Temp < TermoVar.TempResto) { digitalWrite(Relay1, LOW); } else { digitalWrite(Relay1, HIGH);
  • 66. } } if (!TermoVar.Status) digitalWrite(Relay1, HIGH); delay(5); } void ControlCo2(){ if (Co2Var.Status == 1) { // Si el termostato esta encendido if ((MinActual >= Co2Var.HoraInicio) && (MinActual <= Co2Var.HoraFin)) { // Rango de hora de día digitalWrite(Relay2, LOW); } else { digitalWrite(Relay2, HIGH); } // Apagado para el resto del día } if (Co2Var.Status == 0) { digitalWrite(Relay2, HIGH); } // Apagado para Co2 Off delay(5); } void Set_pwm(){ analogWrite(SFetAzul, spwm[1]); analogWrite(SFetRojo, spwm[2]); analogWrite(SFetBlanco, spwm[3]); }
  • 67. void Set_pwmSol(){ spwm[1]= map(ModoSol.Azul , 0, 255, 0, brillo); spwm[2]= map(ModoSol.Rojo , 0, 255, 0, brillo); spwm[3]= map(ModoSol.Blanco, 0, 255, 0, brillo); Set_pwm(); } void Set_pwmLuna(){ spwm[1]= map(ModoLuna.Azul , 0, 255, 0, brillo); spwm[2]= map(ModoLuna.Rojo , 0, 255, 0, brillo); spwm[3]= map(ModoLuna.Blanco, 0, 255, 0, brillo); Set_pwm(); } void Set_pwmNoche(){ spwm[1]= map(spwm[1], 0, 255, 0, brillo); spwm[2]= map(spwm[2], 0, 255, 0, brillo); spwm[3]= map(spwm[3], 0, 255, 0, brillo); Set_pwm(); } Diagrama de flujo