Arduino Nano & HC-SR04 Ultrasonic sensor Not working

"I'm encountering an issue with this sensor and my Arduino Nano board. I'm currently building this project for my 3-year-old son:

When I try to use it, the forward motion stops by itself. If I disable the sensor, everything works fine. When I check the console, I get this message:

15:40:17.476 -> DISTANCIA INICIO RUTINA ULTRASOUND =0
15:40:17.522 -> VELOCIDAD INICIO RUTINA ULTRASOUND = 150
15:40:18.902 -> DISTANCIA INICIO RUTINA ULTRASOUND =0
15:40:18.947 -> VELOCIDAD INICIO RUTINA ULTRASOUND = 150
15:40:20.278 -> DISTANCIA INICIO RUTINA ULTRASOUND =0
15:40:20.323 -> VELOCIDAD INICIO RUTINA ULTRASOUND = 150
15:40:21.702 -> DISTANCIA INICIO RUTINA ULTRASOUND =0
15:40:21.748 -> VELOCIDAD INICIO RUTINA ULTRASOUND = 150
15:40:23.125 -> DISTANCIA INICIO RUTINA ULTRASOUND =0
15:40:23.171 -> VELOCIDAD INICIO RUTINA ULTRASOUND = 150

I tried modifying the program to put the sensor pins on A0 and A1, but same issue.

So I questioned the sensor itself, but when I made a quick test setup with an ESP32 under ESPHome, I'm getting valid measurements just fine!

So I put the sensor back on the Nano. First, I tried soldering the cables between the two, but same issue. I also tried powering it with an external 5V, but same problem. I performed continuity measurements and nothing particular either. I noticed that sometimes by quickly unplugging/replugging the TRIG and ECHO cables, I would get values other than 0. But again, nothing very stable... I also replaced the regular cables with shielded cables and soldered directly, but once again same issue. I don't really know what else to do.

:worried:

We need to see your sketch. Please post it using code tags when you do

There are Spanish and French language sections of the forum if you would be more comfortable using either of those languages

Let me know if you want this topic moved

This is the project's main character, who is Spanish. I don't speak a word of it.
Here's the diagram:

I can also provide the contents of the .ino file if needed


/*      ---------------  LOCOMOTORA "SOFIA" COMPATIBLE CON PISTAS DE TREN DE LEGO DUPLO, CONTROLADO POR MANDO INFRARROJO, CON CONTROL DE VELOCIDAD POR SENSOR DE ULTRASONIDOS Y CON UN SEGUNDO MOTOR PORTA IMANES USO VARIADO -----------------
 *       
 *  MATERIAL NECESARIO :   
 *  - Arduino Nano v3.0      -  Interruptor de Encendido    - 1 Led Verde        - 2 Leds Blancos                 - Sensor de Ultrasonidos "HC-SR04"            - 1 Motor CC para las ruedas con engranaje (con eje para las 2 ruedas)
 *  - Un mini motor de engranajes (30 r.p.m) para colación de los imanes         - 1  ALTAVOZ (Activo)5V 12mm     - Resistencias 47 Y 150 OHMS(para los Leds)   - 1 Controlador de Motores de CC don doble salida "HG7881"(L9110S)
 *  - Terminales (muelles) para la caja de baterías)        - 2 Baterias 18650   - Varilla de 2mmx51mm (bisagra) y otra de 3mmx48 para el eje de las ruedas     - 1 kit Infrarojo (mando y receptor) modelo VS1838
 *  - 4 Imanes de neodimio cilindricos 4mmx4mm  para cierre magnético de tapa    - 6 imanes de neodimio redondos de 10mmx3mm para juegos magnéticos.            - Cables tipo Dupont Hembra-Hembra de 10cm y 20cm para el conexionado.      
 *  
 *  FUNCIONAMIENTO: Mediante un mando por Infrarrojos y un Arduino Nano controlamos La Locomotora "SOFIA", es compactible con las vias del TREN DE LEGO DUPLO.  
 *  Este tiene un sensor de Ultrasonidos para reducir la velocidad o frenar antes de colisionar en el sentido de avance del tren, que podemos habilitar o deshabilitar. 
 *  Señalizado por el led "verde" de Activado/Desactivado Ultrasonido (Led "Verde" encendido --> Trabajo con Ultrasonidos Activado), (Led "Verde" Apagado --> Trabajo con Ultrasonidos Desactivado)
 *  Tambien se puede subir la velocidad manualmente pulsado la tecla de "CH+" (marcha adelante) o "CH-" (marcha atrás) del mando de infrarojos varias veces (motor de las Ruedas) hasta llegar a su velocidad máxima (con Ultrasonidos Desactivado)
 *  Tiene un motor extra en el interior para el montaje de una rueda con imanes de neodimio para futuros proyectos, y podemos subir su velocidad de giro con las teclas "-" y "+", (no le influye la habilitación o no de los Ultrasonidos).
 *  Podemos encender/apagar  las "luces delanteras" para una mayor visibilidad en la conducción nocturna, jeje.
 *  Podemos dar "bocinazos" para pedir paso en un cruze mediante el altavoz. También se le ha añadido, un parpadeo en las luces delanteras cuando seleccionamos alguna de las opciones o cuando el coche ha llegado a su velocidad máxima.
 *  MAS INFORMACIÓN EN:  https://www.thingiverse.com/thing:4012245
 *  

*/ 

//NOTA:   Puede suceder que dependiendo como conectamos la alimentación de los motores (van través del Modulo HG7881 (L9110S)) nos girarían en sentido contrario, para solucionar ésto, simplemente intercambiar los cables que van al motor.
//NOTA 2: Dependiendo del fabricandte del Sensor de Ultrasonidos del modelo "HC-SR04" algunos pueden tener mejor sensibilidad o peor sensibilidad, quizás tengamos que ajustar dentro de la rutina "Ultrasound()" los valores de distancia (dentro de los "if") 
//        para mejorar su funcionamiento. También dentro de la función "Distancia_test()" podemos variar algo los "delayMicroseconds" para mejorar su funcionamiento.

#include "IRLibAll.h"

// Variables usadas para el control del programa.
int VLed;             // Variable "VLed" usada para el estado de Activado o Desactivado trabajo con sensor de Ultrasonido (1 LED Verde)
int VLuz;             // Variable "VLuz" usada para el estado de las luces delanteras (2 LEDs Blancos)
int VMotB;            // Variable "VMotB" usada para el estado del Motor de las Ruedas motrices (MOTOR B)
int VMotA;            // Variable "VMotA" usada para el estado del motor portaimanes (MOTOR A)
int Vdistancia;       // Variable "Vdistancia" usada para el valor del Sensor de Ultrasonidos
int VStopGo;          // Variable para arrancar automáticamente después de producirse una parada debido a que el sensor ultrasonido para antes de colisionar (distancia muy corta)
int NOSound;          // Variable para habilitar o deshabilitar los sonidos

//Constantes con su valor de pin de conexionado para una mejor identificación y control del programa.
const int RECV_PIN=2;       // Constante "RECV_PIN" con valor "2"    (Pin "D2" usado para el Receptor de infrarojos)
const int Led1=4;           // Constante "Led1" con valor "4"        (Pin "D4" usado para el led verde de "Encendido/Apagdo el Sensor de Ultrasonido")
const int Altavoz_Pin=3;    // Constante "Altavoz_Pin" con valor "3" (Pin "D3" usado para conexionado del Altavoz)
const int trigger=5;      // Constante "trigger" con valor "5"     (Pin "D5" usado para Sensor de ultrasonido (patilla trigger)
const int echo=7;         // Constante "echo" con valor "7"        (Pin "D7" usado para el Sensor de ultrasonido (patilla echo)
const int luz=8;            // Constante "luz" con valor "8"         (Pin "D8" usado para las Luces delanteras. Lleva 2 led blancos)


// Conexiones cableadas, Usando el controlador de motores "HG7881" (voltaje de trabajo 2,5v a 12V)
#define HG7881_B_IA 10     // Pin "D10" --> Motor B Input B-IA --> MOTOR B + (MOTOR DE RUEDAS)
#define HG7881_B_IB 11     // Pin "D11" --> Motor B Input B-IB --> MOTOR B - (MOTOR DE RUEDAS)
#define HG7881_A_IA 6      // Pin  "D6" --> Motor A Input A-IA --> MOTOR A + (MOTOR PORTAIMANES)
#define HG7881_A_IB 9      // Pin  "D9" --> Motor A Input A-IB --> MOTOR A - (MOTOR PORTAIMANES)
 
// Conexiones funcionales
#define MOTOR_B_PWM HG7881_B_IA      // Motor B PWM Speed (MOTOR RUEDAS VELOCIDAD) (PIN D10)
#define MOTOR_B_DIR HG7881_B_IB      // Motor B Direction (MOTOR RUEDAS DIRECCION) (PIN D11)
#define MOTOR_A_PWM HG7881_A_IA      // Motor A PWM Speed (MOTOR PORTAIMANES VELOCIDAD) (PIN D6)
#define MOTOR_A_DIR HG7881_A_IB      // Motor A Direction (MOTOR PORTAIMANES DIRECCIÓN) (PIN D9)
 
//Los valores reales de "rápido" (FAST) y "lento" (SLOW) dependen de cada motor (rpm). Variar, ajustando a sus valores para una velocidad adecuada.
#define PWM_SLOW_A 100       // Ciclo de trabajo PWM arbitrario de velocidad lenta  (MOTOR A -> "MOTOR PORTAIMANES")
#define PWM_FAST_A 150       // Ciclo de trabajo PWM arbitrario de velocidad rápida (MOTOR A -> "MOTOR PORTAIMANES")
#define DIR_DELAY_A 1000     // Retardo para evitar cambios brucos de velocidad en inversiones de giro del Motor A Portaimanes
#define PWM_SLOW_B 150       // Ciclo de trabajo PWM arbitrario de velocidad lenta  (MOTOR B -> "MOTOR RUEDAS")
#define PWM_FAST_B 200       // Ciclo de trabajo PWM arbitrario de velocidad rápida (MOTOR B -> "MOTOR RUEDAS")
#define DIR_DELAY 1000       // Retardo para evitar cambios brucos de velocidad en inversiones de giro del Motor B RUEDAS

// Variables usadas para el control de velocidad del motor de ruedas mediante pulsaciones en mando infrarojo. También motor portaimanes con valor fijo.
int Speed = 150;          // Variable "speed" con valor inicial de velocidad (usado en motor B -> RUEDAS)
int SpeedStep = 50;       // Variable "SpeedStep" usada para los pasos de cambios de velocidad (mediante pulsaciones en mando infarojo al mismo botón de avance/retroceso) (usado en Motor B -> RUEDAS)
int Speed_MA = 100;       // Variable "Speed_MA", velocidad para Motor A (Portaimanes), este motor trabaja con pocas rmp (30rpm)
int SpeedStep_MA = 50;    // Variable "SpeedStep_MA" usada para los pasos de cambios de velocidad (mediante pulsaciones en mando infrarojo al mismo botón de avance/retroceso) (usado en Motor A -> PORTAIMANES)

//Crea un objeto receptor para "escuchar" el pin "D2"  (Receptor de infrarojos)
IRrecvPCI myReceiver(RECV_PIN);

//Crea un objeto decodificador
IRdecodeNEC myDecoder;   

void setup() {
// Inicializa los pines digitales como "salida" (OUTPUT), tambien alguno como "entrada" (INPUT)
  VLed=1;                              //LED de "Encendido el ultrasonido" comienza en estado ON (Activado)
  VLuz=0;                              //Luces Led delanteras comienza en estado OFF  (Apagadas)
  Vdistancia=0;                        // Valor inicial variable "Vdistancia" para sensor de ultrasonido
  VStopGo=0;                           // Valor inicial variable "VStopGo" para el arranque automático después de una parada por distancia muy corta del sensor de ultrasonidos.
  NOSound=0;                           // Valor inicial de variable "NOSound" apagado. Se deshabilitan todos los sonidos. Ah... el silencio es precioso....
  pinMode(Led1, OUTPUT);               //Se configura Led1 como salida (pin D4)(Led "Habilitado o Deshabilitado trabajo con Ultrasonidos")
  pinMode(luz, OUTPUT);                //Se configura el pin luz como salida (pin D5)(Leds Luces delanteras)
  pinMode( MOTOR_B_DIR, OUTPUT );      //Se configura el pin D11 como salida (Motor B Direction)
  pinMode( MOTOR_B_PWM, OUTPUT );      //Se configura el pin D10 como salida (Motor B PWM Speed)
  pinMode( MOTOR_A_DIR, OUTPUT );      //Se configura el pin D6 como salida (Motor A Direction)
  pinMode( MOTOR_A_PWM, OUTPUT );      //Se configura el pin D9 como salida (Motor A PWM Speed)
  pinMode( Altavoz_Pin, OUTPUT );      //Se configura el pin D3 como salida (Altavoz)
  pinMode(trigger,OUTPUT);             //Se configura el pin D5 como salida (patilla "trigger" del Sensor Ultrasonidos)
  pinMode(echo,INPUT);                 //Se configura el pin D7 como entrada (patilla "echo" del Sensor Ultrasonidos)
  digitalWrite( Led1, HIGH);           //Se activa "Led1" "Habilitado trabajo con Ultrasonidos" (PIN D4) 
  digitalWrite( luz, LOW);             //Se desactiva "luz" (PIN D8) LUCES DELANTERAS (2 Leds) Comienzan Apagadas
  digitalWrite( MOTOR_B_DIR, LOW );    //Se desactiva Motor B "RUEDAS" (SENTIDO DE GIRO)
  digitalWrite( MOTOR_B_PWM, LOW );    //Se desactiva Motor B "RUEDAS" (VELOCIDAD)
  digitalWrite( MOTOR_A_DIR, LOW );    //Se desactiva Motor A "PORTAIMANES" (SENTIDO DE GIRO)
  digitalWrite( MOTOR_A_PWM, LOW );    //Se desactiva Motor A "PORTAIMANES" (VELOCIDAD)

  Serial.begin(9600);         // Abre el puerto Serie, configura los datos a 9600 bps
  myReceiver.enableIRIn();    // Enciende el receptor
  Serial.println(F("Ready to receive IR signals"));
}

void loop() {                     //Se inicia la rutina Principal "loop" (Bucle)
  if (VLed==1) {                  // Con el VLed activo "Encendido el Ultrasonido" (led verde) trabaja con el control de velocidad por ultrasonidos.
     Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
    } 
  if (myReceiver.getResults()) {  //Continúe en bucle hasta que una señal sea completamente recibida por mando infrarrojo.
    myDecoder.decode();           //Decode it
    myDecoder.dumpResults(true);  //Now print results. Use false for less detail
    translateIR();
    myReceiver.enableIRIn();      //Restart receiver
     }  
}                                 // Fin de rutina Loop (Bucle)

