Reemplazo de delay por millis()

Hola. Lo que debe hacer este programa es muy simple. Con cuatro pulsadores con led contrlar un motor (arranque, parada y dirección).

El arranque y la parada lo hace con un pulso de 200ms.

He cambiado los delay por millis, pero no estoy muy convencido de si habré ganado en algo y de si estará bien hecho.

Y ya puesto quizás el programa se puede escribir, como decir, mas profesional, mas bonito. Me echais una mano? Gracias.
Un saludo.
JoseV

// CONTROLADOR CDS

unsigned long tiempoEspera = 200; // Esperar durante 200 milisegundos
unsigned long tiempoInicio = millis();

const int PulsadorStarPin = 3;  //pulsador
const int LedStartPin = 4;      //led
const int PulsadorStopPin = 5;
const int LedStopPin = 6;
const int PulsadorFwPin = 7;    //forward
const int LedFwPin = 8;
const int PulsadorRvPin = 9;    //Reversa
const int LedRvPin = 10;
const int MotorStartPin = 11;
const int MotorStopPin = 12;
const int MotorFwPin = 13;

int start, sstop, fw, rv;
int estado = 0;

void setup() {
  pinMode(PulsadorStarPin, INPUT_PULLUP);
  pinMode(PulsadorStopPin, INPUT_PULLUP);
  pinMode(PulsadorFwPin, INPUT_PULLUP);
  pinMode(PulsadorRvPin, INPUT_PULLUP);

  pinMode(MotorStartPin, OUTPUT);
  pinMode(MotorStopPin, OUTPUT);
  pinMode(MotorFwPin, OUTPUT);  //fw. HIGH

  pinMode(LedStartPin, OUTPUT);  //led Start
  pinMode(LedStopPin, OUTPUT);   //led Stop
  pinMode(LedRvPin, OUTPUT);     //led Rv
  pinMode(LedFwPin, OUTPUT);     //led am

  digitalWrite(LedStartPin, LOW);
  digitalWrite(LedStopPin, HIGH);
  digitalWrite(LedRvPin, LOW);
  digitalWrite(LedFwPin, HIGH);

  digitalWrite(MotorStartPin, HIGH);
  digitalWrite(MotorStopPin, LOW);
  digitalWrite(MotorFwPin, HIGH);  //Adelante

  delay(500);
}

void loop() {
  switch (estado) {
    case 0:
      start = digitalRead(PulsadorStarPin);  //2
      if (start == LOW) {                    //Start ON
        digitalWrite(LedStartPin, HIGH);     //Encendemos Led Start
        digitalWrite(LedStopPin, LOW);      //Apagamos Led Stop

        /*      digitalWrite(MotorStartPin, LOW);	//Pulso start con delay
                delay(200);							            //--
                digitalWrite(MotorStartPin, HIGH);	//--
        */

        digitalWrite(MotorStartPin, LOW);     //Arrancamos con PULSO 200 ms
        while (millis() - tiempoInicio < tiempoEspera) {
          // No hay acciones específicas que realizar durante el tiempo de espera
        }
        digitalWrite(MotorStartPin, HIGH);     //Fin del Pulso
      }
      estado = 1;
      break;
    //**********************
    case 1:
      sstop = digitalRead(PulsadorStopPin);  //4
      if (sstop == LOW) {                    //Stop ON
        digitalWrite(LedStartPin, LOW);      //Apagamos Led Start
        digitalWrite(LedStopPin, HIGH);     //Encendemos led Stop
        digitalWrite(LedFwPin, HIGH);        //9  Encendemos led Fw
        digitalWrite(LedRvPin, LOW);         //7  Apagamos led Reversa

        /*      digitalWrite(MotorStopPin, HIGH);//Pulso stop con delay
                delay(200);
                digitalWrite(MotorStopPin, LOW);
        */
        digitalWrite(MotorStartPin, HIGH);    //Paramos con PULSO 200 ms
        while (millis() - tiempoInicio < tiempoEspera) {
          // No hay acciones específicas que realizar durante el tiempo de espera
        }
        digitalWrite(LedStartPin, HIGH);
        digitalWrite(MotorFwPin, HIGH);  //Adelante
      }
      estado = 2;
      break;
    //*******************
    case 2:
      rv = digitalRead(PulsadorRvPin);  //6
      if (rv == LOW) {
        digitalWrite(LedRvPin, HIGH);   //7
        digitalWrite(LedFwPin, LOW);    //9
        digitalWrite(MotorFwPin, LOW);  //Reversa
      }
      estado = 3;
      break;
    //*******************
    case 3:
      fw = digitalRead(PulsadorFwPin);  //8
      if (fw == LOW) {
        digitalWrite(LedFwPin, HIGH);    //9
        digitalWrite(LedRvPin, LOW);     //7
        digitalWrite(MotorFwPin, HIGH);  //Adelante
      }
      estado = 0;
      break;
  }
}

