Proyecto montacargas 4 plantas entra en bucle

Hola, os cuento mi situación, tengo entre manos un proyecto para grado superior que en la board me funcionaba pero en la maqueta ya no, y en la simulación nunca funciono.
El proyecto es un montacargas controlado por arduino de cuatro plantas, con 16 pulsadores, cuatro en cada planta, uno para llamar y el resto para enviar a una planta destino, y otros cuatro pulsadores que activa la cabina del montacargas.
En el código lo que hago es darle valores de 1 a 4 a las llamadas (para la llamada del bajo seria valor 1 , para el primero valor 2 y así.) , y a los pulsadores les doy el mismo valor de 1 a 4, con estos valores lo que hago es compararlos para activar el puente H, por ejemplo si la cabina está en la primera planta, nos dará un valor de 2, y la llamada la hacemos desde la planta 3, que tiene un valor de 4, el programara me debería de hacer un 2<4 por lo tanto activo el motor para que suba.
En resumen es muy sencillo, pero en la maqueta se me queda en bucle de subir y bajar cada vez que toca un pulsador la cabina.

Enlazo el código en texto y una captura de la simulación (en el proyecto a los pulsadores les precede una resistencia de 220ohm)

// pulsadores llamada
const int  llamada1 = 2;
const int  llamada2 = 3;
const int  llamada3 = 4;
const int  llamada4 = 5;

//sensores de planta
const int final1 = 6;
const int final2 = 7;
const int final3 = 8;
const int final4 = 9;

//moviento motor
const int bajar = 10;
const int subir = 11;

//variable para ascenso o descenso
int pisoactual;
int pisodestino;

void setup() {
  
//PIN DE LLAMADAS COMO ENTRADAS
pinMode(llamada1, INPUT);
pinMode(llamada2, INPUT);
pinMode(llamada3, INPUT);
pinMode(llamada4, INPUT);

//PIN DE FINAL DE CARRERA COMO ENTRADAS
pinMode(final1, INPUT);
pinMode(final2, INPUT);
pinMode(final3, INPUT);
pinMode(final4, INPUT);

//PINES DE MOVIMIENTO DE MOTOR SALIDAS
pinMode(subir, OUTPUT);
pinMode(bajar, OUTPUT);

}

void loop() {
if(digitalRead(final1)==HIGH)                         //asigadores de valor nuemerico para cada final de carrera
    {pisoactual=1;}                                   //cambio el nombre a pisoactual
if(digitalRead(final2)==HIGH)
    {pisoactual=2;}
if(digitalRead(final3)==HIGH)
    {pisoactual=3;} 
if(digitalRead(final4)==HIGH)
    {pisoactual=4;}

       
if(digitalRead(llamada1)==HIGH)                         //asigadores de valor nuemerico para cada final de llamada
    {pisodestino=1;}                                    //cambio el nombre a pisodestino
if(digitalRead(llamada2)==HIGH)
    {pisodestino=2;}
if(digitalRead(llamada3)==HIGH)
    {pisodestino=3;} 
if(digitalRead(llamada4)==HIGH)
    {pisodestino=4;} 


switch(pisodestino){
    case 1:                                             //caso para la llamada desde el bajo
    if (pisoactual>1)                                   //si el piso en el que esta el montacargas es mayor a 1, esto hara descender al motor
    {digitalWrite (bajar, HIGH);}
    if(digitalRead(final1)==HIGH)                       //cuando el final de carrera de la planta baja se active significa que ya esta el montacargas en la planta baja y detendra el motor
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}         
    break;

    case 2:                                             //caso para la llamada desde la primera planta
    if (pisoactual>2)
    {digitalWrite (bajar, HIGH);}
    else if (pisoactual<2)
    {digitalWrite (subir, HIGH);} 
    if(digitalRead(final2)==HIGH)
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}
    break;
 
    case 3:                                             //caso para la llamada desde la segunda planta
    if (pisoactual> 3)
    {digitalWrite (bajar, HIGH);}
    else if(pisoactual<3)
    {digitalWrite (subir, HIGH);}
    if(digitalRead(final3)==HIGH)
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}
    break;
  
    case 4:                                             //caso para la llamada desde la tercera planta 
    if (pisoactual<4)
    {digitalWrite (subir, HIGH);}
    if(digitalRead(final4)==HIGH)
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}
    break;
  }
}// pulsadores llamada
const int  llamada1 = 2;
const int  llamada2 = 3;
const int  llamada3 = 4;
const int  llamada4 = 5;