//   CONTROL DE VELOCIDAD MEDIANTE SENSOR DE ULTRASONIDOS
//  - Dependiendo de la distancia varía la velocidad:
//  - Si está a menos de 15cm manda parar, también si llega a dar un valor por encima de 601cm cosa que puede suceder cuando tiene un objeto muy cercano,(nos da valores superiores a 2000cm, al menos en el modelo chino que tengo).
//  - Entre 16cm y 22cm va a una velocidad 50
//  - Entre 23cm y 25cm va una velocidad 60
//  - Entre 26cm y 29cm va a una velocidad 100
//  - Entre 30cm y 32cm va una velocidad 120
//  - Entre 33cm y 35cm va a una velocidad 140
//  - Entre 36cm y 45cm va una velocidad 150
//  - Entre 46cm y 600cm va una velocidad 150 (Velocidd estandar cuando trabaja con el sensero de ultrasonidos activo)
void Ultrasound() 
{
    Distancia_test();                 //LLamada a la función de Sensor de Ultrasonido
    Vdistancia = Distancia_test();    //Asignamos el valor leído por el Sensor de ultrasonidos a la variable "Vdistancia"
    Serial.print("DISTANCIA INICIO RUTINA ULTRASOUND =");
    Serial.println(Vdistancia);
    Serial.print ("VELOCIDAD INICIO RUTINA ULTRASOUND = ");
    Serial.println (Speed);
  //Serial.print ("El estado de la variable MOTOR_B_DIR inicio rutina Ultrasound = ");
  //Serial.println (MOTOR_B_DIR);
  //Serial.print ("El estado de la variable MOTOR_B_PWM inicio rutina Ultrasound = ");
  //Serial.println (MOTOR_B_PWM);
  //Serial.print ("Variable VStopGo = ");
  //Serial.println (VStopGo);
    
    if ((Vdistancia>=0) && (Vdistancia <=18) && (VMotB==1) || (Vdistancia>=601) && (Vdistancia <=4000) && (VMotB==1))  {  // Cuando la distancia está entre 0cm y 15cm  o entre 601 y 400 manda parar.  NOTA: Filtra valores erróneos de sensor de 
          if (VStopGo==1) {                                                                                               // ultrasonidos que da cuando tiene un objeto muy cercano, da valores erróneos de distancia superiores a 2000cm.
              Stop_MB();                                                                             //Con "VStopGo" a "1" cada vez que se produce una parada por un objeto muy cercano, no vuelve a arrancar automáticamente.
              }
          else if (VStopGo==0) {                                                                     //Con "VStopGo" a "0" arranca automáticamente cuando el objeto cercano se ha retirado. 
          Speed = 0;                                                                                 //La variable "VStopGo" la podemos variar  manualmente pulsadon la tecla "1" del mando a distancia.         
          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast                                                                             
        //Serial.print("DISTANCIA ENTRE 0 y 15 O ENTRE 601 Y 4000 =   ");
        //Serial.println(Vdistancia);
        //Serial.print ("VELOCIDAD =    ");
        //Serial.println (Speed);
          }
     }
     else if ((Vdistancia>=19) && (Vdistancia <=25) && (VMotB==1))  {                                // Distancia entre 16cm y 22cm damos una velocidad de 50. (tenemos algún obstáculo cercano velocidad inicial muy baja.
          Speed = 50;                                                                                // Para éste tipo de motor con pocas revoluciones (Relación de Reductora 1:48) si bajamos de éste valor mínimo de 50 no será capaz de mover el coche.
          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
        //Serial.print("DISTANCIA ENTRE 16 y 22 =   ");
        //Serial.println(Vdistancia);
        //Serial.print ("VELOCIDAD =    ");
        //Serial.println (Speed);
          }
           else if ((Vdistancia>=26) && (Vdistancia <=30) && (VMotB==1))  {                           // A PARTIR DE AQUÍ VAMOS SUBIENDO LA VELOCIDAD DEPENDIENDO SI NOS ALEJAMOS DEL OBJETO DE POSIBLE COLISIÓN....:
                Speed = 60;                                                                           //Distancia entre 23cm y 25cm velocidad 60
                analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
              //Serial.print("DISTANCIA ENTRE 23 y 25 =   ");
              //Serial.println(Vdistancia);
              //Serial.print ("VELOCIDAD =    ");
              //Serial.println (Speed);
                }
                else if ((Vdistancia>=31) && (Vdistancia <=36) && (VMotB==1))  {                      // Distancia entre 26cm y 29cm velocidad 100
                     Speed = 100;
                     analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                   //Serial.print("DISTANCIA ENTRE 26 y 29 =   ");
                   //Serial.println(Vdistancia);
                   //Serial.print ("VELOCIDAD =    ");
                   //Serial.println (Speed);
                     }
                     else if ((Vdistancia>=37) && (Vdistancia <=42) && (VMotB==1))  {                  // Distancia entre 30cm y 32cm velocidad 120
                          Speed = 120;
                          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                        //Serial.print("DISTANCIA ENTRE 30 y 32 =   ");
                        //Serial.println(Vdistancia);
                        //Serial.print ("VELOCIDAD =    ");
                        //Serial.println (Speed);
                          }
                          else if ((Vdistancia>=43) && (Vdistancia <=48) && (VMotB==1))  {             // Distancia entre 33cm y 35cm velocidad 140
                               Speed = 140;
                               analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                             //Serial.print("DISTANCIA ENTRE 33 y 35 =   ");
                             //Serial.println(Vdistancia);
                             //Serial.print ("VELOCIDAD =    ");
                             //Serial.println (Speed);
                               }
                               else if ((Vdistancia>=48) && (Vdistancia <=55) && (VMotB==1))  {         // Distancia entre 36cm y 45cm velocidad 150
                                    Speed = 150;
                                    analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                                  //Serial.print("DISTANCIA ENTRE 36 y 45 =   ");
                                  //Serial.println(Vdistancia);
                                  //Serial.print ("VELOCIDAD =    ");
                                  //Serial.println (Speed);
                                    }      
                                    else if ((Vdistancia>=56) && (Vdistancia <=600) && (VMotB==1))  {                 // Distancia entre 46cm y 600cm velocidad 150
                                          Speed = 150;                                                                // 400cm valores máximos que mide más o menos fiables sensor ultrasonidos, por encima de esa distancia los valores pueden no ser fiables.
                                          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast                  // Llega a medir hasta 600cm según fabricante...
                                        //Serial.print("DISTANCIA ENTRE 46 y 600 =   ");
                                        //Serial.println(Vdistancia);
                                        //Serial.print ("VELOCIDAD =    ");
                                        //Serial.println (Speed);
                                          }                                                      
}

//MANDO DE INFRAROJOS
// Dependiendo del código recibido por infrarrojo se ejecuta las diversas acciones:
// - Activación/Desactivación de la Luz de encendido,(led verde) que señaliza que el control de velocidad mediante el sensor de ultrasonidos está activado/desactivado.
// - Activación/Desactivación de las Luces delanteras (2 leds blancos)
// - Motor A (Portaimanes) Giro a derechas o izquierdas (Varias Velocidades, si pulsamos varias veces en el mismo sentido sube de velocidad hasta velocidad máxima.
// - Motor B (Ruedas) Adelante/Atrás (Si pulsamos varias veces en el mismo sentido sube de velocidad hasta velocidad máxima), (Sólo con Ultrasonidos Desactivados "led verde apagado")
// - Sonidos Activados/Desactivados (trabaja el altavoz activo para señalizar diversas acciones,(también el parpadeo de las luces delanteras): Como activación/desactivación ultrasonidos, velocidad máxima alcanzada, habilitación de arranque automático,Claxon.
// - NOTA: En caso de querer utilizar un mando infrarojo diferente (quizás valdría uno de una televisión) tendreis que usar el "Monitor Serie" dentro de la pestaña "Herramientas" y al pulsar una tecla examinar la primera linea y donde sale
//   la palabra "Value:FFFFFF". Estas "FFFFFF" es el código que tendréis que poner a continuación de los "case" para realizar la opción deseada (Se pondría de ésta forma->  case 0xFFFFFF:   (Se añade el "0x" sin las comillas antes del valor obtenido)
//   Nota al estar activo el Sensor de Ultrasonido para poder observar el código obtenido deshabilitar el "Autoscroll" en monitor serie. 
// - Códigos de cada tecla del  Mando Infrarrojo (modelo VS1838):  ("CH-"= FFA25D), ("CH"= FF629D), ("CH+"= FFE21D), ("PREV"= FF22DD), ("NEXT"= FF02FD), ("PLAY/PAUSE"= FFC23D), ("VOL-"= FFE01F), ("VOL+"= FFA857), ("EQ"= FF906F), ("0"= FF6897)
//   ("100+"= FF9867), ("200+"= FFB04F),  ("1"= FF30CF),  ("2"= FF18E7),  ("3"= FF7A85),  ("4"= FF10EF),  ("5"= FF38C7),  ("6"= FF5AA5),  ("7"= FF42BD),  ("8"= FF4AB5), ("9"= FF52AD)          
void translateIR() 
{
      switch(myDecoder.value) {  
        case 0xFF22DD:                           // "PRECEDENT" El valor "FF22DD" es la tecla "Anterior" en el mando a distancia por infrarojos (si compráis el que está en el enlace anterior).  
          if(VLed==0){                            // SE ACTIVA O DESACTIVA EL "LED VERDE" "Señaliza el encendido o apagado del SENSOR ULTRASÓNIDOS" Si la variable Vled esta a 0 (led verde de "trabajo con ultrasonido" apagado) se activa en la siguiente instrucción
            digitalWrite(Led1,HIGH);              // Activamos el  Pin "D3" usado para activar el led "verde" que señaliza el "encendido la forma de trabajo con Sensor de Ultrasonidos"
            VLed=1;                               // Valor estado de la variable activo ya que el led se encuentra activo.
            Parpadeo1();
            buzzer(); 
            }
            else{                     
            digitalWrite(Led1,LOW);                // En caso contrario (que VLed1 esté a 1), lo apagamos (deshabilitamos el trabajar con sensor de ultrasonidos)
            VLed=0;   
            // VMotB=0;    // PENDIENTE DE PROBAR SI NO ARRANCA DESPUES DE ESTAR PARADO AL DESHABILITAR EL SENSOR DE ULTRASONIDOS.
            Parpadeo1();
            buzzer2(); 
            }
        break;
          
        case 0xFF02FD:                                  // El valor "FF02FD" es la tecla "Siguiente (NEXT)" en el mando a distancia por infrarojos. SE ACTIVA O DESACTIVA LAS "LUCES DELANTERAS" 
          if(VLuz==0){                                  // La rutina básicamente trabaja que si las "Luces delanteras" estaban apagadas se enciende y si estaban encendidas se apagan
          digitalWrite(luz,HIGH);
          VLuz=1;
          } 
          else{
          digitalWrite(luz,LOW);
          VLuz=0;
           }
        break;
          
        case 0xFFE01F:                                  //  El valor "FFE01F" es la tecla "-" en el mando a distancia por infrarojos. SE ACTIVA EL "MOTOR PORTAIMANES" en dirección ADELANTE (MOTOR A)
          if(VMotA !=1){
            Speed_MA = PWM_SLOW_A;
            go_forward_A ();
            } 
            else{
            Speed_MA = Speed_MA + SpeedStep_MA ;
            Speed_MA = min(255, max(0, Speed_MA));  
            if (Speed_MA == 255){buzzer3();Parpadeo();}
            go_forward_A ();
            }      
        break;
          
        case 0xFF906F:                                  //  El valor "FF906F" es la tecla "EQ" en el mando a distancia por infrarojos. SE ACTIVA EL "MOTOR PORTAIMANES" en dirección ATRAS (MOTOR A)
          if(VMotA !=2){
            Speed_MA = PWM_SLOW_A;
            go_backward_A ();
            } 
            else{
            Speed_MA = Speed_MA + SpeedStep_MA ;
            Speed_MA = min(255, max(0, Speed_MA)); 
            if (Speed_MA == 255){buzzer3();Parpadeo();}
            go_backward_A ();
            }      
        break;
          
        case 0xFF629D:                                 // El valor "FF629D" es la tecla "CH" en el mando a distancia por infrarojos. SE BAJA LA VELOCIDAD EN LOS DOS SENTIDOS DE AVANCE Y RETROCESO DE LAS RUEDAS (MOTOR B)
           if(VMotB ==1){                              // Si la variable "VMotB" Motor Status es 1 (Locomotora hacia ADELANTE) bajamos la velocidad en ese sentido de giro.
            Speed = Speed - SpeedStep ;
            Speed = min(255, max(0, Speed));
            if (Speed <= 40){Speed =0 ;}               //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
            go_forward ();
            if (Speed == 0){buzzer3();Parpadeo();VMotB=0;}     // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero (parados) en el sentido de Avance del tren.
            } 
              else if(VMotB ==2){                      // Si la variable "VMotB" Motor Status es 2 (Locomotora hacia ATRAS) bajamos la velocidad en ese sentido de giro.
              Speed = Speed - SpeedStep ;              // Bajamos de velocidad el valor de la variable "SpeedStep" que va en pasos de "50".
              Speed = min(255, max(0, Speed));  
              if (Speed <= 40){Speed =0 ;}             //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
              go_backward();
              if (Speed == 0){buzzer3();Parpadeo();VMotB=0;}   // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero (parados) en el sentido de Retroceso del tren.
            }       
            //Stop_MB(); 
        break;  
          
          case 0xFFA857:                                // El valor "FFA857" es la tecla "+" en el mando a distancia por infrarojos. SE BAJA LA VELOCIDAD EN LOS DOS SENTIDOS DE GIRO DEL MOTOR PORTA IMANES (MOTOR A)
          if(VMotA ==1){                                // Si la variable "VMotA" (Motor Status) es 1 (MOTOR PORTA IMANES A DERECHAS) bajamos la velocidad en ese sentido de giro.
            Speed_MA = Speed_MA - SpeedStep_MA ;        // Bajamos de velocidad el valor de la variable "SpeedStep_MA" que va en pasos de "50".
            Speed_MA = min(255, max(0, Speed_MA));
            if (Speed_MA <= 40){Speed_MA = 0;}          //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
            go_forward_A ();
            if (Speed_MA == 0){buzzer3();Parpadeo();VMotA=0;}   // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero. (GIRO A DERECHAS VELOCIDAD CERO) 
            } 
            else if(VMotA ==2){                         // Si la variable "VMotA" (Motor Status) es 2 (MOTOR PORTA IMANES A IZQUIERDAS) bajamos la velocidad en ese sentido de giro.
            Speed_MA = Speed_MA - SpeedStep_MA ;           
            Speed_MA = min(255, max(0, Speed_MA)); 
            if (Speed_MA <= 40){Speed_MA = 0;}          //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
            go_backward_A();
            if (Speed_MA == 0){buzzer3();Parpadeo();VMotA=0;}   // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero. (GIRO A IZQUIERDAS VELOCIDAD CERO)
            } 
            //Stop_MA(); 
        break;  
          
        case 0xFFC23D:                                  //  El valor "FFC23D" es la tecla "Play/Pause" en el mando a distancia por infrarojos. STOP PARA LOS 2 MOTORES.
          //if(VMotB !=0  || VMotA !=0) {
            Stop_ALL ();
        break;

        case 0xFF38C7:                                  //  El valor "FF38C7" es la tecla "5" en el mando a distancia por infrarojos. DAR LUCES LARGAS (3 PARPADEOS PARA AVISAR AL CONDUCTOR DELANTERO)
            Parpadeo2();
        break;

        case 0xFF9867:                                  //  El valor "FF9867" es la tecla "100+" en el mando a distancia por infrarojos. SONIDO DEL CLAXON PARA INCORDIAR AL PERSONAL.
          Claxon();
        break;
 
        case 0xFF6897:                                  //  El valor "FF6897" es la tecla "0" en el mando a distancia por infrarojos. HABILITA O DESHABILITA EL ARRANQUE AUTOMÁTICO DESPUES DE UNA PARADA POR POSIBLE COLISIÓN. 
          if(VStopGo==0){                               //  Estando el valor de la variable "VStopGo" a "1" cada vez que para debido a que el detector de ultrasonidos nos dice que hay un objeto muy cercano se para y no vuelve a arrancar           
            VStopGo=1;                                  //  hasta que volvemos a pulsar el boton de avance "CH+" en mando a distancia. Con valor a "0" de ésta variable arranca automáticamente cuando el objeto cercano se ha retirado.
            Parpadeo();
            buzzer2(); 
           }
            else{                                 
            VStopGo=0;
            Parpadeo();
            buzzer(); 
           } 
        break;

          case 0xFFB04F:                                // El valor "FFB04F" es la tecla "200+" del mando a distancia por infrarojos, HABILITA O DESHABILITA TODOS LOS SONIDOS (NOSound=0 => Sonidos activos)
          if(NOSound==0){                                
            Parpadeo();
            buzzer2();
            NOSound=1;                            
           }
            else{                              
            NOSound=0;  
            Parpadeo();
            buzzer();
           } 
        break;
        
        case 0xFFE21D:                                  // El valor "FFE21D" es la tecla "CH+" del mando a distancia por infrarojos. HACIA ADELANTE MOTOR B (RUEDAS)
          if(VMotB !=1){                                // Si la variable "VMotB" Motor Status (Ruedas) es diferente de 1 lanza la rutina de avance
            Speed = PWM_SLOW_B;
            go_forward ();
            } 
              else {
              Speed = Speed + SpeedStep ;               //Realiza uno de los cambios de velocidad para la variable "speed"
              Speed = min(255, max(0, Speed));          // Asigna al valor de Velocidad "Speed" el menor de los números. Sería de 255 en caso que la velocidad sobrepase éste valor.
              if (Speed == 255){buzzer3();Parpadeo(); }
              go_forward();
            }      
        break;
          case 0xFFA25D:                                // El valor "FFA25D" es la tecla "CH-" del mando a distancia por infrarojos. HACIA ATRÁS EL MOTOR B  (RUEDAS)
          if(VMotB !=2){
            Speed = PWM_SLOW_B;
            go_backward ();
           }
            else {
            Speed = Speed + SpeedStep ;                 //Realiza uno de los cambios de velocidad para la variable "speed"
            Speed = min(255, max(0, Speed));            // Asigna al valor de Velocidad "Speed" el menor de los números. Sería de 255 en caso que la velocidad sobrepase éste valor.
            if (Speed == 255){buzzer3();Parpadeo();}
            go_backward();
            }       
        break;  
        default:  //Se ejecuta si nada coíncide....
        //buzzer(); 
        //buzzer1(); 
        //buzzer2(); 
        break;  
             
      }
    
  }

// RUTINA HACIA ADELANTE MOTOR B (RUEDAS)
  void go_forward ()
  {
  Serial.println ("Hacia ADELANTE en motor de las ruedas ...");
  Serial.print ("La velocidad de motor ruedas es: ");
  Serial.println (Speed);
  //Serial.print ("La distancia medida por ultrasonidos es (puede no ser la actual):  ");
  //Serial.println (Vdistancia);
        //if (VMotB == 0){buzzer1 ();}
        // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotB == 2){
        Stop_MB();       //buzzer1 ();
        delay( DIR_DELAY );}
        // Activa el motor la velocidad y dirección
        digitalWrite( MOTOR_B_DIR, HIGH );   // Dirección Avance hacia Adelante
        analogWrite( MOTOR_B_PWM, 255-Speed ); // Velocidad PWM, valor en variable "Speed"
        VMotB=1;  
  }

// RUTINA HACIA ATRAS MOTOR B (RUEDAS)
  void go_backward ()
  {
  Serial.println ("Hacia ATRAS en motor de las ruedas ....");
  Serial.print ("La velocidad de motor ruedas es: ");
  Serial.println (Speed);
  //Serial.print ("La distancia medida por ultrasonidos es (puede no ser la actual): ");
  //Serial.println (Vdistancia);
          // if (VMotB == 0){buzzer1 ();}
          // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotB == 1){
        Stop_MB();  //buzzer1 ();
        delay( DIR_DELAY );}
        // Activa el motor la velocidad y dirección
        digitalWrite( MOTOR_B_DIR, LOW ); // Dirección inversa (marcha atrás)
        analogWrite( MOTOR_B_PWM, Speed ); // Velocidad PWM, valor en variable "Speed"
        VMotB=2;
  }

