segunda-feira, 16 de agosto de 2010

Robô explorador 4x4 com PROGRAM-ME



Depois de montar dois pequenos robôs com o PROGRAM-ME e executar diversas experiências com sensores, displays e motores, resolvi montar um robô agregando todos esses dispositivos de forma funcional permitindo assim um amplo aprendizado em robótica.

A base deste robô é o PROGRAM-ME (Arduino turbinado da Globalcode) e um chassi 4x4 que comprei na forma de kit pronto para montar.


Como os motores que vêm no kit operam entre 3 e 6 volts e eu pretendia alimentar o robô com células LIPO de 11.1 volts, substitui os 4 por motores de autorama modelo Mabuch Green de 12 volts x 24000 RPM.

Na base do chassi além dos motores instalei uma placa que permite controlar os motores (2 a 2) utilizando apenas uma porta do Program_Me, um transmissor de vídeo de 2.4 GHz para transmitir as imagens captadas pela câmera e um relé para controlar a alimentação do transmissor e da câmera.



Logo acima dos motores, na base inferior do chassi, instalei o Program-Me.
Parece que o chassi foi feito para ele não acham ?



Como a quantidade de dispositivos e sensores instalados neste robô é grande, o consumo da voltagem de 5 volts subiu bastante e portanto o regulador de voltagem 7805 tende a aquecer bastante. Para evitar o aquecimento excessivo desse regulador, tomei a decisão de remanejar ele para um pequeno dissipador na lateral do robô.



Para que seja possível estabelecer comunicação wireless com o robô, acoplei ao Program-Me um módulo XBee utilizando um shield.



O fato do Program-Me ter várias portas de conexão (SERVO 1, SERVO 2, POT 1, POT 2 e os bornes), facilitou bastante o trabalho de conexão dos sensores frontais, do display LCD e do Servo que controla a câmera, porém ainda faltavam pontos de conexão para os sensores traseiros, sensor PING, GPS, e portas I2C (sensores de temperatura/umidade, bússola e RTC).
A solução foi utilizar a área de proto do shield XBee para implementar esses pontos de conexão. (foto abaixo)



A próxima etapa seria dar ao robô a oportunidade de falar, para isso instalei um VOICE shield modificado com o chip TTS256-Text to Speech.
Esse chip em conjunto com o Voice shield, permite ao robô pronunciar palavras em inglês bastando enviar a string de caracteres via serial.



Na base superior instalei o servo que posiciona a câmera, o sensor de temperatura/umidade, a bússola, o GPS, os sensores de distância frontais e traseiros e o display LCD gráfico.

A figura seguinte mostra a parte de baixo da base superior do robô, onde são fixados os sensores, o servo e os cabos de conexão de todos os sensores e dispositivos.



Na foto abaixo temos a visão da base superior já com os sensores, GPS, RTC e o display gráfico instalados.
A antena branca é a responsável pela transmissão do vídeo captado pela câmera do robô.



A função do display gráfico é permitir a visualização das várias informações captadas pelos sensores do robô. A interface dele é serial a 115200 bps e utiliza apenas uma porta do PROGRAM-ME.


As informações indicadas pelo display são as seguintes:

superior esquerdo - Temperatura, umidade e ângulo de deslocamento.
central - "bússola" que indica a direção de deslocamento do robô.
superior direito - 3 barras verticais indicam as leituras dos sensores frontais (IR-esquerdo, PING e IR-direito)
Os dois quadradinhos indicam obstáculos na parte traseira.
A barrinha na horizontal indica o nível de luminosidade captado pelo sensor, sendo que o backlight do display é ligado automaticamente quando o nível de luminosidade é baixo.
esquerdo inferior - latitude e longitude obtidas do GPS.
direito inferior - Hora e Data que são obtidas do RTC.


Na parte superior instalei também dois mini autofalantes desses utilizados em Notebooks que são responsáveis em reproduzir as falas do robô, e também uma micro câmera montada em um servo motor.