//sensores de planta
const int final1 = 6;
const int final2 = 7;
const int final3 = 8;
const int final4 = 9;

//moviento motor
const int bajar = 10;
const int subir = 11;

//variable para ascenso o descenso
int pisoactual;
int pisodestino;

void setup() {
  
//PIN DE LLAMADAS COMO ENTRADAS
pinMode(llamada1, INPUT);
pinMode(llamada2, INPUT);
pinMode(llamada3, INPUT);
pinMode(llamada4, INPUT);

//PIN DE FINAL DE CARRERA COMO ENTRADAS
pinMode(final1, INPUT);
pinMode(final2, INPUT);
pinMode(final3, INPUT);
pinMode(final4, INPUT);

//PINES DE MOVIMIENTO DE MOTOR SALIDAS
pinMode(subir, OUTPUT);
pinMode(bajar, OUTPUT);

}

void loop() {
if(digitalRead(final1)==HIGH)                         //asigadores de valor nuemerico para cada final de carrera
    {pisoactual=1;}                                   //cambio el nombre a pisoactual
if(digitalRead(final2)==HIGH)
    {pisoactual=2;}
if(digitalRead(final3)==HIGH)
    {pisoactual=3;} 
if(digitalRead(final4)==HIGH)
    {pisoactual=4;}

       
if(digitalRead(llamada1)==HIGH)                         //asigadores de valor nuemerico para cada final de llamada
    {pisodestino=1;}                                    //cambio el nombre a pisodestino
if(digitalRead(llamada2)==HIGH)
    {pisodestino=2;}
if(digitalRead(llamada3)==HIGH)
    {pisodestino=3;} 
if(digitalRead(llamada4)==HIGH)
    {pisodestino=4;} 


switch(pisodestino){
    case 1:                                             //caso para la llamada desde el bajo
    if (pisoactual>1)                                   //si el piso en el que esta el montacargas es mayor a 1, esto hara descender al motor
    {digitalWrite (bajar, HIGH);}
    if(digitalRead(final1)==HIGH)                       //cuando el final de carrera de la planta baja se active significa que ya esta el montacargas en la planta baja y detendra el motor
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}         
    break;

    case 2:                                             //caso para la llamada desde la primera planta
    if (pisoactual>2)
    {digitalWrite (bajar, HIGH);}
    else if (pisoactual<2)
    {digitalWrite (subir, HIGH);} 
    if(digitalRead(final2)==HIGH)
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}
    break;
 
    case 3:                                             //caso para la llamada desde la segunda planta
    if (pisoactual> 3)
    {digitalWrite (bajar, HIGH);}
    else if(pisoactual<3)
    {digitalWrite (subir, HIGH);}
    if(digitalRead(final3)==HIGH)
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}
    break;
  
    case 4:                                             //caso para la llamada desde la tercera planta 
    if (pisoactual<4)
    {digitalWrite (subir, HIGH);}
    if(digitalRead(final4)==HIGH)
    {digitalWrite (subir, LOW);
    digitalWrite (bajar, LOW);}
    break;
  }
}

montacargas funcional v1.0 (sin lcd).txt (3.01 KB)

Así a la pasada, yo lo que veo es que no hay delay después de leer el estado de cada botón, lo que puede hacer que se lea muchas veces ya que en cada ciclo se lee y si uno no suelta el botón a tiempo, pues...

Yo lo que haría para probar al menos, es leer el estado de los botones de llamada SÓLO cuando pisoactual == pisodestino, o sea cuando el montacargas no se está moviendo.

A ver como marcha asi
Modifica esto en las variables