// RUTINA HACIA ADELANTE MOTOR A (PORTAIMANES)
  void go_forward_A ()
  {
  Serial.println ("Vamos hacia adelante en motor portaimanes...");
  Serial.print ("La velocidad actual portaimanes es: ");
  Serial.println (Speed_MA);
        // if (VMotA == 0){buzzer1 ();} // Un pequeño pitido de arranca de motor portaimanes en dirección Avance
        // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotA == 2){
        Stop_MA();   //buzzer1 ();
        delay( DIR_DELAY_A );}
        // Activa el motor la velocidad y dirección
        digitalWrite( MOTOR_A_DIR, HIGH ); // Dirección Giro hacia la derecha 
        analogWrite( MOTOR_A_PWM, 255-Speed_MA ); // Velocidad PWM, valor en variable "Speed_MA"
        VMotA=1;  
  }

// RUTINA HACIA ATRAS MOTOR A (PORTAIMANES)
  void go_backward_A ()
  {
  Serial.println ("Vamos hacia atrás en motor portaimanes...");
  Serial.print ("La Velocidad actual portaimanes es: ");
  Serial.println (Speed_MA);
          // if (VMotA == 0){buzzer1 ();} // Un pequeño pitido de arranca de motor portaimanes en dirección Retroceso
          // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotA == 1){
        Stop_MA();   // buzzer1 ();
        delay( DIR_DELAY_A );}
        // set the motor speed and direction
        digitalWrite( MOTOR_A_DIR, LOW ); // Dirección Giro hacia la izquierda    
        analogWrite( MOTOR_A_PWM, Speed_MA ); // Velocidad PWM, valor en variable "Speed_MA"
        VMotA=2;
  }

 // RUTINA DE "STOP" PARA LOS 2 DOS MOTORES (MOTOR A Y MOTOR B)
  void Stop_ALL ()
  {
  //Serial.println ("STOP Para los 2 motores...");  
  digitalWrite( MOTOR_B_DIR, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_B_PWM, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_A_DIR, LOW ); //Motor portaimanes OFF
  digitalWrite( MOTOR_A_PWM, LOW ); //Motor portaimanes OFF
  VMotB=0; //Motor Ruedas Valor inicial (parado)
  VMotA=0; //Motor portaimanes valor inicial (parado)
  }

 // RUTINA DE "STOP" PARA EL MOTOR DE LAS RUEDAS (MOTOR B)
  void Stop_MB ()
  {
  //Serial.println ("STOP Para el motor de las ruedas (Motor B....");  
  digitalWrite( MOTOR_B_DIR, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_B_PWM, LOW ); //Motor Ruedas OFF
  VMotB=0; //Motor Ruedas Valor inicial (parado)
  }

 // RUTINA DE "STOP" PARA EL MOTOR PORTAIMANES  (MOTOR A)
  void Stop_MA ()
  {
  //Serial.println ("STOP Para el motor portaimanes (Motor A....");  
  digitalWrite( MOTOR_A_DIR, LOW ); //Motor portaimanes OFF
  digitalWrite( MOTOR_A_PWM, LOW ); //Motor portaimanes OFF
  VMotA=0; //Motor PortaImanes Valor inicial (parado)
  }



// FUNCIÓN DE CÁLCULO DE DISTANCIA MEDIANTE SENSOR DE ULTRASONIDO
int Distancia_test()   
{
  digitalWrite(trigger, LOW);   
  delayMicroseconds(12);        // Valor original 10 (modificado a 12)
  digitalWrite(trigger, HIGH);  
  delayMicroseconds(120);     // Valor Original 100 (modificado a 120)
  digitalWrite(trigger, LOW);   
  float Fdistance = pulseIn(echo, HIGH);  
  Fdistance= Fdistance/58;    
  return (int)Fdistance;
}  

 //RUTINAS PARA EL AVISO SONORO DE DIVERSAS FUNCIONES - Hay que tener en cuenta que si tenemos deshabilitados los sonidos el control de la locomotora irá más fluída, lo mismo sucede deshabilitando el control de velocidad mediante ultrasonidos.
 
 // DOBLE PITIDO DE ALTAVOZ  - Doble pitido que indica que se ha habilitado alguna de las opciones programadas. (Activado control de velocidad por Ultrasonidos, Activado arranque automático después de un paro, o habilitación de todos los sonidos)
  void buzzer ()                                                                  
  {
     if(NOSound==0){          
    for (int thisBuz=0; thisBuz < 2; thisBuz++){
    digitalWrite(Altavoz_Pin, HIGH);
    delay(100);
    digitalWrite(Altavoz_Pin, LOW);
    delay(50);
       }
    }
  }
 
 // PITIDO DE ALTAVOZ 1 - Pitido de arranque o paro, cuando se inicia un movimiento de cualquiera de los 2 motores (DESHABILITADO "Comentado" en rutina de avance y retroceso motores ruedas y portaimanes)
  void buzzer1 ()
  {
      if(NOSound==0){                            
      for (int thisBuz=0; thisBuz < 1; thisBuz++){
      digitalWrite(Altavoz_Pin, HIGH);
      delay(120);
      digitalWrite(Altavoz_Pin, LOW);
      delay(50);
          } 
      }
  }
 
 // PITIDO DE ALTAVOZ 2  Sonido apagado que indica que se ha deshabilitado alguna de las opciones programadas (Desactivado Ultrasonidos, desactivado arranque automático después de un paro, o desactivado todos los sonidos)
    void buzzer2 ()
  {
    if(NOSound==0){  
    for (int thisBuz=25; thisBuz > 0; thisBuz--){
    analogWrite(Altavoz_Pin, thisBuz);
    delay(10);
    analogWrite(Altavoz_Pin, 0);
    delay(10);
    }
    }
  }


 // PITIDO DE ALTAVOZ 3  - Velocidad máxima alcanzada (Trabaja con cualquiera de los 2 motores, cuando pulsamos varias veces el mismo botón de avance (o retroceso) y llegamos al máximo de velocidad.
  void buzzer3 ()
  {
    if(NOSound==0){  
    for (int thisBuz=0; thisBuz < 1; thisBuz++){
    digitalWrite(Altavoz_Pin, HIGH);
    delay(100);
    digitalWrite(Altavoz_Pin, LOW);
    delay(50);
    }
    }
  }


  // PITIDO DE ALTAVOZ 4 -  Claxon para advertir a nuestros rivales. Un dolor de cabeza para los padres.... (3 pitidos largos)
  void Claxon ()
  {
    if(NOSound==0){ 
    for (int thisBuz=0; thisBuz < 3; thisBuz++){
    digitalWrite(Altavoz_Pin, HIGH);
    delay(300);
    digitalWrite(Altavoz_Pin, LOW);
    delay(100);
    }
    }
  }

// RUTINA PARPADEO DE LUCES DELANTERA (BLANCAS) - Señaliza la activación o desactivación de alguna opción (si las luces estaban encendidas después del parpadeo, se vuelven a dejar encendidas).
  void Parpadeo () 
  {
    for (int BlinkL=0; BlinkL < 2; BlinkL++){
    digitalWrite(luz,HIGH);
    delay(100);
    digitalWrite(luz,LOW);
    delay(50);  
    }
     if(VLuz==1){
     digitalWrite(luz,HIGH);    
     }
 }

// RUTINA PARPADEO1 DE LUZ VERDE DE CONTROL DE VELOCIDAD POR ULTRASONIDOS ACTIVADO) - Señaliza la activación o desactivación del Control de Velocidad por ultrasonidos.
  void Parpadeo1 () 
  {
    for (int BlinkL=0; BlinkL < 2; BlinkL++){
    digitalWrite(Led1,HIGH);
    delay(100);
    digitalWrite(Led1,LOW);
    delay(50);  
    }
     if(VLed==1){
     digitalWrite(Led1,HIGH);    
     }
 }

// RUTINA PARPADEO2 DE LUCES DELANTERA (BLANCAS) - Realiza 3 parpadeos de las luces delanteras (dar luces) para que se entere el que va por delante..
  void Parpadeo2 () 
  {
    for (int BlinkL=0; BlinkL < 3; BlinkL++){
    digitalWrite(luz,HIGH);
    delay(200);
    digitalWrite(luz,LOW);
    delay(200);  
    }
     if(VLuz==1){
     digitalWrite(luz,HIGH);    
     }
 }



 

Google Translate says that the text in the page that you linked to is Spanish, hence my reference to it

I don't know if this is the same problem you're having, but I've had a lot of problems using the HC-SR04 over the years because many of them were buggy, crashed very often, and returned distances as 0 or timeout values.
I use HY-SRF05 instead, never had any problem, I strongly suggest you to do the same and throw SR04 away.

But to help you better, you should post your code.
Please remember to use well-indented code and enclose it in CODE tags: open the IDE with your program, press Ctrl-T then Ctrl-Shift-C, then paste into the forum editor.

1 Like

Have you made the simple test on the Nano with just the sensor, the nano powered from usb, and the basic pulse in code?

I'm giving you the content of the .ino file, but as mentioned in my post, this project is not mine - everything I posted comes from the creator's link, who I assume is Spanish

[code]

/*      ---------------  LOCOMOTORA "SOFIA" COMPATIBLE CON PISTAS DE TREN DE LEGO DUPLO, CONTROLADO POR MANDO INFRARROJO, CON CONTROL DE VELOCIDAD POR SENSOR DE ULTRASONIDOS Y CON UN SEGUNDO MOTOR PORTA IMANES USO VARIADO -----------------

    MATERIAL NECESARIO :
    - Arduino Nano v3.0      -  Interruptor de Encendido    - 1 Led Verde        - 2 Leds Blancos                 - Sensor de Ultrasonidos "HC-SR04"            - 1 Motor CC para las ruedas con engranaje (con eje para las 2 ruedas)
    - Un mini motor de engranajes (30 r.p.m) para colación de los imanes         - 1  ALTAVOZ (Activo)5V 12mm     - Resistencias 47 Y 150 OHMS(para los Leds)   - 1 Controlador de Motores de CC don doble salida "HG7881"(L9110S)
    - Terminales (muelles) para la caja de baterías)        - 2 Baterias 18650   - Varilla de 2mmx51mm (bisagra) y otra de 3mmx48 para el eje de las ruedas     - 1 kit Infrarojo (mando y receptor) modelo VS1838
    - 4 Imanes de neodimio cilindricos 4mmx4mm  para cierre magnético de tapa    - 6 imanes de neodimio redondos de 10mmx3mm para juegos magnéticos.            - Cables tipo Dupont Hembra-Hembra de 10cm y 20cm para el conexionado.

    FUNCIONAMIENTO: Mediante un mando por Infrarrojos y un Arduino Nano controlamos La Locomotora "SOFIA", es compactible con las vias del TREN DE LEGO DUPLO.
    Este tiene un sensor de Ultrasonidos para reducir la velocidad o frenar antes de colisionar en el sentido de avance del tren, que podemos habilitar o deshabilitar.
    Señalizado por el led "verde" de Activado/Desactivado Ultrasonido (Led "Verde" encendido --> Trabajo con Ultrasonidos Activado), (Led "Verde" Apagado --> Trabajo con Ultrasonidos Desactivado)
    Tambien se puede subir la velocidad manualmente pulsado la tecla de "CH+" (marcha adelante) o "CH-" (marcha atrás) del mando de infrarojos varias veces (motor de las Ruedas) hasta llegar a su velocidad máxima (con Ultrasonidos Desactivado)
    Tiene un motor extra en el interior para el montaje de una rueda con imanes de neodimio para futuros proyectos, y podemos subir su velocidad de giro con las teclas "-" y "+", (no le influye la habilitación o no de los Ultrasonidos).
    Podemos encender/apagar  las "luces delanteras" para una mayor visibilidad en la conducción nocturna, jeje.
    Podemos dar "bocinazos" para pedir paso en un cruze mediante el altavoz. También se le ha añadido, un parpadeo en las luces delanteras cuando seleccionamos alguna de las opciones o cuando el coche ha llegado a su velocidad máxima.
    MAS INFORMACIÓN EN:  https://www.thingiverse.com/thing:4012245


*/

//NOTA:   Puede suceder que dependiendo como conectamos la alimentación de los motores (van través del Modulo HG7881 (L9110S)) nos girarían en sentido contrario, para solucionar ésto, simplemente intercambiar los cables que van al motor.
//NOTA 2: Dependiendo del fabricandte del Sensor de Ultrasonidos del modelo "HC-SR04" algunos pueden tener mejor sensibilidad o peor sensibilidad, quizás tengamos que ajustar dentro de la rutina "Ultrasound()" los valores de distancia (dentro de los "if")
//        para mejorar su funcionamiento. También dentro de la función "Distancia_test()" podemos variar algo los "delayMicroseconds" para mejorar su funcionamiento.

#include "IRLibAll.h"

// Variables usadas para el control del programa.
int VLed;             // Variable "VLed" usada para el estado de Activado o Desactivado trabajo con sensor de Ultrasonido (1 LED Verde)
int VLuz;             // Variable "VLuz" usada para el estado de las luces delanteras (2 LEDs Blancos)
int VMotB;            // Variable "VMotB" usada para el estado del Motor de las Ruedas motrices (MOTOR B)
int VMotA;            // Variable "VMotA" usada para el estado del motor portaimanes (MOTOR A)
int Vdistancia;       // Variable "Vdistancia" usada para el valor del Sensor de Ultrasonidos
int VStopGo;          // Variable para arrancar automáticamente después de producirse una parada debido a que el sensor ultrasonido para antes de colisionar (distancia muy corta)
int NOSound;          // Variable para habilitar o deshabilitar los sonidos

//Constantes con su valor de pin de conexionado para una mejor identificación y control del programa.
const int RECV_PIN = 2;     // Constante "RECV_PIN" con valor "2"    (Pin "D2" usado para el Receptor de infrarojos)
const int Led1 = 4;         // Constante "Led1" con valor "4"        (Pin "D4" usado para el led verde de "Encendido/Apagdo el Sensor de Ultrasonido")
const int Altavoz_Pin = 3;  // Constante "Altavoz_Pin" con valor "3" (Pin "D3" usado para conexionado del Altavoz)
const int trigger = 5;    // Constante "trigger" con valor "5"     (Pin "D5" usado para Sensor de ultrasonido (patilla trigger)
const int echo = 7;       // Constante "echo" con valor "7"        (Pin "D7" usado para el Sensor de ultrasonido (patilla echo)
const int luz = 8;          // Constante "luz" con valor "8"         (Pin "D8" usado para las Luces delanteras. Lleva 2 led blancos)


// Conexiones cableadas, Usando el controlador de motores "HG7881" (voltaje de trabajo 2,5v a 12V)
#define HG7881_B_IA 10     // Pin "D10" --> Motor B Input B-IA --> MOTOR B + (MOTOR DE RUEDAS)
#define HG7881_B_IB 11     // Pin "D11" --> Motor B Input B-IB --> MOTOR B - (MOTOR DE RUEDAS)
#define HG7881_A_IA 6      // Pin  "D6" --> Motor A Input A-IA --> MOTOR A + (MOTOR PORTAIMANES)
#define HG7881_A_IB 9      // Pin  "D9" --> Motor A Input A-IB --> MOTOR A - (MOTOR PORTAIMANES)

// Conexiones funcionales
#define MOTOR_B_PWM HG7881_B_IA      // Motor B PWM Speed (MOTOR RUEDAS VELOCIDAD) (PIN D10)
#define MOTOR_B_DIR HG7881_B_IB      // Motor B Direction (MOTOR RUEDAS DIRECCION) (PIN D11)
#define MOTOR_A_PWM HG7881_A_IA      // Motor A PWM Speed (MOTOR PORTAIMANES VELOCIDAD) (PIN D6)
#define MOTOR_A_DIR HG7881_A_IB      // Motor A Direction (MOTOR PORTAIMANES DIRECCIÓN) (PIN D9)

//Los valores reales de "rápido" (FAST) y "lento" (SLOW) dependen de cada motor (rpm). Variar, ajustando a sus valores para una velocidad adecuada.
#define PWM_SLOW_A 100       // Ciclo de trabajo PWM arbitrario de velocidad lenta  (MOTOR A -> "MOTOR PORTAIMANES")
#define PWM_FAST_A 150       // Ciclo de trabajo PWM arbitrario de velocidad rápida (MOTOR A -> "MOTOR PORTAIMANES")
#define DIR_DELAY_A 1000     // Retardo para evitar cambios brucos de velocidad en inversiones de giro del Motor A Portaimanes
#define PWM_SLOW_B 150       // Ciclo de trabajo PWM arbitrario de velocidad lenta  (MOTOR B -> "MOTOR RUEDAS")
#define PWM_FAST_B 200       // Ciclo de trabajo PWM arbitrario de velocidad rápida (MOTOR B -> "MOTOR RUEDAS")
#define DIR_DELAY 1000       // Retardo para evitar cambios brucos de velocidad en inversiones de giro del Motor B RUEDAS

// Variables usadas para el control de velocidad del motor de ruedas mediante pulsaciones en mando infrarojo. También motor portaimanes con valor fijo.
int Speed = 150;          // Variable "speed" con valor inicial de velocidad (usado en motor B -> RUEDAS)
int SpeedStep = 50;       // Variable "SpeedStep" usada para los pasos de cambios de velocidad (mediante pulsaciones en mando infarojo al mismo botón de avance/retroceso) (usado en Motor B -> RUEDAS)
int Speed_MA = 100;       // Variable "Speed_MA", velocidad para Motor A (Portaimanes), este motor trabaja con pocas rmp (30rpm)
int SpeedStep_MA = 50;    // Variable "SpeedStep_MA" usada para los pasos de cambios de velocidad (mediante pulsaciones en mando infrarojo al mismo botón de avance/retroceso) (usado en Motor A -> PORTAIMANES)

//Crea un objeto receptor para "escuchar" el pin "D2"  (Receptor de infrarojos)
IRrecvPCI myReceiver(RECV_PIN);

