Depósito con agitador y nivel de máximo y mínimo

Hola a todos. Soy nuevo en esto y quería controlar un depósito que lleva un agitador, un nivel de máximo y mínimo y una electroválvula de llenado. Tengo una duda con el temporizado del agitador. Lo hago con millis, pero me encuentro con la incertidumbre de que pasará cuando millis se desborde y empiece otra vez, no se si me dejará de funcionar el código. Porque, si no lo he entendido mal, millis no se puede igualar a 0 y en aproximadamente 50 días, se desborda. Os lo pego a ver que os parece.

/***   Global variables   ***/
int estadoAgitador;
long intervaloEncendido=150000;
long intervaloApagado=480000;
long intervaloArranque=600000;
int retardoAlarma=400;
long tiempoAnteriorEncendido=0;
long tiempoAnteriorApagado=0;
String Paso1;
String Paso2;
int (electrovalvula) = 3;

void setup() {
  
  estadoAgitador=true;

  pinMode(2,OUTPUT);  //Contactor Agitador

  pinMode(8,INPUT);   //Nivel Bajo

  pinMode(12,INPUT);  //Pulsador anulación Alarma

  pinMode(4,OUTPUT);  //Alarma

  pinMode(10,INPUT);  //Pulsador Llenado

  pinMode (3,OUTPUT);  //Electroválvula

  pinMode(5,OUTPUT);  //Led Llenado

  pinMode(9,INPUT);   //Nivel Alto

  pinMode(11,INPUT);  //Pulsador Agitador

}


void loop() {
  Paso1; {
    if ((millis()-tiempoAnteriorEncendido>=intervaloEncendido)&&estadoAgitador==true) {
      estadoAgitador=false;
      digitalWrite(2,estadoAgitador);
      tiempoAnteriorApagado=millis();
     }
    if ((millis()-tiempoAnteriorApagado>=intervaloApagado)&&estadoAgitador==false) {
      estadoAgitador=true;
      digitalWrite(2,estadoAgitador);
      tiempoAnteriorEncendido=millis();
     }
  }
  Paso2; { 
    if (digitalRead(8) == false) {            //consulta el estado del nivel bajo
      if (digitalRead(12) == true) {          //consulta el pulsador de la alarma
        retardoAlarma=0;                      //fija la variable del retardo de la alarma en 0
        digitalWrite(4,LOW);                  //apaga la alarma
        }
      }
      if (retardoAlarma >= 400) {             //si se ha superado el número fijado en el retardo de la alarma
        digitalWrite(4,HIGH);                 //enciende la alarma
       }else {                                //de lo contrario
        retardoAlarma ++;                     //suma 1 al retardo de la alarma
      }
     }
    if (digitalRead(10) == true) {            //consulta el pulsador de llenado
      digitalWrite(2,HIGH);                   //activa el agitador
      digitalWrite(3,HIGH);                   //activa la electrovalvula
      digitalWrite(5,HIGH);                   //activa el led de llenado
      digitalWrite(4,LOW);                    //desactiva la alarma
     }
    if (digitalRead(9) == false) {            //consulta el nivel alto
      digitalWrite(2,LOW);                    //desactiva el agitador
      digitalWrite(3,LOW);                    //desactiva la electrovalvula
      digitalWrite(5,LOW);                    //desactiva el led de llenado
      digitalWrite(4,LOW);                    //desactiva la alarma
     }
    if (digitalRead(10) == true) {            //consulta el pulsador de llenado
      if (electrovalvula == true) {           //si la electrovalvula esta activada
        digitalWrite(2,LOW);                  //desactiva el agitador
        digitalWrite(3,LOW);                  //desactiva la electrovalvula
        digitalWrite(5,LOW);                  //desactiva el led de llenado
        digitalWrite(4,LOW);                  //desactiva la alarma
       }
     }
    if (digitalRead(11) == true) {            //consulta el pulsador del agitador
      intervaloArranque+=millis();            //suma millis a intervaloArranque
      digitalWrite(2,HIGH);                   //activa el agitador
     }
    if (millis() >= intervaloArranque) {      //si millis es mayor que el intervalo de arranque
      digitalWrite(2,LOW);                    //desactiva el agitador
      Paso1;                                  //salta al paso 1
      }else {                                 //de lo contrario
      Paso2;                                  //salta al paso 2
     }

}

