segunda-feira, 7 de abril de 2014

Controlando Robô pelo Teclado com Arduino e RF 433MHz

Palavras-chave: Robô, Magician, RF, 433MHz, Motor, Shield, Adafruit, Arduino.

O objetivo deste post é mostrar uma forma de controlar um robô pelo teclado, utilizando Arduino e RF 433MHz.

INFORMAÇÕES INICIAIS

Sistema operacional: Slackware_x64 v.14.1.
IDE do Arduino v.1.5.4.
Biblioteca VirtualWire.
Biblioteca AFMotor.

MATERIAIS

Mecânica:

- 1 Kit do chassi Magician DG007.

Eletrônica:

- 1 Arduino Uno R2;
- 1 Arduino stand-alone (estou usando o garagino proto);
- 1 Adafruit Motor Shield;
- 1 Módulo RF TX de 433MHz;
- 1 Módulo RF RX de 433MHz;
- 1 Capacitor de 100nF;
- 1 Conversor USB/Serial.

Diversos:

- 1 Suporte de 6 pilhas AA para o robô;
- 1 Protoboard de 170 pontos para o robô;
- 1 Protoboard para a montagem do Arduino stand-alone;
- Fios (jumpers) para a montagem em protoboard.

* Informações para montagem do Arduino stand-alone como componentes, diagramas elétricos e gravação do bootloader podem ser obtidas em [1].

MONTAGEM E PROGRAMAÇÃO

Instale as bibliotecas AFMotor [2] e VirtualWire [3] no diretório Libraries do Arduino.

As Figuras 1, 2 e 3 mostram a pinagem do ATMega328P-PU/Arduino, a pinagem dos módulos RF e o conversor USB/Serial, respectivamente.

Fig. 1 - Pinagem ATMega328P-PU e Arduino.

Fig. 2 - Pinagem dos módulos de RF.

Fig. 3 - Conversor USB/Serial.
Transmissor:

O módulo TX foi montado com o Arduino stand-alone, Figura 4, no protoboard.

Fig. 4 - Diagrama do Arduino stand-alone.
Conecte o pino DATA do módulo TX em D10 e o conversor USB/Serial ao Arduino conforme a sequência abaixo:

Conversor || Arduino

pino 5V || pino 7 - Vcc
pino Gnd || pino 8 - Gnd
pino TX || pino 2 - RX
pino RX || pino 3 - TX
pino RTS || ligar no capacitor de 100nF e do capacitor no pino 1 - RST
pino CTS || pino 7 - Vcc

Conecte o conversor na porta USB. Abra a IDE do Arduino e configure para a porta /dev/ttyUSB0.

Copie o código abaixo integralmente e faça o upload.
/*-------------------------------------------------- 
 * ROBO CONTROLADO VIA RF 433 MHz
 * 
 * RF TX - 433 MHz 
 * Adafruit Motor Shield
 *
 * Comandos:
 * A-frente/S-tras/A-esquerda/D-direita/E-para
 * 
 * www.binarycodec.blogspot.com 
 * Data: 02/04/2014 
 * v.1.0 
--------------------------------------------------*/ 

#include <VirtualWire.h>

const int TX = 10; // Declarando pino para transmissao
int Comando;

void setup() { 
  
  // Comunicacao com o Serial Monitor 
  Serial.begin(9600); // baud-rate 
  Serial.println("Transmissor"); 

  // Inicializando E/S do transmissor 
  vw_set_tx_pin(TX); 
  vw_set_ptt_inverted(true); // Requerido para DR3100 
  vw_setup(2000); // Bits por segundos 
} 

void loop() { 

  // Funcoes para transmissao
 if (Serial.available() > 0) {
   Comando = Serial.read();
   
   Serial.print("Comando: ");
   Serial.println(Comando);
 }
 
  char MovCharMsg[10];
  itoa(Comando, MovCharMsg,10);

  vw_send((uint8_t *)MovCharMsg, strlen(MovCharMsg)); 
  vw_wait_tx(); // Espera o envio da informacao 
  delay(1000); 
}

Receptor:

Dando sequência, monte o Arduino Uno, o Adafruit motor shield, o protoboard de 170 pontos, o módulo RX e o suporte das pilhas no chassi.

A Figura 5 mostra o Adafruit motor shield. Maiores informações podem ser obtidas em [4].

Fig. 5 - Adafruit Motor Shield.
Conecte o motor shield no Arduino e o pino DATA do módulo RX em D2 (quadrado amarelo no canto superior direito).

Não esquecer de ligar os pinos Vcc e Gnd dos módulos RF!!

Conecte o Arduino na USB. Abra outra IDE e configure para a porta /dev/ttyACM0.

Copie o código abaixo integralmente e faça o upload.
/*-------------------------------------------------- 
 * Robo controlado via RF 433 MHz 
 * 
 * RF RX - 433 MHz 
 * Adafruit Motor Shield
 * 
 * www.binarycodec.blogspot.com 
 * Data: 02/04/2014 
 * v.1.0 
 --------------------------------------------------*/ 
#include <AFMotor.h> // Requerido pelo Motor Shield
#include <VirtualWire.h> // Requerido pelo RF