//Crea un objeto decodificador
IRdecodeNEC myDecoder;

void setup() {
  // Inicializa los pines digitales como "salida" (OUTPUT), tambien alguno como "entrada" (INPUT)
  VLed = 1;                            //LED de "Encendido el ultrasonido" comienza en estado ON (Activado)
  VLuz = 0;                            //Luces Led delanteras comienza en estado OFF  (Apagadas)
  Vdistancia = 0;                      // Valor inicial variable "Vdistancia" para sensor de ultrasonido
  VStopGo = 0;                         // Valor inicial variable "VStopGo" para el arranque automático después de una parada por distancia muy corta del sensor de ultrasonidos.
  NOSound = 0;                         // Valor inicial de variable "NOSound" apagado. Se deshabilitan todos los sonidos. Ah... el silencio es precioso....
  pinMode(Led1, OUTPUT);               //Se configura Led1 como salida (pin D4)(Led "Habilitado o Deshabilitado trabajo con Ultrasonidos")
  pinMode(luz, OUTPUT);                //Se configura el pin luz como salida (pin D5)(Leds Luces delanteras)
  pinMode( MOTOR_B_DIR, OUTPUT );      //Se configura el pin D11 como salida (Motor B Direction)
  pinMode( MOTOR_B_PWM, OUTPUT );      //Se configura el pin D10 como salida (Motor B PWM Speed)
  pinMode( MOTOR_A_DIR, OUTPUT );      //Se configura el pin D6 como salida (Motor A Direction)
  pinMode( MOTOR_A_PWM, OUTPUT );      //Se configura el pin D9 como salida (Motor A PWM Speed)
  pinMode( Altavoz_Pin, OUTPUT );      //Se configura el pin D3 como salida (Altavoz)
  pinMode(trigger, OUTPUT);            //Se configura el pin D5 como salida (patilla "trigger" del Sensor Ultrasonidos)
  pinMode(echo, INPUT);                //Se configura el pin D7 como entrada (patilla "echo" del Sensor Ultrasonidos)
  digitalWrite( Led1, HIGH);           //Se activa "Led1" "Habilitado trabajo con Ultrasonidos" (PIN D4)
  digitalWrite( luz, LOW);             //Se desactiva "luz" (PIN D8) LUCES DELANTERAS (2 Leds) Comienzan Apagadas
  digitalWrite( MOTOR_B_DIR, LOW );    //Se desactiva Motor B "RUEDAS" (SENTIDO DE GIRO)
  digitalWrite( MOTOR_B_PWM, LOW );    //Se desactiva Motor B "RUEDAS" (VELOCIDAD)
  digitalWrite( MOTOR_A_DIR, LOW );    //Se desactiva Motor A "PORTAIMANES" (SENTIDO DE GIRO)
  digitalWrite( MOTOR_A_PWM, LOW );    //Se desactiva Motor A "PORTAIMANES" (VELOCIDAD)

  Serial.begin(9600);         // Abre el puerto Serie, configura los datos a 9600 bps
  myReceiver.enableIRIn();    // Enciende el receptor
  Serial.println(F("Ready to receive IR signals"));
}

void loop() {                     //Se inicia la rutina Principal "loop" (Bucle)
  if (VLed == 1) {                // Con el VLed activo "Encendido el Ultrasonido" (led verde) trabaja con el control de velocidad por ultrasonidos.
    Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
  }
  if (myReceiver.getResults()) {  //Continúe en bucle hasta que una señal sea completamente recibida por mando infrarrojo.
    myDecoder.decode();           //Decode it
    myDecoder.dumpResults(true);  //Now print results. Use false for less detail
    translateIR();
    myReceiver.enableIRIn();      //Restart receiver
  }
}                                 // Fin de rutina Loop (Bucle)

