No hace loop

Buenas, estoy haciendo un pequeño proyecto de un robot controlado por bluetooth con dos modos de funcionamiento; uno manual y otro automatico (esquiva obstaculos).

El robot tiene un sensor de ultrasonidos montado encima de un servo para poder decidir a que lugar girar en caso de obstaculo.

El modo manual funciona correctamente pero tengo un problema en el modo automatico; simplemente tengo una app en Android que envía un churro de datos al arduino, uno de esos datos si es 0 esta en manual y si pincho un boton envía un 1 y se activa el modo automatico.

Al ponerse en modo automatico el robot comienza a avanzar y mide la distancia con el ultrasonido, si el obstaculo está a menos de 15 cm llamo a una funcion que hace girar el servo y tomar distancias de izquierda y derecha, despues llamo a otra funcion para que decida a que lado girar y posteriormente sigue avanzando.
Hasta este punto funciona pero el poblema es que no vuelve a evaluar nada, solo avanza y no vuelve a hacer de nuevo el recorrido.

Os pego el codigo porque ya lo he puesto de muchas formas y me sigue pasando igual; a ver si hay algún ojo de halcon en la sala y me dice donde esta el fallo:

La parte del LOOP (AUTO es la variable que recibo 0 o 1 desde la app):

//MOVIMIENTO
	
	//AUTOMATICO
  if (AUTO == 1 )
  {

    servo1.write(90);
    delay(90);
    cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
    Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);


    
    if (cm_IZQ < 15 )
    {
      Serial.println("OBSTACULO A MENOS DE 15CM *****************************************");
     change();
      
      
    }
    
  }

  
	//MANUAL
	if (AUTO == 0 )
	{
	Serial.println("*********MANUAL************");

esto funciona......

Las funciones para cambiar la dirección:

void comparaCM()
{
  if (izquierdaCM > derechaCM)
  {
    Serial.println("********IZQ TANQUE***********");
      Direccion = 3;
      acelera(150,255,150,255);
      delay(400);
      Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);
  }
  else if (derechaCM > izquierdaCM)
  {
      Serial.println("********DER TANQUE***********");
      Direccion = 4;
      acelera(250,150,255,150);
      delay(400);
      Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);
  }
  else 
  {
    Direccion = 4;
      acelera(250,150,255,150);
      delay(800);
      Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);
  }
}

void change()
{
      Serial.println("********PARADO***********");
      Direccion = 0;
      acelera(0,0,0,0);

      servo1.write(36); // Derecha
      delay(500);
      derechaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(derechaCM);
      delay(500);
      servo1.write(144); // Izquierda
      delay(700);
      izquierdaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(izquierdaCM);
      delay(500);
      servo1.write(90);
      delay(100);
      comparaCM();
}

Yo no veo que haces en manual, asi que poco puedo decir de lo que debiera hacer en AUTO.
Porque no pones todo el código y no parcializado como has posteado.

Asi tenemos la dimensión completa del programa

ok.En primer lugar muchas gracias por tu interes. Pegué el codigo por partes por tratar de hacerlo mas sencillo.

Ahí va el sketch completo:

#include "AFMotor.h"
#include "LedControl.h"
#include <Servo.h>

//SERVO
Servo servo1;
int ang = 0;

//MOTORES
AF_DCMotor MotorDI(1);
AF_DCMotor MotorDD(2);
AF_DCMotor MotorTI(3);
AF_DCMotor MotorTD(4);
int VDI = 0 ;    // Velocidad base Motor Del. izq.
int VDD = 0 ;
int VTI = 0 ;
int VTD = 0 ;
int Direccion = 0 ;// Delante=1, MarchaAtras=2, Parado=0, TanqueIzq=3, TanqueDer=4

int derechaCM;
int izquierdaCM;

//SENSOR ULTRASONICO
int  pinSONIC_disparoIZQ = 30; //trigger
int  pinSONIC_entradaIZQ = 31; //echo
//int  pinSONIC_disparoDER = 32; //trigger
//int  pinSONIC_entradaDER = 33; //echo