Na traseira do robô instalei dois sensores IR que apenas detectam obstáculos. Eles não medem distância, mas o ponto de ativação pode ser ajustado entre 3 e 80 cm. Para alimentar o robô utilizei duas células de baterias LIPO de 1300mAh x 11,1 volts, que associadas em paralelo dão uma capacidade de 2600mAh x 11,1 volts



Para a unidade de controle remoto, utilizei o Brasileirino (Arduíno básico da Globalcode), um shield XBee e um Nunchuck do WII da NINTENDO (este emprestado do vídeo game do Leo).



O Nunchuck possui internamente um acelerômetro (que neste projeto controla os movimentos do robô), um mini joystick (controla a posição da câmera) e dois botões que controlam a alimentação do transmissor de vídeo/câmera e a buzina do robô (speaker do Program-Me).

O melhor de tudo é que ele usa interface I2C o que facilita demais a comunicação com o Arduino usando apenas duas portas.

A figura abaixo mostra a identificação dos sinais no conector do Nunchuck e a tabela mostra a formatação dos 6 bytes que devem ser lidos para obter as informações dos botões, do acelerômetro e do joystick.






Segue abaixo o código que usei como referência para tratar os dados do Nunchuck:

/*
* wii_nunchuck_sevo -- Use a Wii Nunchuck to control a servo
*
* Tod E. Kurt, http://todbot.com/blog/
*
* The Wii Nunchuck reading code is taken from Windmeadow Labs
* http://www.windmeadow.com/node/42
*/

#include
// comment out the below for Arduino 0011 and above, uncomment for older
//#include
//#include

uint8_t outbuf[6]; // array to store arduino output
int cnt = 0;
int ledPin = 13;

int servoPin = 7; // Control pin for servo motor
int pulseWidth = 0; // Amount to pulse the servo
long lastPulse = 0; // the time in millisecs of the last pulse
int refreshTime = 20; // the time in millisecs needed in between pulses
int minPulse = 700; // minimum pulse width

#define pwbuffsize 4
int pwbuff[pwbuffsize]; // buffer for smoothing pulseWidths
int pwbuffpos = 0; // position in pwbuff

void setup()
{
Serial.begin(19200);
Wire.begin (); // join i2c bus with address 0x52
nunchuck_init (); // send the initilization handshake
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pulseWidth = minPulse; // Set the motor position to the minimum
Serial.print ("Finished setup\n");
}

void nunchuck_init()
{
Wire.beginTransmission (0x52); // transmit to device 0x52
Wire.send (0x40); // sends memory address
Wire.send (0x00); // sends sent a zero.
Wire.endTransmission (); // stop transmitting
}

void send_zero()
{
Wire.beginTransmission (0x52); // transmit to device 0x52
Wire.send (0x00); // sends one byte
Wire.endTransmission (); // stop transmitting
}

