Entender millis y no morir en el intento

No tengo el código, pero si eres programador en delphi, debes saber que Lazarus es en realidad un clon de Delphi de código abierto y usando el compilador de freepascal. Iba a hacer el programa usando mi querido borland pero no lo encontraba por ningún sitio, así que descargué Lazarus.

En el programa hay un TForm que tiene contiene los siguientes componentes:

  • Un componente TTimer cuyo evento OnTimer() se ejecuta cada segundo y lo que hace es incrementar una variable llamada millis
  • 3 componentes TLabel fijos cuyo Caption son "millis()", "t=millis()", "millis()-t".
  • 3 componentes TLabel dinámicos cuyo Caption son los valores de millis, t y millis()-t. Estos caption
    se actualizan en cada llamada a la función OnTimer de TTimer.
  • Un componente TButton que al pulsar guarda en una variable t el valor de millis().

Cómo ves es francamente sencillo y si eres programador de Delphi adaptarlo no es un problema.

Ya no soy programador de Delphi pero si hago cositas para no dejarlo atrás, en su ía me gustaba mucho.

[TUTORIAL] Arduino Delphi 10.2 y Puerto serie

Seguiré haciendo más tutoriales sobre ello, esta vez me falta lectura de entradas y salidas analógicas.

Gracias.

Como puedes simular varios delay y que el periodo no sea un inconveniente entre ellos.

Por ejemplo:
Encender luz 2 segundos, apagar a los 2 segundos
después, Encender ventilador por segundos y apagarlo,
por último encender humificador por dos segundos.

Con delay es muy simple, pero cuando realizo con millis los tiempos se cruzan,

Utilice esta sintaxis pero tengo problemas

void loop() {
   task1();
   task2();
   task3();
}

void  task1() {
   //{period}: Periodo de Tiempo en el cual se va a ejecutar esta tarea
   unsigned long period=200; //En Milisegundos

   static unsigned long previousMillis=0;

   if((millis()-previousMillis)>period){
       // ---------------------------------
       // TODO:
       // Codigo de la Tarea 
       // ...
       // ---------------------------------
       previousMillis += period;
   }  
}

void  task2() {
   //{period}: Periodo de Tiempo en el cual se va a ejecutar esta tarea
   unsigned long period=500; //En Milisegundos

   static unsigned long previousMillis=0;

   if((millis()-previousMillis)>period){
       // ---------------------------------
       // TODO:
       // Codigo de la Tarea 
       // ...
       // ---------------------------------
       previousMillis += period;
   }  
}

En tu código lo que planteas son tres tareas diferentes task1, task2 y task3 que se van a ejecutar "concurrentemente" y no es el efecto que buscas.

Tu secuencia es:

paso1: encender luz, 2000ms
paso2: apagar luz, 2000ms
paso3: encender ventilador, 2000ms
paso4: apagar el ventilador y encender el humificador, 2000ms
paso5: apagar el humificador.

Ya tenemos los pasos y la duración de cada uno de ellos, así que necesitamos una variable para controlar el paso y como el tiempo es igual para todas no necesitamos almacenarlo, por ejemplo en un array.

Así el código podría ser parecido a este:

unsigned long t;
int paso=1;

void setup() {
  paso=1;
 digitalWrite(pinLuz, HIGH);
}

