Control de puerta de garaje (funciona)

Hola. Para quien le haga falta. Está funcionando perfectamente. Y para los que saben, que señalen los horrores que he cometido y algunos aprenderemos. Saludos.
JV

unsigned long Crono = 0;
unsigned long inicio_cuenta = 0 ;
const int photoPin = 9;         //FOTOCÉLULA
const int final_abrirPin = 12;  //FINAL DE CARRERA ABRIR
const int pulsadorPin = 10;     //PULSADOR
const int final_cerrarPin = 13; //FINAL DE CARRERA CERRAR
const int M_ABREPin = 15;       //SEÑAL MOTOR ABRIR
const int M_CIERRAPin = 14;     //SEÑAL MOTOR CERRAR
int photo, final_abrir, pulsador, final_cerrar;
int estado = 0;
int indice = 0;

void setup() {
  pinMode (photoPin, INPUT);            // 9-- 0
  pinMode (final_abrirPin, INPUT);      //12-- 1
  pinMode (final_cerrarPin, INPUT);     //13-- 0
  pinMode (pulsadorPin, INPUT);         //10-- 0
  pinMode (M_ABREPin, OUTPUT);          //15-- ?
  pinMode (M_CIERRAPin, OUTPUT);        //14-- ?

  photo = digitalRead(photoPin);
  final_abrir = digitalRead(final_abrirPin);
  pulsador = digitalRead(pulsadorPin);
  final_cerrar  = digitalRead(final_cerrarPin);
  digitalWrite (M_ABREPin, LOW);
  digitalWrite (M_CIERRAPin, LOW);

  delay(500);

  if (final_cerrar == HIGH ) {	//Por si se cortó la corriente
    digitalWrite(M_CIERRAPin, HIGH);
    estado = 3;
  }
}

void loop() {
  switch (estado) {
    case 0: //SI PULSADOR = HIGH, ABRIMOS
      pulsador = digitalRead(pulsadorPin);
      if (pulsador == HIGH)
      {
        digitalWrite(M_ABREPin, HIGH);
        estado = 1;
      }
      break;
    //**********************
    case 1: //ESPERAMOS FIN DE CARRERA ABRIR
      final_abrir = digitalRead(final_abrirPin);
      if (final_abrir == LOW)
      { para();
        estado = 2;
        inicio_cuenta = millis();
        Crono = inicio_cuenta + 30000UL;
      }
      break;
    //*******************
    case 2: // ESPERAMOS POR EL PULSADOR O TIEMPO PARA CERRAR.
      indice = 0;
      pulsador = digitalRead(pulsadorPin);
      while (Crono < millis() || pulsador == HIGH)    //|=alt+124
      { Crono = millis() + 30000UL;
        digitalWrite(M_CIERRAPin, HIGH);    // empezamos a cerrar...
        estado = 3;    // si superamos 120 segundos o pulsamos
        final_cerrar = digitalRead(final_cerrarPin);
        final_abrir = HIGH;
        pulsador = digitalRead(pulsadorPin);
      }
      break;
    //*******************
    case 3: //SUPERVISAMOS PULSADOR Y CELULA MIENTRAS ESPERAMOS FIN DE CIERRE
      while (final_cerrar == HIGH )
      { pulsador = digitalRead(pulsadorPin);
        photo = digitalRead(photoPin);
        if (pulsador == HIGH || photo == HIGH) //Pulsacion de peligro
        { para();
          delay(100);
          indice = 1;
          digitalWrite(M_ABREPin, HIGH);
          break;
        }
        final_cerrar = digitalRead(final_cerrarPin);
      }
      estado = indice;
      if (estado == 1) {
        digitalWrite(M_ABREPin, HIGH);
      }
      else {
        para();
      }
      pulsador = digitalRead(pulsadorPin);
      break;
  }  
}      
//**********************
void para() {	// Funcion PARAR
  digitalWrite(M_ABREPin, LOW);
  digitalWrite(M_CIERRAPin, LOW);
}

Por ahora el único error es haer definido Crono como float.
Debe ser unsigned long porque luego lo comparas con millis() y mas alla que ahora te funcione estoy seguro que habrá mayores problemas con números mayores.
Y en el mismo tema cuando haces cosas como esta

Crono = inicio_cuenta + 30000;

mejor es así

Crono = inicio_cuenta + 30000UL;  // UL es unsigned long y no le das margen al compilador para errores.

Sigo analizando...

Hola.
Gracias Surbyte. Corregido. TODO este programa lo he hecho gracias a tus indicaciones. Gracias. Saludos
JV

