2025-07-26
Jugando con un coche... Bluetooth!!
Me apetecía hacer una coche controlado por bluetooth, me hice de un kit con los materiales y lo monté.
Además de para pasar el rato, esta entrada es para ver como funciona el MotorShield que se encarga del control de los motores, además de para aprender como funcionan los módulos HC-05 y HC-06.
Módulos bluetooth HC-05 y HC-06
Ambos módulos permiten combinación UART (serie) mediante el bluetooth, con lo que podemos conectar nuestro Arduino a uno de estos módulos y enviar información a través de nuestro teléfono.
A nivel de hardware son exactamente iguales, lo único que cambia es el firmware y el modo de funcionamiento. Mientras que el HC-06 solo puede funcionar como esclavo, es decir, no puede iniciar comunicación con otro dispositivo; el HC-05 puede funcionar también como maestro.
A simple vista se pueden distinguir por el número de pines. El HC-06 solo tiene 4 pines VCC, GND, TX y RX; siendo la alimentación y la comunicación serie. El HC-05 tiene más pines STATE (indica si está emparejado o no) y ENABLE para habilitar el módulo o no. Además el HC-05 tiene un pulsador para ponerlo en modo recibir comandos y poder configurarlo.
Los módulos están listos para usar, se hacen las conexiones y a funcionar. Tan solo si queremos cambiar el nombre/contraseña o la velocidad de conexión serie (9600 por defecto), debemos entrar a modo configuración que se hace mediante comandos AT.
Algunos comandos AT son:
- AT : Comprueba la conexión.
- AT+NAME : Muestra el nombre por defecto.
- AT+ADDR : Muestra la dirección por defecto.
- AT+VERSION : Muestra la versión.
- AT+UART : Muestra la velocidad.
- AT+ROLE: Muestra el rol (1=master/0=slave)1
- AT+RESET : Reinicio y sale del modo AT.
- AT+ORGL : Restaura valores por defecto de fábrica.
- AT+PSWD: Muestra el password por defecto.
1El HC-06 solo puede funcionar como esclavo, así que este comando no va a funcionar.
El módulo HC-06 está en modo AT cuando no está emparejado (vinculado a otro dispositivo) y lo notaremos por que el diodo led parpadea rápido mientras que cuando está conectado tienes las luces fijas.
El módulo HC-05 para ponerlo en modo AT hay que mantener pulsado el botón que trae hasta que el led se queda fijo.
La conexión es realmente fácil. Tan solo hemos de llevar la línea TX al RX de Arduino, y la línea RX al TX de Arduino. Una cosa que debemos tener en cuenta es que ambos módulos funcionan a 3.3V y nos podemos cargar el módulo si hacemos la conexión directa. Así que conviene poner un adaptador de niveles entre ambos, sobre todo en la línea Arduino-TX a HC-RX. El adaptador de niveles puede ser un simple divisor de resistencias.
Si lo deseamos podemos usar un puerto serie virtual en Arduino usando la librería SoftwareSerial, librando el puerto serie hardware del Arduino, ya que el modulo bluetooth puede interferir en la programación del Arduino.
He aquí un ejemplo de programa que hace puente de la terminal de Windows y el teléfono. Lo que mandemos por el Serial se retransmite al bluetooth y viceversa. Su utilidad es obvia, probar el módulo.
#include <SoftwareSerial.h> const uint8_t rxPin=3; const uint8_t txPin=4; SoftwareSerial bport(rxPin, txPin); void setup() { bport.begin(9600); Serial.begin(9600); pinMode(13, OUTPUT); } void loop() { if ( bport.available() ) { Serial.write(bport.read()); } if ( Serial.available() ) { bport.write(Serial.read()); } }
Motorshield
La plaquita motorshield es un diseño de Adafruit la cual nos permite controlar cuatro motores pequeños y dos servos. Está diseñada con dos puentes H dobles a base del L293D y para reducir el número de pines necesarios hace uso de un 74xx595 para controlar los cuatro motores de manera independiente.
Su esquema es el siguiente:
Como vemos hace uso de todos los pines PWM del Arduino y aún con el uso del registro de desplazamiento usa casi todos los pines. Tan solo quedan libres el puerto serie, las entradas analógicas y los pines D2 y D13
El módulo dispone de un jumper que nos permite seleccionar la alimentación del Arduino. Si colocamos el jumper el Arduino cogerá la alimentación de las baterías ya que se alimentará vía el pin VIN. Con el quitado tendremos que alimentar el Arduino de alguna forma, ya sea vía Jack-DC o USB.
Aquí dejo un pequeño pinout de referencia:
El uso de los condensadores en los motores es casi opcional, sirven para reducir los posibles "ruidos" que se produzcan y que pueden hacer que nuestro Arduino se reinicie. Se puede usar la conexión en delta o tan solo poner un condensador entre pines del motor. También se pueden sustituir los condensadores por varistores.
Usando la librería AFMotor
La librería define la clase AF_DCMotor de la cual podemos instanciar cuatro objetos, cada uno de ellos representa a cada uno de los cuatro motores que podemos controlar con el motorshield.
Al crear el objeto indicamos el número de motor y, opcionalmente, su frecuencia PWM. Una vez creado podemos controlar la velocidad con la función setSpeed y el movimiento con la función run. A esta última se le pasa como parámetro el tipo de movimiento: FORWARD, movimiento hacia delante; BACKWARD, movimiento hacia atrás; BRAKE, donde los motores están frenados; por último, RELEASE donde los motores quedan libres de giro.
Aquí dejo un código de ejemplo:
// EJEMPLO TEST MOTOR. #include <AFMotor.h> AF_DCMotor motor1(1); AF_DCMotor motor2(2); AF_DCMotor motor3(3); AF_DCMotor motor4(4); void setup() { Serial.begin(9600); Serial.println("Motor test!"); // turn on motor motor1.setSpeed(128); motor1.run(FORWARD); motor2.setSpeed(128); motor2.run(FORWARD); motor3.setSpeed(128); motor3.run(FORWARD); motor4.setSpeed(128); motor4.run(FORWARD); } void loop() { }
Montando el proyecto
Montar el chasis no tiene misterio. Es más ni siquiera trae instrucciones de lo fácil que es. Así que no tiene más explicación.
Para montar el Arduino+Shield Motor si que he tenido que hacer unos orificios para sujetarlos al chasis, mientras que el resto (paquete de pilas y bluetooth) con cinta de doble cara es más que suficiente.
He realizado un pequeño circuito con una pcb perforada para hacer el adaptador de niveles y conectar el módulo HC-06 que he usado en el proyecto.
El resto es poner cables a los motores y conectar todos los cables:
Software de control.
Para el control del vehículo tenía dos opciones, hacer una app programándola desde cero o buscar una ya hecha. Opté por lo segundo que es más rápido.
Elegí la aplicación Arduino Car solo por vistosa y dado que casi todas funcionan igual, eso si, tiene mucha publicidad aviso.
Esta aplicación simula un gamepad donde tenemos un pad de dirección, un par de botones para cosas varias, y dos botones teóricamente para luces. Además nos permite controlar dos servos.
Para cada dirección o botón el programa envía un comando que se compone de una letra y en el caso de los servos también un valor.
Por ejemplo, si apretamos el pad hacía delante el programa envía el carácter 'F' y si dejamos de apretarlo envía 'S'. En el caso de los servos envía el carácter 'J' seguido del valor del slider, en este caso debemos separar el comando del valor.
Aquí dejo un pequeño programa de pruebas:
/* * COCHE BLUETOOTH */ #include <SoftwareSerial.h> #include <AFMotor.h> String cmd; int speed = 0; const uint8_t rxPin = A1; const uint8_t txPin = A0; SoftwareSerial bport(rxPin, txPin); AF_DCMotor motorA(1); AF_DCMotor motorB(2); AF_DCMotor motorC(3); AF_DCMotor motorD(4); // Mueve el motor hacÃa delante. void moveForward() { motorA.run(FORWARD); motorB.run(FORWARD); motorC.run(FORWARD); motorD.run(FORWARD); } // Mueve el motor hacÃa detrás. void moveBackward() { motorA.run(BACKWARD); motorB.run(BACKWARD); motorC.run(BACKWARD); motorD.run(BACKWARD); } // Giro a la izquierda. void rotateLeft() { motorA.run(FORWARD); motorB.run(BACKWARD); motorC.run(BACKWARD); motorD.run(FORWARD); } // Giro a la derecha. void rotateRight() { motorA.run(BACKWARD); motorB.run(FORWARD); motorC.run(FORWARD); motorD.run(BACKWARD); } // Libera el motor o frena. void brake() { motorA.run(RELEASE); motorB.run(RELEASE); motorC.run(RELEASE); motorD.run(RELEASE); } // Establece la velocidad del motor. void setMotorsSpeed(int value) { if ( value>=0 && value<=255 ) { motorA.setSpeed(value); motorB.setSpeed(value); motorC.setSpeed(value); motorD.setSpeed(value); } } void setup() { bport.begin(9600); Serial.begin(9600); pinMode(13, OUTPUT); // Inicialmente todo parado. motorA.run(RELEASE); motorA.setSpeed(speed); motorB.run(RELEASE); motorB.setSpeed(speed); motorC.run(RELEASE); motorC.setSpeed(speed); motorD.run(RELEASE); motorD.setSpeed(speed); } void loop() { if ( bport.available() ) { // Leemos el comando hasta obtener el cambio de línea (LF-0x0A). cmd = bport.readStringUntil(0x0a); // El primer caracter indica el comando. switch ( cmd[0] ) { case 'F': moveForward(); break; case 'B': moveBackward(); break; case 'L': rotateLeft(); break; case 'R': rotateRight(); break; case 'S': brake(); break; case 'J': // Removemos el primer carácter y lo que queda es el valor // recibido que tenemos que convertir a entero. cmd.remove(0,1); int value = cmd.toInt(); // El valor recibido va de 0 a 180 lo "mapeamos" de 0 a 255 speed = map(value,0,180,0,255); // Establecemos la velocidad. setMotorsSpeed(speed); break; default: break; } } }
Y con esto ya podemos jugar un buen rato con el coche...
Referencias
Interfacing HC05 Bluetooth Module with Arduino