void loop() {
  if ( millis()-t > 2000 ) {
  paso ++; // aumentamos el paso.
 switch ( paso ) {
  case 2:
  digitalWrite(pinLuz, LOW);
 break;
  case 3:
  digitalWrite(pinVentilador);
 break;
 case 4:
  digitalWrite(pinVentilador, LOW);
 digitalWrite(pinHumificador, HIGH);
 break;
  case 5:
  digitalWrite(pinHumificador, LOW);
 break;
  default:
  break;
 }
 t=millis();
 }

En la sección de DOCUMENTACION hice un tutorial llamado Una forma sencilla de realizar secuencias, en la que explico como se pueden hacer este tipo de secuencias, con libreria incluida.

PD. El código que postees metelo entre las etiquetas CODE, para que los demas podamos trabajar sobre el.

Felicitarte Victorjam, por la molestia de dejarnos a todos una ayuda a entender unas de las cosas complicadas de esto, y felicitarte más aún por el trabajo de explicarlo todo paso a paso y a nivel de que todo el mundo lo pueda llegar a entender, que eso ha tenido que llevar bastante tiempo. GRACIAS.

Muchas gracias por el aporte y tu tiempo, creo que lo he pillado, lo pasaré a la práctica. Pero como ya dijeron, con lo contento que estaba yo con mis delay. :grinning:.

Cuanto me queda por aprender.

Millones de gracias, me sirvió muchísimo!!!!

Hola, buenas noches.
Estoy haciendo un sistema que tiene 10 sensores y 10 LEDs.
Intento que funcione que un sensor cuando detecte algo empieze un contador de 5 minutos y que te avise con el led encendido que ya pasaron los 5 minutos, lo hize con delay, pero tardan mucho algunos para apagarse cuando dejan de detectar, ahorita eh estado investigando de millis, solo que no se como implementarlo para que encienda el LED después de 5 minutos que sensa el sensor, solo eh logrado que encienda cuando sensa el sensor y que se apague después de cierto tiempo. Me puede ayudar, por favor.

No das muchas información, así que mas o menos intento explicarte como hacerlo.

Por un lado tendrás una función para leer el sensor, llamemos a dicha función leerSensorX. Y el valor leido estará en una variable variableX

Por otro lado tendrás una condición para que cuando haces la lectura, se active algo, en este caso el temporizador. Dicha condición la evaluaremos con una función condicionX() que devolverá true si la condicion del valor del sensor se cumple y false si es al contrario, teniendo en cuenta el valor de la variableX.

Tenemos un total de 10 leds para cada sensor y condicion. Lo llamaremos pinX.

Necesitaremos un total de 10 contadores, los llamaremos contadorX.

Dices que el tiempo es de 5 minutos por lo tanto el tiempo será fijo para todos.

Te pongo como sería para un sensor X.

unsigned long contadorX;

void setup() {
  contadorX=0;
}

void loop() {
  // Leemos el sensor y guardamos el valor en la variable.
  variableX = leerSensorX();

  // Si la variable está dentro de la condición entramos aquí.
  if ( condicionX(variableX) ) {
    // Si el contador vale 0, significa que aun no hemos empezado
    // a contar nada. Guardamos el valor actual de millis en el 
    // contador.
    if ( contadorX==0 ) {
      contadorX = millis();
    }
    // Si el contador no vale 0, significa que tenemos guardado el
    // tiempo en el que la condición se hizo cierta, hemos de comprobar
    // si el tiempo actual ha pasado de los 5 minutos. Si es asi
    // encendemos el led del indicador del sensor.
    else
    if ( millis()-contadorX > 5*60*1000 ) {
      digitalWrite(pinX, HIGH);
    }
  }
  // La condición no se cumple, apagamos el indicador y borramos el
  // tiempo guardado.
  else {
    contadorX = 0;
    digitalWrite(pinX, LOW);
  }
}

El código anterior funciona de tal manera que si la lectura del sensor cumple la condición durante 5 minutos el led se activará. Pero tiene que estar los 5 minutos. Si, por ejemplo, durante 1 minuto la condición es cierta, pero después se hace falsa, la proxima vez no acumula tiempo y tendrá que estar 5 minutos completos.

No especificas si los sensores son iguales, ni nada por el estilo. Así que este código es generico para un sensor. Tendrás que escribir el codigo para cada sensor, sustituyendo X por un número del 1 al 10.

Si todos los sensores/condiciones fueran iguales podriamos guardar la información en un array y realizar un bucle for para compactar el código.

Espero te sirva de ayuda para empezar. Quizás si tuviera un poco más de información podría ser mas específico.