//variable para ascenso o descenso
int pisoactual;
int pisodestino;
// agregar esto
bool vfinal1, vfinal1Ant;
bool vfinal2, vfinal2Ant;
bool vfinal3, vfinal3Ant;
bool vfinal4, vfinal4Ant;
bool vllamada1, vllamada1Ant;
bool vllamada2, vllamada2Ant;
bool vllamada3, vllamada3Ant;
bool vllamada4, vllamada4Ant;

y este el nuevo loop

void loop() {

	vfinal1 = digitalRead(final1);
	if (vfinal1 && vfinal1Ant)                         //asigadores de valor nuemerico para cada final de carrera
	    pisoactual = 1;                                //cambio el nombre a pisoactual 
	vfinal1Ant = vfinal1;    

	vfinal2 = digitalRead(final2);
	if (vfinal2 && vfinal2Ant)
	    pisoactual = 2;       
	vfinal2Ant = vfinal2;    
	
	vfinal3 = digitalRead(final3);
	if (vfinal3 && vfinal3Ant)
	    pisoactual = 3;       
	vfinal3Ant = vfinal3;    
	
	vfinal4 = digitalRead(final4);
	if (vfinal4 && vfinal4Ant)
	    pisoactual = 4;
	vfinal4Ant = vfinal4;    

	       
	vllamada1 = digitalRead(llamada1);
	if (vllamada1 && vllamada1Ant)                     // asigadores de valor nuemerico para cada final de llamada
	    pisodestino = 1;                               // cambio el nombre a pisodestino
	vllamada1Ant = vllamada1;    
	                               
	vllamada2 = digitalRead(llamada2);
	if (vllamada2 && vllamada2Ant)
	    pisodestino = 2;
	vllamada2Ant = vllamada2;

	vllamada3 = digitalRead(llamada3);
	if (vllamada3 && vllamada3Ant)
	    pisodestino = 3;
	vllamada3Ant = vllamada3;

	vllamada4 = digitalRead(llamada4);
	if (vllamada4 && vllamada4Ant)
	    pisodestino = 4;
	vllamada4Ant = vllamada4;

	switch (pisodestino) {
	    case 1:                                             //caso para la llamada desde el bajo
			    if (pisoactual > 1)                                   //si el piso en el que esta el montacargas es mayor a 1, esto hara descender al motor
			    	digitalWrite (bajar, HIGH);
			    if (digitalRead(final1)) {                     //cuando el final de carrera de la planta baja se active significa que ya esta el montacargas en la planta baja y detendra el motor
			    	digitalWrite (subir, LOW);
			    	digitalWrite (bajar, LOW); 
			    }         
			    break;

		case 2:                                             //caso para la llamada desde la primera planta
			    if (pisoactual >2)
			    	digitalWrite(bajar, HIGH);
			    else if (pisoactual<2)
			    	digitalWrite(subir, HIGH); 
			    if (digitalRead(final2)) {
			    	digitalWrite(subir, LOW);
			    	digitalWrite (bajar, LOW);
			    } 
			    break;
			 
		case 3:                                             //caso para la llamada desde la segunda planta
			    if (pisoactual > 3)
			    	digitalWrite(bajar, HIGH);
			    else if(pisoactual < 3)
			    	digitalWrite(subir, HIGH);
			    if (digitalRead(final3)) {
			    	digitalWrite(subir, LOW);
			    	digitalWrite (bajar, LOW);
			    } 
			    break;
			  
		case 4:                                             //caso para la llamada desde la tercera planta 
			    if (pisoactual < 4)
			    	digitalWrite(subir, HIGH);
			    if (digitalRead(final4)) {
			    	digitalWrite(subir, LOW);
			    	digitalWrite (bajar, LOW);
			    }
			    break;
	  }
}

Verifica a ver si la situación mejora/cambia.
NOTA: asi es como se deben postear los códigos. Te mandé privado por favor lee atentamente las indicaciones y luego realiza las correcciones.

