Quiero controlar el sentido de giro y la velocidad de un motor mediante un comunicación Bluetooth , consta de un mando formado por una placa Arduino Nano, un Joystick y un modulo Bluetooth HC05 como maestro previamente configurado mediante comandos AT.
Como receptor una placa Arduino Mega, un modulo Bluetooth HC05 ( esclavo) y un puente H BTS7960
Código del mando:
int xAxis, yAxis;
void setup() {
Serial.begin(38400); // Tasa de comunicación predeterminada del módulo Bluetooth
}
void loop() {
xAxis = analogRead(A0); // Leer Joysticks eje X
yAxis = analogRead(A1); // Leer Joysticks eje Y
// Enviar los valores a través del puerto serie al dispositivo Bluetooth esclavo HC-05
Serial.write(xAxis/4); // Dividir por 4 para convertir de 0-1023 a 0-256, rango (1 byte)
Serial.write(yAxis/4);
delay(20);
}
Código del receptor:
#define enA 9 // Salida PWM = MotorSpeedA
#define enB 10 // Salida PWM = MotorSpeedB
int xAxis, yAxis;
unsigned int x = 0;
unsigned int y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
Serial.begin(38400); // Tasa de comunicación predeterminada del módulo Bluetooth
}
void loop() {
// Valor predeterminado: sin movimiento cuando el joystick permanece en el centro
x = 510 / 4;
y = 510 / 4;
// Leer los datos entrantes del Joystick o del dispositivo Bluetooth maestro
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
delay(10);
// Convierta de nuevo el rango 0-255 a 0-1023, adecuado para el código de control del motor a continuación
xAxis = x*4;
yAxis = y*4;
// Eje Y utilizado para control hacia adelante y hacia atrás
if (yAxis < 470) {
// Pon el motor A hacia atrás
// Convierta las lecturas decrecientes del eje Y para retroceder de 470 a 0 en un valor de 0 a 255 para la señal PWM para aumentar la velocidad del motor
motorSpeedA = map(yAxis, 470, 0, 0, 255);
motorSpeedB = 0;
}
else if (yAxis > 550) {
// Pon el motor A hacia adelante
// Convierta las lecturas crecientes del eje Y para avanzar de 550 a 1023 en un valor de 0 a 255 para la señal PWM para aumentar la velocidad del motor
motorSpeedA = 0;
motorSpeedB = map(yAxis, 550, 1023, 0, 255);
}
// Si el joystick permanece en el medio, los motores no se mueven
else {
motorSpeedA = 0;
motorSpeedB = 0;
}
analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}
NOTA:
xAxis = analogRead(A0); // Leer Joysticks eje X
Lo usare en un futuro para controlar un servomotor, si logro solucionar el problema del control de velocidad del motor.
Resultado:
El motor responde correctamente a lo enviado por el mando, es decir sentido de giro y control de velocidad correcto pero va a tirones ( hace pequeñas interrupciones cuando gira )
¿Veis algún fallo en los códigos?
¿Alguna idea de lo que pueda estar sucediendo?
Gracias.
// Valor predeterminado: sin movimiento cuando el joystick permanece en el centro
x = 510 / 4;
y = 510 / 4;
Si no recibes nada
// Si el joystick permanece en el medio, los motores no se mueven
else {
motorSpeedA = 0;
motorSpeedB = 0;
}
Entonces, arranca con velocidad 0, llegan valores, y actúa en consecuencia, vuelve al principio del loop() y si no llegan nuevos valores vuelve a asignar velocidad 0, y vuelta a empezar.
Como resultado: mueve, frena, mueve, frena... o sea, va a los saltos.
Prueba colocar
// Valor predeterminado: sin movimiento cuando el joystick permanece en el centro
x = 510 / 4;
y = 510 / 4;
en setup() no en loop(), así una vez iniciado solo responde a lo que recibe.
Mis observaciones del código:
Para qué envias xAxis y yAxis / 4 y luego los multiplicas x 4 en el receptor?
Para hacer eso no hagas nada y envíalos normales o crees que no se puede hacer? Supongo que si pero te resultó mas simple asi no es cierto?
Claro que hay que modificar como recibes los datos porque ya serán 2 bytes para cada uno pero es posible.
Otra cosa. envias todo lo que leen el ADC en A0 y A1 cuando lo lógico es enviar solo datos distintos del anterior, dandole respiro al sistema y no tan rápido como cada 20mseg
Finalmente, envias x e y pero solo usas yAxis, entonces elimina xAxis y usa lo que necesitas.
Hoy he decidido modificar el receptor cambiando el Arduino Mega por un Arduino Nano.
El Nano lo he programado con el mismo código que programe el Mega:
#include <Servo.h> //Libreria para Servomotor
Servo servo1; //Creo un Servomotor
#define enA 9// Pin 9 para retoceder
#define enB 10 // Pin 10 para avanzar
int xAxis, yAxis;//Traccion
unsigned int x = 0;//Traccion
unsigned int y = 0;//Traccion
int RETROCEDER = 0;//Traccion
int AVANZAR = 0;//Traccion
int PINSERVO = 2;//Salida por el pin 2 Servomotor
int PULSOMIN = 500;//Servomotor
int PULSOMAX = 2500;//Servomotor
int VALORPOT;//Servomotor
int ANGULO;//Servomotor
int POT = 0;//Servomotor
void setup() {
servo1.attach (PINSERVO, PULSOMIN, PULSOMAX); //Servomotor
pinMode(enA, OUTPUT);//Traccion
pinMode(enB, OUTPUT);//Traccion
// Valor predeterminado: sin movimiento cuando el joystick permanece en el centro
x = 510 / 4;//Traccion
y = 510 / 4;//Traccion
Serial.begin(38400); // Tasa de comunicación predeterminada del módulo Bluetooth
}
void loop() {
// Leer los datos entrantes del Joystick o del dispositivo Bluetooth maestro
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
delay(10);
// Convierta de nuevo el rango 0-255 a 0-1023, adecuado para el código de control del motor a continuación
xAxis = x*4;
yAxis = y*4;
// Eje Y utilizado para control hacia adelante y hacia atrás
if (yAxis < 470) {
// Pon el motor hacia atrás
// Convierta las lecturas decrecientes del eje Y para retroceder de 470 a 0 en un valor de 0 a 255 para la señal PWM para aumentar la velocidad del motor
RETROCEDER = map(yAxis, 470, 0, 0, 255);
AVANZAR = 0;
}
else if (yAxis > 550) {
// Pon el motor hacia adelante
// Convierta las lecturas crecientes del eje Y para avanzar de 550 a 1023 en un valor de 0 a 255 para la señal PWM para aumentar la velocidad del motor
RETROCEDER = 0;
AVANZAR = map(yAxis, 550, 1023, 0, 255);
}
// Si el joystick permanece en el medio, los motores no se mueven
else {
RETROCEDER = 0;
AVANZAR = 0;
}
VALORPOT = xAxis;
ANGULO = map(VALORPOT,0, 1023, 0, 180);
servo1.write(ANGULO);
analogWrite(enA, RETROCEDER); // Envia señal PWM en pin 9 para retoceder
analogWrite(enB, AVANZAR); // Envia señal PWM en pin 10 para avanzar
}
Sorpresa la mía que solo responde cuando llevo el Joystick hacia delante y en su posición máxima el motor gira al máximo, lo demás nada.
¿Quizás debería de modificar algo del código, ya que estoy usando un Arduino Nano?
Aprende a debuggear o sea entender que pasa.
cuando llevas el joystick para adelante yAxis es >550 hasta 1023
Empieza viendo que valores estas leyendo para eso usa Serial.println( datos)
En tu caso esos datos los lees por puerto serie. Entonces asegúrate de recibir lo que crees.
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
Acá recibes x e y. Muestra por Serial que estas recibiendo.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(4, 5);
int xAxis, yAxis;
unsigned int x = 0;
unsigned int y = 0;
void setup() {
Serial.begin(9600);
mySerial.begin(38400);
}
void loop() {
while (mySerial.available() >= 2) {
x = mySerial.read();
delay(10);
y = mySerial.read();
delay(10);
}
Serial.println(x);
Serial.println(y);
}
¿podre ver lo que recibo del Bluetooth?
La idea seria conectar los pines TX , RX del Bluetooth a los pines 4 y 5 del Nano y que me los envié por el puerto serie al Monitor Serie para así poder ver lo que recibo del mando.
Gracias.
Para ello tendría que modificar el código del post #6 para incluir el softwareSerial del post #10 de tal manera que pueda enviar los valores de RETROCEDER y AVANZAR al monitor serie.
VALORPOT y ANGULO no los veo necesario verlos, ya que el servo de la direccion si me responde.
Bueno, a ver como hago la modificación siendo novato en Arduino.
Cualquier duda os doy la lata.........
Entendí que pusiese 9600 a mySerial. Ya te entendí te referías a que ponga en Serial. 38400 también. Entendido y modificado.
Respecto al código ya lo he modificado:
#include <SoftwareSerial.h>
#include <Servo.h> //Libreria para Servomotor
Servo servo1; //Creo un Servomotor
SoftwareSerial mySerial(4, 5);
#define enA 9// Pin 9 para retoceder
#define enB 10 // Pin 10 para avanzar
int xAxis, yAxis;//Traccion
unsigned int x = 0;//Traccion
unsigned int y = 0;//Traccion
int RETROCEDER = 0;//Traccion
int AVANZAR = 0;//Traccion
int PINSERVO = 3;//Salida por el pin 3 Servomotor
int PULSOMIN = 500;//Servomotor
int PULSOMAX = 2500;//Servomotor
int VALORPOT;//Servomotor
int ANGULO;//Servomotor
int POT = 0;//Servomotor
void setup() {
servo1.attach (PINSERVO, PULSOMIN, PULSOMAX); //Servomotor
pinMode(enA, OUTPUT);//Traccion
pinMode(enB, OUTPUT);//Traccion
// Valor predeterminado: sin movimiento cuando el joystick permanece en el centro
x = 510 / 4;//Traccion
y = 510 / 4;//Traccion
Serial.begin(38400); // Tasa de comunicación MONITOR SERIE
mySerial.begin(38400);
}
void loop() {
// Leer los datos entrantes del Joystick o del dispositivo Bluetooth maestro
while (mySerial.available() >= 2) {
x = mySerial.read();
delay(10);
y = mySerial.read();
}
delay(10);
// Convierta de nuevo el rango 0-255 a 0-1023, adecuado para el código de control del motor a continuación
xAxis = x*4;
yAxis = y*4;
// Eje Y utilizado para control hacia adelante y hacia atrás
if (yAxis < 470) {
// Pon el motor hacia atrás
// Convierta las lecturas decrecientes del eje Y para retroceder de 470 a 0 en un valor de 0 a 255 para la señal PWM para aumentar la velocidad del motor
RETROCEDER = map(yAxis, 470, 0, 0, 255);
AVANZAR = 0;
}
else if (yAxis > 550) {
// Pon el motor hacia adelante
// Convierta las lecturas crecientes del eje Y para avanzar de 550 a 1023 en un valor de 0 a 255 para la señal PWM para aumentar la velocidad del motor
RETROCEDER = 0;
AVANZAR = map(yAxis, 550, 1023, 0, 255);
}
// Si el joystick permanece en el medio, los motores no se mueven
else {
RETROCEDER = 0;
AVANZAR = 0;
}
VALORPOT = xAxis;
ANGULO = map(VALORPOT,0, 1023, 0, 180);
servo1.write(ANGULO);
analogWrite(enA, RETROCEDER); // Envia señal PWM en pin 9 para retoceder
analogWrite(enB, AVANZAR); // Envia señal PWM en pin 10 para avanzar
Serial.print("X=");
Serial.print(x);
Serial.println(" ");
Serial.print("Y=");
Serial.print(y);
Serial.println(" ");
Serial.print("RETROCEDER=");
Serial.print(RETROCEDER);
Serial.println(" ");
Serial.print("AVANZAR=");
Serial.print(AVANZAR);
Serial.println(" ");
Serial.print("VALORPOT=");
Serial.print(VALORPOT);
Serial.println(" ");
Serial.print("ANGULO=");
Serial.print(ANGULO);
Serial.println(" ");
Serial.println(" ");
delay(500);
Van al revés porque tengo el Joystick al revés en el mando ( tendré que modificar el código)
Pero el problema no es ese.
El problema es que solo responde cuando llevo el Joystick hacia delante y en su posición máxima el motor gira al máximo, lo demás nada ( excepto el Servo que si funciona)
Estoy utilizando un puente H en concreto el BTS7960 el cual esta conectado a estos pines del Nano:
En resumen viendo los resultados el problema tiene que estar en esta linea de codigo:
Ya que los valores de las variables: RETROCEDER y AVANZAR no las envia por los pines 9 y 10 del Nano.
¿Veis algún error?
¿Alguna idea de que podría probar?
Estuve haciendo unas pruebas en wokwi y lo que está interfiriendo es la librería Servo.
Luego, mirando la documentación (Servo - Arduino Reference) encuentro:
On boards other than the Mega, use of the library disables (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins.
"En placas que no sean Mega, el uso de la biblioteca deshabilita la funcionalidad PWM en los pines 9 y 10, haya o no un servo en esos pines."
Ahí está el problema.
Saludos
Agrego: Podrías usar los pines 5 y 6 (cambiando los pines para SoftwareSerial si es que la sigues usando).