Entrega rápida
Condiciones de descuento para empresas
Hasta un 10% de descuento para alumnos, estudiantes y centros de enseñanza
Envío a toda Europa por €4.90
Cerrar filtro
Filtrar por:

Construye un coche teledirigido con Arduino: Vehículo autónomo - Parte 2

Comprender la movilidad del futuro con los coches robot, parte 2

Bienvenido a la segunda entrega de nuestra nueva serie de blogs sobre coches robot. En la primera parte, conocimos los fundamentos del vehículo básico. Esta vez queremos hablar de las posibilidades del control remoto, desarrollar un sistema de códigos con el que podamos determinar los niveles de velocidad del coche robot y, por último, realizar un control remoto sencillo con un mando a distancia por infrarrojos.

¿Por qué necesito pasos de velocidad para un coche teledirigido para microcontroladores Arduino?

1. Para controlar las velocidades del motor desde otro dispositivo, existe básicamente la posibilidad de determinar y transmitir continuamente valores con un potenciómetro (poti), o de aumentar o disminuir el valor del paso de velocidad pulsando un botón. Las siguientes imágenes muestran algunos ejemplos seleccionados, en la primera imagen controles de joystick:

 Construye un coche teledirigido para Arduino - Joysticks

 

En la segunda imagen vemos mandos a distancia por infrarrojos, una aplicación para smartphone con receptor Bluetooth, y el escudo del teclado LCD1602, que puede funcionar con un transceptor de 433 MHz, entre otras cosas:

 Construye un coche teledirigido para Arduino - Unidad de control

 

Para conseguir un esquema uniforme, tiene sentido utilizar la función map() para reducir los valores analógicos de la olla a valores que puedan transmitirse por radio. El convertidor analógico-digital proporciona números de 10 bits, es decir, valores entre 0 y 1023. La posición media de los mini joysticks es aproximadamente 511. Dividiendo el valor por 100, un joystick puede determinar dos valores (dirección x e y) que se encuentran entre 0 y 10 o, si se utiliza la función map()-, entre 1 y 9. Esto es suficiente para introducir la velocidad y para tomar las curvas. Independientemente de si determinamos valores 11 ó 9, la parada significa el valor 5 en la dirección y y para la conducción en línea recta también el valor 5.

Mirando el mando con los dos joysticks (parte del kit del brazo robótico Mini 4DOF con joysticks y servomotor), dada la variedad de sistemas diferentes, me decido por un código entre 1111 y 9999 que sea fácil de transmitir. El primer dígito se puede utilizar para la dirección y del joystick izquierdo, el segundo dígito para la dirección x del joystick izquierdo, el tercer y cuarto dígitos para un segundo joystick opcional o determinadas teclas. En el primer ejemplo con el mando a distancia por infrarrojos, sólo necesitamos los dos primeros dígitos del código de cuatro cifras.

El control de velocidad del Coche teledirigido para Arduino

El control de velocidad de los motores se realiza mediante modulación por ancho de pulsos (PWM). El valor del llamado ciclo de trabajo es un número de 8 bits, es decir, un valor entre 0 y 255 (=2 a la potencia de 8 -1). Si aplicas tensiones de entre 0 y 6 V al motor con una fuente de alimentación ajustable, observarás que hasta aproximadamente 1,5 V no se nota nada. Después, el motor empieza a zumbar, pero no se mueve. Si mides la corriente al mismo tiempo, notarás un valor relativamente alto. La energía se convierte en calor y zumbidos, nada bueno. A partir de 2,4 - 3 voltios, el motor empieza a girar, el amperaje baja un poco cuando el motor está descargado. Después, la velocidad aumenta en función de la tensión aplicada. Al regular la tensión a la baja, el motor girará por debajo de 2 voltios, pero si se detiene, por ejemplo debido a un aumento de la resistencia a la fricción o a un obstáculo, no volverá a arrancar. Conclusión: deben evitarse los valores por debajo de 2,4 voltios aproximadamente, la entrada debe ajustarse igual a 0 (cero) para evitar un desgaste y un consumo de energía innecesarios. Excepto para la parada (código=5) necesitamos Duty Cycle entre aprox. 40% y 100% con una tensión de alimentación de 6V para los motores.

La fuente de alimentación del Coche RC para Arduino

Ya hemos hablado de varias posibilidades para la fuente de alimentación en la primera parte. Cuatro pilas AA de 1,5 V cada una dan 6 V, la tensión máxima de los pequeños motores amarillos. Cuatro pilas AA de 1,2 V cada una no son suficientes para la fuente de alimentación. Entonces necesitas un portapilas para 6 pilas y eso da 7,2 voltios. Y dos pilas de iones de litio (tensión nominal de 3,7 V) dan más de 8 voltios cuando están totalmente cargadas. Así que tiene sentido establecer un factor en el programa que limite la tensión del nivel de accionamiento más alto a 6 V.