https://forum.arduino.cc/t/entender-millis-y-no-morir-en-el-intento/626976/30
Lee esta guía.
Ahora lo miro y te hago las observaciones.

Lo hice muy rápido revisa el código y mira como se comporta

#include <Arduino.h>

// CONTROLADOR CDS

unsigned long tiempoEspera = 200; // Esperar durante 200 milisegundos
unsigned long tiempoInicio = millis();

const int PulsadorStarPin = 3;  //pulsador
const int LedStartPin = 4;      //led
const int PulsadorStopPin = 5;
const int LedStopPin = 6;
const int PulsadorFwPin = 7;    //forward
const int LedFwPin = 8;
const int PulsadorRvPin = 9;    //Reversa
const int LedRvPin = 10;
const int MotorStartPin = 11;
const int MotorStopPin = 12;
const int MotorFwPin = 13;

int start, sstop, fw, rv;
int estado = 0;

void setup() {
  pinMode(PulsadorStarPin, INPUT_PULLUP);
  pinMode(PulsadorStopPin, INPUT_PULLUP);
  pinMode(PulsadorFwPin, INPUT_PULLUP);
  pinMode(PulsadorRvPin, INPUT_PULLUP);

  pinMode(MotorStartPin, OUTPUT);
  pinMode(MotorStopPin, OUTPUT);
  pinMode(MotorFwPin, OUTPUT);  //fw. HIGH

  pinMode(LedStartPin, OUTPUT);  //led Start
  pinMode(LedStopPin, OUTPUT);   //led Stop
  pinMode(LedRvPin, OUTPUT);     //led Rv
  pinMode(LedFwPin, OUTPUT);     //led am

  digitalWrite(LedStartPin, LOW);
  digitalWrite(LedStopPin, HIGH);
  digitalWrite(LedRvPin, LOW);
  digitalWrite(LedFwPin, HIGH);

  digitalWrite(MotorStartPin, HIGH);
  digitalWrite(MotorStopPin, LOW);
  digitalWrite(MotorFwPin, HIGH);  //Adelante

  delay(500);
}

void loop() {
  switch (estado) {
    case 0: start = digitalRead(PulsadorStarPin);  //2
            if (start == LOW) {                    //Start ON
                digitalWrite(LedStartPin, HIGH);     //Encendemos Led Start
                digitalWrite(LedStopPin, LOW);       //Apagamos Led Stop
                digitalWrite(MotorStartPin, LOW);	//Pulso start con delay
                estado = 1;
                tiempoInicio = millis();               
            }    
            break;
    case 2: // tal vez haya que mantener la situacion de if (start == LOW) { 
            if (millis() - tiempoInicio < tiempoEspera) {
                digitalWrite(MotorStartPin, HIGH);	//--
                estado = 3;
            }
            break;

    case 3: sstop = digitalRead(PulsadorStopPin);  //4
            if (sstop == LOW) {                    //Stop ON
                digitalWrite(LedStartPin, LOW);      //Apagamos Led Start
                digitalWrite(LedStopPin, HIGH);     //Encendemos led Stop
                digitalWrite(LedFwPin, HIGH);        //9  Encendemos led Fw
                digitalWrite(LedRvPin, LOW);         //7  Apagamos led Reversa
                digitalWrite(MotorStartPin, HIGH);	//Pulso start con delay
                estado = 4;
                tiempoInicio = millis();
            }
            break;
    case 4: // 
            if (millis() - tiempoInicio < tiempoEspera) {
              digitalWrite(MotorStartPin, LOW);	//--
              estado = 5;
            }
            digitalWrite(LedStartPin, HIGH);  // revisa si esto va o no
            digitalWrite(MotorFwPin, HIGH);   //
            break;

    case 5:
            rv = digitalRead(PulsadorRvPin);  //6
            if (rv == LOW) {
              digitalWrite(LedRvPin, HIGH);   //7
              digitalWrite(LedFwPin, LOW);    //9
              digitalWrite(MotorFwPin, LOW);  //Reversa
            }
            estado = 6;
            break;
    case 6:
            fw = digitalRead(PulsadorFwPin);  //8
            if (fw == LOW) {
                digitalWrite(LedFwPin, HIGH);    //9
                digitalWrite(LedRvPin, LOW);     //7
                digitalWrite(MotorFwPin, HIGH);  //Adelante
            }
            estado = 0;
            break;
  }
}