//ZUMBADOR
const int zumbador= 53;

//FOTOCELULA
int fotocelulaPIN = A15; // Pin Analogico
int fotocelula = 0;

//TEMPERATURA
//int pinTemperatura=A14;

//LUCES
//const int led22 = 22;
//LedControl lc=LedControl(24,26,25,1);
//unsigned long delaytime1=500;
//unsigned long delaytime2=50;

//BLUETOOTH
#define max_char 20
char message[max_char];    // stores you message
char r_char;               // reads each character
byte index = 0;            // defines the position into your array 

void setup()
{
   
  servo1.attach(23);
  servo1.write(90);
  Serial.begin(115200);
  Serial1.begin(115200);  //Bluetooth
  pinMode(zumbador , OUTPUT);
  //pinMode(led22 , OUTPUT);
  pinMode(pinSONIC_disparoIZQ, OUTPUT);
  pinMode(pinSONIC_entradaIZQ, INPUT);
  //pinMode(pinSONIC_disparoDER, OUTPUT);
  //pinMode(pinSONIC_entradaDER, INPUT);
  
  //Tests arranque
  digitalWrite(zumbador , HIGH);
  //digitalWrite(led22 , HIGH);
  //lc.shutdown(0,false);
  //lc.setIntensity(0,8);
  //LEDON();
  delay(1000);
  digitalWrite(zumbador , LOW);
  //digitalWrite(led22 , LOW);
  //lc.clearDisplay(0);
}

///////////////
// FUNCIONES //
///////////////

int ping(int TriggerPin, int EchoPin)  //ULTRASONICO
{
 long duration, distanceCm;
 digitalWrite(TriggerPin, LOW);  //para generar un pulso limpio ponemos a LOW 4us
    delayMicroseconds(2);
    digitalWrite(TriggerPin, HIGH);  //generamos Trigger (disparo) de 10us
    delayMicroseconds(5);
    digitalWrite(TriggerPin, LOW);
    duration = pulseIn(EchoPin, HIGH);  //medimos el tiempo entre pulsos, en microsegundos
    distanceCm = duration * 10 / 292/ 2;   //convertimos a distancia, en cm
    return distanceCm;
}

String getValue(String data, char separator, int index)
{
       int found = 0;
       int strIndex[] = {0, -1};
       int maxIndex = data.length()-1;

       for(int i=0; i<=maxIndex && found<=index; i++)
   {
 if(data.charAt(i)==separator || i==maxIndex)
 {
            found++;
            strIndex[0] = strIndex[1]+1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
 }
        }
     return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

/*void LEDON()
{
 for (int row=0; row<8; row++)
 {
 for (int col=0; col<8; col++)
 {
 lc.setLed(0,col,row,true); // turns on LED at col, row
 }
 }
 
}
*/

void acelera(int DIzq, int DDer, int TIzq, int TDer)
{
 
 if (Direccion == 1) //DELANTE
 {
 MotorDI.run(FORWARD);
 MotorDD.run(FORWARD);
 MotorTI.run(FORWARD);
 MotorTD.run(FORWARD);
 }
 if (Direccion == 2) //MARCHA ATRAS
 {
 MotorDI.run(BACKWARD);
 MotorDD.run(BACKWARD);
 MotorTI.run(BACKWARD);
 MotorTD.run(BACKWARD);
 }
 if (Direccion == 0) //PARADO
 {
 MotorDI.run(RELEASE);
 MotorDD.run(RELEASE);
 MotorTI.run(RELEASE);
 MotorTD.run(RELEASE);
 }
 if (Direccion == 3) //IZQUIERDA TANQUE
 {
 MotorDI.run(BACKWARD);
 MotorDD.run(FORWARD);
 MotorTI.run(BACKWARD);
 MotorTD.run(FORWARD);
 }
 if (Direccion == 4) //DERECHA TANQUE
 {
 MotorDI.run(FORWARD);
 MotorDD.run(BACKWARD);
 MotorTI.run(FORWARD);
 MotorTD.run(BACKWARD);
 }
  //Velocidad motores
  MotorDI.setSpeed(DIzq);
  MotorDD.setSpeed(DDer);
  MotorTI.setSpeed(TIzq);
  MotorTD.setSpeed(TDer);
}

void comparaCM()
{
  if (izquierdaCM > derechaCM)
  {
    Serial.println("********IZQ TANQUE***********");
      Direccion = 3;
      acelera(150,255,150,255);
      delay(400);
      Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);
  }
  else if (derechaCM > izquierdaCM)
  {
      Serial.println("********DER TANQUE***********");
      Direccion = 4;
      acelera(250,150,255,150);
      delay(400);
      Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);
  }
  else 
  {
    Direccion = 4;
      acelera(250,150,255,150);
      delay(800);
      Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);
  }
}