Control del coche teledirigido por Arduino

Si las instrucciones de conducción se dan con botones, que pueden estar incluso en una aplicación de smartphone, se aumenta o disminuye el valor adecuado para el valor de salida 55xx (parada) sin superar el máximo.

Leer correctamente el código

La asignación del primer dígito del código a los valores requeridos de las etapas de desplazamiento se realiza mediante el índice de una lista con los respectivos valores numéricos.

Conclusión: con un código de cuatro dígitos, podemos controlar la velocidad y el paso por curva con los dos primeros dígitos, los dos dígitos posteriores se utilizan para otras funciones (no necesarias al principio). Así, por ejemplo, el código95xx para la mayor velocidad en línea recta, 55xx para la parada, 77xx para el avance hacia la derecha. 

y ↓ 0  x→

1

2

3

4

5

6

7

8

9

9

 

 

 

 

 

 

8

 

 

 

 

 

 

7

 

 

 

 

 

 

6

 

 

 

 

 

 

5

 

 

 

0

 

 

 

4

 

 

 

 

3

 

 

 

 

2

 

 

 

 

1

 

 

 

 

 

Ahora queremos construir nuestro primer Coche Robot Inteligente con el kit, un microcontrolador ATmega328 (diseño UNO R3), un MotorShield V2 y un transmisor y receptor de infrarrojos.

El Motor Shield V2 puede controlar hasta cuatro motores, utilizando el llamado bus I2C con las conexiones SDA (=Datos serie) en la entrada analógica A4 y SCL (=Reloj serie) en A5 para la conexión de las líneas de control. Adafruit también ha desarrollado y proporcionado una biblioteca de programas adecuada para ello. Atención: Las librerías para Motor Shields V1 y V2 no son compatibles.

 Construir coche RC para Arduino - Conexión al controlador del motor

Imagen Motor Shield V2 con modificación:
Conectores hembra soldados (conectores hembra) para conectar equipos adicionales

Independientemente de la Motor Shield que quieras utilizar -V1 o V2-,  tiene sentido soldar conectores hembra adicionales para ambas Motor Shields, con el fin de conectar posteriormente transmisores/receptores o sensores Bluetooth o de 433 MHz. Más sobre esto en las siguientes entradas del blog. El receptor de infrarrojos sólo necesita alimentación de las patillas 3 y 4, así como de la patilla 2 para el receptor de infrarrojos. El soldador puede permanecer frío.

Para el control utilizaremos primero el pequeño mando a distancia por infrarrojos de Funduino y un receptor IR. Aunque el sensor IR "desnudo" es suficiente, recomiendo la pequeña placa breakout, ya que aquí un LED parpadea cuando se reciben señales IR; una herramienta valiosa a la hora de buscar un fallo.

El boceto se compone de dos piezas probadas: El sketch de ejemplo de Armin Joachimsmeyer, que añadió a su estupenda biblioteca de programas IRremote, y un sketch de Coche Robot del autor basado en la biblioteca de programas de Adafruit.

El código del programa del Coche RC para Arduino