Hola. Gracias Surbyte. Me alegra que un Gran Maestro fije su atención en mis pequeños trabajos.
Si tienes a bien le echas un vistazo a ver si pueden valer las modificaciones que he hecho siguiendo tus sugerencias.
No lo he probado mucho porque no me fío para esas cuentas de los simuladores.
Un Saludo
Jose V

#include <Arduino.h>

// CONTROLADOR CDS

unsigned long tiempoEspera = 200;  // Esperar durante 200 milisegundos
unsigned long tiempoInicio = millis();

const int PulsadorStarPin = 3;  //pulsador
const int LedStartPin = 4;      //led
const int PulsadorStopPin = 5;
const int LedStopPin = 6;
const int PulsadorFwPin = 7;  //forward
const int LedFwPin = 8;
const int PulsadorRvPin = 9;  //Reversa
const int LedRvPin = 10;
const int MotorStartPin = 11;
const int MotorStopPin = 12;
const int MotorFwPin = 13;

int start, sstop, fw, rv;
int estado = 0;

void setup() {
  pinMode(PulsadorStarPin, INPUT_PULLUP);
  pinMode(PulsadorStopPin, INPUT_PULLUP);
  pinMode(PulsadorFwPin, INPUT_PULLUP);
  pinMode(PulsadorRvPin, INPUT_PULLUP);

  pinMode(MotorStartPin, OUTPUT);
  pinMode(MotorStopPin, OUTPUT);
  pinMode(MotorFwPin, OUTPUT);  //fw. HIGH

  pinMode(LedStartPin, OUTPUT);  //led Start
  pinMode(LedStopPin, OUTPUT);   //led Stop
  pinMode(LedRvPin, OUTPUT);     //led Rv
  pinMode(LedFwPin, OUTPUT);     //led am

  digitalWrite(LedStartPin, LOW);
  digitalWrite(LedStopPin, HIGH);
  digitalWrite(LedRvPin, LOW);
  digitalWrite(LedFwPin, HIGH);

  digitalWrite(MotorStartPin, HIGH);
  digitalWrite(MotorStopPin, LOW);
  digitalWrite(MotorFwPin, HIGH);  //Adelante

  delay(500);
}

void loop() {
  switch (estado) {
    case 0:
      start = digitalRead(PulsadorStarPin);  //2
      if (start == LOW) {                    //Start ON con Pulso bajo
        digitalWrite(LedStartPin, HIGH);     //Encendemos Led Start
        digitalWrite(LedStopPin, LOW);       //Apagamos Led Stop
        digitalWrite(MotorStartPin, LOW);    //Pulso start con delay

        tiempoInicio = millis();
      }
      if (millis() - tiempoInicio < tiempoEspera && (start = 0)) {  // Para que sólo eche cuentas en esta condicion
        digitalWrite(MotorStartPin, HIGH);                          //--
      }
      estado = 1;
      break;

    case 1:
      sstop = digitalRead(PulsadorStopPin);  //4
      if (sstop == LOW) {                    //Stop ON con Pulso alto
        digitalWrite(LedStartPin, LOW);      //Apagamos Led Start
        digitalWrite(LedStopPin, HIGH);      //Encendemos led Stop
        digitalWrite(LedFwPin, HIGH);        //9  Encendemos led Fw
        digitalWrite(LedRvPin, LOW);         //7  Apagamos led Reversa

        tiempoInicio = millis();
      }

      if (millis() - tiempoInicio < tiempoEspera && sstop) {  // Lo mismo que antes
        digitalWrite(MotorStartPin, LOW);                     //--
      }
      estado = 2;
      break;

    case 2:
      rv = digitalRead(PulsadorRvPin);  //6
      if (rv == LOW) {
        digitalWrite(LedRvPin, HIGH);   //7
        digitalWrite(LedFwPin, LOW);    //9
        digitalWrite(MotorFwPin, LOW);  //Reversa
      }
      estado = 3;
      break;
    case 3:
      fw = digitalRead(PulsadorFwPin);  //8
      if (fw == LOW) {
        digitalWrite(LedFwPin, HIGH);    //9
        digitalWrite(LedRvPin, LOW);     //7
        digitalWrite(MotorFwPin, HIGH);  //Adelante
      }
      estado = 0;
      break;
  }
}