Seguramente haya cosas mejorables y agradezco los consejos que me podáis dar.

Un saludo y gracias

Gracias por la idea, pero esa solución no me sirve porque habrá veces que la placa esté apagada durante tiempo y no puedo estar pendiente de si se le acabó la pila al módulo RTC. ¿Se os ocurre alguna manera de hacerlo con millis?

Un saludo

La idea del rtc, no la descartaría ademas puedes monitorear el estado de la bateria por un puerto analogo y generar alguna alarma si se encuentra baja, ademas el circuito rtc no consume mucho de la bateria, segun los fabricantes puede durar 5 años.

Si fuera obligatorio usar millis() porque no evaluas si es menor que 1000 y reescribes todas las variables,

Cuando millis() se desborde si usas unsigned long para cada variable no pasará nada. Ya se ha explicado varias veces en este foro que no hay error en las cuentas superados los 47 dias y chirolas.

Si tienes alguna duda busca arriba derecha noter millis() y verás de lo que hablo.

Entonces, si no he entendido mal, si cambio los long que tengo por unsigned long bastará ¿no?

Para comenzar te vuelvo a decir que ese problema de desbordamiento no va a ocurrir siempre que uses unsigned long SIEMPRE que hagas operaciones con millis().

Por otro lado la batería de un rtc no se acaba en meses tarda años. Asi que olvida esas cosas que has leído por ahi porque no son ciertas. Es como la batería que tenian las PC digamos del 95 en adelante... las cambiabas? No.. eso lo hacias luego de 5 años o mas.

Ya lo tengo todo mas o menos encaminado. Gracias por la ayuda.
Ahora estoy con la simulación del proyecto, pero hay una cosa que no tengo claro que me la esté haciendo bien.
Para consultar el estado de un Pin digital de salida le pongo donde las variables int (electrovalvula) = 3; que es el número de pin que activo para llenar el depósito y cada vez que quiero saber el estado de la electroválvula pregunto por ella poniendo (electrovalvula == true);
Cuando quieres saber el estado de un pin de salida ¿Esto se hace así?

No entiendo como hiciste ese programa y preguntas lo de la electroválvula. Es como leer un botón, es lo mismo. Un estado digital, con digitalRead(pinElectroválvula)

int (electrovalvula) = 3;

esta mal.

Se define asi int no es buena idea porque un pin solo ocupa un byte de modo que con esto es suficiente

const byte electrovalvula = 3;

podria haber sido byte electrovalvula = 3;

pero le agrego el const porque se trata de algo que no vas a cambiar o sea una constante.

Te recomiendo vayas a

Ve a Documentación => Indice de temas tutoriales => Clases de Youtube

Te darán una mejor base de conocimientos que la que tienes ahora. Sin base de arduino es dificil avanzar y cada línea será una duda tras otra.

Hola, ya tengo el código listo y probado. Gracias por la ayuda.
Ahora tengo otra duda, pero es con un módulo de relés que le quiero poner. He leído todo lo que he encontrado sobre estos módulos y me queda claro que la alimentación tengo que conectarla con una fuente externa de 12VCC entre los pines donde lleva el jumper, quitándolo y conectando entre GND y JC-VCC (creo que ponía esto). Y la VCC y GND del Arduino, lo conecto a la VCC y GND que tiene al lado de las entradas.
Ahora bien, la duda que tengo es si con una fuente de 12VCC me vale para alimentar todo. Y si es así, ¿el Arduino lo puedo alimentar por los pines GND y Vin o tiene que ser por el conector de alimentación?
Quería usar algo así: Mean Well MDR-20-12 - Fuente Alimentación Conmutada Carril Din - 20W - 12V ("DIN RAIL","mdr20-12","MDR20-12","mdr2012","MDR2012")

No me queda claro lo de alimentar los reles con 12VDC. Por que no pones un link al módulo relé del que hablas?

Sería este: https://www.electronicaembajadores.com/es/Productos/Detalle/LCRL004/modulos-electronicos/modulos-rele/modulo-4-reles-5v-optoaislado-10a