/* Código de ejemplo para Coche Robot con Motor Shield V2 y receptor IR, a partir de 20220515
* basado en la biblioteca Adafruit Motor shield V2, copyright Adafruit Industries LLC, 2009
* y SimpleReceiver.cpp, parte de Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote
* Licencia MIT Copyright (c) 2020-2022 Armin Joachimsmeyer
* modificado para Funduino
* Motor Shield V2 utiliza I2C con SDA=A4 y SCL=A5
* El receptor IR utiliza el pin 2
************************************************************************************
* Por la presente se concede permiso, de forma gratuita, a cualquier persona que obtenga una copia
* de este software y de los archivos de documentación asociados (el "Software"), a comerciar
* con el Software sin restricción alguna, incluyendo sin limitación los derechos
* de usar, copiar, modificar, fusionar, publicar, distribuir, sublicenciar y/o vender
* sublicenciar y/o vender copias del Software, y a permitir que las personas a las que se proporcione el Software
* a hacerlo, con sujeción a las siguientes condiciones:
*
* El anterior aviso de copyright y este aviso de permiso se incluirán en todas
* copias o partes sustanciales del Software.
*
* EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA,
* INCLUIDAS, PERO SIN LIMITARSE A ELLAS, LAS GARANTÍAS DE COMERCIABILIDAD, IDONEIDAD PARA UN FIN DETERMINADO Y NO INFRACCIÓN
* PARA UN FIN DETERMINADO Y DE NO INFRACCIÓN. EN NINGÚN CASO LOS AUTORES O LOS TITULARES
* DERECHOS DE AUTOR SERÁN RESPONSABLES DE NINGUNA RECLAMACIÓN, DAÑO U OTRA RESPONSABILIDAD, YA SEA
* CONTRACTUAL, EXTRACONTRACTUAL O DE OTRO TIPO, DERIVADA O RELACIONADA CON EL SOFTWARE
* O EL USO U OTRAS OPERACIONES CON EL SOFTWARE.
*************************************************************************************/
#include <Adafruit_MotorShield.h>
// Crea el objeto escudo motor con la dirección I2C por defecto 0x60
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Selecciona qué 'puerto' M1, M2, M3 o M4. 
Adafruit_DCMotor *motor1 = AFMS.getMotor(2);
Adafruit_DCMotor *motor2 = AFMS.getMotor(3);
// define el protocolo para el control remoto, para más información consulta el código de ejemplo SimpleReceiver.cpp
#define DECODE_NEC // Incluye Apple y Onkyo, también para el minúsculo control remoto Funduino
//#define INFO // Para ver información valiosa del decodificador universal para los protocolos de ancho de pulso o distancia de pulso
#define PIN_RECIBIDO_IR 2 //  en lugar de #include "PinDefinitionsAndMore.h"
#include <Arduino.h>
#include <IRremote.hpp>
// Señal del receptor IR conectada a Pin2, VCC a Pin3, GND a Pin4
int IR_GND = 4
int IR_VCC = 3;
int x = 0
int y = 0
int izquierda = 0
int derecha = 0
int código = 5555;
int velocidadL = 0
float factor = 1.8; // Corrección para speedLevel 255/100 * 6V/VBatt
void setup() {
Serial.begin(9600);
Serial.println("¡Prueba motor!");
Serial.println("¡Escudo motor v2 - Prueba motor CC!");
si (!AFMS.begin()) {         // create with the default frequency 1.6KHz
Serial.println("Could not find Motor Shield. Check wiring.");
while (1);
}
Serial.println("Escudo motor encontrado.");
// Sólo para saber qué programa se está ejecutando en mi Arduino
Serial.println(F("START " __FILE__ " de " __DATE__ "\r\nUsando la versión de la biblioteca " VERSIÓN_IRREMOTA));
// Inicia el receptor
IrReceiver.begin(IR_RECEIVE_PIN); //, ENABLE_LED_FEEDBACK);
Serial.print(F("Listo para recibir señales IR de los protocolos: "));
printActiveIRProtocols(&Serial);
Serial.print(F("en el pin "));
Serial.println(IR_RECEPCION_PIN);
// inicializa los pines digitales como salida para la fuente de alimentación
pinMode(IR_GND,SALIDA);
pinMode(IR_VCC,SALIDA);
digitalWrite(IR_GND,BAJO);
digitalWrite(IR_VCC,HIGH);
} // fin de la configuración
void bucle() {
si (IrReceiver.decode()) {
// Imprime un breve resumen de los datos recibidos
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
// We have an unknown protocol here, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
Serial.println();
/*
* ¡¡¡!!!¡¡¡Importante!!! Activa la recepción del siguiente valor
* ya que la recepción se ha detenido tras el final del actual paquete de datos recibido.
*/
delay(100); // Rebote, sin reintento rápido 
IrReceiver.resume(); // Activar la recepción del siguiente  valor
/*
* Por último, comprueba los datos recibidos y realiza acciones según el comando recibido
*/
if (IrReceiver.decodedIRData.command == 0x46)  {
if (code<9000)   code = code + 1000;
Serial.print("Code = ");
Serial.println(code);
}
else if (IrReceiver.decodedIRData.command == 0x15) {
if (code>2000)   code = code - 1000;
Serial.print("Code = ");
Serial.println(code);
}
else if (IrReceiver.decodedIRData.command == 0x43)  {
if ((code-1000*int(code/1000))<900)  code = code + 100;
Serial.print("Code = ");
Serial.println(code);
}
si no (IrReceiver.decodedIRData.command == 0x44)  {
if (code-1000*int(code/1000) > 200)   code = code - 100;
Serial.print("Code = ");
Serial.println(code);
}
else if (IrReceiver.decodedIRData.command == 0x40)  {
code = 5555;
Serial.print("Code = ");
Serial.println(code);
}
si no {
Serial.print("invalid code");
}
motor();
}
} // fin de bucle
void motor(){
int velocidadNivel[9]={-100,-80,-60,-40,0,40,60,80,100};
y = int(código / 1000);
x = int((código - 1000*y) / 100);
velocidadL = velocidadNivel[y-1];
Serial.print("código = ");
Serial.print(código);
Serial.print(" y= ");
Serial.print(y);
Serial.print(" x= ");
Serial.print(x);
Serial.print(" velocidadL= ");
Serial.println(velocidadL);
//Corrección de los pasos de velocidad para las curvas
si (x==1){
right = speedL+16;
left = speedL-16;
}
si (x==2){
right = speedL+13;
left = speedL-13;
}
si (x==3) {
right = speedL+10;
left = speedL-10;
}
si no (x==4) {
right = speedL+7;
left = speedL-7;
}
si no (x==6) {
right = speedL -7;
left = speedL+7;
}
si no (x==7) {
right = speedL-10;
left = speedL+10;
}
si (x==8) {
right = speedL-13;
left = speedL+13;
}
si (x==9) {
right = speedL-16;
left = speedL+16;
}
si no {
right = speedL;
left = speedL;
}
//Introducción de los pasos de conducción para "izquierda" y "derecha
Serial.print("izquierda= ");
Serial.print(izquierda);
Serial.print(" derecha = ");
Serial.println(derecha);
si (izquierda < 40 & izquierda > -40) {
motor1->run(RELEASE);
}
si (derecha < 40 y derecha > -40) {
motor2->run(RELEASE);
}
si (izquierda>=40) {
if (left>100) left=100;
motor1->run(FORWARD);
motor1->setSpeed(left * factor);
}
si (derecha>=40) {
if (right>100) right=100;
motor2->run(FORWARD);
motor2->setSpeed(right * factor);
}
si (izquierda<= -40) {
if (left<-100) left=-100;
motor1->run(BACKWARD);
motor1->setSpeed(-left * factor);
}
si (derecha<= -40) {
if (right<-100) right=-100;
motor2->run(BACKWARD);
motor2->setSpeed(-right * factor);
}
} // fin motor