//   CONTROL DE VELOCIDAD MEDIANTE SENSOR DE ULTRASONIDOS
//  - Dependiendo de la distancia varía la velocidad:
//  - Si está a menos de 15cm manda parar, también si llega a dar un valor por encima de 601cm cosa que puede suceder cuando tiene un objeto muy cercano,(nos da valores superiores a 2000cm, al menos en el modelo chino que tengo).
//  - Entre 16cm y 22cm va a una velocidad 50
//  - Entre 23cm y 25cm va una velocidad 60
//  - Entre 26cm y 29cm va a una velocidad 100
//  - Entre 30cm y 32cm va una velocidad 120
//  - Entre 33cm y 35cm va a una velocidad 140
//  - Entre 36cm y 45cm va una velocidad 150
//  - Entre 46cm y 600cm va una velocidad 150 (Velocidd estandar cuando trabaja con el sensero de ultrasonidos activo)
void Ultrasound()
{
  Distancia_test();                 //LLamada a la función de Sensor de Ultrasonido
  Vdistancia = Distancia_test();    //Asignamos el valor leído por el Sensor de ultrasonidos a la variable "Vdistancia"
  Serial.print("DISTANCIA INICIO RUTINA ULTRASOUND =");
  Serial.println(Vdistancia);
  Serial.print ("VELOCIDAD INICIO RUTINA ULTRASOUND = ");
  Serial.println (Speed);
  //Serial.print ("El estado de la variable MOTOR_B_DIR inicio rutina Ultrasound = ");
  //Serial.println (MOTOR_B_DIR);
  //Serial.print ("El estado de la variable MOTOR_B_PWM inicio rutina Ultrasound = ");
  //Serial.println (MOTOR_B_PWM);
  //Serial.print ("Variable VStopGo = ");
  //Serial.println (VStopGo);

  if ((Vdistancia >= 0) && (Vdistancia <= 18) && (VMotB == 1) || (Vdistancia >= 601) && (Vdistancia <= 4000) && (VMotB == 1))  { // Cuando la distancia está entre 0cm y 15cm  o entre 601 y 400 manda parar.  NOTA: Filtra valores erróneos de sensor de
    if (VStopGo == 1) {                                                                                             // ultrasonidos que da cuando tiene un objeto muy cercano, da valores erróneos de distancia superiores a 2000cm.
      Stop_MB();                                                                             //Con "VStopGo" a "1" cada vez que se produce una parada por un objeto muy cercano, no vuelve a arrancar automáticamente.
    }
    else if (VStopGo == 0) {                                                                   //Con "VStopGo" a "0" arranca automáticamente cuando el objeto cercano se ha retirado.
      Speed = 0;                                                                                 //La variable "VStopGo" la podemos variar  manualmente pulsadon la tecla "1" del mando a distancia.
      analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
      //Serial.print("DISTANCIA ENTRE 0 y 15 O ENTRE 601 Y 4000 =   ");
      //Serial.println(Vdistancia);
      //Serial.print ("VELOCIDAD =    ");
      //Serial.println (Speed);
    }
  }
  else if ((Vdistancia >= 19) && (Vdistancia <= 25) && (VMotB == 1))  {                           // Distancia entre 16cm y 22cm damos una velocidad de 50. (tenemos algún obstáculo cercano velocidad inicial muy baja.
    Speed = 50;                                                                                // Para éste tipo de motor con pocas revoluciones (Relación de Reductora 1:48) si bajamos de éste valor mínimo de 50 no será capaz de mover el coche.
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
    //Serial.print("DISTANCIA ENTRE 16 y 22 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
  else if ((Vdistancia >= 26) && (Vdistancia <= 30) && (VMotB == 1))  {                      // A PARTIR DE AQUÍ VAMOS SUBIENDO LA VELOCIDAD DEPENDIENDO SI NOS ALEJAMOS DEL OBJETO DE POSIBLE COLISIÓN....:
    Speed = 60;                                                                           //Distancia entre 23cm y 25cm velocidad 60
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
    //Serial.print("DISTANCIA ENTRE 23 y 25 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
  else if ((Vdistancia >= 31) && (Vdistancia <= 36) && (VMotB == 1))  {                 // Distancia entre 26cm y 29cm velocidad 100
    Speed = 100;
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
    //Serial.print("DISTANCIA ENTRE 26 y 29 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
  else if ((Vdistancia >= 37) && (Vdistancia <= 42) && (VMotB == 1))  {             // Distancia entre 30cm y 32cm velocidad 120
    Speed = 120;
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
    //Serial.print("DISTANCIA ENTRE 30 y 32 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
  else if ((Vdistancia >= 43) && (Vdistancia <= 48) && (VMotB == 1))  {        // Distancia entre 33cm y 35cm velocidad 140
    Speed = 140;
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
    //Serial.print("DISTANCIA ENTRE 33 y 35 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
  else if ((Vdistancia >= 48) && (Vdistancia <= 55) && (VMotB == 1))  {    // Distancia entre 36cm y 45cm velocidad 150
    Speed = 150;
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast
    //Serial.print("DISTANCIA ENTRE 36 y 45 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
  else if ((Vdistancia >= 56) && (Vdistancia <= 600) && (VMotB == 1))  {            // Distancia entre 46cm y 600cm velocidad 150
    Speed = 150;                                                                // 400cm valores máximos que mide más o menos fiables sensor ultrasonidos, por encima de esa distancia los valores pueden no ser fiables.
    analogWrite( MOTOR_B_PWM, 255 - Speed ); // PWM speed = fast                  // Llega a medir hasta 600cm según fabricante...
    //Serial.print("DISTANCIA ENTRE 46 y 600 =   ");
    //Serial.println(Vdistancia);
    //Serial.print ("VELOCIDAD =    ");
    //Serial.println (Speed);
  }
}

//MANDO DE INFRAROJOS
// Dependiendo del código recibido por infrarrojo se ejecuta las diversas acciones:
// - Activación/Desactivación de la Luz de encendido,(led verde) que señaliza que el control de velocidad mediante el sensor de ultrasonidos está activado/desactivado.
// - Activación/Desactivación de las Luces delanteras (2 leds blancos)
// - Motor A (Portaimanes) Giro a derechas o izquierdas (Varias Velocidades, si pulsamos varias veces en el mismo sentido sube de velocidad hasta velocidad máxima.
// - Motor B (Ruedas) Adelante/Atrás (Si pulsamos varias veces en el mismo sentido sube de velocidad hasta velocidad máxima), (Sólo con Ultrasonidos Desactivados "led verde apagado")
// - Sonidos Activados/Desactivados (trabaja el altavoz activo para señalizar diversas acciones,(también el parpadeo de las luces delanteras): Como activación/desactivación ultrasonidos, velocidad máxima alcanzada, habilitación de arranque automático,Claxon.
// - NOTA: En caso de querer utilizar un mando infrarojo diferente (quizás valdría uno de una televisión) tendreis que usar el "Monitor Serie" dentro de la pestaña "Herramientas" y al pulsar una tecla examinar la primera linea y donde sale
//   la palabra "Value:FFFFFF". Estas "FFFFFF" es el código que tendréis que poner a continuación de los "case" para realizar la opción deseada (Se pondría de ésta forma->  case 0xFFFFFF:   (Se añade el "0x" sin las comillas antes del valor obtenido)
//   Nota al estar activo el Sensor de Ultrasonido para poder observar el código obtenido deshabilitar el "Autoscroll" en monitor serie.
// - Códigos de cada tecla del  Mando Infrarrojo (modelo VS1838):  ("CH-"= FFA25D), ("CH"= FF629D), ("CH+"= FFE21D), ("PREV"= FF22DD), ("NEXT"= FF02FD), ("PLAY/PAUSE"= FFC23D), ("VOL-"= FFE01F), ("VOL+"= FFA857), ("EQ"= FF906F), ("0"= FF6897)
//   ("100+"= FF9867), ("200+"= FFB04F),  ("1"= FF30CF),  ("2"= FF18E7),  ("3"= FF7A85),  ("4"= FF10EF),  ("5"= FF38C7),  ("6"= FF5AA5),  ("7"= FF42BD),  ("8"= FF4AB5), ("9"= FF52AD)
void translateIR()
{
  switch (myDecoder.value) {
    case 0xFF22DD:                           // "PRECEDENT" El valor "FF22DD" es la tecla "Anterior" en el mando a distancia por infrarojos (si compráis el que está en el enlace anterior).
      if (VLed == 0) {                        // SE ACTIVA O DESACTIVA EL "LED VERDE" "Señaliza el encendido o apagado del SENSOR ULTRASÓNIDOS" Si la variable Vled esta a 0 (led verde de "trabajo con ultrasonido" apagado) se activa en la siguiente instrucción
        digitalWrite(Led1, HIGH);             // Activamos el  Pin "D3" usado para activar el led "verde" que señaliza el "encendido la forma de trabajo con Sensor de Ultrasonidos"
        VLed = 1;                             // Valor estado de la variable activo ya que el led se encuentra activo.
        Parpadeo1();
        buzzer();
      }
      else {
        digitalWrite(Led1, LOW);               // En caso contrario (que VLed1 esté a 1), lo apagamos (deshabilitamos el trabajar con sensor de ultrasonidos)
        VLed = 0;
        // VMotB=0;    // PENDIENTE DE PROBAR SI NO ARRANCA DESPUES DE ESTAR PARADO AL DESHABILITAR EL SENSOR DE ULTRASONIDOS.
        Parpadeo1();
        buzzer2();
      }
      break;

    case 0xFF02FD:                                  // El valor "FF02FD" es la tecla "Siguiente (NEXT)" en el mando a distancia por infrarojos. SE ACTIVA O DESACTIVA LAS "LUCES DELANTERAS"
      if (VLuz == 0) {                              // La rutina básicamente trabaja que si las "Luces delanteras" estaban apagadas se enciende y si estaban encendidas se apagan
        digitalWrite(luz, HIGH);
        VLuz = 1;
      }
      else {
        digitalWrite(luz, LOW);
        VLuz = 0;
      }
      break;

    case 0xFFE01F:                                  //  El valor "FFE01F" es la tecla "-" en el mando a distancia por infrarojos. SE ACTIVA EL "MOTOR PORTAIMANES" en dirección ADELANTE (MOTOR A)
      if (VMotA != 1) {
        Speed_MA = PWM_SLOW_A;
        go_forward_A ();
      }
      else {
        Speed_MA = Speed_MA + SpeedStep_MA ;
        Speed_MA = min(255, max(0, Speed_MA));
        if (Speed_MA == 255) {
          buzzer3();
          Parpadeo();
        }
        go_forward_A ();
      }
      break;

    case 0xFF906F:                                  //  El valor "FF906F" es la tecla "EQ" en el mando a distancia por infrarojos. SE ACTIVA EL "MOTOR PORTAIMANES" en dirección ATRAS (MOTOR A)
      if (VMotA != 2) {
        Speed_MA = PWM_SLOW_A;
        go_backward_A ();
      }
      else {
        Speed_MA = Speed_MA + SpeedStep_MA ;
        Speed_MA = min(255, max(0, Speed_MA));
        if (Speed_MA == 255) {
          buzzer3();
          Parpadeo();
        }
        go_backward_A ();
      }
      break;

    case 0xFF629D:                                 // El valor "FF629D" es la tecla "CH" en el mando a distancia por infrarojos. SE BAJA LA VELOCIDAD EN LOS DOS SENTIDOS DE AVANCE Y RETROCESO DE LAS RUEDAS (MOTOR B)
      if (VMotB == 1) {                           // Si la variable "VMotB" Motor Status es 1 (Locomotora hacia ADELANTE) bajamos la velocidad en ese sentido de giro.
        Speed = Speed - SpeedStep ;
        Speed = min(255, max(0, Speed));
        if (Speed <= 40) {
          Speed = 0 ; //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
        }
        go_forward ();
        if (Speed == 0) {
          buzzer3();  // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero (parados) en el sentido de Avance del tren.
          Parpadeo();
          VMotB = 0;
        }
      }
      else if (VMotB == 2) {                   // Si la variable "VMotB" Motor Status es 2 (Locomotora hacia ATRAS) bajamos la velocidad en ese sentido de giro.
        Speed = Speed - SpeedStep ;              // Bajamos de velocidad el valor de la variable "SpeedStep" que va en pasos de "50".
        Speed = min(255, max(0, Speed));
        if (Speed <= 40) {
          Speed = 0 ; //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
        }
        go_backward();
        if (Speed == 0) {
          buzzer3();  // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero (parados) en el sentido de Retroceso del tren.
          Parpadeo();
          VMotB = 0;
        }
      }
      //Stop_MB();
      break;

    case 0xFFA857:                                // El valor "FFA857" es la tecla "+" en el mando a distancia por infrarojos. SE BAJA LA VELOCIDAD EN LOS DOS SENTIDOS DE GIRO DEL MOTOR PORTA IMANES (MOTOR A)
      if (VMotA == 1) {                             // Si la variable "VMotA" (Motor Status) es 1 (MOTOR PORTA IMANES A DERECHAS) bajamos la velocidad en ese sentido de giro.
        Speed_MA = Speed_MA - SpeedStep_MA ;        // Bajamos de velocidad el valor de la variable "SpeedStep_MA" que va en pasos de "50".
        Speed_MA = min(255, max(0, Speed_MA));
        if (Speed_MA <= 40) {
          Speed_MA = 0; //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
        }
        go_forward_A ();
        if (Speed_MA == 0) {
          buzzer3();  // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero. (GIRO A DERECHAS VELOCIDAD CERO)
          Parpadeo();
          VMotA = 0;
        }
      }
      else if (VMotA == 2) {                      // Si la variable "VMotA" (Motor Status) es 2 (MOTOR PORTA IMANES A IZQUIERDAS) bajamos la velocidad en ese sentido de giro.
        Speed_MA = Speed_MA - SpeedStep_MA ;
        Speed_MA = min(255, max(0, Speed_MA));
        if (Speed_MA <= 40) {
          Speed_MA = 0; //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
        }
        go_backward_A();
        if (Speed_MA == 0) {
          buzzer3();  // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero. (GIRO A IZQUIERDAS VELOCIDAD CERO)
          Parpadeo();
          VMotA = 0;
        }
      }
      //Stop_MA();
      break;

    case 0xFFC23D:                                  //  El valor "FFC23D" es la tecla "Play/Pause" en el mando a distancia por infrarojos. STOP PARA LOS 2 MOTORES.
      //if(VMotB !=0  || VMotA !=0) {
      Stop_ALL ();
      break;

    case 0xFF38C7:                                  //  El valor "FF38C7" es la tecla "5" en el mando a distancia por infrarojos. DAR LUCES LARGAS (3 PARPADEOS PARA AVISAR AL CONDUCTOR DELANTERO)
      Parpadeo2();
      break;

    case 0xFF9867:                                  //  El valor "FF9867" es la tecla "100+" en el mando a distancia por infrarojos. SONIDO DEL CLAXON PARA INCORDIAR AL PERSONAL.
      Claxon();
      break;

    case 0xFF6897:                                  //  El valor "FF6897" es la tecla "0" en el mando a distancia por infrarojos. HABILITA O DESHABILITA EL ARRANQUE AUTOMÁTICO DESPUES DE UNA PARADA POR POSIBLE COLISIÓN.
      if (VStopGo == 0) {                           //  Estando el valor de la variable "VStopGo" a "1" cada vez que para debido a que el detector de ultrasonidos nos dice que hay un objeto muy cercano se para y no vuelve a arrancar
        VStopGo = 1;                                //  hasta que volvemos a pulsar el boton de avance "CH+" en mando a distancia. Con valor a "0" de ésta variable arranca automáticamente cuando el objeto cercano se ha retirado.
        Parpadeo();
        buzzer2();
      }
      else {
        VStopGo = 0;
        Parpadeo();
        buzzer();
      }
      break;

    case 0xFFB04F:                                // El valor "FFB04F" es la tecla "200+" del mando a distancia por infrarojos, HABILITA O DESHABILITA TODOS LOS SONIDOS (NOSound=0 => Sonidos activos)
      if (NOSound == 0) {
        Parpadeo();
        buzzer2();
        NOSound = 1;
      }
      else {
        NOSound = 0;
        Parpadeo();
        buzzer();
      }
      break;

    case 0xFFE21D:                                  // El valor "FFE21D" es la tecla "CH+" del mando a distancia por infrarojos. HACIA ADELANTE MOTOR B (RUEDAS)
      if (VMotB != 1) {                             // Si la variable "VMotB" Motor Status (Ruedas) es diferente de 1 lanza la rutina de avance
        Speed = PWM_SLOW_B;
        go_forward ();
      }
      else {
        Speed = Speed + SpeedStep ;               //Realiza uno de los cambios de velocidad para la variable "speed"
        Speed = min(255, max(0, Speed));          // Asigna al valor de Velocidad "Speed" el menor de los números. Sería de 255 en caso que la velocidad sobrepase éste valor.
        if (Speed == 255) {
          buzzer3();
          Parpadeo();
        }
        go_forward();
      }
      break;
    case 0xFFA25D:                                // El valor "FFA25D" es la tecla "CH-" del mando a distancia por infrarojos. HACIA ATRÁS EL MOTOR B  (RUEDAS)
      if (VMotB != 2) {
        Speed = PWM_SLOW_B;
        go_backward ();
      }
      else {
        Speed = Speed + SpeedStep ;                 //Realiza uno de los cambios de velocidad para la variable "speed"
        Speed = min(255, max(0, Speed));            // Asigna al valor de Velocidad "Speed" el menor de los números. Sería de 255 en caso que la velocidad sobrepase éste valor.
        if (Speed == 255) {
          buzzer3();
          Parpadeo();
        }
        go_backward();
      }
      break;
    default:  //Se ejecuta si nada coíncide....
      //buzzer();
      //buzzer1();
      //buzzer2();
      break;

  }

}

// RUTINA HACIA ADELANTE MOTOR B (RUEDAS)
void go_forward ()
{
  Serial.println ("Hacia ADELANTE en motor de las ruedas ...");
  Serial.print ("La velocidad de motor ruedas es: ");
  Serial.println (Speed);
  //Serial.print ("La distancia medida por ultrasonidos es (puede no ser la actual):  ");
  //Serial.println (Vdistancia);
  //if (VMotB == 0){buzzer1 ();}
  // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
  if (VMotB == 2) {
    Stop_MB();       //buzzer1 ();
    delay( DIR_DELAY );
  }
  // Activa el motor la velocidad y dirección
  digitalWrite( MOTOR_B_DIR, HIGH );   // Dirección Avance hacia Adelante
  analogWrite( MOTOR_B_PWM, 255 - Speed ); // Velocidad PWM, valor en variable "Speed"
  VMotB = 1;
}

// RUTINA HACIA ATRAS MOTOR B (RUEDAS)
void go_backward ()
{
  Serial.println ("Hacia ATRAS en motor de las ruedas ....");
  Serial.print ("La velocidad de motor ruedas es: ");
  Serial.println (Speed);
  //Serial.print ("La distancia medida por ultrasonidos es (puede no ser la actual): ");
  //Serial.println (Vdistancia);
  // if (VMotB == 0){buzzer1 ();}
  // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
  if (VMotB == 1) {
    Stop_MB();  //buzzer1 ();
    delay( DIR_DELAY );
  }
  // Activa el motor la velocidad y dirección
  digitalWrite( MOTOR_B_DIR, LOW ); // Dirección inversa (marcha atrás)
  analogWrite( MOTOR_B_PWM, Speed ); // Velocidad PWM, valor en variable "Speed"
  VMotB = 2;
}

// RUTINA HACIA ADELANTE MOTOR A (PORTAIMANES)
void go_forward_A ()
{
  Serial.println ("Vamos hacia adelante en motor portaimanes...");
  Serial.print ("La velocidad actual portaimanes es: ");
  Serial.println (Speed_MA);
  // if (VMotA == 0){buzzer1 ();} // Un pequeño pitido de arranca de motor portaimanes en dirección Avance
  // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
  if (VMotA == 2) {
    Stop_MA();   //buzzer1 ();
    delay( DIR_DELAY_A );
  }
  // Activa el motor la velocidad y dirección
  digitalWrite( MOTOR_A_DIR, HIGH ); // Dirección Giro hacia la derecha
  analogWrite( MOTOR_A_PWM, 255 - Speed_MA ); // Velocidad PWM, valor en variable "Speed_MA"
  VMotA = 1;
}

// RUTINA HACIA ATRAS MOTOR A (PORTAIMANES)
void go_backward_A ()
{
  Serial.println ("Vamos hacia atrás en motor portaimanes...");
  Serial.print ("La Velocidad actual portaimanes es: ");
  Serial.println (Speed_MA);
  // if (VMotA == 0){buzzer1 ();} // Un pequeño pitido de arranca de motor portaimanes en dirección Retroceso
  // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
  if (VMotA == 1) {
    Stop_MA();   // buzzer1 ();
    delay( DIR_DELAY_A );
  }
  // set the motor speed and direction
  digitalWrite( MOTOR_A_DIR, LOW ); // Dirección Giro hacia la izquierda
  analogWrite( MOTOR_A_PWM, Speed_MA ); // Velocidad PWM, valor en variable "Speed_MA"
  VMotA = 2;
}

// RUTINA DE "STOP" PARA LOS 2 DOS MOTORES (MOTOR A Y MOTOR B)
void Stop_ALL ()
{
  //Serial.println ("STOP Para los 2 motores...");
  digitalWrite( MOTOR_B_DIR, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_B_PWM, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_A_DIR, LOW ); //Motor portaimanes OFF
  digitalWrite( MOTOR_A_PWM, LOW ); //Motor portaimanes OFF
  VMotB = 0; //Motor Ruedas Valor inicial (parado)
  VMotA = 0; //Motor portaimanes valor inicial (parado)
}

// RUTINA DE "STOP" PARA EL MOTOR DE LAS RUEDAS (MOTOR B)
void Stop_MB ()
{
  //Serial.println ("STOP Para el motor de las ruedas (Motor B....");
  digitalWrite( MOTOR_B_DIR, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_B_PWM, LOW ); //Motor Ruedas OFF
  VMotB = 0; //Motor Ruedas Valor inicial (parado)
}

// RUTINA DE "STOP" PARA EL MOTOR PORTAIMANES  (MOTOR A)
void Stop_MA ()
{
  //Serial.println ("STOP Para el motor portaimanes (Motor A....");
  digitalWrite( MOTOR_A_DIR, LOW ); //Motor portaimanes OFF
  digitalWrite( MOTOR_A_PWM, LOW ); //Motor portaimanes OFF
  VMotA = 0; //Motor PortaImanes Valor inicial (parado)
}



// FUNCIÓN DE CÁLCULO DE DISTANCIA MEDIANTE SENSOR DE ULTRASONIDO
int Distancia_test()
{
  digitalWrite(trigger, LOW);
  delayMicroseconds(12);        // Valor original 10 (modificado a 12)
  digitalWrite(trigger, HIGH);
  delayMicroseconds(120);     // Valor Original 100 (modificado a 120)
  digitalWrite(trigger, LOW);
  float Fdistance = pulseIn(echo, HIGH);
  Fdistance = Fdistance / 58;
  return (int)Fdistance;
}

//RUTINAS PARA EL AVISO SONORO DE DIVERSAS FUNCIONES - Hay que tener en cuenta que si tenemos deshabilitados los sonidos el control de la locomotora irá más fluída, lo mismo sucede deshabilitando el control de velocidad mediante ultrasonidos.

// DOBLE PITIDO DE ALTAVOZ  - Doble pitido que indica que se ha habilitado alguna de las opciones programadas. (Activado control de velocidad por Ultrasonidos, Activado arranque automático después de un paro, o habilitación de todos los sonidos)
void buzzer ()
{
  if (NOSound == 0) {
    for (int thisBuz = 0; thisBuz < 2; thisBuz++) {
      digitalWrite(Altavoz_Pin, HIGH);
      delay(100);
      digitalWrite(Altavoz_Pin, LOW);
      delay(50);
    }
  }
}

// PITIDO DE ALTAVOZ 1 - Pitido de arranque o paro, cuando se inicia un movimiento de cualquiera de los 2 motores (DESHABILITADO "Comentado" en rutina de avance y retroceso motores ruedas y portaimanes)
void buzzer1 ()
{
  if (NOSound == 0) {
    for (int thisBuz = 0; thisBuz < 1; thisBuz++) {
      digitalWrite(Altavoz_Pin, HIGH);
      delay(120);
      digitalWrite(Altavoz_Pin, LOW);
      delay(50);
    }
  }
}

// PITIDO DE ALTAVOZ 2  Sonido apagado que indica que se ha deshabilitado alguna de las opciones programadas (Desactivado Ultrasonidos, desactivado arranque automático después de un paro, o desactivado todos los sonidos)
void buzzer2 ()
{
  if (NOSound == 0) {
    for (int thisBuz = 25; thisBuz > 0; thisBuz--) {
      analogWrite(Altavoz_Pin, thisBuz);
      delay(10);
      analogWrite(Altavoz_Pin, 0);
      delay(10);
    }
  }
}


// PITIDO DE ALTAVOZ 3  - Velocidad máxima alcanzada (Trabaja con cualquiera de los 2 motores, cuando pulsamos varias veces el mismo botón de avance (o retroceso) y llegamos al máximo de velocidad.
void buzzer3 ()
{
  if (NOSound == 0) {
    for (int thisBuz = 0; thisBuz < 1; thisBuz++) {
      digitalWrite(Altavoz_Pin, HIGH);
      delay(100);
      digitalWrite(Altavoz_Pin, LOW);
      delay(50);
    }
  }
}


// PITIDO DE ALTAVOZ 4 -  Claxon para advertir a nuestros rivales. Un dolor de cabeza para los padres.... (3 pitidos largos)
void Claxon ()
{
  if (NOSound == 0) {
    for (int thisBuz = 0; thisBuz < 3; thisBuz++) {
      digitalWrite(Altavoz_Pin, HIGH);
      delay(300);
      digitalWrite(Altavoz_Pin, LOW);
      delay(100);
    }
  }
}

// RUTINA PARPADEO DE LUCES DELANTERA (BLANCAS) - Señaliza la activación o desactivación de alguna opción (si las luces estaban encendidas después del parpadeo, se vuelven a dejar encendidas).
void Parpadeo ()
{
  for (int BlinkL = 0; BlinkL < 2; BlinkL++) {
    digitalWrite(luz, HIGH);
    delay(100);
    digitalWrite(luz, LOW);
    delay(50);
  }
  if (VLuz == 1) {
    digitalWrite(luz, HIGH);
  }
}

// RUTINA PARPADEO1 DE LUZ VERDE DE CONTROL DE VELOCIDAD POR ULTRASONIDOS ACTIVADO) - Señaliza la activación o desactivación del Control de Velocidad por ultrasonidos.
void Parpadeo1 ()
{
  for (int BlinkL = 0; BlinkL < 2; BlinkL++) {
    digitalWrite(Led1, HIGH);
    delay(100);
    digitalWrite(Led1, LOW);
    delay(50);
  }
  if (VLed == 1) {
    digitalWrite(Led1, HIGH);
  }
}

// RUTINA PARPADEO2 DE LUCES DELANTERA (BLANCAS) - Realiza 3 parpadeos de las luces delanteras (dar luces) para que se entere el que va por delante..
void Parpadeo2 ()
{
  for (int BlinkL = 0; BlinkL < 3; BlinkL++) {
    digitalWrite(luz, HIGH);
    delay(200);
    digitalWrite(luz, LOW);
    delay(200);
  }
  if (VLuz == 1) {
    digitalWrite(luz, HIGH);
  }
}




[/code]

No, I'm absolutely not familiar with Arduino IDE, hence my test under ESPHome with an ESP32

sorry, I'm French and I may have expressed myself poorly. What I mean is that I'm not Spanish. It's probably the creator of this project who is. That's why his code, I find, is rather well documented in Spanish.

So, when testing with this Arduino IDE project, with only the sensor connected to pins D5 and D7, everything works correctly.

/*
 * Projet Arduino Nano + HC-SR04
 * Mesure de distance avec capteur ultrasonique HC-SR04
 * Compatible avec Arduino IDE 1.8
 * 
 * Connexions HC-SR04 vers Arduino Nano:
 * VCC  -> 5V
 * GND  -> GND
 * Trig -> Pin 5
 * Echo -> Pin 7
 * 
 * Auteur: Assistant Claude
 * Version: 1.0
 */

// Définition des broches
const int trigPin = 5;    // Broche de déclenchement (Trigger)
const int echoPin = 7;    // Broche d'écho (Echo)
const int ledPin = 13;    // LED intégrée pour indication

// Variables globales
long duration;            // Durée de l'impulsion
float distance;           // Distance mesurée en cm
float filteredDistance;   // Distance filtrée
const int numReadings = 5; // Nombre de lectures pour le filtrage
float readings[numReadings]; // Tableau pour stocker les lectures
int readIndex = 0;        // Index de lecture actuel
float total = 0;          // Total des lectures

// Paramètres de mesure
const float soundSpeed = 0.034; // Vitesse du son (cm/µs)
const int measurementDelay = 1000; // Délai entre mesures (ms) - 1 seconde
const float maxDistance = 400;    // Distance max en cm
const float minDistance = 2;      // Distance min en cm

void setup() {
  // Initialisation de la communication série
  Serial.begin(9600);
  Serial.println("=== Capteur HC-SR04 avec Arduino Nano ===");
  Serial.println("Initialisation en cours...");
  
  // Configuration des broches
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  // Initialisation du tableau de filtrage
  for (int i = 0; i < numReadings; i++) {
    readings[i] = 0;
  }
  
  // Signal de démarrage
  digitalWrite(ledPin, HIGH);
  delay(1000);
  digitalWrite(ledPin, LOW);
  
  Serial.println("Système prêt !");
  Serial.println("Distance (cm) | État");
  Serial.println("--------------|------");
}

void loop() {
  // Mesure de la distance
  distance = measureDistance();
  
  // Diagnostic détaillé
  Serial.print("Durée: ");
  Serial.print(duration);
  Serial.print(" µs, Distance: ");
  Serial.print(distance, 1);
  Serial.print(" cm");
  
  // Validation de la mesure
  if (distance >= minDistance && distance <= maxDistance) {
    // Filtrage de la distance pour réduire le bruit
    filteredDistance = filterDistance(distance);
    
    // Affichage des résultats
    Serial.print(" -> ");
    displayResults(filteredDistance);
    
    // Indication visuelle basée sur la distance
    handleLED(filteredDistance);
    
  } else {
    // Mesure hors limites avec plus de détails
    Serial.print(" -> ERREUR (");
    if (distance == -1) {
      Serial.print("Pas d'écho détecté");
    } else if (distance < minDistance) {
      Serial.print("Trop proche: < ");
      Serial.print(minDistance);
      Serial.print(" cm");
    } else if (distance > maxDistance) {
      Serial.print("Trop loin: > ");
      Serial.print(maxDistance);
      Serial.print(" cm");
    }
    Serial.println(")");
    digitalWrite(ledPin, LOW);
  }
  
  delay(measurementDelay);
}

/**
 * Fonction de mesure de distance avec HC-SR04
 * @return distance en centimètres
 */
float measureDistance() {
  // Nettoyage de la broche trigger
  digitalWrite(trigPin, LOW);
  delayMicroseconds(5);  // Augmenté à 5µs pour être sûr
  
  // Génération d'une impulsion de 10µs
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Lecture de la durée de l'écho avec timeout plus long
  duration = pulseIn(echoPin, HIGH, 50000); // Timeout à 50ms au lieu de 30ms
  
  // Calcul de la distance
  if (duration > 0) {
    return (duration * soundSpeed) / 2;
  } else {
    return -1; // Erreur de mesure
  }
}

/**
 * Filtrage par moyenne mobile
 * @param newReading nouvelle lecture
 * @return distance filtrée
 */
float filterDistance(float newReading) {
  // Soustraction de l'ancienne lecture
  total = total - readings[readIndex];
  
  // Ajout de la nouvelle lecture
  readings[readIndex] = newReading;
  total = total + readings[readIndex];
  
  // Avancement de l'index
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  
  // Calcul de la moyenne
  return total / numReadings;
}

/**
 * Affichage des résultats formatés
 * @param dist distance à afficher
 */
void displayResults(float dist) {
  String status;
  
  // Détermination du statut basé sur la distance
  if (dist < 10) {
    status = "TRÈS PROCHE";
  } else if (dist < 30) {
    status = "PROCHE";
  } else if (dist < 100) {
    status = "MOYEN";
  } else {
    status = "LOIN";
  }
  
  // Affichage sans sprintf (problème connu avec %f sur Arduino)
  Serial.print("  ");
  Serial.print(dist, 1);  // 1 décimale
  Serial.print(" cm     | ");
  Serial.println(status);
}

/**
 * Gestion de la LED d'indication
 * @param dist distance mesurée
 */
void handleLED(float dist) {
  static unsigned long previousMillis = 0;
  static bool ledState = false;
  unsigned long interval;
  
  // Définition de l'intervalle de clignotement basé sur la distance
  if (dist < 10) {
    interval = 100;  // Clignotement rapide
  } else if (dist < 30) {
    interval = 300;  // Clignotement moyen
  } else if (dist < 100) {
    interval = 1000; // Clignotement lent
  } else {
    digitalWrite(ledPin, LOW); // LED éteinte
    return;
  }
  
  // Gestion du clignotement non-bloquant
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
  }
}

/**
 * Fonction utilitaire pour afficher les informations système
 * Appelez cette fonction depuis le moniteur série si besoin
 */
void printSystemInfo() {
  Serial.println("\n=== Informations Système ===");
  Serial.print("Distance min détectable: ");
  Serial.print(minDistance);
  Serial.println(" cm");
  Serial.print("Distance max détectable: ");
  Serial.print(maxDistance);
  Serial.println(" cm");
  Serial.print("Délai entre mesures: ");
  Serial.print(measurementDelay);
  Serial.println(" ms");
  Serial.print("Nombre d'échantillons pour filtrage: ");
  Serial.println(numReadings);
  Serial.println("==============================\n");
}

Console:

22:10:19.395 -> Durée: 432 µs, Distance: 7.3 cm ->   1.5 cm     | TRÈS PROCHE
22:10:20.406 -> Durée: 426 µs, Distance: 7.2 cm ->   2.9 cm     | TRÈS PROCHE
22:10:21.419 -> Durée: 3109 µs, Distance: 52.9 cm ->   13.5 cm     | PROCHE
22:10:22.432 -> Durée: 432 µs, Distance: 7.3 cm ->   15.0 cm     | PROCHE
22:10:23.444 -> Durée: 625 µs, Distance: 10.6 cm ->   17.1 cm     | PROCHE
22:10:24.453 -> Durée: 873 µs, Distance: 14.8 cm ->   18.6 cm     | PROCHE
22:10:25.464 -> Durée: 1046 µs, Distance: 17.8 cm ->   20.7 cm     | PROCHE
22:10:26.481 -> Durée: 970 µs, Distance: 16.5 cm ->   13.4 cm     | PROCHE
22:10:27.490 -> Durée: 2799 µs, Distance: 47.6 cm ->   21.5 cm     | PROCHE
22:10:28.500 -> Durée: 2963 µs, Distance: 50.4 cm ->   29.4 cm     | PROCHE
22:10:29.514 -> Durée: 3043 µs, Distance: 51.7 cm ->   36.8 cm     | MOYEN

Do you have any idea why the above-mentioned project doesn’t work, then? :roll_eyes:

How would you know ?

1 Like

That's good news. Now you need to figure out what part of the extended code or wiring is breaking the correct reading of the SR04.

With the original code and complete wiring, if you comment out everything in loop( ) except this, do you get correct readings?

if (VLed==1) {                  // Con el VLed activo "Encendido el Ultrasonido" (led verde) trabaja con el control de velocidad por ultrasonidos.
     Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
    }

If not then you will need to disconnect hardware until the distance sensor is working properly.

If you do get correct readings, then you will need to add back the IR detection and see if that is what breaks it. Then go for the motors.

there is an error


XX:Tren_Lego_Duplo_Sofia_v1.2\Tren_Lego_Duplo_Sofia_v1.2.ino: In function 'void loop()':
Tren_Lego_Duplo_Sofia_v1.2:108:6: error: 'Ultrasound' was not declared in this scope
      Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
      ^~~~~~~~~~
xx:Tren_Lego_Duplo_Sofia_v1.2\Tren_Lego_Duplo_Sofia_v1.2.ino:108:6: note: suggested alternative: 'lround'
      Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
      ^~~~~~~~~~
      lround
Tren_Lego_Duplo_Sofia_v1.2:132:1: error: a function-definition is not allowed here before '{' token
 {
 ^
Tren_Lego_Duplo_Sofia_v1.2:230:1: error: a function-definition is not allowed here before '{' token
 {
 ^
Tren_Lego_Duplo_Sofia_v1.2:396:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:415:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:434:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:451:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:468:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:480:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:489:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:500:1: error: a function-definition is not allowed here before '{' token
 {
 ^
Tren_Lego_Duplo_Sofia_v1.2:515:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:528:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:541:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:555:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:569:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:582:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:596:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:610:3: error: a function-definition is not allowed here before '{' token
   {
   ^
Tren_Lego_Duplo_Sofia_v1.2:620:2: error: expected '}' at end of input
  }
  ^
exit status 1
'Ultrasound' was not declared in this scope

Have you posted the sketch that caused the error ?

Hello blastmun,
I think that when you tried to do what cattledog suggested in post #12, you have commented out too much.

I suggest that loop( ) needs to be commented out as follows:

void loop() {                     //Se inicia la rutina Principal "loop" (Bucle)
  if (VLed == 1) {                // Con el VLed activo "Encendido el Ultrasonido" (led verde) trabaja con el control de velocidad por ultrasonidos.
    Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
  }
  /*
    if (myReceiver.getResults()) {  //Continúe en bucle hasta que una señal sea completamente recibida por mando infrarrojo.
    myDecoder.decode();           //Decode it
    myDecoder.dumpResults(true);  //Now print results. Use false for less detail
    translateIR();
    myReceiver.enableIRIn();      //Restart receiver
     }
  */
}                                 // Fin de rutina Loop (Bucle)

You need to have that last line
} // Fin de rutina Loop (Bucle)
in place, as it is the necessary closing bracket for loop( ).

I commented that line out and got multiple errors like yours.

With it left in, I only got 2 errors, which were due to the IR library / hardware which I don't have.

Apparently everything seems ok now! :grinning_face:
Having no knowledge in Arduino, I therefore tried asking GPT5 for help and here is (after several prompts) its response that solved the problem:

Edit:
The pin change didn't change anything to the problem I think, because with this same pin but the old code it was not working, but I left him pin 12 to thank him for his work :sweat_smile:


Recommended fixes

  1. Isolate the HC‑SR04 on pins used by nothing else
  • Move TRIG to a free pin not used elsewhere (no motor PWM, no LED, etc.). Example: D12.
  • Keep ECHO on a free input (D7 is fine if used only for this).

Change these lines:

// BEFORE
const int trigger = 5;
const int echo    = 7;

// AFTER
const int trigger = 12;  // D12: TRIG (wire it physically to D12)
const int echo    = 7;   // D7 : ECHO
  1. setup(): ensure a clean idle state

Make sure you have this (once), right after pinMode:

pinMode(trigger, OUTPUT);
digitalWrite(trigger, LOW);   // TRIG idle low
pinMode(echo, INPUT);         // INPUT is enough (INPUT_PULLUP not required for HC-SR04)
  1. Replace Distancia_test() with a robust version
  • Standard 10 µs TRIG pulse
  • pulseIn() timeout so it doesn’t block 1 s
  • Enforce a minimum period between pings
  • Optional small median to stabilize readings

Paste this to replace your current function:

// Robust HC-SR04 read (returns distance in cm; 0 if no echo)
int Distancia_test() {
  static unsigned long lastPingMs = 0;
  const unsigned long minPeriodMs = 60;        // recommended min period between pings
  const unsigned long echoTimeoutUs = 30000UL; // 30 ms ~ 5 m (avoids 1 s blocking)

  // respect minimum cadence
  unsigned long now = millis();
  if (now - lastPingMs < minPeriodMs) {
    delay(minPeriodMs - (now - lastPingMs));
  }
  lastPingMs = millis();

  // TRIG pulse: 10 µs
  digitalWrite(trigger, LOW);
  delayMicroseconds(4);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  // measure echo with timeout
  unsigned long duration = pulseIn(echo, HIGH, echoTimeoutUs);
  if (duration == 0) {
    return 0; // no echo detected within the window
  }

  // convert to cm (≈ duration/58)
  int cm = (int)(duration / 58UL);
  return cm;
}

Optional (simple filtering): take 3 measurements and return the median to reject spikes:

int Distancia_filtrada() {
  int a = Distancia_test();
  int b = Distancia_test();
  int c = Distancia_test();
  // median of a,b,c
  if ((a<=b && b<=c) || (c<=b && b<=a)) return b;
  if ((b<=a && a<=c) || (c<=a && a<=b)) return a;
  return c;
}
  1. Don’t call Distancia_test() twice in a row

In Ultrasound(), replace:

Distancia_test();
Vdistancia = Distancia_test();

with:

Vdistancia = Distancia_test();  // or Distancia_filtrada();
  1. Verify no other constant reuses D12/D7

Make sure MOTOR_A_PWM, MOTOR_B_PWM, MOTOR_A_DIR, MOTOR_B_DIR, LEDs, buzzer, IR, etc. do not use D12 or D7. If they do, pick other free pins for TRIG/ECHO.


Why this fixes your issue

  • By moving TRIG off D5 (likely a motor PWM), you eliminate the conflict that prevented a valid TRIG pulse.
  • The 30 ms pulseIn() timeout avoids 1 s stalls and returns 0 quickly if nothing is received.
  • Enforcing at least 60 ms between pings gives the sensor time to settle and reduces zero readings.
  • A single call per cycle avoids “re-triggering” the sensor before the previous measurement completes.

I spoke too soon! I put everything back together, and now the IR sensor is on, but I notice that it seems to restart in a loop with the following message regularly in the console:

Ready to receive IR signals

which, if I'm not mistaken, only appear once at the beginning

Please post the code which is giving the restarts.


/*      ---------------  LOCOMOTORA "SOFIA" COMPATIBLE CON PISTAS DE TREN DE LEGO DUPLO, CONTROLADO POR MANDO INFRARROJO, CON CONTROL DE VELOCIDAD POR SENSOR DE ULTRASONIDOS Y CON UN SEGUNDO MOTOR PORTA IMANES USO VARIADO -----------------
 *       
 *  MATERIAL NECESARIO :   
 *  - Arduino Nano v3.0      -  Interruptor de Encendido    - 1 Led Verde        - 2 Leds Blancos                 - Sensor de Ultrasonidos "HC-SR04"            - 1 Motor CC para las ruedas con engranaje (con eje para las 2 ruedas)
 *  - Un mini motor de engranajes (30 r.p.m) para colación de los imanes         - 1  ALTAVOZ (Activo)5V 12mm     - Resistencias 47 Y 150 OHMS(para los Leds)   - 1 Controlador de Motores de CC don doble salida "HG7881"(L9110S)
 *  - Terminales (muelles) para la caja de baterías)        - 2 Baterias 18650   - Varilla de 2mmx51mm (bisagra) y otra de 3mmx48 para el eje de las ruedas     - 1 kit Infrarojo (mando y receptor) modelo VS1838
 *  - 4 Imanes de neodimio cilindricos 4mmx4mm  para cierre magnético de tapa    - 6 imanes de neodimio redondos de 10mmx3mm para juegos magnéticos.            - Cables tipo Dupont Hembra-Hembra de 10cm y 20cm para el conexionado.      
 *  
 *  FUNCIONAMIENTO: Mediante un mando por Infrarrojos y un Arduino Nano controlamos La Locomotora "SOFIA", es compactible con las vias del TREN DE LEGO DUPLO.  
 *  Este tiene un sensor de Ultrasonidos para reducir la velocidad o frenar antes de colisionar en el sentido de avance del tren, que podemos habilitar o deshabilitar. 
 *  Señalizado por el led "verde" de Activado/Desactivado Ultrasonido (Led "Verde" encendido --> Trabajo con Ultrasonidos Activado), (Led "Verde" Apagado --> Trabajo con Ultrasonidos Desactivado)
 *  Tambien se puede subir la velocidad manualmente pulsado la tecla de "CH+" (marcha adelante) o "CH-" (marcha atrás) del mando de infrarojos varias veces (motor de las Ruedas) hasta llegar a su velocidad máxima (con Ultrasonidos Desactivado)
 *  Tiene un motor extra en el interior para el montaje de una rueda con imanes de neodimio para futuros proyectos, y podemos subir su velocidad de giro con las teclas "-" y "+", (no le influye la habilitación o no de los Ultrasonidos).
 *  Podemos encender/apagar  las "luces delanteras" para una mayor visibilidad en la conducción nocturna, jeje.
 *  Podemos dar "bocinazos" para pedir paso en un cruze mediante el altavoz. También se le ha añadido, un parpadeo en las luces delanteras cuando seleccionamos alguna de las opciones o cuando el coche ha llegado a su velocidad máxima.
 *  MAS INFORMACIÓN EN:  https://www.thingiverse.com/thing:4012245
 *  

*/ 

//NOTA:   Puede suceder que dependiendo como conectamos la alimentación de los motores (van través del Modulo HG7881 (L9110S)) nos girarían en sentido contrario, para solucionar ésto, simplemente intercambiar los cables que van al motor.
//NOTA 2: Dependiendo del fabricandte del Sensor de Ultrasonidos del modelo "HC-SR04" algunos pueden tener mejor sensibilidad o peor sensibilidad, quizás tengamos que ajustar dentro de la rutina "Ultrasound()" los valores de distancia (dentro de los "if") 
//        para mejorar su funcionamiento. También dentro de la función "Distancia_test()" podemos variar algo los "delayMicroseconds" para mejorar su funcionamiento.

#include "IRLibAll.h"

// Variables usadas para el control del programa.
int VLed;             // Variable "VLed" usada para el estado de Activado o Desactivado trabajo con sensor de Ultrasonido (1 LED Verde)
int VLuz;             // Variable "VLuz" usada para el estado de las luces delanteras (2 LEDs Blancos)
int VMotB;            // Variable "VMotB" usada para el estado del Motor de las Ruedas motrices (MOTOR B)
int VMotA;            // Variable "VMotA" usada para el estado del motor portaimanes (MOTOR A)
int Vdistancia;       // Variable "Vdistancia" usada para el valor del Sensor de Ultrasonidos
int VStopGo;          // Variable para arrancar automáticamente después de producirse una parada debido a que el sensor ultrasonido para antes de colisionar (distancia muy corta)
int NOSound;          // Variable para habilitar o deshabilitar los sonidos

//Constantes con su valor de pin de conexionado para una mejor identificación y control del programa.
const int RECV_PIN=2;       // Constante "RECV_PIN" con valor "2"    (Pin "D2" usado para el Receptor de infrarojos)
const int Led1=4;           // Constante "Led1" con valor "4"        (Pin "D4" usado para el led verde de "Encendido/Apagdo el Sensor de Ultrasonido")
const int Altavoz_Pin=3;    // Constante "Altavoz_Pin" con valor "3" (Pin "D3" usado para conexionado del Altavoz)
const int trigger=5;      // Constante "trigger" con valor "5"     (Pin "D5" usado para Sensor de ultrasonido (patilla trigger)
const int echo=7;         // Constante "echo" con valor "7"        (Pin "D7" usado para el Sensor de ultrasonido (patilla echo)
const int luz=8;            // Constante "luz" con valor "8"         (Pin "D8" usado para las Luces delanteras. Lleva 2 led blancos)


// Conexiones cableadas, Usando el controlador de motores "HG7881" (voltaje de trabajo 2,5v a 12V)
#define HG7881_B_IA 10     // Pin "D10" --> Motor B Input B-IA --> MOTOR B + (MOTOR DE RUEDAS)
#define HG7881_B_IB 11     // Pin "D11" --> Motor B Input B-IB --> MOTOR B - (MOTOR DE RUEDAS)
#define HG7881_A_IA 6      // Pin  "D6" --> Motor A Input A-IA --> MOTOR A + (MOTOR PORTAIMANES)
#define HG7881_A_IB 9      // Pin  "D9" --> Motor A Input A-IB --> MOTOR A - (MOTOR PORTAIMANES)
 
// Conexiones funcionales
#define MOTOR_B_PWM HG7881_B_IA      // Motor B PWM Speed (MOTOR RUEDAS VELOCIDAD) (PIN D10)
#define MOTOR_B_DIR HG7881_B_IB      // Motor B Direction (MOTOR RUEDAS DIRECCION) (PIN D11)
#define MOTOR_A_PWM HG7881_A_IA      // Motor A PWM Speed (MOTOR PORTAIMANES VELOCIDAD) (PIN D6)
#define MOTOR_A_DIR HG7881_A_IB      // Motor A Direction (MOTOR PORTAIMANES DIRECCIÓN) (PIN D9)
 
//Los valores reales de "rápido" (FAST) y "lento" (SLOW) dependen de cada motor (rpm). Variar, ajustando a sus valores para una velocidad adecuada.
#define PWM_SLOW_A 100       // Ciclo de trabajo PWM arbitrario de velocidad lenta  (MOTOR A -> "MOTOR PORTAIMANES")
#define PWM_FAST_A 150       // Ciclo de trabajo PWM arbitrario de velocidad rápida (MOTOR A -> "MOTOR PORTAIMANES")
#define DIR_DELAY_A 1000     // Retardo para evitar cambios brucos de velocidad en inversiones de giro del Motor A Portaimanes
#define PWM_SLOW_B 150       // Ciclo de trabajo PWM arbitrario de velocidad lenta  (MOTOR B -> "MOTOR RUEDAS")
#define PWM_FAST_B 200       // Ciclo de trabajo PWM arbitrario de velocidad rápida (MOTOR B -> "MOTOR RUEDAS")
#define DIR_DELAY 1000       // Retardo para evitar cambios brucos de velocidad en inversiones de giro del Motor B RUEDAS

// Variables usadas para el control de velocidad del motor de ruedas mediante pulsaciones en mando infrarojo. También motor portaimanes con valor fijo.
int Speed = 150;          // Variable "speed" con valor inicial de velocidad (usado en motor B -> RUEDAS)
int SpeedStep = 50;       // Variable "SpeedStep" usada para los pasos de cambios de velocidad (mediante pulsaciones en mando infarojo al mismo botón de avance/retroceso) (usado en Motor B -> RUEDAS)
int Speed_MA = 100;       // Variable "Speed_MA", velocidad para Motor A (Portaimanes), este motor trabaja con pocas rmp (30rpm)
int SpeedStep_MA = 50;    // Variable "SpeedStep_MA" usada para los pasos de cambios de velocidad (mediante pulsaciones en mando infrarojo al mismo botón de avance/retroceso) (usado en Motor A -> PORTAIMANES)

//Crea un objeto receptor para "escuchar" el pin "D2"  (Receptor de infrarojos)
IRrecvPCI myReceiver(RECV_PIN);

//Crea un objeto decodificador
IRdecodeNEC myDecoder;   

void setup() {
// Inicializa los pines digitales como "salida" (OUTPUT), tambien alguno como "entrada" (INPUT)
  VLed=1;                              //LED de "Encendido el ultrasonido" comienza en estado ON (Activado)
  VLuz=0;                              //Luces Led delanteras comienza en estado OFF  (Apagadas)
  Vdistancia=0;                        // Valor inicial variable "Vdistancia" para sensor de ultrasonido
  VStopGo=0;                           // Valor inicial variable "VStopGo" para el arranque automático después de una parada por distancia muy corta del sensor de ultrasonidos.
  NOSound=0;                           // Valor inicial de variable "NOSound" apagado. Se deshabilitan todos los sonidos. Ah... el silencio es precioso....
  pinMode(Led1, OUTPUT);               //Se configura Led1 como salida (pin D4)(Led "Habilitado o Deshabilitado trabajo con Ultrasonidos")
  pinMode(luz, OUTPUT);                //Se configura el pin luz como salida (pin D5)(Leds Luces delanteras)
  pinMode( MOTOR_B_DIR, OUTPUT );      //Se configura el pin D11 como salida (Motor B Direction)
  pinMode( MOTOR_B_PWM, OUTPUT );      //Se configura el pin D10 como salida (Motor B PWM Speed)
  pinMode( MOTOR_A_DIR, OUTPUT );      //Se configura el pin D6 como salida (Motor A Direction)
  pinMode( MOTOR_A_PWM, OUTPUT );      //Se configura el pin D9 como salida (Motor A PWM Speed)
  pinMode( Altavoz_Pin, OUTPUT );      //Se configura el pin D3 como salida (Altavoz)
  pinMode(trigger,OUTPUT);             //Se configura el pin D5 como salida (patilla "trigger" del Sensor Ultrasonidos)
  pinMode(echo,INPUT);                 //Se configura el pin D7 como entrada (patilla "echo" del Sensor Ultrasonidos)
 
  
  digitalWrite( Led1, HIGH);           //Se activa "Led1" "Habilitado trabajo con Ultrasonidos" (PIN D4) 
  digitalWrite( luz, LOW);             //Se desactiva "luz" (PIN D8) LUCES DELANTERAS (2 Leds) Comienzan Apagadas
  digitalWrite( MOTOR_B_DIR, LOW );    //Se desactiva Motor B "RUEDAS" (SENTIDO DE GIRO)
  digitalWrite( MOTOR_B_PWM, LOW );    //Se desactiva Motor B "RUEDAS" (VELOCIDAD)
  digitalWrite( MOTOR_A_DIR, LOW );    //Se desactiva Motor A "PORTAIMANES" (SENTIDO DE GIRO)
  digitalWrite( MOTOR_A_PWM, LOW );    //Se desactiva Motor A "PORTAIMANES" (VELOCIDAD)

  Serial.begin(9600);         // Abre el puerto Serie, configura los datos a 9600 bps
  myReceiver.enableIRIn();    // Enciende el receptor
  Serial.println(F("Ready to receive IR signals"));
}

void loop() {                     //Se inicia la rutina Principal "loop" (Bucle)
  if (VLed==1) {                  // Con el VLed activo "Encendido el Ultrasonido" (led verde) trabaja con el control de velocidad por ultrasonidos.
     Ultrasound();                // Se lanza la rutina de Ultrasonidos para el control de velocidad del tren
    } 
  if (myReceiver.getResults()) {  //Continúe en bucle hasta que una señal sea completamente recibida por mando infrarrojo.
    myDecoder.decode();           //Decode it
    myDecoder.dumpResults(true);  //Now print results. Use false for less detail
    translateIR();
    myReceiver.enableIRIn();      //Restart receiver
     }  
}                                 // Fin de rutina Loop (Bucle)

//   CONTROL DE VELOCIDAD MEDIANTE SENSOR DE ULTRASONIDOS
//  - Dependiendo de la distancia varía la velocidad:
//  - Si está a menos de 15cm manda parar, también si llega a dar un valor por encima de 601cm cosa que puede suceder cuando tiene un objeto muy cercano,(nos da valores superiores a 2000cm, al menos en el modelo chino que tengo).
//  - Entre 16cm y 22cm va a una velocidad 50
//  - Entre 23cm y 25cm va una velocidad 60
//  - Entre 26cm y 29cm va a una velocidad 100
//  - Entre 30cm y 32cm va una velocidad 120
//  - Entre 33cm y 35cm va a una velocidad 140
//  - Entre 36cm y 45cm va una velocidad 150
//  - Entre 46cm y 600cm va una velocidad 150 (Velocidd estandar cuando trabaja con el sensero de ultrasonidos activo)
void Ultrasound() 
{
    Distancia_test();                 //LLamada a la función de Sensor de Ultrasonido
    Vdistancia = Distancia_test();    //Asignamos el valor leído por el Sensor de ultrasonidos a la variable "Vdistancia"
    Serial.print("DISTANCIA INICIO RUTINA ULTRASOUND =");
    Serial.println(Vdistancia);
    Serial.print ("VELOCIDAD INICIO RUTINA ULTRASOUND = ");
    Serial.println (Speed);
  //Serial.print ("El estado de la variable MOTOR_B_DIR inicio rutina Ultrasound = ");
  //Serial.println (MOTOR_B_DIR);
  //Serial.print ("El estado de la variable MOTOR_B_PWM inicio rutina Ultrasound = ");
  //Serial.println (MOTOR_B_PWM);
  //Serial.print ("Variable VStopGo = ");
  //Serial.println (VStopGo);
    
    if ((Vdistancia>=0) && (Vdistancia <=18) && (VMotB==1) || (Vdistancia>=601) && (Vdistancia <=4000) && (VMotB==1))  {  // Cuando la distancia está entre 0cm y 15cm  o entre 601 y 400 manda parar.  NOTA: Filtra valores erróneos de sensor de 
          if (VStopGo==1) {                                                                                               // ultrasonidos que da cuando tiene un objeto muy cercano, da valores erróneos de distancia superiores a 2000cm.
              Stop_MB();                                                                             //Con "VStopGo" a "1" cada vez que se produce una parada por un objeto muy cercano, no vuelve a arrancar automáticamente.
              }
          else if (VStopGo==0) {                                                                     //Con "VStopGo" a "0" arranca automáticamente cuando el objeto cercano se ha retirado. 
          Speed = 0;                                                                                 //La variable "VStopGo" la podemos variar  manualmente pulsadon la tecla "1" del mando a distancia.         
          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast                                                                             
        //Serial.print("DISTANCIA ENTRE 0 y 15 O ENTRE 601 Y 4000 =   ");
        //Serial.println(Vdistancia);
        //Serial.print ("VELOCIDAD =    ");
        //Serial.println (Speed);
          }
     }
     else if ((Vdistancia>=19) && (Vdistancia <=25) && (VMotB==1))  {                                // Distancia entre 16cm y 22cm damos una velocidad de 50. (tenemos algún obstáculo cercano velocidad inicial muy baja.
          Speed = 50;                                                                                // Para éste tipo de motor con pocas revoluciones (Relación de Reductora 1:48) si bajamos de éste valor mínimo de 50 no será capaz de mover el coche.
          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
        //Serial.print("DISTANCIA ENTRE 16 y 22 =   ");
        //Serial.println(Vdistancia);
        //Serial.print ("VELOCIDAD =    ");
        //Serial.println (Speed);
          }
           else if ((Vdistancia>=26) && (Vdistancia <=30) && (VMotB==1))  {                           // A PARTIR DE AQUÍ VAMOS SUBIENDO LA VELOCIDAD DEPENDIENDO SI NOS ALEJAMOS DEL OBJETO DE POSIBLE COLISIÓN....:
                Speed = 60;                                                                           //Distancia entre 23cm y 25cm velocidad 60
                analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
              //Serial.print("DISTANCIA ENTRE 23 y 25 =   ");
              //Serial.println(Vdistancia);
              //Serial.print ("VELOCIDAD =    ");
              //Serial.println (Speed);
                }
                else if ((Vdistancia>=31) && (Vdistancia <=36) && (VMotB==1))  {                      // Distancia entre 26cm y 29cm velocidad 100
                     Speed = 100;
                     analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                   //Serial.print("DISTANCIA ENTRE 26 y 29 =   ");
                   //Serial.println(Vdistancia);
                   //Serial.print ("VELOCIDAD =    ");
                   //Serial.println (Speed);
                     }
                     else if ((Vdistancia>=37) && (Vdistancia <=42) && (VMotB==1))  {                  // Distancia entre 30cm y 32cm velocidad 120
                          Speed = 120;
                          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                        //Serial.print("DISTANCIA ENTRE 30 y 32 =   ");
                        //Serial.println(Vdistancia);
                        //Serial.print ("VELOCIDAD =    ");
                        //Serial.println (Speed);
                          }
                          else if ((Vdistancia>=43) && (Vdistancia <=48) && (VMotB==1))  {             // Distancia entre 33cm y 35cm velocidad 140
                               Speed = 140;
                               analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                             //Serial.print("DISTANCIA ENTRE 33 y 35 =   ");
                             //Serial.println(Vdistancia);
                             //Serial.print ("VELOCIDAD =    ");
                             //Serial.println (Speed);
                               }
                               else if ((Vdistancia>=48) && (Vdistancia <=55) && (VMotB==1))  {         // Distancia entre 36cm y 45cm velocidad 150
                                    Speed = 150;
                                    analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast
                                  //Serial.print("DISTANCIA ENTRE 36 y 45 =   ");
                                  //Serial.println(Vdistancia);
                                  //Serial.print ("VELOCIDAD =    ");
                                  //Serial.println (Speed);
                                    }      
                                    else if ((Vdistancia>=56) && (Vdistancia <=600) && (VMotB==1))  {                 // Distancia entre 46cm y 600cm velocidad 150
                                          Speed = 150;                                                                // 400cm valores máximos que mide más o menos fiables sensor ultrasonidos, por encima de esa distancia los valores pueden no ser fiables.
                                          analogWrite( MOTOR_B_PWM, 255-Speed ); // PWM speed = fast                  // Llega a medir hasta 600cm según fabricante...
                                        //Serial.print("DISTANCIA ENTRE 46 y 600 =   ");
                                        //Serial.println(Vdistancia);
                                        //Serial.print ("VELOCIDAD =    ");
                                        //Serial.println (Speed);
                                          }                                                      
}

//MANDO DE INFRAROJOS
// Dependiendo del código recibido por infrarrojo se ejecuta las diversas acciones:
// - Activación/Desactivación de la Luz de encendido,(led verde) que señaliza que el control de velocidad mediante el sensor de ultrasonidos está activado/desactivado.
// - Activación/Desactivación de las Luces delanteras (2 leds blancos)
// - Motor A (Portaimanes) Giro a derechas o izquierdas (Varias Velocidades, si pulsamos varias veces en el mismo sentido sube de velocidad hasta velocidad máxima.
// - Motor B (Ruedas) Adelante/Atrás (Si pulsamos varias veces en el mismo sentido sube de velocidad hasta velocidad máxima), (Sólo con Ultrasonidos Desactivados "led verde apagado")
// - Sonidos Activados/Desactivados (trabaja el altavoz activo para señalizar diversas acciones,(también el parpadeo de las luces delanteras): Como activación/desactivación ultrasonidos, velocidad máxima alcanzada, habilitación de arranque automático,Claxon.
// - NOTA: En caso de querer utilizar un mando infrarojo diferente (quizás valdría uno de una televisión) tendreis que usar el "Monitor Serie" dentro de la pestaña "Herramientas" y al pulsar una tecla examinar la primera linea y donde sale
//   la palabra "Value:FFFFFF". Estas "FFFFFF" es el código que tendréis que poner a continuación de los "case" para realizar la opción deseada (Se pondría de ésta forma->  case 0xFFFFFF:   (Se añade el "0x" sin las comillas antes del valor obtenido)
//   Nota al estar activo el Sensor de Ultrasonido para poder observar el código obtenido deshabilitar el "Autoscroll" en monitor serie. 
// - Códigos de cada tecla del  Mando Infrarrojo (modelo VS1838):  ("CH-"= FFA25D), ("CH"= FF629D), ("CH+"= FFE21D), ("PREV"= FF22DD), ("NEXT"= FF02FD), ("PLAY/PAUSE"= FFC23D), ("VOL-"= FFE01F), ("VOL+"= FFA857), ("EQ"= FF906F), ("0"= FF6897)
//   ("100+"= FF9867), ("200+"= FFB04F),  ("1"= FF30CF),  ("2"= FF18E7),  ("3"= FF7A85),  ("4"= FF10EF),  ("5"= FF38C7),  ("6"= FF5AA5),  ("7"= FF42BD),  ("8"= FF4AB5), ("9"= FF52AD)          
void translateIR() 
{
      switch(myDecoder.value) {  
        case 0xFF22DD:                           // "PRECEDENT" El valor "FF22DD" es la tecla "Anterior" en el mando a distancia por infrarojos (si compráis el que está en el enlace anterior).  
          if(VLed==0){                            // SE ACTIVA O DESACTIVA EL "LED VERDE" "Señaliza el encendido o apagado del SENSOR ULTRASÓNIDOS" Si la variable Vled esta a 0 (led verde de "trabajo con ultrasonido" apagado) se activa en la siguiente instrucción
            digitalWrite(Led1,HIGH);              // Activamos el  Pin "D3" usado para activar el led "verde" que señaliza el "encendido la forma de trabajo con Sensor de Ultrasonidos"
            VLed=1;                               // Valor estado de la variable activo ya que el led se encuentra activo.
            Parpadeo1();
            buzzer(); 
            }
            else{                     
            digitalWrite(Led1,LOW);                // En caso contrario (que VLed1 esté a 1), lo apagamos (deshabilitamos el trabajar con sensor de ultrasonidos)
            VLed=0;   
            // VMotB=0;    // PENDIENTE DE PROBAR SI NO ARRANCA DESPUES DE ESTAR PARADO AL DESHABILITAR EL SENSOR DE ULTRASONIDOS.
            Parpadeo1();
            buzzer2(); 
            }
        break;
          
        case 0xFF02FD:                                  // El valor "FF02FD" es la tecla "Siguiente (NEXT)" en el mando a distancia por infrarojos. SE ACTIVA O DESACTIVA LAS "LUCES DELANTERAS" 
          if(VLuz==0){                                  // La rutina básicamente trabaja que si las "Luces delanteras" estaban apagadas se enciende y si estaban encendidas se apagan
          digitalWrite(luz,HIGH);
          VLuz=1;
          } 
          else{
          digitalWrite(luz,LOW);
          VLuz=0;
           }
        break;
          
        case 0xFFE01F:                                  //  El valor "FFE01F" es la tecla "-" en el mando a distancia por infrarojos. SE ACTIVA EL "MOTOR PORTAIMANES" en dirección ADELANTE (MOTOR A)
          if(VMotA !=1){
            Speed_MA = PWM_SLOW_A;
            go_forward_A ();
            } 
            else{
            Speed_MA = Speed_MA + SpeedStep_MA ;
            Speed_MA = min(255, max(0, Speed_MA));  
            if (Speed_MA == 255){buzzer3();Parpadeo();}
            go_forward_A ();
            }      
        break;
          
        case 0xFF906F:                                  //  El valor "FF906F" es la tecla "EQ" en el mando a distancia por infrarojos. SE ACTIVA EL "MOTOR PORTAIMANES" en dirección ATRAS (MOTOR A)
          if(VMotA !=2){
            Speed_MA = PWM_SLOW_A;
            go_backward_A ();
            } 
            else{
            Speed_MA = Speed_MA + SpeedStep_MA ;
            Speed_MA = min(255, max(0, Speed_MA)); 
            if (Speed_MA == 255){buzzer3();Parpadeo();}
            go_backward_A ();
            }      
        break;
          
        case 0xFF629D:                                 // El valor "FF629D" es la tecla "CH" en el mando a distancia por infrarojos. SE BAJA LA VELOCIDAD EN LOS DOS SENTIDOS DE AVANCE Y RETROCESO DE LAS RUEDAS (MOTOR B)
           if(VMotB ==1){                              // Si la variable "VMotB" Motor Status es 1 (Locomotora hacia ADELANTE) bajamos la velocidad en ese sentido de giro.
            Speed = Speed - SpeedStep ;
            Speed = min(255, max(0, Speed));
            if (Speed <= 40){Speed =0 ;}               //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
            go_forward ();
            if (Speed == 0){buzzer3();Parpadeo();VMotB=0;}     // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero (parados) en el sentido de Avance del tren.
            } 
              else if(VMotB ==2){                      // Si la variable "VMotB" Motor Status es 2 (Locomotora hacia ATRAS) bajamos la velocidad en ese sentido de giro.
              Speed = Speed - SpeedStep ;              // Bajamos de velocidad el valor de la variable "SpeedStep" que va en pasos de "50".
              Speed = min(255, max(0, Speed));  
              if (Speed <= 40){Speed =0 ;}             //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
              go_backward();
              if (Speed == 0){buzzer3();Parpadeo();VMotB=0;}   // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero (parados) en el sentido de Retroceso del tren.
            }       
            //Stop_MB(); 
        break;  
          
          case 0xFFA857:                                // El valor "FFA857" es la tecla "+" en el mando a distancia por infrarojos. SE BAJA LA VELOCIDAD EN LOS DOS SENTIDOS DE GIRO DEL MOTOR PORTA IMANES (MOTOR A)
          if(VMotA ==1){                                // Si la variable "VMotA" (Motor Status) es 1 (MOTOR PORTA IMANES A DERECHAS) bajamos la velocidad en ese sentido de giro.
            Speed_MA = Speed_MA - SpeedStep_MA ;        // Bajamos de velocidad el valor de la variable "SpeedStep_MA" que va en pasos de "50".
            Speed_MA = min(255, max(0, Speed_MA));
            if (Speed_MA <= 40){Speed_MA = 0;}          //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
            go_forward_A ();
            if (Speed_MA == 0){buzzer3();Parpadeo();VMotA=0;}   // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero. (GIRO A DERECHAS VELOCIDAD CERO) 
            } 
            else if(VMotA ==2){                         // Si la variable "VMotA" (Motor Status) es 2 (MOTOR PORTA IMANES A IZQUIERDAS) bajamos la velocidad en ese sentido de giro.
            Speed_MA = Speed_MA - SpeedStep_MA ;           
            Speed_MA = min(255, max(0, Speed_MA)); 
            if (Speed_MA <= 40){Speed_MA = 0;}          //Cuando bajamos de velocidad y el valor es menor o igual a 40 (insuficiente para mover el motor) Por tanto lo paramos por completo.
            go_backward_A();
            if (Speed_MA == 0){buzzer3();Parpadeo();VMotA=0;}   // Señalizamos con un pitido y parpadeo luces delanteras que llegamos a velocidad cero. (GIRO A IZQUIERDAS VELOCIDAD CERO)
            } 
            //Stop_MA(); 
        break;  
          
        case 0xFFC23D:                                  //  El valor "FFC23D" es la tecla "Play/Pause" en el mando a distancia por infrarojos. STOP PARA LOS 2 MOTORES.
          //if(VMotB !=0  || VMotA !=0) {
            Stop_ALL ();
        break;

        case 0xFF38C7:                                  //  El valor "FF38C7" es la tecla "5" en el mando a distancia por infrarojos. DAR LUCES LARGAS (3 PARPADEOS PARA AVISAR AL CONDUCTOR DELANTERO)
            Parpadeo2();
        break;

        case 0xFF9867:                                  //  El valor "FF9867" es la tecla "100+" en el mando a distancia por infrarojos. SONIDO DEL CLAXON PARA INCORDIAR AL PERSONAL.
          Claxon();
        break;
 
        case 0xFF6897:                                  //  El valor "FF6897" es la tecla "0" en el mando a distancia por infrarojos. HABILITA O DESHABILITA EL ARRANQUE AUTOMÁTICO DESPUES DE UNA PARADA POR POSIBLE COLISIÓN. 
          if(VStopGo==0){                               //  Estando el valor de la variable "VStopGo" a "1" cada vez que para debido a que el detector de ultrasonidos nos dice que hay un objeto muy cercano se para y no vuelve a arrancar           
            VStopGo=1;                                  //  hasta que volvemos a pulsar el boton de avance "CH+" en mando a distancia. Con valor a "0" de ésta variable arranca automáticamente cuando el objeto cercano se ha retirado.
            Parpadeo();
            buzzer2(); 
           }
            else{                                 
            VStopGo=0;
            Parpadeo();
            buzzer(); 
           } 
        break;

          case 0xFFB04F:                                // El valor "FFB04F" es la tecla "200+" del mando a distancia por infrarojos, HABILITA O DESHABILITA TODOS LOS SONIDOS (NOSound=0 => Sonidos activos)
          if(NOSound==0){                                
            Parpadeo();
            buzzer2();
            NOSound=1;                            
           }
            else{                              
            NOSound=0;  
            Parpadeo();
            buzzer();
           } 
        break;
        
        case 0xFFE21D:                                  // El valor "FFE21D" es la tecla "CH+" del mando a distancia por infrarojos. HACIA ADELANTE MOTOR B (RUEDAS)
          if(VMotB !=1){                                // Si la variable "VMotB" Motor Status (Ruedas) es diferente de 1 lanza la rutina de avance
            Speed = PWM_SLOW_B;
            go_forward ();
            } 
              else {
              Speed = Speed + SpeedStep ;               //Realiza uno de los cambios de velocidad para la variable "speed"
              Speed = min(255, max(0, Speed));          // Asigna al valor de Velocidad "Speed" el menor de los números. Sería de 255 en caso que la velocidad sobrepase éste valor.
              if (Speed == 255){buzzer3();Parpadeo(); }
              go_forward();
            }      
        break;
          case 0xFFA25D:                                // El valor "FFA25D" es la tecla "CH-" del mando a distancia por infrarojos. HACIA ATRÁS EL MOTOR B  (RUEDAS)
          if(VMotB !=2){
            Speed = PWM_SLOW_B;
            go_backward ();
           }
            else {
            Speed = Speed + SpeedStep ;                 //Realiza uno de los cambios de velocidad para la variable "speed"
            Speed = min(255, max(0, Speed));            // Asigna al valor de Velocidad "Speed" el menor de los números. Sería de 255 en caso que la velocidad sobrepase éste valor.
            if (Speed == 255){buzzer3();Parpadeo();}
            go_backward();
            }       
        break;  
        default:  //Se ejecuta si nada coíncide....
        //buzzer(); 
        //buzzer1(); 
        //buzzer2(); 
        break;  
             
      }
    
  }

// RUTINA HACIA ADELANTE MOTOR B (RUEDAS)
  void go_forward ()
  {
  Serial.println ("Hacia ADELANTE en motor de las ruedas ...");
  Serial.print ("La velocidad de motor ruedas es: ");
  Serial.println (Speed);
  //Serial.print ("La distancia medida por ultrasonidos es (puede no ser la actual):  ");
  //Serial.println (Vdistancia);
        //if (VMotB == 0){buzzer1 ();}
        // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotB == 2){
        Stop_MB();       //buzzer1 ();
        delay( DIR_DELAY );}
        // Activa el motor la velocidad y dirección
        digitalWrite( MOTOR_B_DIR, HIGH );   // Dirección Avance hacia Adelante
        analogWrite( MOTOR_B_PWM, 255-Speed ); // Velocidad PWM, valor en variable "Speed"
        VMotB=1;  
  }

// RUTINA HACIA ATRAS MOTOR B (RUEDAS)
  void go_backward ()
  {
  Serial.println ("Hacia ATRAS en motor de las ruedas ....");
  Serial.print ("La velocidad de motor ruedas es: ");
  Serial.println (Speed);
  //Serial.print ("La distancia medida por ultrasonidos es (puede no ser la actual): ");
  //Serial.println (Vdistancia);
          // if (VMotB == 0){buzzer1 ();}
          // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotB == 1){
        Stop_MB();  //buzzer1 ();
        delay( DIR_DELAY );}
        // Activa el motor la velocidad y dirección
        digitalWrite( MOTOR_B_DIR, LOW ); // Dirección inversa (marcha atrás)
        analogWrite( MOTOR_B_PWM, Speed ); // Velocidad PWM, valor en variable "Speed"
        VMotB=2;
  }

// RUTINA HACIA ADELANTE MOTOR A (PORTAIMANES)
  void go_forward_A ()
  {
  Serial.println ("Vamos hacia adelante en motor portaimanes...");
  Serial.print ("La velocidad actual portaimanes es: ");
  Serial.println (Speed_MA);
        // if (VMotA == 0){buzzer1 ();} // Un pequeño pitido de arranca de motor portaimanes en dirección Avance
        // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotA == 2){
        Stop_MA();   //buzzer1 ();
        delay( DIR_DELAY_A );}
        // Activa el motor la velocidad y dirección
        digitalWrite( MOTOR_A_DIR, HIGH ); // Dirección Giro hacia la derecha 
        analogWrite( MOTOR_A_PWM, 255-Speed_MA ); // Velocidad PWM, valor en variable "Speed_MA"
        VMotA=1;  
  }

// RUTINA HACIA ATRAS MOTOR A (PORTAIMANES)
  void go_backward_A ()
  {
  Serial.println ("Vamos hacia atrás en motor portaimanes...");
  Serial.print ("La Velocidad actual portaimanes es: ");
  Serial.println (Speed_MA);
          // if (VMotA == 0){buzzer1 ();} // Un pequeño pitido de arranca de motor portaimanes en dirección Retroceso
          // Siempre se para los motores antes de realizar un cambio de sentido (evita cambios de dirección bruscos)
        if (VMotA == 1){
        Stop_MA();   // buzzer1 ();
        delay( DIR_DELAY_A );}
        // set the motor speed and direction
        digitalWrite( MOTOR_A_DIR, LOW ); // Dirección Giro hacia la izquierda    
        analogWrite( MOTOR_A_PWM, Speed_MA ); // Velocidad PWM, valor en variable "Speed_MA"
        VMotA=2;
  }

 // RUTINA DE "STOP" PARA LOS 2 DOS MOTORES (MOTOR A Y MOTOR B)
  void Stop_ALL ()
  {
  //Serial.println ("STOP Para los 2 motores...");  
  digitalWrite( MOTOR_B_DIR, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_B_PWM, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_A_DIR, LOW ); //Motor portaimanes OFF
  digitalWrite( MOTOR_A_PWM, LOW ); //Motor portaimanes OFF
  VMotB=0; //Motor Ruedas Valor inicial (parado)
  VMotA=0; //Motor portaimanes valor inicial (parado)
  }

 // RUTINA DE "STOP" PARA EL MOTOR DE LAS RUEDAS (MOTOR B)
  void Stop_MB ()
  {
  //Serial.println ("STOP Para el motor de las ruedas (Motor B....");  
  digitalWrite( MOTOR_B_DIR, LOW ); //Motor Ruedas OFF
  digitalWrite( MOTOR_B_PWM, LOW ); //Motor Ruedas OFF
  VMotB=0; //Motor Ruedas Valor inicial (parado)
  }

 // RUTINA DE "STOP" PARA EL MOTOR PORTAIMANES  (MOTOR A)
  void Stop_MA ()
  {
  //Serial.println ("STOP Para el motor portaimanes (Motor A....");  
  digitalWrite( MOTOR_A_DIR, LOW ); //Motor portaimanes OFF
  digitalWrite( MOTOR_A_PWM, LOW ); //Motor portaimanes OFF
  VMotA=0; //Motor PortaImanes Valor inicial (parado)
  }



// FUNCIÓN DE CÁLCULO DE DISTANCIA MEDIANTE SENSOR DE ULTRASONIDO
int Distancia_test() {
  // Impulsion TRIG conforme à la spec (10 µs)
  digitalWrite(trigger, LOW);  delayMicroseconds(2);
  digitalWrite(trigger, HIGH); delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  // Timeout ~30 ms ≈ 5 m (évite de bloquer trop longtemps)
  unsigned long us = pulseIn(echo, HIGH, 30000UL);
  if (us == 0) return -1;     // pas d’écho / hors de portée

  return (int)(us / 58.0);    // conversion µs -> cm
}





 //RUTINAS PARA EL AVISO SONORO DE DIVERSAS FUNCIONES - Hay que tener en cuenta que si tenemos deshabilitados los sonidos el control de la locomotora irá más fluída, lo mismo sucede deshabilitando el control de velocidad mediante ultrasonidos.
 
 // DOBLE PITIDO DE ALTAVOZ  - Doble pitido que indica que se ha habilitado alguna de las opciones programadas. (Activado control de velocidad por Ultrasonidos, Activado arranque automático después de un paro, o habilitación de todos los sonidos)
  void buzzer ()                                                                  
  {
     if(NOSound==0){          
    for (int thisBuz=0; thisBuz < 2; thisBuz++){
    digitalWrite(Altavoz_Pin, HIGH);
    delay(100);
    digitalWrite(Altavoz_Pin, LOW);
    delay(50);
       }
    }
  }
 
 // PITIDO DE ALTAVOZ 1 - Pitido de arranque o paro, cuando se inicia un movimiento de cualquiera de los 2 motores (DESHABILITADO "Comentado" en rutina de avance y retroceso motores ruedas y portaimanes)
  void buzzer1 ()
  {
      if(NOSound==0){                            
      for (int thisBuz=0; thisBuz < 1; thisBuz++){
      digitalWrite(Altavoz_Pin, HIGH);
      delay(120);
      digitalWrite(Altavoz_Pin, LOW);
      delay(50);
          } 
      }
  }
 
 // PITIDO DE ALTAVOZ 2  Sonido apagado que indica que se ha deshabilitado alguna de las opciones programadas (Desactivado Ultrasonidos, desactivado arranque automático después de un paro, o desactivado todos los sonidos)
    void buzzer2 ()
  {
    if(NOSound==0){  
    for (int thisBuz=25; thisBuz > 0; thisBuz--){
    analogWrite(Altavoz_Pin, thisBuz);
    delay(10);
    analogWrite(Altavoz_Pin, 0);
    delay(10);
    }
    }
  }


 // PITIDO DE ALTAVOZ 3  - Velocidad máxima alcanzada (Trabaja con cualquiera de los 2 motores, cuando pulsamos varias veces el mismo botón de avance (o retroceso) y llegamos al máximo de velocidad.
  void buzzer3 ()
  {
    if(NOSound==0){  
    for (int thisBuz=0; thisBuz < 1; thisBuz++){
    digitalWrite(Altavoz_Pin, HIGH);
    delay(100);
    digitalWrite(Altavoz_Pin, LOW);
    delay(50);
    }
    }
  }


  // PITIDO DE ALTAVOZ 4 -  Claxon para advertir a nuestros rivales. Un dolor de cabeza para los padres.... (3 pitidos largos)
  void Claxon ()
  {
    if(NOSound==0){ 
    for (int thisBuz=0; thisBuz < 3; thisBuz++){
    digitalWrite(Altavoz_Pin, HIGH);
    delay(300);
    digitalWrite(Altavoz_Pin, LOW);
    delay(100);
    }
    }
  }

// RUTINA PARPADEO DE LUCES DELANTERA (BLANCAS) - Señaliza la activación o desactivación de alguna opción (si las luces estaban encendidas después del parpadeo, se vuelven a dejar encendidas).
  void Parpadeo () 
  {
    for (int BlinkL=0; BlinkL < 2; BlinkL++){
    digitalWrite(luz,HIGH);
    delay(100);
    digitalWrite(luz,LOW);
    delay(50);  
    }
     if(VLuz==1){
     digitalWrite(luz,HIGH);    
     }
 }

// RUTINA PARPADEO1 DE LUZ VERDE DE CONTROL DE VELOCIDAD POR ULTRASONIDOS ACTIVADO) - Señaliza la activación o desactivación del Control de Velocidad por ultrasonidos.
  void Parpadeo1 () 
  {
    for (int BlinkL=0; BlinkL < 2; BlinkL++){
    digitalWrite(Led1,HIGH);
    delay(100);
    digitalWrite(Led1,LOW);
    delay(50);  
    }
     if(VLed==1){
     digitalWrite(Led1,HIGH);    
     }
 }

// RUTINA PARPADEO2 DE LUCES DELANTERA (BLANCAS) - Realiza 3 parpadeos de las luces delanteras (dar luces) para que se entere el que va por delante..
  void Parpadeo2 () 
  {
    for (int BlinkL=0; BlinkL < 3; BlinkL++){
    digitalWrite(luz,HIGH);
    delay(200);
    digitalWrite(luz,LOW);
    delay(200);  
    }
     if(VLuz==1){
     digitalWrite(luz,HIGH);    
     }
 }



 

Do you see any other serial print outs before it restarts?

Is the distance reading occuring and then the restart occurs with the ir read or motor operation?

Do you get the restarts if you use the code that @JohnLincoln gave in post #15 which separates the distance reading from the rest of the code.

EDIT:

I put everything back together, and now the IR sensor is on,

Are you saying that the reset is occurring when the motors are trying to run based on some distance measurement.