Carrito a control remoto controlado por arduino se atasca y no recibe ordenes

Mi proyecto consta de 3 modulos:
El transmisor (Funciona perfectamente)
El Receptor (Funciona perfecto aparentemente)
En Motor Driver (el que me esta dando problemas)

Los tres módulos los hice yo mismo, no son prefabricados pero tanto el receptor como el transmisor funcionan perfectamente, el receptor tiene Led's en cada salida de datos para monitorearlas y no aparenta haber ningún problema hasta ese punto.

El problema en concreto es que de pronto los motores que quedan "pegados" con la ultima orden recibida, por ejemplo si le ordeno "1000" (Adelante) a veces aunque suelte el pulsador y por ende se transmita y reciba "0000" se queda avanzando hacia adelante hasta que lo reseteo o lo apago y lo vuelvo a encender.

también ocurre que esta funcionando todo perfecto y de pronto envío dos ordenes a la vez, por ejemplo: "1010" (Adelante + Izquierda), y, primero, no las obedece, y segundo ocurre que se queda con la orden anterior pegado.

Este comportamiento me hace pensar que probablemente sea un problema en mi código, lo adjuntare como referencia.

Uso un Arduino Nano y 2 L293D para controlar los motores, a continuación el código y el circuito:

Codigo:

int ade = 12;
int atr = 11;
int der = 10;
int izq = 9;
int mtr01 = 8;
int mtr02 = 7;
int velder = 6;
int velizq = 5;

int valade = 0;
int valatr = 0;
int valder = 0;
int valizq = 0;
int vel1 = 0;
int vel2 = 0;

void setup() {
 pinMode(ade, INPUT);
 pinMode(atr, INPUT);
 pinMode(der, INPUT);
 pinMode(izq, INPUT);

 pinMode(mtr01, OUTPUT);
 pinMode(mtr02, OUTPUT);

}

void loop() {
  valade = digitalRead(ade);
  valatr = digitalRead(atr);
  valder = digitalRead(der);
  valizq = digitalRead(izq);

  

  if (valade == HIGH)
  {
    if (valatr == LOW){
    adelante();
    }
    else{
      detener();
    }
  }
  else if (valatr == HIGH)
  {
    if (valade == LOW){
    atras();
    }
    else{
      detener();
    }
   }
   else{
    detener();
   }
}

void adelante() { 
  if (valder == HIGH)
  {
    if (valizq == LOW){
    vel1 = 100;
    vel2 = 250;
    digitalWrite(mtr01, HIGH);
    digitalWrite(mtr02, LOW);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
    }
  }
  else if (valizq == HIGH)
  {
    if (valder == LOW){
      vel1 = 250;
      vel2 = 100;
      digitalWrite(mtr01, HIGH);
      digitalWrite(mtr02, LOW);
      analogWrite(velder, vel1);
      analogWrite(velizq, vel2);
    }
  }
  else{
  vel1 = 150;
  vel2 = 150;
  digitalWrite(mtr01, HIGH);
  digitalWrite(mtr02, LOW);
  analogWrite(velder, vel1);
  analogWrite(velizq, vel2);
  }
}

void atras() {
  if (valder == HIGH)
  {
    if (valizq == LOW){
      vel1 = 100;
      vel2 = 250;
      digitalWrite(mtr01, LOW);
      digitalWrite(mtr02, HIGH);
      analogWrite(velder, vel1);
      analogWrite(velizq, vel2);
    }
  }
  else if (valizq == HIGH)
  {
    if (valder == LOW){
      vel1 = 250;
      vel2 = 100;
      digitalWrite(mtr01, LOW);
      digitalWrite(mtr02, HIGH);
      analogWrite(velder, vel1);
      analogWrite(velizq, vel2);
    }
  }
  else {
    vel1 = 150;
    vel2 = 150;
    digitalWrite(mtr01, LOW);
    digitalWrite(mtr02, HIGH);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
  }
}

void detener () { 
  if (valder == HIGH)
  {
    if (valizq == LOW){
    digitalWrite(mtr01, HIGH);
    digitalWrite(mtr02, LOW);
    vel1 = 50;
    vel2 = 250;
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
    }
  }
  else if (valizq == HIGH)
  {
    if (valder == LOW){
    digitalWrite(mtr01, HIGH);
    digitalWrite(mtr02, LOW);
    vel1 = 250;
    vel2 = 50;
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
    }
  }
  else{
    vel1 = 0;
    vel2 = 0;
    digitalWrite(mtr01, LOW);
    digitalWrite(mtr02, LOW);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
  }
}