Explicaciones del código del programa para el Coche teledirigido

Tras incluir las librerías Motor Shield V2 e IRremote, se instancian dos motores con el número en el bloque de terminales del controlador y se declaran algunas variables globales (tipo de datos) y se inicializan (valor inicial).

En la función setup () se inicializan la interfaz serie y el receptor IR y se configuran los pines para la alimentación del receptor IR como salidas con el estado HIGH o LOW.

En la función bucle (), primero se recibe la señal del mando a distancia IR, después se cambia el código para el control del motor en función de la tecla pulsada. Las teclas de cursor arriba y abajo cambian el primer dígito, izquierda y derecha el segundo dígito del código en el rango de valores de 1 a 9. La tecla X lleva a la parada con el código 5555. El tercer y cuarto dígito del código no son actualmente significativos. Al final, se llama a la función autodefinida motor( ) sin argumentos, ya que habíamos definido las variables globalmente, es decir, válidas en todas las funciones.

En la función autodefinida motor( ), que también utilizaremos en otras configuraciones con otros mandos a distancia, los niveles de velocidad del motor izquierdo y derecho se determinan a partir del código. El valor porcentual del nivel de velocidad se convierte finalmente en el valor PWM para setSpeed utilizando el factor definido al principio.

 Construir un coche teledirigido con Arduino - Primer experimento 1

El Coche Robot ya está listo para su uso. Funciona bien siempre que puedas mantener la conexión óptica entre el mando a distancia y el receptor de infrarrojos. Sin embargo, al conducir por carretera, he experimentado que la luz solar intensa dificulta la recepción. Por eso voy a cambiar al mando a distancia por radio. Hasta pronto.

Introduce la cadena en el campo de texto de abajo.

Los campos marcados con * son obligatorios.

Artículos coincidentes
- 36%
Chasis para Arduino (robot de un eje más rodillo) Chasis para Arduino (robot de un eje más rodillo)
Contenido 1 Stück
5,72 € * 8,90 € *
Nº de artículo F23107456
Añade
- 4%
Mando a distancia por infrarrojos Funduino Mando a distancia por infrarrojos Funduino
Contenido 1 Stück
1,82 € * 1,90 € *
Nº de artículo F23106774
Añade
RoboMall Motorshield V2.0 - mit I2C Schnittstelle, TB6612 MOSFET RoboMall Motorshield V2.0 - mit I2C...
Contenido 1 Stück
24,21 € *
Nº de artículo F23107315
Añade
Microcontrolador Funduino UNO R3 - Compatible con Arduino Microcontrolador Funduino UNO R3 - Compatible...
Contenido 1 Stück
18,90 € *
Nº de artículo F23107480
Añade