Bueno, lo de /code lo intente pero no me lo cogía. Y gracias llegare a probarlo a casa, pero lo que más me interesa es aprender, y un compañero me comento de cambiar mis int por boléanos pero por qué? ¿Por qué pones v delante de las llamadas (vllamada) y por qué luego creas otra igual que acaba en Ant?

Con este proyecto apruebo o no el curso, pero eso me da igual, lo que busco es aprender a controlar esta herramienta y cuando acabe cogerme yo uno para mí y trastear sin límites ;)

lo llame vllamada como pude llamarlo valor_llamada, solo para que sea fácil. vllamada1 a 4 resulta como valor llamada 1 a 4. La variable Ant es para guardar el estado anterior.

Lo que hago es que tu pulsador en lugar de responder a HIGH o nivel alto, responde a un cambio de 0 a 1. Cuando va de LOW a HIGH. He probado y en la mayor cantidad de situaciones es suficiente para muchos pulsadores y entornos. Existen otras situaciones como la tuya donde yo usaría una rutina antirebotes o una librería como bounce, bounce2 o switch. Búscala en google asi: arduino bounce2 library o arduino switch library

Lo he estado consultando con un ingeniero en mis practicas y me explico todo lo que has hecho, hasta el organizarme bien las comillas y corchetes, te lo has currado, el programa ya esta funcionando a la perfección seguro que hay cosas redundantes que tendré que quitar o añadir para presentarlo.

Muchísimas gracias.

Aquí lo dejo por si alguien lo quiere copiar y quedárselo, que es de todos para todos.

// pulsadores llamada
const int  llamada1 = 2;
const int  llamada2 = 3;
const int  llamada3 = 4;
const int  llamada4 = 5;

//sensores de planta
const int final1 = 6;
const int final2 = 7;
const int final3 = 8;
const int final4 = 9;

//moviento motor
const int bajar = 10;
const int subir = 11;

//variable para ascenso o descenso
int pisoactual;
int pisodestino;

// boleanos para la asignacion de un numero a cada llamada o final de carrera 
//para poder operar
bool vfinal1, vfinal1Ant;
bool vfinal2, vfinal2Ant;
bool vfinal3, vfinal3Ant;
bool vfinal4, vfinal4Ant;
bool vllamada1, vllamada1Ant;
bool vllamada2, vllamada2Ant;
bool vllamada3, vllamada3Ant;
bool vllamada4, vllamada4Ant;

void setup() {
  
//PIN DE LLAMADAS COMO ENTRADAS
pinMode(llamada1, INPUT);
pinMode(llamada2, INPUT);
pinMode(llamada3, INPUT);
pinMode(llamada4, INPUT);

//PIN DE FINAL DE CARRERA COMO ENTRADAS
pinMode(final1, INPUT);
pinMode(final2, INPUT);
pinMode(final3, INPUT);
pinMode(final4, INPUT);

//PINES DE MOVIMIENTO DE MOTOR SALIDAS
pinMode(subir, OUTPUT);
pinMode(bajar, OUTPUT);

}