Circuito:

De antemano muchas gracias.

Porque esa costumbre de usar if else como si pudieran de ese modo controlar algo a consiencia?
dime como funciona esta parte del código?

  if (valade == HIGH)  {
      if (valatr == LOW){
          adelante();
    }
    else{
          detener();
    }
  }
  else if (valatr == HIGH)
  {
    if (valade == LOW){
    atras();
    }
    else{
      detener();
    }
   }
   else{
    detener();
   }

Porque yo veo muchos detener() y casi que no puedo entenderlo?
prueba con esta simplificación de tu código.

void loop() {
  valade = digitalRead(ade);
  valatr = digitalRead(atr);
  valder = digitalRead(der);
  valizq = digitalRead(izq);
  
  if (valade)  
      adelante();
  if (valatr)
      atras();
  if (!valade && !valatr)
      detener();
}

Si presionas valade vas adelante
si presionas valatr vas atras
y si no los presionas te detienes
Supongo que para ir adelante derecha presionas ambos y lo mismo a izquierda.
Los códigos de adelante y atras tambien esta sobrecargados pero si dices que funcionan no los corrijo.

Gracias por la respuesta.

Esa parte del código tiene tantos "Detener()" por que quería que cualquiera fuera otro caso no establecido, forzara la detención por defecto (esto lo corregí mas adelante).

Con el código simplificado que me sugieres modifiqué y simplifiqué todo el código; incluyendo las secciones de control de dirección que dices estaban muy sobrecargadas y obtuve esto:

int ade = 12;
int atr = 11;
int der = 10;
int izq = 9;
int mtr01 = 8;
int mtr02 = 7;
int velder = 6;
int velizq = 5;

int valade = 0;
int valatr = 0;
int valder = 0;
int valizq = 0;
int orden = 0;
/*int vel1 = 0;
int vel2 = 0;*/

void setup() {
 pinMode(ade, INPUT);
 pinMode(atr, INPUT);
 pinMode(der, INPUT);
 pinMode(izq, INPUT);

 pinMode(mtr01, OUTPUT);
 pinMode(mtr02, OUTPUT);

}

void loop() {
  valade = digitalRead(ade);
  valatr = digitalRead(atr);
  valder = digitalRead(der);
  valizq = digitalRead(izq);
  
  if (valade){
      adelante();
  }
  if (valatr){
      atras();
  }
  if (valade == valatr){
      detener();
  }
}

void adelante() {
   
  if (valder){
    WriteAdel(100,250);
  }
  
  if (valizq) {
    WriteAdel(250,100);
  }
  
  if (valder == valizq){
    WriteAdel(150,150);
  }
}

void atras() {
  
  if (valder){
      WriteAtra(100,250);
      }
      
  if (valizq){
    WriteAtra(250,100);
  }
  
  if (valder == valizq){
    WriteAtra(150,150);
  }
}

void detener() { 
  if (valder){
    WriteAdel(50,250);
  }
  
  if (valizq){
    WriteAdel(250,50);
  }
  
  if (valder == valizq){
    WriteDete();
  }
}

void WriteAdel(int vel1, int vel2) {
    digitalWrite(mtr01, HIGH);
    digitalWrite(mtr02, LOW);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
}

void WriteAtra(int vel1, int vel2) {
    digitalWrite(mtr01, LOW);
    digitalWrite(mtr02, HIGH);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
}

void WriteDete() {
    digitalWrite(mtr01, LOW);
    digitalWrite(mtr02, LOW);
    analogWrite(velder, 0);
    analogWrite(velizq, 0);
}

Con este nuevo código se solucionó la mitad del problema, Ya no se atascaba hacia adelante y atrás ni a derecha o izquierda a menos que se hiciera combinación de ambas, por ejemplo "Adelante + Derecha".

Estuve intentando diversos cambios pero ninguno terminaba de solucionar el problema del todo, así que traté de pensar de forma mas simple y tratar de prescindir lo mas que pude de los "if else" tal como lo sugieres también en la respuesta y decidí probar aislando los eventos de pulsación en "Casos".

Determiné 9 casos posibles:
Standby, Standby+derecha, Standby+Izquierda, Adelante, Adelante+Derecha, Adelante+Izquierda, Atras, Atras+Derecha y Atras+Izquierda.

Dividí el código en una etapa de "Reconocimiento de ordenes" basándome en elementos "if", y en una etapa de "Ejecución de ordenes" en la que se toma la resolución de la primera etapa y la ejecuta según el caso. ambas se juntan en el "Void Loop" en la linea: "OrderExecution(OrderPicking());".

