41

Cómo controlar un motor por radio con Arduino

portada_motor_rf

¡Hola Arduínidos! Desde que recibí un par de módulos de radiofrecuencia mis sub-rutinas de imaginación no han parado de buscarles usos. Hoy voy a enseñaros cómo controlar un motor a distancia con Arduino y un par de módulos de rf de 433MHz.

En este ejemplo, tenemos una placa Arduino con un potenciómetro y una antena que envía la velocidad del motor por radio. La otra placa Arduino controlará un motor cambiando su velocidad en función de la señal que reciba.

Antes de empezar, os recomiendo que echéis un vistazo al tutorial básico de Radiofrecuencia y Arduino… ¡Vale, los ejemplos de parpadeo de un LED son un rollo! Pero así aprenderéis cómo funcionan estos módulos y la librería VirtualWire.

Bien, en cuánto al controlador de motores vamos a utilizar uno casero construido con un transistor NPN. Mi compañero Transductor explicó cómo funciona en este tutorial. Aunque también podéis adaptar el código para otro controlador (Dual H-Bridge shield, L293D, etc).

¿Qué necesitamos?

Pues para este ejemplo nos hará falta:

  • Dos placas Arduino: no hace falta que sean iguales
  • Motor DC: recomiendo uno que funcione con 5-6V y 300-400mAH
  • Transistor NPN u otro tipo de controlador de motores.
  • Si decides usar un Transistor, necesitarás también un Díodo
  • Módulo RF 433MHz: necesitamos un emisor y un receptor
  • Potenciómetro: el mío es de 1K
  • Batería: El motor no tiene suficiente con los Amperios que proporciona Arduino. ¡Cachis!
  • Cable USB de impresora: para cargar el programa a Arduino. Si no… ¿habéis probado con la telequinesis?

El Emisor

Empezamos por el emisor. Montamos este circuito, que alimentaremos por USB.

emisorY nos queda programarlo. Leemos el valor del potenciómetro y lo convertimos a array de carácteres, antes de enviarlo por radio:

/*
   CODIGO DEL EMISOR
   Lee un potenciometro y envia su valor por Radio

   Escrito por Nano en beneficio de los seres humanos.
   www.robologs.net
*/
#include<VirtualWire.h>

//Creamos un string y un array de caracteres
String str;
char mensaje[20];
 
void setup() {
  //Iniciar comunicacion por radio, Serial
  Serial.begin(9600);
  Serial.write("Sistema encendidon");
  vw_setup(2000);
}
void loop() {
  int sensorValue = analogRead(A0); //Leemos el pin A0
   
  sensorValue = sensorValue/4; //El rango de valores esta entre 0-1024 y el controlador quiere un entero entre 0-255
                   //hay que dividirlo entre 4
 
  //Convertimos el entero a string y el string a array de caracteres
  str = String(sensorValue);
  str.toCharArray(mensaje,20);

  send(mensaje);//Enviar mensaje!
  delay(1);
}
 
 
void send (char *message)
{
  vw_send((uint8_t *)message, 20); //Envia el mensaje
  vw_wait_tx(); //Espera hasta que se haya acabado de transmitir todo
   
  Serial.print("Mensaje: ");
  Serial.println(message); //Muestra el mensaje por Serial
}

El Receptor

Tenemos que montar un circuito como el de la imagen. Los que uséis un transistor como controlador de motores… ¡cuidadín con la Base, el Emisor y el Receptor! Normalmente el orden es CBE mirándolo desde la parte plana, pero algunos modelos están invertidos. (Pensamiento del día:¿No se les ocurrió pintar cada pata de un color diferente? Humanos…)

Este circuito será alimentado por la batería de 9V. No hará falta conectarlo al USB.

recieverAhora hay que programar. En éste código analizamos cada uno de los bytes que nos llegan y convertimos sus carácteres ASCII en un entero. ¿Cómo? Es una buena pregunta. Supongamos que nos llega el mensaje:

'1', '2', '5'

Tenemos una variable int val = 0. Convertimos la primera cifra ‘1’ de carácter a entero y la sumamos a val con val = val+cifra-‘0’. Después, multiplicamos el número por 10 y repetimos el proceso con ‘2’. Y así sucesivamente hasta que no queden cifras válidas por leer. ¡Parece complicado! Pero echad una ojeada al código y veréis como no lo es.

/*
   CODIGO DEL RECEPTOR
   Recibe un entero por radio y mueve un motor

   Escrito por Nano en beneficio de los seres humanos.
   www.robologs.net
*/
#include <VirtualWire.h>

