Motores + Servo + Ultrasonico

¡Buenas!

Tengo una duda sobre la programación combinada de motores, servo y ultrasonico.

La cosa es que quiero que el coche al llegar frente a un pared, se detenga. Gire el servo a la derecha y verifique la distancia si es menor de 30cm girar hacia la izquierda y verificar si la distancia es menor de 30cm y si fuese mayor, que iniciase los motores para girar en caso de que la distancia fuera inferior a 30cm que de marcha atrás 5 segundos y repita el proceso anterior.

Llevo de momento esta programación (Sin motores, de momento). Fijaros solo en la última parte. OTra duda es si pasa algo que el servo tarde 1s en girar. (Por si se rompe o algo)

long distancia;
long tiempo;   
  
Servo miservo;    
  
int Distancia;  
  
void setup(){  
  Serial.begin(9600);
  pinMode(11, OUTPUT); 
  pinMode(10, INPUT); 
    miservo.attach(12);  
  
    miservo.write(90);    
}  
  
void loop(){  
  digitalWrite(11,LOW); 
  delayMicroseconds(5);
  digitalWrite(11, HIGH);
  delayMicroseconds(10);
  tiempo=pulseIn(10, HIGH); 
  distancia= int(0.017*tiempo); 
  Serial.println("Distancia ");
  Serial.println(distancia);
  Serial.println(" cm");
  miservo.write(90); 
  
    if(distancia <= 30){  
  
        miservo.write(0);  
        delay(1500); 
    if(distancia <= 30)
        miservo.write(180);  
        delay(1500); 
    }else{  
        miservo.write(90); 
        delay(1500);  
    }  
  
    delay(500);  
}

arma una máquina de estados para programar esto. De otro modo será complicado hacerlo
En una máquina de estados, visualizas cada estado y las opciones disponibles.
De todos modos miro tu código tal como está.

void loop(){  
  
  digitalWrite(11,LOW); 
  delayMicroseconds(5);
  digitalWrite(11, HIGH);
  delayMicroseconds(10);
  tiempo=pulseIn(10, HIGH); 
  distancia= int(0.017*tiempo); 
  Serial.println("Distancia ");
  Serial.println(distancia);
  Serial.println(" cm");
  miservo.write(90); 
  
    if(distancia <= 30){   // Primer IF
        miservo.write(0);  
        delay(1500); 
    if(distancia <= 30)    // Segundo IF
        miservo.write(180);  
        delay(1500); 
    } else {  
        miservo.write(90); 
        delay(1500);  
    }  
    delay(500);  
}

He puesto en tu código dos leyendas 1er IF y 2do if para explicar tu error.
Como tu preguntas en el primer if si la dist es menor a 30 y actuas el 2do if que esta ligado al primero siempre será VERDADERO porque distancia como variable sigue siendo menor a 30
Lo que debes hacer es, crear un procedimiento para medir la distancia e intrrograrlo cuando lo requieras.
Algo asi.

void loop(){  

  Serial.println("Distancia ");
  Serial.println(sonar());
  Serial.println(" cm");
  miservo.write(90); 
  
    if(sonar() <= 30){  
        miservo.write(0);  
        delay(1500); 
    if(sonar() <= 30)
        miservo.write(180);  
        delay(1500); 
    }else{  
        miservo.write(90); 
        delay(1500);  
    }  
  
    delay(500);  
} 

int sonar() {
  digitalWrite(11,LOW); 
  delayMicroseconds(5);
  digitalWrite(11, HIGH);
  delayMicroseconds(10);
  tiempo = pulseIn(10, HIGH); 
  distancia = int(0.017*tiempo); 
  return distancia;
}

¿Es necesario que haya dos parentesis después de distancia?

Lo que hice fue según cambiando la variable sonar -> distancia.

    if(distancia() <= 30)

Al compilar me da error:


Arduino:1.6.9 (Windows 7), Tarjeta:"Arduino/Genuino Uno"
C:\Users\Usuario\Documents\Arduino\sketch_may15a\sketch_may15a.ino: In function 'void loop()':
sketch_may15a:40: error: 'distancia' cannot be used as a function
** if(distancia() <= 30){ **
** ^**
sketch_may15a:47: error: 'distancia' cannot be used as a function
** if(distancia() <= 30) **
** ^**
sketch_may15a:50: error: 'distancia' cannot be used as a function
** if(distancia() <= 30) **
** ^**
exit status 1
'distancia' cannot be used as a function
Este reporte podría tener más información con
"Mostrar salida detallada durante la compilación"
opción habilitada en Archivo -> Preferencias.


Debo añadir que no puse el codigo que me indicastes ya que me parece innecesario ya que lo que indicas en ese código ya esta mencionado en void loop salvo el return distancia; que no se cual es la función.

int sonar() {
  digitalWrite(11,LOW); 
  delayMicroseconds(5);
  digitalWrite(11, HIGH);
  delayMicroseconds(10);
  tiempo = pulseIn(10, HIGH); 
  distancia = int(0.017*tiempo); 
  return distancia;
}

Aprovecho para decir que lo que intento es un coche "inteligente". Intentaré explicar lo que intento.

A = Coche
B = Servo
C = Ultrasonico

A esta rodando recto hasta encontrar un muro. Los motores se paran, y B en un angulo inicial de 90º gira hacia 0º (Osea a la derecha) y por tanto C al estar pegado con el servo se queda mirando hacia la izquierda.
C observa que hay un muro en la izquierda y por tanto se requiere que el servo vaya hacia 180º hacia la izquierda. Todo esto sin que el A se mueva, es decir, solo se mueve B.
B al observar que en una vista de 180º (izquierda) hay otro muro procede a que los motores se enciendan y corran hacia atras 5 segundos.

Por favor, si yo te di todo un loop nuevo porque lo parcializas?
Toma mi loop completo no lo que tu crees (con mal criterio) que debiste usar.
Al crear un procedimiento para medir la distancia uso sonar() no distancia.
Porque necesito que mida en cada momento que lo requiero y debe ser diferente al anterior, porque tu mueves el servo.
En tu loop que ya lo expliqué, lees al comienzo y usas esa misma distancia para diferentes decisiones y eso no es correcto.
Imagina esto. Llegas a la pared porque mediste < 30.
Giras a la derecha... mides..Segun tu programa, usasla misma distancia anterior MAL. Debes medir de nuevo. Lo que hace mi código.
Luego giras a otro sitio y debes medir tambien.
Eso aun no esta hecho.

surbyte:
Por favor, si yo te di todo un loop nuevo porque lo parcializas?
Toma mi loop completo no lo que tu crees (con mal criterio) que debiste usar.
Al crear un procedimiento para medir la distancia uso sonar() no distancia.
Porque necesito que mida en cada momento que lo requiero y debe ser diferente al anterior, porque tu mueves el servo.
En tu loop que ya lo expliqué, lees al comienzo y usas esa misma distancia para diferentes decisiones y eso no es correcto.
Imagina esto. Llegas a la pared porque mediste < 30.
Giras a la derecha... mides..Segun tu programa, usasla misma distancia anterior MAL. Debes medir de nuevo. Lo que hace mi código.
Luego giras a otro sitio y debes medir tambien.
Eso aun no esta hecho.

Es que soy un alumno de 4ºESO y estoy muy interesado en arduino, y la verdad es que copiar programaciones no me gusta (Aun que a veces es indispensable, pero en este caso siempre los edito a mi manera (y que sigue funcionando y de mejor forma o a mi gusto..)

Si no funciona, que probaré mañana, pongo aqui dudas y tal y sino perfect. y Gracias.

Cuando yo era estudiante también pensaba lo mismo que tu. Prefería hacer las cosas yo mismo, y las hacía. Luego venía un compañero de clases más avanzado y lo modificaba de una manera mucho más eficiente.

Ahí me daba cuenta de que yo no sabía todo lo que tenía que saber y me ponía a estudiar más fuerte que antes.

Si llamas a una función, puedes o no pasarle parámetros.
La función en este caso sonar no tiene parámetros que le pasé mi loop, entonces queda vacía ().

Pero ella si devuelve un dato, justamente la distancia.
Había dos maneras de hacerla: como la hice es decir una función y como rutina o sea en este caso void sonar()
Cuando es función devuelve un dato via el comando return.
Defines entonces como será ese dato en nuestro caso int sonar() { y al final return (int) valor;
donde valor es obviamente un entero

Ahora dentro del loop cada llamado a esta rutina sera del tipo sonar() y cuando se la invoque imagina que es una variable entera entonces
if (sonar() <= 30) sera VERDADERO si asi lo indica el ULTRASONICO o FALSO si es mayor a 30