void change()
{
      Serial.println("********PARADO***********");
      Direccion = 0;
      acelera(0,0,0,0);

      servo1.write(36); // Derecha
      delay(500);
      derechaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(derechaCM);
      delay(500);
      servo1.write(144); // Izquierda
      delay(700);
      izquierdaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(izquierdaCM);
      delay(500);
      servo1.write(90);
      delay(100);
      comparaCM();
}

///////////////////////////////////////////////////////////////////////////////////////////////
//   LOOP                                                                                    //
///////////////////////////////////////////////////////////////////////////////////////////////

void loop()
{

 Serial.println("**********************************");
 Serial.println("**********************************");
 
 //FOTOCELULA
 fotocelula = analogRead(fotocelulaPIN);
 if (fotocelula < 275 )
 {
 //LEDON();
 }
 //else lc.clearDisplay(0);

  /*
 //TEMPERATURA
 int tempReading = analogRead(pinTemperatura);
 double tempK = log(10000.0 * ((1024.0 / tempReading - 1)));
 tempK = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * tempK * tempK )) * tempK );       //  Temp Kelvin
 float tempC = tempK - 273.15;            // Convert Kelvin to Celcius
 float tempVolts = tempReading * 5.0 / 1024.0;
  tempC = (tempVolts - 0.5) * 10.0;
 */
 int tempC = 1;
 
 //SENSOR ULTRASONICO
 int cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
 //int cm_DER = ping(pinSONIC_disparoDER,pinSONIC_entradaDER);
 int cm_DER = cm_IZQ;
 
 //RECOPILA DATOS DE BLUETOOTH Y SPLIT
    index=0;
    while (Serial1.available() > 0)
 {
       //the message can have up to 20 characters 
       if(index < (max_char-1)) 
       {         
 r_char = Serial1.read();      // Reads a character
 message[index] = r_char;     // Stores the character in message array
 index++;      // Increment position
 message[index] = '\0';       // Delete the last position
       }
 }
   String campo1 = getValue(message,';',0);
   String campo2 = getValue(message,';',1);
   String campo3 = getValue(message,';',2);
   int campo1int = campo1.toInt();
   int AUTO = campo2.toInt();
   int campo3int = campo3.toInt(); 

 //MOVIMIENTO
 
 //AUTOMATICO
  if (AUTO == 1 )
  {

    servo1.write(90);
    delay(90);
    cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
    Serial.println("********DELANTE***********");
      Direccion = 1;
      acelera(120,120,120,120);


    
    if (cm_IZQ < 15 )
    {
      Serial.println("OBSTACULO A MENOS DE 15CM *****************************************");
     change();
      
      
    }
    
  }

  
 //MANUAL
 if (AUTO == 0 )
 {
 Serial.println("*********MANUAL************");
 if (campo1int == 0 )
 {
 Serial.println("********PARADO***********");
 Direccion = 0;
 acelera(0,0,0,0);
 }
 if (campo1int == 1 )
 {
 Serial.println("********DELANTE***********");
 Direccion = 1;
 acelera(200,200,200,200);
 }
 if (campo1int == 2 )
 {
 Serial.println("********MARCHA ATRAS***********");
 Direccion = 2;
 acelera(150,150,150,150);
 }
 if (campo1int == 3 )
 {
 Serial.println("********IZQ TANQUE***********");
 Direccion = 3;
 acelera(150,255,150,255);
 }
 if (campo1int == 4 )
 {
 Serial.println("********DER TANQUE***********");
 Direccion = 4;
 acelera(250,150,255,150);
 }
 if (campo1int == 5 )
 {
 Serial.println("********ACELERA e IZQ***********");
 Direccion = 1;
 acelera(0,200,0,200);
 }
 if (campo1int == 6 )
 {
 Serial.println("********ACELERA y DER***********");
 Direccion = 1;
 acelera(150,0,150,0);
 }
 }

//ENVIA DATOS A ANDROID POR BLUETOOTH
 Serial1.print("<");
  Serial1.print(";");
 Serial1.print(tempC);
 Serial1.print(";");
 Serial1.print(cm_IZQ);
 Serial1.print(";");
 Serial1.print(cm_DER);
  Serial1.print(";");
  Serial1.print(">");
  Serial1.print(";");
   
   

 

}

