Buen día, hice un proyecto de un carrito que detecta obstáculos por medio de un sensor ultrasonido que se mueve al estar pegado a un servo, basado en este proyecto le agregué un modulo HC-05 para poder controlar de dos maneras el carrito, ya sea como un carrito a control normal y corriente además de poder activar desde la aplicación RC Controler la función del ultrasonido y al presionar de nuevo que se desactive esa función. El problema surge al momento de presionar el botón que acciona la función del ultrasonido, el servo se queda trabado moviéndose erráticamente y el carro avanza sin que detecte nada el ultrasonido. Creo que es algún problema en mi código ya que probé por separado ambos códigos con todos los componentes soldados y conectados y funciona correctamente, pero a la hora de juntar ambos códigos me salta ese detalle. Gracias.
#include <Servo.h>
#include <NewPing.h>
#include <AFMotor.h>
#include <SoftwareSerial.h>
SoftwareSerial bluetoothSerial(1, 2); // RX, TX
NewPing Dist(11, 10, 200); // (trig, echo, dist max)
Servo myServo;
int distancia = 0;
int distanciaD = 0;
int distanciaIz = 0;
boolean Booleano = false;
AF_DCMotor Motor1(1, MOTOR12_1KHZ);
AF_DCMotor Motor2(2, MOTOR12_1KHZ);
AF_DCMotor Motor3(3, MOTOR34_1KHZ);
AF_DCMotor Motor4(4, MOTOR34_1KHZ);
char command;
void setup() {
bluetoothSerial.begin(9600); // Set the baud rate to your Bluetooth module.
myServo.attach(9); // Mover la inicialización del servo aquí
}
void loop() {
if (bluetoothSerial.available() > 0) {
command = bluetoothSerial.read();
Stop(); // Initialize with motors stopped
switch (command) {
case 'F':
forward();
break;
case 'B':
back();
break;
case 'L':
left();
break;
case 'R':
right();
break;
case 'X':
while(true){
Obstaculos();
}
break;
case 'x':
Stop();
break;
}
}
}
void Obstaculos() {
myServo.write(115);
delay(1000);
myServo.write(65);
delay(500);
myServo.write(160);
delay(500);
myServo.write(115);
distancia = medirDistancia();
if (distancia >= 25 && distancia <= 250) {
Adelante();
} else if (distancia < 25) {
Frenar();
delay(150);
Reversa();
delay(250);
Frenar();
delay(250);
distanciaD = mirarDerecha();
delay(250);
distanciaIz = mirarIzquierda();
delay(250);
if(distanciaD >= distanciaIz) {
GirarDerecha();
Frenar();
} else if(distanciaIz >= distanciaD) {
GirarIzquierda();
Frenar();
}
}
}
int mirarDerecha() {
myServo.write(60);
delay(350);
int distancia = medirDistancia();
return distancia;
}
int mirarIzquierda() {
myServo.write(165);
delay(350);
int distancia = medirDistancia();
delay(50);
myServo.write(115);
return distancia;
}
int medirDistancia() {
delay(10);
int distanciaCM = Dist.ping_cm();
if(distanciaCM <= 0 || distanciaCM >= 250) {
distanciaCM = 250;
}
return distanciaCM;
}
void Frenar() {
Motor1.run(RELEASE);
Motor2.run(RELEASE);
Motor3.run(RELEASE);
Motor4.run(RELEASE);
}
void Adelante() {
if(Booleano == false) {
Booleano = true;
Motor1.run(BACKWARD);
Motor2.run(FORWARD);
Motor3.run(BACKWARD);
Motor4.run(FORWARD);
controlVelocidad();
}
}
void Reversa() {
Booleano = false;
Motor1.run(FORWARD);
Motor2.run(BACKWARD);
Motor3.run(FORWARD);
Motor4.run(BACKWARD);
controlVelocidad();
}
void GirarDerecha() {
Motor1.run(FORWARD);
Motor2.run(FORWARD);
Motor3.run(FORWARD);
Motor4.run(FORWARD);
delay(400);
}
void GirarIzquierda() {
Motor1.run(BACKWARD);
Motor2.run(BACKWARD);
Motor3.run(BACKWARD);
Motor4.run(BACKWARD);
delay(400);
}
void controlVelocidad() {
for (int velocidad = 0; velocidad < 160; velocidad += 2) {
Motor1.setSpeed(velocidad);
Motor2.setSpeed(velocidad);
Motor3.setSpeed(velocidad);
Motor4.setSpeed(velocidad);
delay(3);
}
}
void forward() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(BACKWARD); // Rotate the motor clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(FORWARD); // Rotate the motor clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(BACKWARD); // Rotate the motor clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(FORWARD); // Rotate the motor clockwise
}
void back() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(FORWARD); // Rotate the motor anti-clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(BACKWARD); // Rotate the motor anti-clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(FORWARD); // Rotate the motor anti-clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(BACKWARD); // Rotate the motor anti-clockwise
}
void left() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(BACKWARD); // Rotate the motor clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(BACKWARD); // Rotate the motor clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(BACKWARD); // Rotate the motor anti-clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(BACKWARD); // Rotate the motor anti-clockwise
}
void right() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(FORWARD); // Rotate the motor anti-clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(FORWARD); // Rotate the motor anti-clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(FORWARD); // Rotate the motor clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(FORWARD); // Rotate the motor clockwise
}
void Stop() {
Motor1.setSpeed(0); // Define minimum velocity
Motor1.run(RELEASE); // Stop the motor when release the button
Motor2.setSpeed(0); // Define minimum velocity
Motor2.run(RELEASE); // Rotate the motor clockwise
Motor3.setSpeed(0); // Define minimum velocity
Motor3.run(RELEASE); // Stop the motor when release the button
Motor4.setSpeed(0); // Define minimum velocity
Motor4.run(RELEASE); // Stop the motor when release the button
}
Aquí la idea es que cuando reciba el comando ‘X’ ejecute la función Obstáculos() indefinidamente (hasta que se reinicie el Arduino)?
1 Like
La idea es que al recibir el comando X se ejecute la función del sensor ultrasonido y que cuando reciba el comando x (en minúscula) se deje de ejecutar y se pueda usar como un carrito a control remoto mediante los botones de la aplicación
En esa imagen se pueden ver los controles, el botón encerrado en el cuadro rojo es el que recibe la señal 'X' cuando se presiona y se mantiene activo hasta recibir 'x'
Lo que pasa es que sin el while no funcionaban los otros controles, no sé por qué. Gracias por la ayuda.
Se va a mantener activo mientras true sea true. Para siempre, pues. A menos que reinicies el Arduino.
Tal vez te sirva ponerlo así:
Tienes que revisar si conservas Stop() al principio de loop()
Saca el switch()
del bloque if()
Cambia el case 'X'
por
case 'X':
Obstaculos();
break;
Y luego del switch()
agrega
if (command != 'X') {
command = 0;
}
Listo, se ejecuta X hasta que envíes otro comando.
¿Por qué?
Porque la variable command es global y solo cambia su valor cuando se recibe un nuevo comando, entonces cuando de recibe uno nuevo luego de ejecutar lo que deba la pones a 0 salvo que el contenido sea 'X'.
Luego, en cada pasada de loop()
se repetirá Obstaculos()
mientras command sea igual a 'X'.
Algo asi
void loop() {
if (bluetoothSerial.available() > 0) {
command = bluetoothSerial.read();
Stop(); // Initialize with motors stopped
}
switch (command) {
// aca los case
}
if (command != 'X') {
command = 0;
}
}
Gracias por el consejo, hice lo que me recomendaste y de plano ya no hace nada al momento de presionar el botón. El stop tiene que estar ya que si no lo incluyo al momento de usar las flechas en la aplicación ya no frena si dejo de presionar.
Por un momento pensé que si funcionaría, pero creo que hay un error al recorrer el loop. Luego de cargar el código y presionar el boton para ejecutar la función Obstaculos() el servo gira y el ultrasonido parece ser que también detecta pero avanza un poco el carrito y ahí se queda, pongo nuevamente un objeto en frente y ya no detecta nada el ultrasonido. La idea es que se deje de ejecutar 'X' cuando mande la señal 'x' por que ese es el nombre para cuando el botón está desactivado. Gracias igualmente.
Si, ya se cual es "la idea".
Adjunta nuevamente el código tal y como lo tienes ahora con la modificación que te sugerí y no te funciona
Una consulta:
¿La aplicación solo manda comandos cuando pulsas un botón, verdad?
¿O manda algo siempre aunque no sea un comando?
#include <Servo.h>
#include <NewPing.h>
#include <AFMotor.h>
#include <SoftwareSerial.h>
SoftwareSerial bluetoothSerial(1, 2); // RX, TX
NewPing Dist(11, 10, 200); // (trig, echo, dist max)
Servo myServo;
int distancia = 0;
int distanciaD = 0;
int distanciaIz = 0;
boolean Booleano = false;
AF_DCMotor Motor1(1, MOTOR12_1KHZ);
AF_DCMotor Motor2(2, MOTOR12_1KHZ);
AF_DCMotor Motor3(3, MOTOR34_1KHZ);
AF_DCMotor Motor4(4, MOTOR34_1KHZ);
char command;
void setup() {
bluetoothSerial.begin(9600); // Set the baud rate to your Bluetooth module.
myServo.attach(9); // Mover la inicialización del servo aquí
}
/*void loop() {
if (bluetoothSerial.available() > 0) {
command = bluetoothSerial.read();
Stop(); // Initialize with motors stopped
switch (command) {
case 'F':
forward();
break;
case 'B':
back();
break;
case 'L':
left();
break;
case 'R':
right();
break;
case 'X':
Obstaculos();
break;
case 'x':
Stop();
break;
}
}
}*/
void loop() {
if (bluetoothSerial.available() > 0) {
command = bluetoothSerial.read();
Stop(); // Initialize with motors stopped
}
switch (command) {
case 'F':
forward();
break;
case 'B':
back();
break;
case 'L':
left();
break;
case 'R':
right();
break;
case 'X':
Obstaculos();
break;
case 'x':
Stop();
break;
}
if (command != 'X') {
command = 0;
}
}
void Obstaculos() {
myServo.write(115);
delay(1000);
myServo.write(65);
delay(500);
myServo.write(160);
delay(500);
myServo.write(115);
distancia = medirDistancia();
if (distancia >= 25 && distancia <= 250) {
Adelante();
} else if (distancia < 25) {
Frenar();
delay(150);
Reversa();
delay(250);
Frenar();
delay(250);
distanciaD = mirarDerecha();
delay(250);
distanciaIz = mirarIzquierda();
delay(250);
if(distanciaD >= distanciaIz) {
GirarDerecha();
Frenar();
} else if(distanciaIz >= distanciaD) {
GirarIzquierda();
Frenar();
}
}
}
int mirarDerecha() {
myServo.write(60);
delay(350);
int distancia = medirDistancia();
return distancia;
}
int mirarIzquierda() {
myServo.write(165);
delay(350);
int distancia = medirDistancia();
delay(50);
myServo.write(115);
return distancia;
}
int medirDistancia() {
delay(10);
int distanciaCM = Dist.ping_cm();
if(distanciaCM <= 0 || distanciaCM >= 250) {
distanciaCM = 250;
}
return distanciaCM;
}
void Frenar() {
Motor1.run(RELEASE);
Motor2.run(RELEASE);
Motor3.run(RELEASE);
Motor4.run(RELEASE);
}
void Adelante() {
if(Booleano == false) {
Booleano = true;
Motor1.run(BACKWARD);
Motor2.run(FORWARD);
Motor3.run(BACKWARD);
Motor4.run(FORWARD);
controlVelocidad();
}
}
void Reversa() {
Booleano = false;
Motor1.run(FORWARD);
Motor2.run(BACKWARD);
Motor3.run(FORWARD);
Motor4.run(BACKWARD);
controlVelocidad();
}
void GirarDerecha() {
Motor1.run(FORWARD);
Motor2.run(FORWARD);
Motor3.run(FORWARD);
Motor4.run(FORWARD);
delay(400);
}
void GirarIzquierda() {
Motor1.run(BACKWARD);
Motor2.run(BACKWARD);
Motor3.run(BACKWARD);
Motor4.run(BACKWARD);
delay(400);
}
void controlVelocidad() {
for (int velocidad = 0; velocidad < 160; velocidad += 2) {
Motor1.setSpeed(velocidad);
Motor2.setSpeed(velocidad);
Motor3.setSpeed(velocidad);
Motor4.setSpeed(velocidad);
delay(3);
}
}
void forward() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(BACKWARD); // Rotate the motor clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(FORWARD); // Rotate the motor clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(BACKWARD); // Rotate the motor clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(FORWARD); // Rotate the motor clockwise
}
void back() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(FORWARD); // Rotate the motor anti-clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(BACKWARD); // Rotate the motor anti-clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(FORWARD); // Rotate the motor anti-clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(BACKWARD); // Rotate the motor anti-clockwise
}
void left() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(BACKWARD); // Rotate the motor clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(BACKWARD); // Rotate the motor clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(BACKWARD); // Rotate the motor anti-clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(BACKWARD); // Rotate the motor anti-clockwise
}
void right() {
Motor1.setSpeed(255); // Define maximum velocity
Motor1.run(FORWARD); // Rotate the motor anti-clockwise
Motor2.setSpeed(255); // Define maximum velocity
Motor2.run(FORWARD); // Rotate the motor anti-clockwise
Motor3.setSpeed(255); // Define maximum velocity
Motor3.run(FORWARD); // Rotate the motor clockwise
Motor4.setSpeed(255); // Define maximum velocity
Motor4.run(FORWARD); // Rotate the motor clockwise
}
void Stop() {
Motor1.setSpeed(0); // Define minimum velocity
Motor1.run(RELEASE); // Stop the motor when release the button
Motor2.setSpeed(0); // Define minimum velocity
Motor2.run(RELEASE); // Rotate the motor clockwise
Motor3.setSpeed(0); // Define minimum velocity
Motor3.run(RELEASE); // Stop the motor when release the button
Motor4.setSpeed(0); // Define minimum velocity
Motor4.run(RELEASE); // Stop the motor when release the button
}
También algo que sigue pasando y no se si tiene que ver, es que al conectar el BT desde la aplicación el servo se pone a moverse en su sitio, cuando presiono el botón se mueve normalmente como debería hacerlo pero digamos que se pone así como moviendose cuando espera una orden
Prueba esto y dime qué dice la consola cuando no pulsas nada en la app
if (bluetoothSerial.available() > 0) {
command = bluetoothSerial.read();
Serial.println("Recibio algo...");
Stop(); // Initialize with motors stopped
}
Recuerda agregar Serial.begin(9600);
en setup()
Acerca de la aplicación, hay dos tipos de botones. Lo que son las flechas como está en la imagen y los botones que se encuentran al lado del que encerré. Al presionar las flechas se ejecuta la función hasta que dejes de presionar. Y los otros ejecutan la función presionando una vez, se mantiene ejecutando hasta que vuelvas a presionar el botón.
O sea que continuamente envía "stop" si no hay otra cosa pulsada.
Ese es el problema.
Por el Stop del loop() no?
No porque la app se la pasa mandando "stops". (Además que el código original no estaba del todo bien, obvio).
Prueba seteando en la app "data stream frequency" a "on change/touch"
Ahora no manda ningun stop y el servo se calmó
Pero ahora funciona X o no?
Mientras está en ejecución X se mueve el servo y parece que también detecta el ultrasonido al momento de poner algo en frente pero solo avanza y ya no se detiene para poder ir por otro camino. Y también al presionar nuevamente el boton, osea 'x', si se detiene que es lo bueno
Ese ya es otro problema del código así que ponte a revisarlo.
Cuando lo pueda ver con tiempo te digo si encuentro lo que pueda estar mal.
Gracias amigo, enserio.
Estaré revisando eso y si tengo buenas noticias avisaré por aquí.