Debo decirte que el programa esta muy bien, lo único que no me convence es que dentro de los case tienes esos while que no salen hasta que cambie algo. Ahi tenemos una diferencia de criterio pero visto que el resto del código forma parte de la máquina de estados que has creado, esta bien.
Muchos al igual que yo, no lo hacemos asi. No mantenmos las cosas dentro de un case. El case debe ser la opción dentro de la máquina de estados y el programa debe fluir para atender todo o externo que haga falta.
Ejemplo: que pasaría si tu sistema tuviera que prestar atención a una entrada serial de un BT o un GPS, tendrías que incluirla dentro de ese loop.
Y si hubiera un teclado o teclas para salir cuando alguien digita algo? Lo mismo.
Entonces... lo correcto es que tus estados hagan lo que deban y si necesitas agrega mas estados intermedios a los que no se llega si no se cumplen las condiciones de esos while.
Dime si me comprendes?

Mira tu case 3: por tomar uno
En cuanto comienza me quedo ATRAPADO en

while(final_cerrar)

asi lo haría yo, no necesito preguntar en cada case

  pulsador = digitalRead(pulsadorPin);

Lo hago en cada loop
No comparto esto que haces en case 2:

final_abrir = HIGH;

final_abrir es la entrada que responde a un final de carrera (supongo) no puedes forzar su estado, el estado debe ser el que refleja la lectura del pin correspondiente.

Esta es la versión que te propongo. Tengo alguna duda en el comportamiento de case 3 que desdoblado en 2 o sea un estado = 3 y otro = 4.

unsigned long Crono;
unsigned long inicio_cuenta = 0 ;
const int photoPin = 9;         //FOTOCÉLULA
const int final_abrirPin = 12;  //FINAL DE CARRERA ABRIR
const int pulsadorPin = 10;     //PULSADOR
const int final_cerrarPin = 13; //FINAL DE CARRERA CERRAR
const int M_ABREPin = 15;       //SEÑAL MOTOR ABRIR
const int M_CIERRAPin = 14;     //SEÑAL MOTOR CERRAR
int photo, final_abrir, pulsador, final_cerrar;
int estado = 0;
int indice = 0;

void setup() {
  pinMode (photoPin, INPUT);            // 9-- 0
  pinMode (final_abrirPin, INPUT);      //12-- 1
  pinMode (final_cerrarPin, INPUT);     //13-- 0
  pinMode (pulsadorPin, INPUT);         //10-- 0
  pinMode (M_ABREPin, OUTPUT);          //15-- ?
  pinMode (M_CIERRAPin, OUTPUT);        //14-- ?

  digitalWrite (M_ABREPin, LOW);
  digitalWrite (M_CIERRAPin, LOW);

  delay(500);

  if (final_cerrar) {	//Por si se cortó la corriente
      digitalWrite(M_CIERRAPin, HIGH);
      estado = 3;
  }
}

void loop() {
  photo = digitalRead(photoPin);
  final_abrir = digitalRead(final_abrirPin);
  pulsador = digitalRead(pulsadorPin);
  final_cerrar  = digitalRead(final_cerrarPin);

  switch (estado) {
    case 0: //SI PULSADOR = HIGH, ABRIMOS
            if (pulsador)  {
              digitalWrite(M_ABREPin, HIGH);
              estado = 1;
            }
            break;
          
    case 1: //ESPERAMOS FIN DE CARRERA ABRIR
            if (!final_abrir) { 
                para();
                estado = 2;
                inicio_cuenta = millis();
            }
            break;
            
    case 2: // ESPERAMOS POR EL PULSADOR O TIEMPO PARA CERRAR.
            indice = 0;
            digitalWrite(M_CIERRAPin, HIGH);    // empezamos a cerrar...
            if (millis() - inicio_cuenta > 30000UL || pulsador) {   //|=alt+124
                estado = 3;    // si superamos 120 segundos o pulsamos
            }
            break;

    case 3: //SUPERVISAMOS PULSADOR Y CELULA MIENTRAS ESPERAMOS FIN DE CIERRE
            if (final_cerrar) { 
                if (pulsador || photo) { //Pulsacion de peligro
                    para();
                    delay(100);
                    indice = 1;
                    digitalWrite(M_ABREPin, HIGH);
                }
            }
            else 
              estado = 4;
            break;
    case 4:             
            estado = indice;
            if (estado == 1) {
              digitalWrite(M_ABREPin, HIGH);
            }
            else 
              para();
            break;
  }  
}      

void para() {	// Funcion PARAR
  digitalWrite(M_ABREPin, LOW);
  digitalWrite(M_CIERRAPin, LOW);
}

Como verás al comienzo del loop se leen todos los estados de los switch.
Y el flujo del programa no se detiene jamás, siempre garantiza que esta actualizado.
Si agregas un display, leds, una entrada de cualquier tipo no tendras problemas aunque claramente ahora no importe, solo sirve de ejemplo a futuro.

Hola nose si me podran ayudar estoy en medio de un examen y es muy importante nose ni como crear preguntas por aqui jajajaja os pongo las preguntas ruego ayuda me juego el curso
1
precedente: float medición;
medicion2 = int(medicion);

2 Dado el array
int vect={1,0,-5,7,10,2};

escribe un programa que por el puerto serie la posición (y no el valor) del número más grande del array vect.