void loop() {

  vfinal1 = digitalRead(final1);                     
  if (vfinal1 && vfinal1Ant)                         //asigadores de valor nuemerico para cada final de carrera
      pisoactual = 1;                                //cambio el nombre a pisoactual 
  vfinal1Ant = vfinal1;                              //de esta forma me aseguro que no entre por algun error
                                                     //y que se debean cumplir esas dos condiciones para entrar en el if
  vfinal2 = digitalRead(final2);
  if (vfinal2 && vfinal2Ant)
      pisoactual = 2;       
  vfinal2Ant = vfinal2;    
  
  vfinal3 = digitalRead(final3);
  if (vfinal3 && vfinal3Ant)
      pisoactual = 3;       
  vfinal3Ant = vfinal3;    
  
  vfinal4 = digitalRead(final4);
  if (vfinal4 && vfinal4Ant)
      pisoactual = 4;
  vfinal4Ant = vfinal4;    

         
  vllamada1 = digitalRead(llamada1);
  if (vllamada1 && vllamada1Ant)                     // asigadores de valor nuemerico para cada final de llamada
      pisodestino = 1;                               // cambio el nombre a pisodestino
  vllamada1Ant = vllamada1;    
                                 
  vllamada2 = digitalRead(llamada2);
  if (vllamada2 && vllamada2Ant)
      pisodestino = 2;
  vllamada2Ant = vllamada2;

  vllamada3 = digitalRead(llamada3);
  if (vllamada3 && vllamada3Ant)
      pisodestino = 3;
  vllamada3Ant = vllamada3;

  vllamada4 = digitalRead(llamada4);
  if (vllamada4 && vllamada4Ant)
      pisodestino = 4;
  vllamada4Ant = vllamada4;

  switch (pisodestino) {
      case 1:                                             //caso para la llamada desde el bajo
          if (pisoactual > 1)                                   //si el piso en el que esta el montacargas es mayor a 1, esto hara descender al motor
            digitalWrite (bajar, HIGH);
          if (digitalRead(final1)) {                     //cuando el final de carrera de la planta baja se active significa que ya esta el montacargas en la planta baja y detendra el motor
            digitalWrite (subir, LOW);
            digitalWrite (bajar, LOW); 
          }         
          break;

    case 2:                                             //caso para la llamada desde la primera planta
          if (pisoactual >2)
            digitalWrite(bajar, HIGH);
          else if (pisoactual<2)
            digitalWrite(subir, HIGH); 
          if (digitalRead(final2)) {
            digitalWrite(subir, LOW);
            digitalWrite (bajar, LOW);
          } 
          break;
       
    case 3:                                             //caso para la llamada desde la segunda planta
          if (pisoactual > 3)
            digitalWrite(bajar, HIGH);
          else if(pisoactual < 3)
            digitalWrite(subir, HIGH);
          if (digitalRead(final3)) {
            digitalWrite(subir, LOW);
            digitalWrite (bajar, LOW);
          } 
          break;
        
    case 4:                                             //caso para la llamada desde la tercera planta 
          if (pisoactual < 4)
            digitalWrite(subir, HIGH);
          if (digitalRead(final4)) {
            digitalWrite(subir, LOW);
            digitalWrite (bajar, LOW);
          }
          break;
    }
}

Bueno, varias cosas entonces para aprender y usar.
Hay que ser ordenado.
Indentar ayuda.
Comentar que se hace tambien.
mi nomenclatura es cómoda para mi pero puede no serlo para otro pero es eso, nomenclatura.
llamar vllamada1 o valor_llamada1 o simplemente valor1 es igual.
Basta con que lo expliques claramente.

Tambien explica como has montado los pulsadores o switches… si son pull up o pull down, las respuestas serán diferentes en cada caso.
Como te dije, suelo usar mucho (y muchos programadores tmb) esta tecnica de ver solo la transición 0 a 1 o 1 a 0.
Nada de ver cuando estoy solo en ALTO o BAJO. Eso no sirve porque le da multiples ordenes al resto del código.
Aca se lo digo solo una vez.
Por ejemplo… para mi decirle a un led enciedete con digitalWrite(LED, HIGH) me alcanza con una sola vez
imagina que si tu estas viendo un switch, que cambia de estado de 0 a 1, y entonces tu codigo dijera algo asi

if (switch == HIGH) 
   digitalWrite(LED, HIGH);

supongamos no lo se que eso fueran 200 useg por darle un tiempo, cada loop se malgastan 200 uSeg
En cambio ver la transición 0 a 1, ejecuta y gasta solo una vez 200 useg y luego serán solo supongamos 20 useg del iF que no se cumple porque no hay mas transición.
Se ve la sutileza pero prolijidad a la vez?
Son detalles que te haran destinar mas tiempo a aquellas cosas que lo requieran.
Recuerda que tenemos recursos limitados.
Lo mismo con las variables. Un estado es 0 o 1. porque o para qué usar int para algo que es 0 o 1.
Usar 16 bits para eso cuando 1 solo alcanza.
El problema del compilador optimazarlo y claro que lo hace. Por eso hay gente detras de la conversión del código C a código máquina del Arduino.