Tankduino – tu primer tanque controlado desde tu smartphone
TANKDUINO
1. Introducción
en un tanque a control remoto mediante una conexión bluetooth.
piezas del tanque están diseñadas e impresas en una impresora 3D, salvo el
cañón, que es una tubería de plástico adaptada en tamaño, y la plataforma
superior que es una madera, para poder atornillar bien los drivers y
controladores de Arduino.
mostramos el tanque en funcionamiento:
2.
Autoría
realizado por los integrantes del grupo 3 de la asignatura Sistemas Empotrados
y Tiempo Real del año 2018/2019 en el Campus de Vicálvaro de la URJC:
- Javier
Rogina Gallego. - Guillermo
Castro Martínez.
3. Componentes
no se nos ha entregado ningún pack de Arduino, por lo que hemos tenido que
comprar todas las piezas. La inversión se ha realizado de la siguiente manera:
- 2 x ELEGOO Conjunto
Mas Completo y Avanzado de Iniciación a Arduino (55€/u). Este pack incluye la
placa de Arduino Mega 2560 y varios componentes que se suelen usar con mucha
frecuencia.
- 2x Motor Stepper con
controlador (incluido en el pack Elengoo[1 en cada pack])
- Placa de Arduino Mega 2560 (incluido
en el pack Elengoo)
- 4 x Motores 5-12V con estructura
de engranaje (15,99€)
- Driver L298 para motores DC (10€).
- Module BT HC05 (13€).
- 20x Pilas 9 Voltios. (2€/u).
- Bobina PLA 1Kg (25€)
- 64x Piezas de oruga (Diseño 3D).
- 4x Engranajes (Diseño 3D)
- 6x Conectores cuadrados (Diseño
3D).
- 2x Frontal (Diseño 3D).
- 4x Guardabarros. (Diseño 3D).
- 4x CubreRuedas. (Diseño 3D).
- 2 x miniProtoplaca (incluido en el pack
Elengoo).
- Cables (incluido en el pack
Elengoo).
- Tubería de plástico 1cm de sección
(0,5€).
- Madera, tornillos, y pegamento
(~12€).
4. Montaje
para el montaje fue la parte inferior del tanque. Necesitábamos imprimir las
piezas en la impresora 3D, lo que nos ha llevado alrededor de 9 días netos de
Impresión:
- 64x Piezas de oruga (1
hora por pieza). - 4x Engranajes (3 horas
por pieza). - 6X Conectores
cuadrados (10 horas por pieza). - 2x Frontal (20 horas
por pieza). - 4x Guardabarros. (5h por pieza).
- 4x CubreRuedas. (5h por pieza).
https://mega.nz/#F!TEMzQAzK!UG1YQw-sWRlo1OBW4s0N8Q
motores DC montados en Paralelo 2 a 2, que provocan el movimiento de los
engranajes de las orugas. Los Leds están todos montados en paralelo para
encenderlos al mismo tiempo. A continuación, facilitamos unos bocetos del
diseño final del tanque:
electrónicos están montados según se muestra en la siguiente imagen:
Aquí ofrecemos unas imágenes del tanque real para que se
aprecie cómo se ha montado:
5.
Código
explicar cómo configurar el Bluetooth HC-05, puesto que es necesario para tener
la conectividad con el smartphone.
para configurarlo:
Código que debemos
usar:
#include <SoftwareSerial.h>
SoftwareSerial mySerial (12, 13); // RX, TX
void setup() {
Serial.begin(9600);
mySerial.begin(38400);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
serial.print(«Configuración»);
}
void loop() {
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
} |
Antes de conectar el cable al pin de 5V, tras haber cargado el código en Arduino, debemos mantener pulsado el botón del dispositivo para entrar en AT (Modo configuración). Cuando el led del dispositivo parpadee levemente, es que hemos entrado.
Abrimos el Serial (ponemos a “Ambos NL & CR” y 9600
Baudios). Después ejecutamos los comandos en el siguiente Orden para ponerlo en
modo esclavo:
- AT+ORGL para hacer un
reset de fábrica, por si tuviera ya una configuración puesta. - AT+NAME? Para
comprobar el nombre del dispositivo. - AT+ROLE? Para ver si
es Esclavo o Maestro. (0=Esclave, 1=Maestro) - AT+PSWD? Para comprobar qué PIN tiene.
- AT+UART? para
comprobar la velocidad a la que se conectarán los BT (debe ser 9600).
alguno de esos parámetros debemos asignarle un nuevo valor. Ejemplo con
AT+NAME:
aparecerá al buscarlo con nuestro smartphone.
conectar a la placa con todos los demás componentes, a la que hemos cargado el
siguiente código:
//@Autor Javier Rogina & Guillermo Castro
// Pines del Motor Driver.
int ena = 48;
int enb = 53;
int in1 = 49; //Primer Pin para manejar motor A.
int in2 = 50; //Segundo Pin para manejar motor A.
int in3 = 51; //Primer Pin para manejar motor B.
int in4 = 52; //Segundo Pin para manejar motor B.
//Pines del Stepper de la Torreta
int s1 = 9;
int s2 = 10;
int s3 = 11;
int s4 = 12;
//Pines del Stepper del Cañón
int s5 = 5;
int s6 = 6;
int s7 = 7;
int s8 = 8;
void setup() {
//Declaramos todos los pines que vamos a usar.
pinMode(13, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);
pinMode(s4, OUTPUT);
pinMode(s5, OUTPUT);
pinMode(s6, OUTPUT);
pinMode(s7, OUTPUT);
pinMode(s8, OUTPUT);
pinMode(ena, OUTPUT);
pinMode(enb, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(9600); //iniciamos el serial que se comunicará con el dispositivo BT.
}
void cannon_Arriba() {
//Mueve el Stepper del caón hacia arriba(si el tanque está en posición frontal) un paso.
digitalWrite(s5, HIGH);
digitalWrite(s6, LOW);
digitalWrite(s7, LOW);
digitalWrite(s8, LOW);
delay(2); //Es obligatorio poner un delay de almenos 2, ya que sino no hace los pasos correctamente.
digitalWrite(s5, HIGH);
digitalWrite(s6, HIGH);
digitalWrite(s7, LOW);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, HIGH);
digitalWrite(s7, LOW);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, HIGH);
digitalWrite(s7, HIGH);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, LOW);
digitalWrite(s7, HIGH);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, LOW);
digitalWrite(s7, HIGH);
digitalWrite(s8, HIGH);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, LOW);
digitalWrite(s7, LOW);
digitalWrite(s8, HIGH);
delay(2);
digitalWrite(s5, HIGH);
digitalWrite(s6, LOW);
digitalWrite(s7, LOW);
digitalWrite(s8, HIGH);
}
void cannon_Abajo() {
//Baja el cañón.
digitalWrite(s5, LOW);
digitalWrite(s6, LOW);
digitalWrite(s7, LOW);
digitalWrite(s8, HIGH);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, LOW);
digitalWrite(s7, HIGH);
digitalWrite(s8, HIGH);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, LOW);
digitalWrite(s7, HIGH);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, HIGH);
digitalWrite(s7, HIGH);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, LOW);
digitalWrite(s6, HIGH);
digitalWrite(s7, LOW);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, HIGH);
digitalWrite(s6, HIGH);
digitalWrite(s7, LOW);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, HIGH);
digitalWrite(s6, LOW);
digitalWrite(s7, LOW);
digitalWrite(s8, LOW);
delay(2);
digitalWrite(s5, HIGH);
digitalWrite(s6, LOW);
digitalWrite(s7, LOW);
digitalWrite(s8, HIGH);
delay(2);
}
void torreta_Derecha() {
//Mueve la torreta en sentido agujas del reloj un paso.
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, HIGH);
digitalWrite(s2, HIGH);
digitalWrite(s3, LOW);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, HIGH);
digitalWrite(s3, LOW);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, HIGH);
digitalWrite(s3, HIGH);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, HIGH);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, HIGH);
digitalWrite(s4, HIGH);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(s4, HIGH);
delay(2);
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(s4, HIGH);
}
void torreta_Izquierda() {
//Mueve la torreta en sentido antihorario un paso.
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(s4, HIGH);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, HIGH);
digitalWrite(s4, HIGH);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, HIGH);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, HIGH);
digitalWrite(s3, HIGH);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, LOW);
digitalWrite(s2, HIGH);
digitalWrite(s3, LOW);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, HIGH);
digitalWrite(s2, HIGH);
digitalWrite(s3, LOW);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(s4, LOW);
delay(2);
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
digitalWrite(s4, HIGH);
delay(2);
}
void motor_alante(){
digitalWrite(ena, 255); //Potencia del motor A (0-255).
digitalWrite(enb, 255); //Potencia del motor B (0-255).
digitalWrite(in1, HIGH); //Motor A sentido horario.
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH); // Motor B sentido horario.
digitalWrite(in4, LOW);
}
void motor_atras(){
digitalWrite(ena, 255); //Potencia del motor A (0-255).
digitalWrite(enb, 255); //Potencia del motor B (0-255).
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH); // Motor A sentido antihorario.
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH); // Motor B sentido antihorario.
}
void motor_derecha(){
//Se apagan los motores derechos, de manera que la oruga izquierda hace el movimiento y simula el giro.
digitalWrite(ena, 255); //Potencia del motor A (0-255).
digitalWrite(enb, 0); //Motor B apagado.
digitalWrite(in1, HIGH); //Motor A sentido horario.
digitalWrite(in2, LOW);
digitalWrite(in3, LOW); //Motor B apagado.
digitalWrite(in4, LOW); //Motor B apagado.
}
void motor_izquierda(){
//Se apagan los motores izquierdos para simular el giro a la derecha.
digitalWrite(ena, 0); //Motor B apagado.
digitalWrite(enb, 255); //Potencia del motor B (0-255).
digitalWrite(in1, LOW); //Motor A apagado.
digitalWrite(in2, LOW); //Motor A apagado.
digitalWrite(in3, HIGH); //Potencia del motor A (0-255).
digitalWrite(in4, LOW);
}
void disparar(){
//Enciende el Led 2 segundos y luego lo apaga (simula el disparo).
digitalWrite(13, 255);
delay(2000);
digitalWrite(13, 0);
}
void pausa(){
//Apaga todos los motores para que el tanque permanezca en el sitio.
digitalWrite(ena, 0);
digitalWrite(enb, 0);
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}
void loop(){
int varBT = Serial.read(); //Leemos lo que manda el smartphone.
int vari = varBT – 48; //Al ser un Char ASCII, restamos 48 para simular números del 1 al 9.
switch (varBT) { //Dependiendo de lo que hayamos recibido:
case ‘0’:
motor_derecha(); //Giro a la derecha
break;
case ‘1’:
motor_izquierda(); //Giro a la izquierda
break;
case ‘2’:
motor_atras(); //Marcha atrás
break;
case ‘3’:
motor_alante(); //Avanzar
break;
case ‘4’:
cannon_Arriba(); //Sube el cañón.
break;
case ‘5’:
cannon_Abajo(); //Baja el cañon.
break;
case ‘6’:
torreta_Derecha(); //Gira la torreta sentido horario.
break;
case ‘7’:
torreta_Izquierda(); //Gira la torreta sentido antihorario.
break;
case ‘8’:
disparar(); //Enciende el Led del cañon.
break;
case ‘9’:
pausa(); //Para los motores.
break;
default:
//Nada. Si recibimos datos erróneos (el -1 se recibe si se pierde la conexión hasta que se conecta de nuevo)
break;
}
} |
tanque, hemos usado la aplicación Arduino BlueTooth Control. Para conectarlo,
debemos emparejarnos con el dispositivo HC-05 que hemos usado,
Controller mode.
- Flecha Arriba: 3
- Flecha Abajo: 2
- Fecha derecha: 0
- Flecha izquierda: 1
- Triángulo: 4
- Cuadrado: 7
- Círculo: 5
- Equis: 6
- Select: 8
- Start: 9
los distintos “Case” del código del tanque.
6.
Problemas encontrados
6.1 Disparo del tanque
disparase pelotas de goma, o de caucho. Probamos usando un solenoide de 32V,
pero no tenía la fuerza suficiente como percusor para disparar. Este problema
intentamos reconducirlo con dos ruedas que girasen y aumentaran la velocidad
instantánea de la pelota al entrar en contacto con ellas (Como un lanzapelotas
de Golf o Tenis), pero la potencia que se necesitaba era demasiado alta, y las
pilas caían como moscas. Entonces se nos vino a la cabeza usar un sistema de
ballesta o catapulta, pero ocupaba demasiado espacio en la plataforma del
tanque, y los servos que usábamos (sg90) no aguantaban la tensión de la cuerda/goma
elástica.
simular el disparo con luz.
6.2 Espacio
nos dimos cuenta de que no tenía espacio suficiente para albergar los 4
motores, la protoplaca y la placa Arduino. Para solucionarlo, pusimos un
separador más (inicialmente 3), y tuvimos que sumarle 2 piezas más a la oruga.
6.3 Parte
Superior
La parte superior del tanque que habíamos impreso no encajaba. Al haber gastado
tanto PLA (1Kg aproximadamente), y por falta de tiempo y recursos, decidimos
suplirlo con una madera en la que encajamos todos los controladores en la parte
inferior.
6.4 Potencia
Motores
la primera prueba con todo el peso, vimos que una pila de 9V no era suficiente
para los motores. Por eso mismo usamos 2 pilas de 9V en serie (18V) lo que aumentó el rendimiento
considerablemente.
6.5 Mando
Bluetooth
distancia con 2 JoySticks y un módulo BT para manejar el tanque. El problema
que encontramos fue que la sincronización de ambos módulos BT no se realizaba
correctamente, cada pocos segundos se perdía la conexión. Tras consultar en
Foros de Arduino, vimos que parecía un problema de fábrica de algunas unidades
del módulo HC-05 que impedía conectarse Master-Slave con otro HC-05, y que era
necesario un HC-06. Por eso mismo, decidimos usar la aplicación Arduino
Bluetooth Control, que solucionó el problema en su totalidad.
6.6 Servo
VS Stepper
servos. Uno manejaba el eje X y el otro el Eje y. Sin embargo, en cuanto le
pusimos la tubería, el Servo ya no podía levantar el Peso, y el giro de la
torreta era irregular. Esto lo solucionamos con 2 motores Steppers, que giraban
360º y tienen mayor fuerza si se programan adecuadamente.
6.7 Consumo
de Pilas
para pruebas, alrededor de 20. Este problema pensamos en solucionarlo con un
PowerBank de 20mil mAh para conectarlo a la placa, pero el peso era demasiado y
hacía oscilar al tanque. Como el consumo de pila es, en su mayoría, por el
controlador de los motores, decidimos dejarlo como estaba.
7.
Mejoras que se podrían hacer.
proyecto es hacer el movimiento del tanque progresivo. Es decir, que se pueda
elegir la velocidad de los motores DC. Esto se haría con los pines ENA y ENB del driver, indicándoles
un valor de 0 a 255.
probarlo, que se puede hacer con aire comprimido, y se le puede regular la
potencia.
podría incorporar cierta adherencia con puntos de silicona colocados en cada
pieza (pero no en las juntas), o usando FilaFlex en vez de PLA. Nosotros no
pudimos hacerlo por falta de tiempo y dinero.
8.
Conclusión.
muy largo para hacer en estos 2-3 meses. Si hubiésemos sabido el tiempo de
impresión de las piezas lo hubiéramos priorizado, aunque era difícil saber qué
imprimir sin tener claro qué componentes íbamos a usar.
el espacio y los pines de la placa de Arduino, y nos ha ayudado a ver lo fácil
que es hacer cualquier cosa con este tipo de sistemas si le pones empeño y
tiempo, y la versatilidad con la que se solucionan los problemas gracias al
Open Source.