Lo que supuse.. Donde ves 12V? Veo reles de 5V y lógica de 5V. De modo que se alimentan con 5V. Prueba primero Alimentando VCC con los 5V del Arduino siempre que uses una fuente adecuada para Arduino de mas de 500mA sino mi consejo es que lo hagas con una fuente independiende del Arduino y comparte GND con el.

Pues leí lo de los 12V en esta otra: https://www.todoelectronica.com/es/modulo-rele-5vdc-de-4-canales-10a-para-arduino-p-110228.html Puse el otro enlace, porque es donde seguramente compre todo, y a mi me parece el mismo módulo. No se por qué en un sitio pone que hay que alimentarla con 12V y en otro no.

EDITO : porque veo tu placa y comenta de usar 12V. La verdad me sorprende mucho. Tus reles son 5V no veo regulador en la placa. Porque no comienzas con 5V y pruebas a ver como funciona?

long intervaloEncendido=150000;
long intervaloApagado=480000;
long intervaloArranque=600000;

estos deben modificarse por estos

unsigned long intervaloEncendido=150000;
unsigned long intervaloApagado=480000;
unsigned long intervaloArranque=600000;

EDITO 2: Este es el esquema de tu módulo 4 reles

|419x500

En el se ve claramente que no hay regulador. WIKIpedia dice

VCC is system power source, and JD_VCC is relay power source. Ship 5V relay by default. Plug jumper cap to use

O sea 5V

Mira el enlace porque esta muy claro link que tengo razón y no es 12V la alimentación.

Cuando los reles son 12VDC entonces si.

Otro link mas en pdf

Muchas gracias, da gusto con explicaciones tan claras. Es cierto que viendo el esquema queda bastante claro que debe funcionar a 5V, no se como ponían en la pagina lo de los 12V. De todas maneras, como lo voy a comprar en la tienda física, preguntaré para asegurarme. Lo de cambiar los tiempos a unsigned long, ya me había quedado claro y en el definitivo lo tengo corregido. Para acabar, me gustaría que me recomendarais con que se alimenta mejor Arduino. Comentaros que quiero meterlo todo en una caja y tendré un carril DIN para poner un magnetotérmico y un contactor que necesito para el agitador. Por eso pensaba ponerle una fuente de las que van en carril DIN (por ejemplo, la HDR-15 de Mean Well) Os lanzo las preguntas: 1º ¿Con la de 5V bastará o tendré que irme a la de 12V? porque he leído que Arduino con 5VCC de entrada no garantiza que tengamos 5VCC en las salidas. 2º ¿En caso de tener que irme a la de 12V? también he leído que se genera demasiado calor en Arduino. 3º ¿Cualquiera de las 2 opciones las puedo conectar al Vin? o tiene que ser por el conector de alimentación. Yo creo que resolviendo esto, me queda todo claro, por lo menos para este proyecto, porque ya tengo algún otro en mente... que parece que esto engancha cuando te van saliendo las cosas. Un saludo y gracias.

1º ¿Con la de 5V bastará o tendré que irme a la de 12V? porque he leído que Arduino con 5VCC de entrada no garantiza que tengamos 5VCC en las salidas.

No entiendo a que 5V te refieres? En Internet hay de todo, muchos tutoriales buenos y muchos malos. Ejemplo ha sido ese comentario de 12V que te seguramente escribió un vendedor o un programador de pagina web sin conocimiento de arduino y sus módulos. Creo o supongo que sugieres alimentar Arduino por VIN con 5V lo que ya te digo que es insuficiente. Minimo 6.5V a 7.0Vdc.

2º ¿En caso de tener que irme a la de 12V? también he leído que se genera demasiado calor en Arduino. Mentira. Si vas a la pagina de arduino.cc y miras TU Arduino y buscas especificaciones, lee cual es la tensión sugerida? verás que dices incluso mayor a 12VDC. Entonces como van a sugerir algo que compromete termicamente al regulador del Arduino. Arduino o mejor dicho ATmega328 (en genaral) requiere 5V que son provistos por un regulador de tensión. El Regulador es el que tiene restricciones (asi como el mismo ATmega328) entonces si tu le pones muchas cosas (sensores, modulos rele, etc) el consumo crece y por ende la disipación de potencia también.