int t = 0; // when it gets to 25, read nunchuck
void loop()
{
t++;
if( t == 25 ) {
t = 0;
Wire.requestFrom (0x52, 6); // request data from nunchuck
while (Wire.available ()) {
// receive byte as an integer
outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());
digitalWrite (ledPin, HIGH); // sets the LED on
cnt++;
}
// If we recieved the 6 bytes, then go print them
if (cnt >= 5) {
printNunchuckData(); // uncomment this for debug
// update servo pulseWidth
float tilt = outbuf[4]; // z-axis, in this case ranges from ~75 - ~185
tilt = (tilt - 70) * 1.5; // convert to degrees angle, approximately
pulseWidth = (tilt * 9) + minPulse; // convert angle to microseconds
pwbuff[pwbuffpos] = pulseWidth; // save for averaging
if( ++pwbuffpos == pwbuffsize ) pwbuffpos = 0;

pulseWidth=0; // reset so we can
for( int p=0; p= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseWidth); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}

// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits. That is why I
// multiply them by 2 * 2
int i=0;
void printNunchuckData()
{
int joy_x_axis = outbuf[0];
int joy_y_axis = outbuf[1];
int accel_x_axis = outbuf[2]; // * 2 * 2;
int accel_y_axis = outbuf[3]; // * 2 * 2;
int accel_z_axis = outbuf[4]; // * 2 * 2;

int z_button = 0;
int c_button = 0;

// byte outbuf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if ((outbuf[5] >> 0) & 1)
z_button = 1;
if ((outbuf[5] >> 1) & 1)
c_button = 1;

if ((outbuf[5] >> 2) & 1)
accel_x_axis += 2;
if ((outbuf[5] >> 3) & 1)
accel_x_axis += 1;

if ((outbuf[5] >> 4) & 1)
accel_y_axis += 2;
if ((outbuf[5] >> 5) & 1)
accel_y_axis += 1;

if ((outbuf[5] >> 6) & 1)
accel_z_axis += 2;
if ((outbuf[5] >> 7) & 1)
accel_z_axis += 1;

Serial.print ("seq");
Serial.print ("\t");

Serial.print ("joy_x");
Serial.print ("\t");
Serial.print ("joy_y");
Serial.print ("\t");

Serial.print ("X_axis");
Serial.print ("\t");
Serial.print ("Y_axis");
Serial.print ("\t");
Serial.print ("Z_axis");
Serial.print ("\t");

Serial.print ("Z_but");
Serial.print (" ");
Serial.println ("C_but");



Serial.print (i,DEC);
Serial.print ("\t");

Serial.print (joy_x_axis, DEC);
Serial.print ("\t");
Serial.print (joy_y_axis, DEC);
Serial.print ("\t");

Serial.print (accel_x_axis, DEC);
Serial.print ("\t");
Serial.print (accel_y_axis, DEC);
Serial.print ("\t");
Serial.print (accel_z_axis, DEC);
Serial.print ("\t");

Serial.print (z_button, DEC);
Serial.print ("\t");
Serial.print (c_button, DEC);

Serial.print ("\r\n");
i++;
delay (200);
}

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}




A distribuição de portas do PROGRAM-ME ficou da seguinte forma:




Abaixo temos uma foto do conjunto finalizado, sendo que agora estou trabalhando nos últimos ajustes no código para corrigir pequenos bugs e melhorar o desempenho do robô. Assim que concluir disponibilizarei o código aqui para todos.



Os participantes do TDC2010 poderão ver o robô ao vivo no evento no próximo Domingo.

Segue abaixo uma pequena demo do robô.




Como a voz robótica nem sempre é fácil de ser compreeendida, seguem abaixo as falas do robô pronunciadas no vídeo acima.

"Robot activated"
"Hello, this is an explorer robot from Globalcode"
"I will be waiting for you on The Developers Conference 2010"
"Temperature is about 21 Celsius Degrees"
"Humidity is about 56 %"

[]s

José Luiz
http://twitter.com/jllorenzo