Pues fíate como tu dices porque nosotros usamos mucho esos simuladores para no tener que invertir mas tiempo en reproducir ciertos casos.

No entiendo esto:

start es la variable que viene del estado del pulsador y en teoria buscas LOW
Antes preguntas si esta en LOW y supongo accionas el motor con

digitalWrite(MotorStartPin, LOW);    //Pulso start con delay

y luego tienes esta linea que no me gusta

if (millis() - tiempoInicio < tiempoEspera && (start = 0)) {

acabas de activar tiempoinicio con un valor porque el boton esta presionado en LOW y le pides que mientras estemos en un lapso de tiempoEspera con boton en LOW que se encienda el motor?
O sea apagas y 1 useg despues enciendes?
Todo eso funcionará mientras presiones el boton porque cuando lo sueltes no hara ni una cosa ni otra y se queda en? motor apagado

La idea sería que presiones el boton pero mirando el flanco y no el estado LOW
Luego de tiempoespera entonces apagas el motor.
veo que esta lógica errada esta en el resto del código

Esto corrige tu primer case pero debes hacer lo mismo con los demás

case 0:
          start = digitalRead(PulsadorStarPin);  //2
          if (start == LOW && startAnt == HIGH) {                    //Start ON con Pulso bajo
            digitalWrite(LedStartPin, HIGH);     //Encendemos Led Start
            digitalWrite(LedStopPin, LOW);       //Apagamos Led Stop
            digitalWrite(MotorStartPin, LOW);    //Pulso start con delay

            tiempoInicio = millis();
          }
          if (millis() - tiempoInicio > tiempoEspera) {  // Para que sólo eche cuentas en esta condicion
              digitalWrite(MotorStartPin, HIGH);                          //--
          }
          startAnt = start;
          estado = 1;
          break;

Yo no lo hago de este modo.
Creo otro estado llamado 2 y desplazo los demás tal que el tiempo de espera sea el 2do estado.. ya la acción que inicia pasó.. ahora la acción o estado es esperar hasta que se cumpla tiempoEspera.
cuando se cumple, paso al estado 3 que es tu esado 2

Se comprende?

Hola. Voy a tratar de explicar mi razonamiento, que a buen seguro devendrá en ser errónea en algún o en todo momento, porque si ya tengo problemas con la sintaxis, con la lógica...
Cuando pasamos por case 0 , además de luces ponemos en marcha el motor, pero cuando llegamos al "if (millis() - ...) no le ha dado tiempo para que se cumpla y seguimos ejecutando hasta que en la pasadas siguiente o siguientes si se cumple; en consecuencia el flanco sube "digitalWrite(MotorStarPin, HIGH) y hemos completado el Pulso.
En siguientes pasadas start nos estará LOW y a partir de ese momento no cambia la situación.
en la linea "if (millis() - tiempoInicio < tiempoEspera && (start = 0))" para que sólo sea con el botón pulsado.
A mi suena bonito, pero esyoy preparado para enfrentarme a la realidad que seguramente me mostrarás.
Pero lo que he ejercitado mis escasas nueronas habrá valido la pena. Solo programo por ejercitar mi coco y me gusta. Aunque este proyecto si va a ser operativo.
Un saludo
JoseV

Explicación para case 0:
Como tu boton start fue presionado estamos en LOW repites esto cada case 0

        digitalWrite(LedStartPin, HIGH);     //Encendemos Led Start
        digitalWrite(LedStopPin, LOW);       //Apagamos Led Stop
        digitalWrite(MotorStartPin, LOW);    //Pulso start con delay

        tiempoInicio = millis();

En los reles de arduino poner un LOW es activar el RELE le estas diciendo 100 veces aunque eso no daña nada
activar motor activar motor activar motor activar motor activar motor activar motor activar motor activar motor activar motor activar motor activar motor activar motor activar motor
Espero a ver sido claro. Como dije.. ni se entera el rele que le pides en cada ciclo lo mismo, pero obviamente es una mala practica.
Luego nos encontramos con el if que incluye millis() y durante el intervalo y boton presionado le dices
desactivar motor desactivar motor desactivar motor desactivar motor desactivar motor desactivar motor desactivar motor desactivar motor desactivar motor desactivar motor
hasta que termina el intervalo y queda desactivado.

Asi que si la idea era ponerlo en marcha durante un tiempo eso no ocurrirá.

Como era mas que nada un ejercicio para trabajar con los tiempos de millis(), pues ya lo he practicado. Na iva fino el programa así que vuelvo para la aplicacion real a el bucle delay. Por 200ms o menos, ni es mucha espera ni merece seguir.
Por mí cerramos el hilo y a otro proyecto...Gracias.
Saludos
Jose V

Si me permites es un error volver a la cómoda del delay() y te explico por qué?
Mañana haces un código que tiene sensores, pulsadores y que tiene retardos de tiempo.
Dime como lo haras.. pondras delay y supon que el retardo es de 1 minuto.
Cuando pongas el delay de 1 min ni sensores ni pulsadores serán refrezcados o atendidos.
COnclusión ir por el camino del delay te estrellará tarde o temprano contra la pared.
Ve a Documentación y lee sobre millis(). Si quieres seguir en este mundo debes convivir con millis()

1 Like

Hola. Le daré alguna vuelta más. Estoy reparando el PC y cuando acabe seguiré en ello. Sé que estoy cerca. ya casi me simulaba bien.
Saludos.
Jose V

Hola. Después de peleas con el ordenador, con Windows y con el programa, le he dado unas vueltas y parece que funciona. Pongo solo los bloques de los pulsadores que interesan. Saludos.

const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int MotorStartPin = 11;
const int MotorStopPin = 12;

int flag1 = LOW;
int flag2 = LOW;
int state1 = HIGH;
int state2 = HIGH;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
int interval1 = 200;
int interval2 = 200;

void setup() {
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(MotorStartPin, OUTPUT);
  pinMode(MotorStopPin, OUTPUT);
  digitalWrite(MotorStartPin, HIGH);
  digitalWrite(MotorStopPin, LOW);
}

void loop() {
  unsigned long currentMillis = millis();
  state1 = digitalRead(buttonPin1);    //leer el botom
  if (state1 == 0) {                    //Si se ha pulado
    while (state1 == 0) {               //mantener hasta  soltar
      state1 = digitalRead(buttonPin1); //seguir leyendo el boton
    }
    digitalWrite(MotorStartPin, LOW);   //pulso por flanco de bajada
    flag1 = 1;                          // levantamos flag
    previousMillis1 = currentMillis;    // inicializamos previusMillis1
  }
  if (flag1 == HIGH && currentMillis - previousMillis1 >= interval1) { //Probamos si ha pasado el tiempo
    digitalWrite(MotorStartPin, HIGH);  // pulso por flanco de subida
  }
  //*****************************************************************
  state2 = digitalRead(buttonPin2);    //leer el botom
  if (state2 == 0) {                    //Si se ha pulsado
    while (state2 == 0) {               //mantener hasta  soltar
      state2 = digitalRead(buttonPin2); //seguir leyendo el boton
    }
    digitalWrite(MotorStopPin, HIGH);   //pulso por flanco de bajada
    flag2 = 1;                          // levantamos flag
    previousMillis2 = currentMillis;    // inicializamos previusMillis1
  }
  if (flag2 == HIGH && currentMillis - previousMillis2 >= interval2) { //Probamos si ha pasado el tiempo
    digitalWrite(MotorStopPin, LOW);   // pulso por flanco de subida
    //while(1);
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.