El limite esta en general en los 500mA sumados Arduino + modulos. Si te pasas de ese valor empiezan los problemas además que tal vez no pueda con el requerimiento. Por eso siempre pedimos que los módulos sean alimentados externamente.

Pues yo creo que lo tengo todo claro. Voy a poner una fuente Mean Well MDR-10-12 y la conectaré directamente en los pines Vin y GND. https://www.meanwell.co.uk/mdr-10-12.html Cuando lo tenga listo todo, os comentaré que tal va. Una vez mas, gracias.

Hola a todos.
Por fin tengo mi proyecto andando, pero me surge un último problemilla y es con los dichosos ruidos de las entradas digitales.
Resulta que el agitador lo tengo conectado a un contactor que activo con un relé y tengo varios pulsadores en pull down con resistencias de 4,7k. Uno de ellos sirve para activar el llenado del depósito cuando se pulsa. Funciona todo bien, si no fuese porque de vez en cuando se activa solo el llenado. Me imagino que será por el ruido que genera la parte de alterna que tengo en el cuadro, sobre todo el arranque del agitador.
He leído varios post sobre ruido y uno de ellos decía que para solucionar estos problemas, habría que poner resistencias en el pull down de menor valor (creo que decía de 2,2k).
Para mi tiene su sentido, porque de esta manera, garantizas que lo que tienes en esa entrada sea mas próximo a 0V.
¿Vosotros que pensáis? Las resistencias actuales son de 0,5W ¿tendría que ponerlas de mas potencia? Yo creo que no.

Gracias.

tal vez tu problema no sea ruido sino rebotes ya que usas un rele según tu explicación como indicador para comenzar una tarea. Un rele al accionarse puede rebotar mecánicamente asi que tienes que implementar una rutina antirebotes.

Puntualmente cual es el pin que hace la lectura?

es este

pinMode(10,INPUT);  //Pulsador Llenado

Lo de los rebotes está descartado porque lo hace cuando nadie está accionando el pulsador, por eso lo achacaba al ruido.
Te pongo el código completo:

/***   Global variables   ***/
byte (estadoAgitador);
unsigned long intervaloEncendido;
unsigned long intervaloApagado;
unsigned long intervaloArranque;
unsigned long retardoAlarma;
byte (arranqueAgitador);                      //indica que el agitador está activo por el pulsador de arranque
unsigned long actualAgitador;                 //para saber cuando se activó el arranque del agitador
unsigned long finretardoAlarma;
unsigned long tiempoAnteriorEncendido;
unsigned long tiempoAnteriorApagado;
byte (electrovalvula);
byte (llenadoAgitador);


void setup() {

  intervaloEncendido=120000;          //agitador encendido durante 2 minutos

  intervaloApagado=600000;            //agitador apagado durante 10 minutos
  
  intervaloArranque=600000;           //agitador encendido al activar pulsador de arranque durante 10 minutos

  retardoAlarma=300000;               //alarma apagada durante 5 minutos

  finretardoAlarma=0;

  tiempoAnteriorEncendido=0;

  tiempoAnteriorApagado=0;
  
  estadoAgitador=false;               //para que el agitador empiece encendido

  electrovalvula=true;                //para que la electrovalvula empiece apagada

  pinMode(2,OUTPUT);                  //Contactor Agitador

  pinMode(8,INPUT);                   //Nivel Bajo

  pinMode(12,INPUT);                  //Pulsador anulación Alarma

  pinMode(4,OUTPUT);                  //Alarma

  pinMode(10,INPUT);                  //Pulsador Llenado

  pinMode (3,OUTPUT);                 //Electroválvula

  pinMode(5,OUTPUT);                  //Led Llenado

  pinMode(9,INPUT);                   //Nivel Alto

  pinMode(11,INPUT);                  //Pulsador Agitador

}