El Código Resultante es este:

int ade = 12;
int atr = 11;
int der = 10;
int izq = 9;
int mtr01 = 8;
int mtr02 = 7;
int velder = 6;
int velizq = 5;

int valade = 0;
int valatr = 0;
int valder = 0;
int valizq = 0;

void setup() {
 pinMode(ade, INPUT);
 pinMode(atr, INPUT);
 pinMode(der, INPUT);
 pinMode(izq, INPUT);

 pinMode(mtr01, OUTPUT);
 pinMode(mtr02, OUTPUT);

}

void loop() { 
  valade = digitalRead(ade);
  valatr = digitalRead(atr);
  valder = digitalRead(der);
  valizq = digitalRead(izq);

  OrderExecution(OrderPicking());
}

//------------------------------Funciones:----------------------------------


int OrderPicking(){ // Retorna un valor entero entre 0 y 8
  
  int orden;
  
  if (!valade && !valatr && !valder && !valizq){ //0000 Detener / Standby
    orden = 0; 
  }
  if (!valade && !valatr && valder && !valizq){ //0010 Detener + Derecha
    orden = 1; 
  }  
  if (!valade && !valatr && !valder && valizq){ //0001 Detener + Izquierda
    orden = 2; 
  }
  if (valade && !valatr && !valder && !valizq){ //1000 Adelante
    orden = 3; 
  }
  if (valade && !valatr && valder && !valizq){ //1010 Adelante + Derecha
    orden = 4; 
  }
  if (valade && !valatr && !valder && valizq){ //1001 Adelante + Izquierda
    orden = 5; 
  }
  if (!valade && valatr && !valder && !valizq){ //0100 Atrás
    orden = 6; 
  }
  if (!valade && valatr && valder && !valizq){ //0110 Atrás + Derecha
    orden = 7; 
  }
  if (!valade && valatr && !valder && valizq){ //0101 Atrás + Izquierda
    orden = 8; 
  }

  return orden;
}


void  OrderExecution(int valor){ // Toma el valor retornado por "OrderPikking()" escribe las ordenes en pines 5,6,7 y 8

  switch(valor){
    case 0:
    WriteDete();  //Detener
    break;

    case 1:
    WriteAdel(50,250); 
    break;

    case 2:
    WriteAdel(250,50);
    break;

    case 3:
    WriteAdel(150,150);
    break;

    case 4:
    WriteAdel(100,250);
    break;

    case 5:
    WriteAdel(250,100);
    break;

    case 6:
    WriteAtra(150,150);
    break;

    case 7:
    WriteAtra(100,250);
    break;

    case 8:
    WriteAtra(250,100);
    break;

    default:
    WriteDete(); //Detener por defecto
    break;
  }
  
}

void WriteAdel(int vel1, int vel2) { //Escribe en los pines 5,6,7 y 8: Dirección de avance delantera y velocidad (independiente en cada lado)
    digitalWrite(mtr01, HIGH);
    digitalWrite(mtr02, LOW);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
}

void WriteAtra(int vel1, int vel2) { //Escribe en los pines 5,6,7 y 8: Dirección de avance trasera y velocidad (independiente en cada lado)
    digitalWrite(mtr01, LOW);
    digitalWrite(mtr02, HIGH);
    analogWrite(velder, vel1);
    analogWrite(velizq, vel2);
}

void WriteDete() { //Escribe en los pines 5,6,7 y 8: Todo cero para mantener los motores estáticos.
    digitalWrite(mtr01, LOW);
    digitalWrite(mtr02, LOW);
    analogWrite(velder, 0);
    analogWrite(velizq, 0);
}

Con este código aparentemente funciona todo perfecto, sin embargo no puedo estar seguro al 100% debido a que las baterías que estoy usando para pruebas se están agotando y solo pueden mover correctamente 2 de los 4 motores. incluso así se nota claramente que el problema se solucionó al menos a un nivel en el que ya no es un factor constante.

Dejo el código por si a alguien le sirve.
Muchas gracias por la ayuda.
Un saludo.

-----------------------------------EDIT:--------------------------------

Luego de varias pruebas, se seguían presentando errores de forma esporádica durante el funcionamiento; Un condensador electrolítico de 330uf entre VIN y GND terminó de eliminar cualquier bug presente y ahora el carrito funciona 100% Perfecto.

Muy bien!!!!!!!!
Veo que has dato un salto en tu programación. Realmente bien.
Asi debes verlo no como lo hacias antes.
Estas en el camino correcto.