const int RX = 2; // Recepcao no pino Digital 2

AF_DCMotor motor1(1, MOTOR12_1KHZ); // Motor direito - Born 1 e 1KHz pwm - Visto de tras para frente
AF_DCMotor motor4(4); // Motor esquerdo - Born 4 e 1KHz pwm - Motores 3 e 4 apenas em 1KHz

#define M1_DEFAULT_SPEED 100
#define M4_DEFAULT_SPEED 100
#define M1_MAX_SPEED 180
#define M4_MAX_SPEED 180

void setup() {      

  // Comunicacao com o Serial Monitor 
  Serial.begin(9600); 
  Serial.println("Receptor");

  // Inicializando E/S do receptor 
  vw_set_rx_pin(RX); 
  vw_set_ptt_inverted(true); // Requerido para DR3100 
  vw_setup(2000); // Bits por segundo 

  vw_rx_start(); // Inicia a recepcao 
} 

void loop() { 
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 

  if (vw_get_message(buf, &buflen)) { // Sem bloqueios na recepcao 
     Serial.println("Cmd. OK - "); // Verifica checksum. Se comando integro, escreve: Cmd. OK - 

    char MovCharMsg[10]; // Conteudo da transmissao
    for (int i = 0; i < buflen; i++) { 
      MovCharMsg[i] = (char)buf[i]; 
    } 

    // Verifica se terminou a transmissao 
    MovCharMsg[buflen] = '\0'; 
    
   //Convertendo char para inteiro
   int Comando = atoi(MovCharMsg);
   
    // Comandos para movimento
  if (Comando == 'w') { // Para frente
    motor1.run(FORWARD);
    motor4.run(FORWARD);
    motor1.setSpeed(M1_MAX_SPEED);
    motor4.setSpeed(M4_MAX_SPEED);
}

  if (Comando == 's') { // Para tras
    motor1.run(BACKWARD);
    motor4.run(BACKWARD);
    motor1.setSpeed(M1_MAX_SPEED);
    motor4.setSpeed(M4_MAX_SPEED);    
}

  if (Comando == 'a') { // Para esquerda
    motor1.run(FORWARD);
    motor4.run(RELEASE);
    motor1.setSpeed(M1_DEFAULT_SPEED);
}

  if (Comando == 'd') { // Para direita
    motor1.run(RELEASE);
    motor4.run(FORWARD);
    motor4.setSpeed(M4_DEFAULT_SPEED);
}

  if (Comando == 'e') { // Parar
    motor1.run(RELEASE);
    motor4.run(RELEASE);
}
     
   } 
 }

Desligue o cabo da USB e conecte as pilhas.

TESTE

Os comandos para o robô se mover são:

w - frente;
s - trás;
a - esquerda;
d - direita;
e - parada.

Abra o Serial Monitor da IDE que utilizou para gravar o código do transmissor.

Certifique-se que o caminho da porta é /dev/ttyUSB0.

Digite uma das letras de movimento e pressione Enter. O robô ficará executando até receber outro comando (sempre seguido da tecla Enter).

É possível, também, enviar uma sequência de 10 comandos para serem executados automaticamente.

O Vídeo abaixo mostra uma pequena sequência de movimentos.


MATERIAIS/LINKS RELACIONADOS

[1]. Bootloader, Diagramas - http://binarycodec.blogspot.com.br/2013/08/enviando-temperatura-entre-dois_15.html
[2]. AFMotor - https://github.com/adafruit/Adafruit-Motor-Shield-library
[3]. VirtualWire - http://www.pjrc.com/teensy/td_libs_VirtualWire.html
[4]. Motor Shield pinagem - http://binarycodec.blogspot.com.br/2013/09/robo-seguidor-de-linha-com-arduino.html

5 comentários:

Diego Neto Magalhães disse...

Boa noite... Estou fazendo um código para que meu RF 433 possa acionar um relé... Porém não estou conseguindo identificar a variável que vou utilizar para realizar a função "if"... Estou utilizando o código base da biblioteca VirtualWire, porém quando utilizo message[i] para comparar com o código recebido no Serial.read, ele não executa nenhuma ação. Pode me ajudar?

Binary Codec disse...

#Diego Neto Magalhães: Bem, se entendi sua dúvida... No lado transmissor, o valor de Serial.read é passado para "Comando" (que é uma variável inteira)depois é convertido para char e armazenado em MovCharMsg para então ser enviado. No lado receptor, a informação enviada é novamente convertida para inteiro e passada para a variável "Comando". Se der tempo está semana (e se ainda tiver os módulos RF em casa) vou montar esse código e postar aqui.

Rogerio Nascimento disse...

Prezado, estou tentando desenvolver um codigo para usar um IR para controlar um chasis com 2 motores com esse Adafruit motor shield, porém não estou conseguindo. Seria esses comandos de frente, tras, direita e esquerda. Tens como me ajudar?

Julio Guedes disse...

Qual distancia ele suporta?

Binary Codec disse...

@Julio Guedes: Possui alcance de 20 a 200 metros (sem obstáculos e com antena - fio de cobre com 15cm de comprimento soldado no pad indicado para antena).