21 comentários:

  1. Bah...muito legal, quero ver o bichinho andando e falando lá no TDC2010. :)
    Seria possível passar o link de onde você comprou o kit? tenho interesse em me aventurar em montar um robô também.

    ResponderExcluir
    Respostas
    1. montar o robo é baba.. a desgraça é a alimentaçao

      Excluir
  2. Gustavo o chassi você encontra na Robotshop ou na DFRobot.
    Seguem os links:

    http://www.dfrobot.com/index.php?route=product/product&path=37&product_id=97

    http://www.robotshop.ca/dfrobot-4wd-arduino-mobile-platform-3.html

    ResponderExcluir
  3. Show de Bola, quero ver ele cantar o hino do São Paulo Futebol Clube mesmo que em Inglês lá na TDC Domingo.
    Parabèns Lorenzo, mas me tira uma dúvida, qual foi o custo final deste projeto ?

    ResponderExcluir
  4. Como a imagem da webcam é transmitida?

    ResponderExcluir
  5. Ademir, não cheguei a fazer as contas do custo total dele, pois vários ítens aproveitei de outros projetinhos que tinha feito. Essa é a parte legal de brincar com Arduino,shields etc.. Você sempre pode aproveitar os sensores, shields e dispositivos em outros projetos, então o seu investimento vai sendo reaproveitado várias vezes.

    ResponderExcluir
  6. Fábio, a imagem é transmitida por um link de RF de 2.4GHz. Existe um módulo transmissor na base do robo e um externo que você acopla em uma tv ou mesmo no PC. Assim que possível vou colocar um video aqui no blog com as imagens da câmera ON-Board.

    ResponderExcluir
  7. Olá José, parabéns pelo projeto, sou iniciante no mundo da robótica e comecei a usar o Arduino recentemente. Seu projeto é meu sonho de consumo, seria possivel postar para o pessoal, mais a respeito da programação, ou qualquer conteudo adicional ?
    Grato,
    Rodolfo Bontempo

    ResponderExcluir
  8. Ola, José.
    Gostaria de saber se é confiavel comprar o chassi da Robotshop ou da DFRobot?
    É que estou fazendo um projeto sobre robotica para a minha faculdade e ficamos interresados em comprar esse chassi.
    Obrigado,
    Alexandro Weiss

    ResponderExcluir
  9. Rodolfo, assim que possivel vou postar o código aqui para você.

    ResponderExcluir
  10. Alexandro já comprei nas duas e a experiência foi excelente com ambas. A DfRobot tem preço um pouco mais baixo.
    Atenciosamente

    ResponderExcluir
  11. Alexandro, você também pode comprar da seeedstudio[1] que o frete é gratis, no entanto, demora bem mais que a DFRobot
    1. http://www.seeedstudio.com/depot/4wd-arduino-robot-platform-global-free-shipping-p-658.html?cPath=119_125

    ResponderExcluir
  12. José, poderia postar o código que você implementou nesse carro?
    Estou dando uma estudada em arduino e robótica e comprei esse mesmo carro e algumas outras coisas da dfrobot. Onde vc achou esses motores de 12v para comprar?

    ResponderExcluir
  13. Roterdan e demais colegas, me desculpem por estar devendo o post do código. Vou postar o código completo provisóriamente na comunidade PROGRAM-ME no NING (http://program-me.ning.com). Os motores de 12volts eu comprei no MercadoLivre, eles são motores de autorama utilizados em réplicas. Tem que tomar cuidado pois existem motores de autorama que não encaixam nesse conjunto de engrenagens.

    ResponderExcluir
  14. Obrigado pela Resposta!
    Eu até encontrei esse mesmo motor no ML, mas o vendedor não tem mais 4 unidades dele... Pelo visto vou precisar continuar com esses motores de 6V, talvez com um circuito regulador para reduzir de 12v para 5v só para alimentar os motores...
    Abraços

    ResponderExcluir
  15. Este comentário foi removido pelo autor.

    ResponderExcluir
  16. Great robot !
    I've seen that you assamble many modules.
    Can i have an idea of the overall cost of this solution ?

    ResponderExcluir
  17. Olá, boa tarde.
    Gostaria de saber como funciona a compra por roboshop e dfrobot, ou seja: o preço do frete, impostos aduaneiros, etc (ate o brasil)
    para ter uma idéia, qual foi o preço do chassis no total?
    obrigado

    ResponderExcluir
  18. Como você fez para substituir os motores ? Vc trocou as coixas de redução deles ou acoplou nas mesmas ? Como vc o fez ? Obrigado.

    ResponderExcluir
  19. eu gostaria de montar um desses para minha feira tecnica em setembro a onde posso conseguir as peças

    ResponderExcluir