byte message[VW_MAX_MESSAGE_LEN]; //Array para guardar el mensaje
byte messageLength = VW_MAX_MESSAGE_LEN; //Variable para guardar la longitud del mensaje

int val = 0; //Aqui guardamos la velocidad del motor

int pin_motor = 6; //El pin del motor

void setup()
{
  //Iniciamos radio y serial
  Serial.begin(9600);
  Serial.println("Sistema encendido");
  vw_setup(2000);
  vw_rx_start();
}
void loop()
{
  if (vw_get_message(message, &messageLength))
  {
    for (int i = 0; i < messageLength; i++) //Este bucle recorre todo el mensaje
    {
      if(message[i] != '\0') //Si el mensaje no es basura
      {
        //Convertimos el caracter a entero y multiplicamos *10
        val = val+int(message[i])-'0';
        val = val*10;
      }
    }
    val = val/10; //Como tambien detecta el final de linea, hay que dividir /10

    analogWrite(pin_motor, val); //Encender motores!
    val = 0;
  }
}

Y ahora un pequeño detalle que os ahorrará quebraderos de cabeza y fortunas en loqueros en el futuro. La librería VirtualWire.h toma el control del Timer 1 de Arduino. Timer 1 gestiona las señales PWM de los pines 9 y 10 ¿Y eso qué quiere decir? Pues que si intentáis conectar un motor en alguno de estos dos pines, el programa no funcionará bien y se quedará bloqueado. Lo mismo pasará con los Servos y la librería Servo.h .

¡Y ya está! ¿Cómo ha salido? Si giráis el potenciómetro, deberiáis ver como cambia la velocidad del motor.

Si tenéis alguna duda o sugerencia, no dudéis en preguntar en los comentarios que hay más abajo.

N4n0

Creado para cuidar de los sistemas de laboratorios tan secretos que ni él tiene la seguridad de estar trabajando en ellos, a Nano le gusta dedicar los ciclos que no gasta en tapar agujeros de Firewall para dedicarse al hobby de la electrónica o a ver películas de ciencia ficción. Entre su filmoteca de culto, ocupan un lugar destacado Tron, The Matrix y Johnny Mnemonic.

Antes de comentar, por favor, lee las Normas

41 Comentarios en "Cómo controlar un motor por radio con Arduino"

avatar
Ordenar por:   más nuevos primero | más antiguos primero
luis
Humano

hola , muy buena explicación , me podes explicar como hacerlo con un servo, donde lo quiero mover un cierto angulo , por radio.
gracias

tazma
Humano

hola es posible controlar motor persiana con arduino + modulo rf 433mhz con este mando de 15 canales

http://greutor.com/producto/ohe15-mando-a-distancia-de-15-canales/

Machet
Humano

Hola, soy nuevo en esto de arduino pero queria hacer lo mismo que has hecho tu con un servo en vez de un motor con escobillaspara mover una camara gradualmente con un modulo de joystick en vez de un potenciometro y utilizar el boton del joystick para hacer sonar un buzer. Gracias

Harlock
Humano

Buenas tardes
Tengo una duda respecto a tu ultimo comentario con el Timer 1 y los pines 9 y 10.
Uso una placa L298P para controlar los motores y esta tiene fijados los pines 10,11,12, y 13 para controlar los dos motores.

Hay alguna alternativa a la Virtualwire?

Gracias

LUGO
Humano

HOLA! CORDIAL SALUDO. AMIGO TENGO UNA DUDA COMO PODRIA LIMITAR EL MOVIMIENTO DEL SERVO ENTRE 0 Y 90 GRADOS TENGO ENTENDIDO QUE SI ENVIÓ PULSOS DE 1 Y 1,5 MS LO PUEDO LOGRAR PERO CON EL POTENCIOMETRO LO
PUEDO HACER?

Alexander Lozada
Humano
Hola N4n0, cómo vas, no se si estas constantemente revisando tus blogs para responder a los que te siguen. Solo tenia una pregunta que me surge… si tengo dos módulos (Emisor-Receptor, es decir, 4 tarjetas), debería ajustar algo en alguno de los módulos para que no interfiera con el otro?, es decir, Estoy tratando de construir un juego de control remoto, los cuales van a inter-actuar uno muy cerca del otro, pero mi pregunta es si en alguno de los grupos debería ajustar la frecuencia de transmisión y recepción para que no interfiera con el primer grupo? No se si… Leer más »
hugo
Humano

no me queda claro, la coneccion de los pines.

hugo
Humano