void loop() {
 digitalWrite(2,estadoAgitador);
 digitalWrite(3,electrovalvula);
  {
    if ((electrovalvula == false)||(arranqueAgitador == true)) {                              //si la electrovalvula está activa o el agitador se activó por el pulsador de arranque
      digitalWrite(2,LOW);                                                                   //activa el agitador
      estadoAgitador=false;
    }
     else{                                                                                   //de lo contrario
      if ((millis()-tiempoAnteriorEncendido>=intervaloEncendido)&&estadoAgitador==false) {   //comprueba el tiempo transcurrido en el ciclo encendido del agitador
      estadoAgitador=true;
      digitalWrite(2,estadoAgitador);
      tiempoAnteriorApagado=millis();
     }
      if ((millis()-tiempoAnteriorApagado>=intervaloApagado)&&estadoAgitador==true) {        //comprueba el tiempo transcurrido en el ciclo apagado del agitador
      estadoAgitador=false;
      digitalWrite(2,estadoAgitador);
      tiempoAnteriorEncendido=millis();
     }
     }
     if ((digitalRead(8) == false)&&(electrovalvula == true)) {                              //consulta el estado del nivel bajo y si la electrovalvula está apagada
      digitalWrite(2,HIGH);                                                                   //desactiva el agitador
      estadoAgitador=true;
      if (digitalRead(12) == true) {                                                          //consulta el pulsador de la alarma
        delay (50);
        finretardoAlarma=millis()+retardoAlarma;                                              //fija la variable del fin del retardo de la alarma
        digitalWrite(4,HIGH);                                                                 //apaga la alarma
        }
      if (finretardoAlarma <= millis()) {                                                     //si se ha superado el número fijado en el retardo de la alarma y el nivel bajo sigue bajo
        digitalWrite(4,LOW);                                                                  //enciende la alarma
      }
     }
     if (digitalRead(8) == true) {                                                            //consulta que está por encima del nivel bajo
        digitalWrite(4,HIGH);                                                                 //apaga la alarma
      }
    if ((digitalRead(10) == true)&&(electrovalvula == true)) {                               //consulta el pulsador de llenado y si la electrovalvula no está activa
      delay (50);
      digitalWrite(2,LOW);                                                                    //activa el agitador
      digitalWrite(3,LOW);                                                                    //activa la electrovalvula
      electrovalvula=false;
      digitalWrite(5,HIGH);                                                                   //activa el led de llenado
      digitalWrite(4,HIGH);                                                                   //desactiva la alarma
     }
    if ((digitalRead(9) == false)&&(electrovalvula == false)) {                                //consulta el nivel alto y si la electrovalvula está activa
      digitalWrite(2,HIGH);                                                                   //desactiva el agitador
      digitalWrite(3,HIGH);                                                                   //desactiva la electrovalvula
      electrovalvula=true;
      llenadoAgitador=true;
      digitalWrite(5,LOW);                                                                    //desactiva el led de llenado
      digitalWrite(4,HIGH);                                                                   //desactiva la alarma
     }
    if ((digitalRead(12) == true)&&(electrovalvula == false)) {                                //consulta el pulsador de la alarma y si la electrovalvula está activa, cancela el llenado
      delay (50);
        digitalWrite(2,HIGH);                                                                 //desactiva el agitador
        digitalWrite(3,HIGH);                                                                 //desactiva la electrovalvula
        electrovalvula=true;
        llenadoAgitador=true;
        digitalWrite(5,LOW);                                                                  //desactiva el led de llenado
        digitalWrite(4,HIGH);                                                                 //desactiva la alarma
       }
    if ((digitalRead(11) == true)||(llenadoAgitador == true)) {                               //consulta el pulsador del agitador
      arranqueAgitador=true;
      llenadoAgitador=false;
      actualAgitador=millis();                                                                //iguala actualAgitador a millis
      digitalWrite(2,LOW);                                                                    //activa el agitador
     }
    if ((millis()-intervaloArranque)>=actualAgitador) {                                       //si millis menos intervaloArranque se iguala a cuando se inicio actualAgitador
      arranqueAgitador=false;
      digitalWrite(2,HIGH);                                                                   //desactiva el agitador
     }

}
}

Pongo una foto para que veáis el montaje.

En las pruebas de ayer, se sumó otro problema y es que cuando lleva unas horas funcionando se bloquea y no hace nada, ni cuando pulsas un botón. Eso si que ya no se por qué puede ser.

Gracias,