El post pasaba de 9000 lineas.

He quitado estas salidas de consola en el final:

//CONSOLA ARDUINO
 //Serial.print("Temp: ");
 //Serial.println(tempC);
 Serial.print("Luz: ");
 Serial.println(fotocelula);
 Serial.print("Distancia Izquierda: ");
 Serial.println(cm_IZQ);
 Serial.print("Distancia Derecha: ");
 Serial.println(cm_DER);
  //VELOCIDAD MOTORES
  Serial.print("VDI: ");
  Serial.println(VDI);
  Serial.print("VDD: ");
  Serial.println(VDD);
  Serial.print("VTI: ");
  Serial.println(VTD);
  Serial.print("VTD: ");
  Serial.println(VTD);
  //DATOS RECIBIDOS DEL BLUETOOTH
 Serial.print("CAMPO1: ");
 Serial.println(campo1int);
 Serial.print("AUTO: ");
 Serial.println(AUTO);

A modo de resumen el robot cuando le conecto la corriente (bateria lipo) por defecto AUTO es igual a 0 por lo que está en modo manual. El funcionamiento es correcto.

Desde la app del movil cambio la variable AUTO a 1 y el coche entra en modo automatico y comienza a avanzar hacia delante. Cuando detecta un obstaculo a menos de 15cm se para gira el ultrasonido y toma distancias a cada lado. Evalua donde hay mas distancia y efectua un giro en esa dirección. Posteriormente avanza.... y ahí se queda. No vuelve a medir distancia por lo que si hay un nuevo osbtaculo a 15cm se da con el y tambien dejo de recibir información en la app del movil ni funciona si le quito el modo AUTO.

No se si en lugar de usar IF hacerlo con SWITCH por si el break tiene algo mas de eficacia...

