Hola
Con la guia de Daniel_Arg se realizara un controlador de acuario, donde se iran agregando partes del código hasta completarlo, constara menú para modificar parametros luz,Hora,fecha,etc, 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 coneccion
Esquema fácil de leer
Nota: La entrada de alimentación varia según su arduino
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 asi 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 tu 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 codigo 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
}
Qué te parece @surbyte sería una mejor forma o no haría gran diferencia
C:\Users\Car127\Downloads\ProyectoControlAcuarioDM\CADUSA1\CADUSA1.ino: In function 'void ImprimeFecha()':
CADUSA1:354: error: too many arguments to function 'void printDigits(int)'
printDigits(now.day(), DEC); // Imprime el dÃa
^
C:\Users\Car127\Downloads\ProyectoControlAcuarioDM\CADUSA1\CADUSA1.ino:330:6: note: declared here
void printDigits(int digits) { // Esta función agrega un cero a dÃgitos menores a 10
^
CADUSA1:356: error: too many arguments to function 'void printDigits(int)'
printDigits(now.month(), DEC); // Imprime el mes
^
C:\Users\Car127\Downloads\ProyectoControlAcuarioDM\CADUSA1\CADUSA1.ino:330:6: note: declared here
void printDigits(int digits) { // Esta función agrega un cero a dÃgitos menores a 10
^
exit status 1
too many arguments to function 'void printDigits(int)'
Muy complicado aunque funciona, porque no usan sprintf
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 problmea de los dias/meses/horas/minutos de 1 digitos 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.
}
En el void ImprimeTemp la parte del else faltaba los //
La parte del termometro con RTC tengo que probar con otro sketch para ver si funciona, ley por hay que en algunas versiones no funciona.
verificando eso sigo.
C:\Users\Car127\Downloads\ProyectoControlAcuarioDM\CADUSA1\CADUSA1.ino: In function 'void ImprimeTemp()':
CADUSA1:366: error: 'class RTC_DS3231' has no member named 'getTemperature'
Tlamp = rtc.getTemperature(); // Asigna a Tlamp la temperatura del RTC
^
C:\Users\Car127\Downloads\ProyectoControlAcuarioDM\CADUSA1\CADUSA1.ino: In function 'void MideTemperatura()':
CADUSA1:380: error: 'class RTC_DS3231' has no member named 'getTemperature'
Tlamp = rtc.getTemperature(); // Se asigna a la variable Tlamp la temperatura del RTC
^
C:\Users\Car127\Downloads\ProyectoControlAcuarioDM\CADUSA1\CADUSA1.ino: In function 'void overheating()':
CADUSA1:445: error: 'Termostato' was not declared in this scope
Termostato(); // Corrobora el termostato para el calefactor
^
CADUSA1:446: error: 'ControlCo2' was not declared in this scope
ControlCo2(); // Comprueba si el Co2 debe estar activo
^
exit status 1
'class RTC_DS3231' has no member named 'getTemperature'
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
Hola
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 dia 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