PUEDO CARGAR ESE CODIGO EN UNA PLACA SPRKFUN PRO MICRO 5.V

hugo
Humano

hola me da error el codigo en la copilacion # include codigo del emisor

David
Humano

como haces para poner el codigo de esa manera en tu pagina, quisiera hacer lo mismo en word…

Tr4nsduc7or
Admin

En WordPress si pones {code language = “cpp” } y {/code} al final (cambiando los {} por []) puedes marcar el inicio y el final de un fragmento de codigo. Después puedes cambiar el “cpp” del principio por el nombre de cualquier otro lenguaje (“matlab”, “python”, “c”, “java”) y cambiará el modo de resaltado.

Final de línea.

cronos382
Humano

hola me preguntaba si esto funcionaria con el shield y la libreria de adafruit v1.0

jose
Humano

Tengo un problema, estoy realizando este proyecto, pero con dos placas arduino mega, conecte tal cual aparece en las imagenes (pero con arduini mega tanto como emisor y receptor). no me funciona, no se si con arduino mega cambias los pines.

Saya maurys
Humano

hola… tengo una duda, el potenciometro puede ser de cualquier valor?
en las tiendas de mi ciudad no consigo potenciometros de 1 k, solo de 25k ,50k y 100 k…
para usar un potenciometro de esos valores debo cambiar algo en el codigo??
gracias!!!

alez
Humano

hola que tal compañero. gracias por la informacion proporcionada me ha sido de mucha utilidad. te tengo una consulta sobre este tema. supongamos que yo tengo 2 motores. con 2 potes del lado del emisor. como hago para enviar esos 2 datos? no entiendo bien esa parte para el envio. gracias !

penetreitor
Humano

como mando el comando encender no tengo ni idea de.eso:c

ismael lira
Humano

n4no me marca este error en el receptor

sketch_dec08b:18: error: stray ‘\’ in program
sketch_dec08b.ino: In function ‘void loop()’:
sketch_dec08b:18: error: expected `;’ before ‘u2010’

sketch_dec08b:18: error: stray ‘\’ in program
sketch_dec08b.ino: In function ‘void loop()’:
sketch_dec08b:18: error: expected `;’ before ‘u2010’

ismael
Humano

n4no he estado viendo tu blog y es muy bueno
estoy tratando de controlar un motor por onda de radio al momento de utilizar el codigo del receptor me marca lo siguiente me podrias ayudar

sketch_dec08b:18: error: stray ‘\’ in program
sketch_dec08b.ino: In function ‘void loop()’:
sketch_dec08b:18: error: expected `;’ before ‘u2010’

Brumi
Humano

Si conectara el puente Dual H-Bridge shield, L293D como debo hacer la conexion?

Eduardo
Humano

Hola soy Eduardo de La Plata, mil gracias por el codigo, hago una pregunta tendria que tener dos receptores y dos emisores para que puedan enviar y recibir en ambos sentidos?, gracias.

Asa
Humano

Si llegara a colocar un motor de mayor consumo de amperaje a lo recomendado en tu descripción,
¿correría algún riesgo mi placa?

Mpr Mpr
Humano

N4N0, gracias por tomarte tiempo en responder.
E conseguido descargar y compilar la libreria VirtualWire.
Lo estaba haciendo mal.
DE todas formas , te comento. E comprado los modulos de RF y estoy a la espera de recibirlos y probarlos.
Cuando los tenga y pruebe te comento.
Hasta entonces recibe un saludo y gracias por tu tiempo en enseñar a los humanos…….

Mpr Mpr
Humano

Estimado amigo, tengo el problema de que copio y pego y no consigo compilar tus codigos.
Estaria agradecido si me puedes dar solucion
No tengo ni idea de programacion pero me gusta tu proyecto y me e comprado el harwar para hacerlo.
Porfa, me puedes ayudar????

Antonio
Humano
Hola! Antes de nada gracias por el código que llevaba unos días loco buscando como enviar un valor analógico via RF. Tal como copié tu código no me funcionaba, tuve que declarar que pin iba a hacer de emisor y cual de receptor dentro del setup, de la siguiente manera “vw_set_tx_pin(3);” para el emisor y “vw_set_rx_pin(3);” para el receptor, quedando el setup así: void setup() { //Iniciar comunicacion por radio, Serial Serial.begin(9600); Serial.write(“Sistema encendidon”); vw_set_ptt_inverted(true); vw_setup(2000); //Tiempo de espera vw_set_tx_pin(3); //Pin donde se conecta el transmisor } Un saludo y mucho animo!!
wpDiscuz