Bien he analizado el código, lo indenté para que se entienda mejor al menos por mi.
Tambien simplifiqué algunas cosas para de nuevo que sea mas claro.
Veo algunas ordenes que en teoría son iguales y las pones diferente. en un caso adelante es acelera(200… y en el otro es acelera(120… los 4 numeros).

El loop ahora luce como debe ser, es una secuencia de rutinas debidamente consultadas.

#include "AFMotor.h"
#include "LedControl.h"
#include <Servo.h>

Servo servo1;       //SERVO
int ang = 0;

//MOTORES
AF_DCMotor MotorDI(1);
AF_DCMotor MotorDD(2);
AF_DCMotor MotorTI(3);
AF_DCMotor MotorTD(4);
int VDI = 0 ;    // Velocidad base Motor Del. izq.
int VDD = 0 ;
int VTI = 0 ;
int VTD = 0 ;
int Direccion = 0 ;// Delante=1, MarchaAtras=2, Parado=0, TanqueIzq=3, TanqueDer=4

int derechaCM;
int izquierdaCM;

//SENSOR ULTRASONICO
int  pinSONIC_disparoIZQ = 30; //trigger
int  pinSONIC_entradaIZQ = 31; //echo

//ZUMBADOR
const int zumbador= 53;

//FOTOCELULA
int fotocelulaPIN = A15; // Pin Analogico
int fotocelula = 0;

//BLUETOOTH
#define max_char 20
char message[max_char];    // stores you message
char r_char;               // reads each character
byte index = 0;            // defines the position into your array 

void setup() {
   
  servo1.attach(23);
  servo1.write(90);
  Serial.begin(115200);
  Serial1.begin(115200);  //Bluetooth
  pinMode(zumbador , OUTPUT);
  //pinMode(led22 , OUTPUT);
  pinMode(pinSONIC_disparoIZQ, OUTPUT);
  pinMode(pinSONIC_entradaIZQ, INPUT);

  
  //Tests arranque
  digitalWrite(zumbador , HIGH);

  delay(1000);
  digitalWrite(zumbador , LOW);
  Serial.println("**********************************");
  Serial.println("**********************************");
 

}

int ping(int TriggerPin, int EchoPin)  {      //ULTRASONICO
  long duration, distanceCm;
  digitalWrite(TriggerPin, LOW);  //para generar un pulso limpio ponemos a LOW 4us
  delayMicroseconds(2);
  digitalWrite(TriggerPin, HIGH);  //generamos Trigger (disparo) de 10us
  delayMicroseconds(5);
  digitalWrite(TriggerPin, LOW);
  duration = pulseIn(EchoPin, HIGH);  //medimos el tiempo entre pulsos, en microsegundos
  distanceCm = duration * 10 / 292/ 2;   //convertimos a distancia, en cm
  
  return distanceCm;
}

String getValue(String data, char separator, int index) {
   int found = 0;
   int strIndex[] = {0, -1};
   int maxIndex = data.length()-1;

   for (int i=0; i<=maxIndex && found<=index; i++)  {
        if (data.charAt(i)==separator || i==maxIndex) {
           found++;
           strIndex[0] = strIndex[1]+1;
           strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void acelera(int DIzq, int DDer, int TIzq, int TDer) {
 
  if (Direccion == 1) {       //DELANTE
      MotorDI.run(FORWARD);
      MotorDD.run(FORWARD);
      MotorTI.run(FORWARD);
      MotorTD.run(FORWARD);
  }
  if (Direccion == 2) {       //MARCHA ATRAS
      MotorDI.run(BACKWARD);
      MotorDD.run(BACKWARD);
      MotorTI.run(BACKWARD);
      MotorTD.run(BACKWARD);
  }
  if (Direccion == 0) {       // PARADO
      MotorDI.run(RELEASE);
      MotorDD.run(RELEASE);
      MotorTI.run(RELEASE);
      MotorTD.run(RELEASE);
  }
  if (Direccion == 3) {       //IZQUIERDA TANQUE
      
      MotorDI.run(BACKWARD);
      MotorDD.run(FORWARD);
      MotorTI.run(BACKWARD);
      MotorTD.run(FORWARD);
  }
  if (Direccion == 4) {       //DERECHA TANQUE
      MotorDI.run(FORWARD);
      MotorDD.run(BACKWARD);
      MotorTI.run(FORWARD);
      MotorTD.run(BACKWARD);
  }
  //Velocidad motores
  MotorDI.setSpeed(DIzq);
  MotorDD.setSpeed(DDer);
  MotorTI.setSpeed(TIzq);
  MotorTD.setSpeed(TDer);
}

void izquierda() {
  Serial.println("********IZQ TANQUE***********");
  Direccion = 3;
  acelera(150,255,150,255);
}

void derecha() {
  Serial.println("********DER TANQUE***********");
  Direccion = 4;
  acelera(250,150,255,150);
}

void delante() {
  Serial.println("********DELANTE***********");
  Direccion = 1;
  acelera(120,120,120,120);
}

void atras() {
  Serial.println("********MARCHA ATRAS***********");
  Direccion = 2;
  acelera(150,150,150,150);
}

void parado() {
  Serial.println("********PARADO***********");
  Direccion = 0;
  acelera(0,0,0,0);
}

void comparaCM()  {
  if (izquierdaCM > derechaCM)  {
      izquierda();
      delay(400);
      delante();
  }
  else if (derechaCM > izquierdaCM)  {
      derecha();
      delay(400);
      delante();
  }
  else   {
      Direccion = 4;
      acelera(250,150,255,150); // no coincide con Direccion 4 anterior
      delay(800);
      delante();
  }
}

void change() {
      Serial.println("********PARADO***********");
      Direccion = 0;
      acelera(0,0,0,0);

      servo1.write(36); // Derecha
      delay(500);
      derechaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(derechaCM);
      delay(500);
      servo1.write(144); // Izquierda
      delay(700);
      izquierdaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(izquierdaCM);
      delay(500);
      servo1.write(90);
      delay(100);
      comparaCM();
}

void loop() {

  actualizo_sensores()
   
  leo_serial();           //RECOPILA DATOS DE BLUETOOTH Y SPLIT

  //MOVIMIENTO AUTOMATICO
  if (AUTO == 1 )   
      automatico();
  else 
      manual();

  refrezco_BT();
  presento_Monitor_serie();
}

void automatico(){
  servo1.write(90);
  delay(90);
  cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      
  if (cm_IZQ < 15 )    {
      Serial.println("OBSTACULO A MENOS DE 15CM *****************************************");
      change();
  }  
}

void manual() {
    Serial.println("*********MANUAL************");
    switch (campo1int) {
      case 0 : parado();
               break;
      case 1 : delante();
               break;
      case 2 : atras();
               break;
      case 3 : izquierda();
               break;
      case 4 : derecha();
               break;
      case 5 : Serial.println("********ACELERA e IZQ***********");
               Direccion = 1;
               acelera(0,200,0,200);
               break;
      case 6 : Serial.println("********ACELERA y DER***********");
                Direccion = 1;
                acelera(150,0,150,0);
                break;
    }
}

void actualizo_sensores() {
   //FOTOCELULA
  fotocelula = analogRead(fotocelulaPIN);
  if (fotocelula < 275 ) {
      //LEDON();
  }

  int tempC = 1;
   //SENSOR ULTRASONICO
  int cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
  //int cm_DER = ping(pinSONIC_disparoDER,pinSONIC_entradaDER);
  int cm_DER = cm_IZQ;
}

void leo_serial() {
  index = 0;
  while (Serial1.available() > 0) {
         //the message can have up to 20 characters 
         if (index < (max_char-1))    {         
             r_char = Serial1.read();      // Reads a character
             message[index] = r_char;     // Stores the character in message array
             index++;      // Increment position
             message[index] = '\0';       // Delete the last position
         }
  }
  
  String campo1 = getValue(message,';',0);
  String campo2 = getValue(message,';',1);
  String campo3 = getValue(message,';',2);
  int campo1int = campo1.toInt();
  int AUTO = campo2.toInt();
  int campo3int = campo3.toInt(); 
}

void refrezco_BT() {
  //ENVIA DATOS A ANDROID POR BLUETOOTH
  Serial1.print("<");
  Serial1.print(";");
  Serial1.print(tempC);
  Serial1.print(";");
  Serial1.print(cm_IZQ);
  Serial1.print(";");
  Serial1.print(cm_DER);
  Serial1.print(";");
  Serial1.print(">");
  Serial1.print(";");   

}
void presento_Monitor_serie() {         //CONSOLA ARDUINO
  //Serial.print("Temp: ");
  //Serial.println(tempC);
  Serial.print("Luz: ");
  Serial.println(fotocelula);
  Serial.print("Distancia Izquierda: ");
  Serial.println(cm_IZQ);
  Serial.print("Distancia Derecha: ");
  Serial.println(cm_DER);
  //VELOCIDAD MOTORES
  Serial.print("VDI: ");
  Serial.println(VDI);
  Serial.print("VDD: ");
  Serial.println(VDD);
  Serial.print("VTI: ");
  Serial.println(VTD);
  Serial.print("VTD: ");
  Serial.println(VTD);
  //DATOS RECIBIDOS DEL BLUETOOTH
  Serial.print("CAMPO1: ");
  Serial.println(campo1int);
  Serial.print("AUTO: ");
  Serial.println(AUTO);
  Serial.println("**********************************");
  Serial.println("**********************************");
}

Muchas gracias por tu tiempo, una vez más me dejas sorprendido. El código es mucho más elegante y eficiente.

Hasta el lunes no podré probarlo pero tiene muy buena pinta.

Maquina!

A ver.. no hay mucho diferente. Si orden y se puede mejorar.

Pero ahora vos lo mirás y lo entendes no es cierto? De la otra forma lo entendías solo tu.

Ahora en el loop esta claro como funciona y hasta puedes hacer cosas como que no te muestre por serial en cada ciclo sino cada X tiempo usando millis().

Otra cosa. Mira AUTOmatico y le quite algo que quiero que evalúes respecto de tu rutina. compara esas partes de código. Lo demas es lo mismo

Algo mas, estudia que son los ENUMeradores te lo escribo asi porque luego veras que la etiqueta que se usa es enum. Bueno con el puedes definir etiquetas y por ejemplo donde usas Direccion = algo en lugar que ese algo se un número que solo tu conoces usas algo asi

enum ternary { DELANTE=1, DERECHA, IZQUIERDA, PARADO, DELIZQ, DELDER};

Este simple comando hace que estas etiquetas DELANTE = 1 DERECHA = 2 y asi sucesivamente Entonces en tu código en lugar de poner

Direccion = 1;            // pones
Direccion = DELANTE;

y el código lucirá mas claro. Lo mismo pero mas claro.

Cuando vengas 2 meses después a revisarlo, le darás un vistazo y ya estas en tema!!

Ayer por la noche pude probar el código.
Tuve que declarar como globales algunas variables y vi que faltaba en la función automatico añadir que el robot avance automáticamente.

Pero me temo que pasa lo mismo, el robot en modo automático una vez detecta que la distancia es inferior a 15cm gira el sensor ultrasonico, toma medidas a los lados y decide hacia donde girar. Después de girar vuelve a avanzar y ahí se queda… … no responde a nada y queda avanzando.
No se si tendrá que ver con lo que has quitado adrede pero no encuentro explicación.

Con respecto a las etiquetas lo tendré en cuenta, veo que se trata de una especie de alias para poder humanizar un poco el código.

Por cierto, buena idea lo de usar millis() para controlar la salida por consola. Lo he implantado.

Ok. Ahora que esta mas amigable el código veamos que ocurre porque al menos para mi es mas fácil de seguir ahora.

En tu rutina AUTO dices que no tiene la secuencia para ir delante.
En tu código tu habias puesto asi

void automatico(){
  servo1.write(90);
  delay(90);
  cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
  delante();
  if (cm_IZQ < 15 )    {
      Serial.println("OBSTACULO A MENOS DE 15CM *****************************************");
      change();
  }  
}

Para mi esta mal, porque veamos la secuencia.
Pones el servo en posición 90 para que el sensor apunte donde debe.
Lees la distancia y lo mueves? Guau,
es decir que si hay un obstaculo a menos de 15 cm se lo lleva por delante?
Luego de hacerlo preguntas había un obstaculo, ahhh gira a donde corresponda.

Por eso yo quite delante, porque luego en change() tienes un delante() al compararCM();

Prueba asi a ver si mejora

void automatico(){
  servo1.write(90);
  delay(90);
  cm_IZQ = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
  
  if (cm_IZQ < 15 )    {
      Serial.println("OBSTACULO A MENOS DE 15CM *****************************************");
      change();
  }
  else 
      delante();  
}

Repito, ya tienes una función delante en change pero ahora si no hay obstáculo entonces si le dices que avance.

La función change solo es llamada si la distancia a un obstáculo es menor a 15cm por lo que si activo el modo automático se queda parado.

He incluido el ELSE tal como me has recomendado pero el resultado es el mismo.

No termino de ver el problema en tomar la medida lo mas cerca posible de la condición, de hecho el robot no choca con el obstáculo, se para, evalúa por donde girar, gira hacia un lado y luego se queda enganchado en la función delante().

En todo caso el resultado es el mismo, no entiendo porque se queda avanzando y no repite el loop.

Pero no has visto el último código?

Si es menor a 15 cambia de dirección pero si no, se va para delante();

Con todos los respetos Surbyte pero creo que te leo un tanto soberbio.

Claro que he visto el delante(), como te he escrito he añadido el ELSE.

Te agradezco la ayuda pero creo que al margen de ordenar el código no estas entendiendo el fondo del problema o por lo menos me parece. Se que son tus dominios y la materia que dominas pero tengo la sensación que contestas los post de forma brusca. Por tu experiencia dejo el margen de la duda a que no me esté enterando de lo que me quieres decir pero desde luego no encuentro las formas adecuadas.

En todo caso vuelvo a reiterar las gracias por tu tiempo.

He incluido el ELSE tal como me has recomendado pero el resultado es el mismo.

Ahh perdona no te leí ese comentario.

Pero no has visto el último código?

Esto te parece soberbio?

Vaya que respuesta me das, por favor y yo invirtiendo mi tiempo para ayudarte... y tengo problemas ecónomicos y me tomas por soberbio. Okay

Muecha Suerte!!.

Creo que por acá esta el problema

void comparaCM()  {
  if (izquierdaCM > derechaCM)  {
      izquierda();
      delay(400);
      delante();
  }
  else if (derechaCM > izquierdaCM)  {
      derecha();
      delay(400);
      delante();
  }
  else   {
      Direccion = 4;
      acelera(250,150,255,150); // no coincide con Direccion 4 anterior
      delay(800);
      delante();
  }
}

void change() {
      Serial.println("********PARADO***********");
      Direccion = 0;
      acelera(0,0,0,0);

      servo1.write(36); // Derecha
      delay(500);
      derechaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(derechaCM);
      delay(500);
      servo1.write(144); // Izquierda
      delay(700);
      izquierdaCM = ping(pinSONIC_disparoIZQ,pinSONIC_entradaIZQ);
      Serial.println(izquierdaCM);
      delay(500);
      servo1.write(90);
      delay(100);
      comparaCM();
}

Veamos change()
Empieza con tu problema. Se detiene. Asi que algo pasa a continuación, no?
en comparaCM() tienes 3 comparaciones
Se supone que si
izquierdaCM > derechaCM es falso y
derechaCM > izquierdaCM es falso debería entonces
ir delante() pero no lo hace, asi que ahi podría estar el problema.

NOTA: cierro mis comentarios en este hilo.

He detectado de donde viene el problema; añadiendo salidas por consola en cada paso a modo debug he comprobado que después de ejecutar comparaCM() finaliza el loop y vuelve a empezar y se queda en la función que lee los datos del Bluetooth, concretamente en el WHILE.

Lo curioso es que solo ocurre después de haber pasado un obstáculo.

Desde la app simplemente envío el churro x;y; y en las demás condiciones no hay problema. Sigo investigando.

Últimamente no he podido dedicarle mucho tiempo pero parece claro que el bluetooth deja de recibir correctamente los datos después de mover el servomotor... Es posible algún tipo de interferencia?

Por fin he solucionado este tema.

El problema estaba en el bluetooth; no tengo claro si al enviarlo en un string o al recibirlo en arduino pero en todo caso arduino se quedaba dentro de: while (Serial1.available() >0) y no salia.

He cambiado el modo de enviarlo desde la app aun modo mas rudimentario; envío una letra y en arduino dependiendo de la letra hago lo que creo oportuno.

Por fin puedo pasar a la siguiente fase y afinar el esquiva obstáculos antes de añadirle mas sensores.