Sempre que passo em uma loja de brinquedos e vejo carrinhos de controle remoto na vitrine, fico doido para levar-los para casa, deve ser porque tinha adoração por este tipo de brinquedo, mas por falta de opções e grana, não cheguei a ter um quando criança. Para compensar e ter uma desculpa para comprar um ? vamos desmontar um desses, “raqueando” suas principais partes e substituindo a eletrônica embarcada original por um microcontrolador tipo Arduino facilmente comandado a distância por um dispositivo Android. Com isso, ficará muito fácil adicionar ao carrinho novas funcionalidades, sensores, etc. É uma forma muito barata de se construir um robô para uso didático.
O vídeo abaixo, mostra como ficará o projeto final:
Conhecendo o carrinho
O primeiro passo será desarmar o carrinho para se ter uma idéia de como ele funciona, o que se aproveitará e o que se deve ser adicionado:
Na parte inferior da carcaça, estão os os dois motores (frontal e traseiro), o compartimento da bateria (recarregável, 5V) e o modulo eletrônico. Na parte superior da carcaça, está a antena (placa de cobre conectada a um cabo negro) e os 4 LEDs que funcionam como os faróis dianteiros e traseiros. Cada LED está conectado separadamente por um par de fios. Com esse arranjo, se pode:
- Acender os faróis (acender os dois LEDs frontais)
- Dar pisca (acender os LEDs esquerdos ou direitos)
- Sinalizar uma frenagem (acender os dois LEDs traseiros)
O diagrama em blocos da eletrônica original é:
Em relação a mobilidade, nos projetos anteriores de robôs utilizamos a técnica de “Differential Steering” onde variando-se o sentido de giro das rodas, varia-se a direção do rob0, mas aqui se pode ver que o carrinho, apesar de também possuir dois motores DC , possui uma confirmação diferente de motores:
O motor frontal, não possui nenhum controle de velocidade ou posição, sendo utilizado apenas para virar o carrinho “à direita”ou “à esquerda”, movendo-se simultaneamente todo o conjunto rodas/eixo frontal (mais ou menos como em um automóvel). Em geral o carrinho sempre se move para a frente em linha reta e o motor está desligado, deixando assim as rodas livres. Um comando para “virar à esquerda” por exemplo, fará o motor girar, fazendo o mecanismo de engrenagens como um todo se mover para a esquerda. Enquanto o motor estiver alimentado o mecanismo ficará nessa posição limite e o carrinho continuará “virando à esquerda”).
O motor traseiro está acoplado a um sistema redutor de velocidade por engrenagens e fornece torque variável as rodas traseiras (conjunto fixo). Pode-se assim variar a velocidade, mas não a direção (as duas rodas sempre girarão em um mesmo sentido).
Raqueando a eletrônica embarcada
Uma vez que tudo foi identificado, é a hora de remover a eletrônica original, deixando somente os cabos dos motores e bateria. Como não vou voltar a usar a carcaça superior por enquanto, não me preocuparei com os LEDs originais.
No lugar do módulo eletrônico, usaremos um Arduino Uno, que será o responsável pela lógica do processamento, acionando os motores, LEDs e um Buzzer. O controle remoto que antes era conseguido por um sistema receptor de RF de 27MHz será agora substituído pelo modulo HC-06, o qual se comunicará com um dispositivo Android. A bateria original do carrinho será mantida exclusivamente para a alimentação dos motores via a H-Bridge L293D, pois os motores DC além de consumirem bastante corrente geram ruído devido a suas escovas. Pela maneira que o carrinho foi construído, o motor frontal consome bastante energia no momento em que recebe um comando de virar para um dos lados, pois seu eixo será travado e o consumo de corrente será alto. Para o Arduino usaremos uma bateria de 9V (Vin), sendo que o modulo HC-06 será alimentado pela saída de 5V do Arduino).
O novo diagrama de blocos para implementação do circuito é:
Neste ponto é importante testar os motores individualmente. Usando uma bateria, alimente o motor e observe para que lado lado ele gira. Inverta a bateria e repita o teste anotando as cores dos fios:
No caso de meu carrinho, temos:
Front Motor:
- Yellow: LEFT
- White: RIGH
Rear Motor:
- Green: Backward
- Blue: Forward
Montagem Final
O circuito (as cores dos fios do motor não são as corretas):
O HW do novo carrinho à controle remoto está pronto para seus primeiros testes. Agora, falta implementar o SW e o aplicativo Android.
O Aplicativo Android
Para controlar o carrinho, usaremos uma App que desenvolvi utilizando o MIT AppInventor 2: “MJRoBot BT Remote Control”. A app pode ser baixada gratuitamente da loja da Google através do link: MJRoBot BT Remote Control
A app possui uma interface simples, permitindo o envio de comandos ao modulo de BT tanto em modo TEXT, como diretamente via botões pre-programados (cada vez que um botão é pressionado, um caracter é enviado):
w: Forward
s: Backward
d: Right
a: Left
f: Stop
p: ON/OFF
m: Manual / Automatic
+: Speed+
-: Speed-
Também existe uma janela de texto para mensagens recebidas do modulo BT. Esta característica é bem importante durante a fase de testes, pois pode ser usada da mesma maneira que o “Serial monitor”.
O Diagrama de blocos para o projeto no MIT appInventor2:
O Código Arduino
O bloco principal do código é bem simples:
void loop() { checkBTcmd(); // verify if a command is received from BT remote control receiveCmd (); if (turnOn) manualCmd (); else stopRobot (); }
A primeira coisa a se fazer é verificar se existe algum novo comando BT chegando. Quem checará isso é a função “checkBTcmd()”:
void checkBTcmd() // verify if a command is received from BT remote control { if (BT1.available()) { command = BT1.read(); BT1.flush(); } }
A variável “turnOn” é utilizada para ligar ou desligar o carrinho. A função “receiveCmd()” será a encarregada de definir o status dessa variável em função do comando recebido do modulo BT. Observe que pela lógica usada, cada vez que o botão vermelho com o símbolo de “POWER” é pressionado, o caracter “p” será enviado pelo app e a a variável “turnOn”, mudará se valor (de 1 para 0 e vice e versa):
void receiveCmd () { switch (command) { case 'p': turnOn = !turnOn; command = 0; analogWrite(ledStatus, turnOn*128); // Robot ON - Led ON beep(outBuz, 1000, 100); BT1.print(" COMMAND ON/OFF"); BT1.println('\n'); delay(200); //Delay to call attention to mode change break; case 'm': //not used here break; } }
Voltando ao loop principal, enquanto a variável “turnOn” é HIGH (1), a função “manualCmd()” executará um comando, dependendo do caracter recebido:
void manualCmd() { switch (command) { case 'f': moveStop(); //turn off both motors state = command; break; case 'w': moveForward(); state = command; break; case 'd': moveRight(); break; case 'a': moveLeft(); break; case 's': moveBackward(); state = command; break; case '+': if (state == 'w') { motorSpeed = motorSpeed + 10; if (motorSpeed > MAX_SPEED) motorSpeed = MAX_SPEED; command = 'w'; } else command = state; break; case '-': if (state == 'w') motorSpeed = motorSpeed - 10; if (motorSpeed < MIN_SPEED ) motorSpeed = MIN_SPEED; command = state; break; } }
Por exemplo, se o comando “w” é recebido a função específica para mover o carrinho para a frente “moveForward()” é executada.
Em caso “powerOn” esteja em HIGH e a tecla “POWER” seja pressionada, a variável “powerOn”, passará a LOW e a função “stopRobot()” será a executada ao invés de “manualCmd()”. Esta função garante que o motor traseiro esteja parado, os LEDs apagados e variáveis zeradas.
void stopRobot () { digitalWrite(ledBlue, LOW); digitalWrite(ledRed, LOW); state = 0; moveStop(); //turn off both motors }
Acionando os motores DC via H-Bridge
Os motores frontal e traseiro estão ligados a ponte-H como mostrado abaixo:
e a cada um dos pinos do Arduino, os quais deverão ser definidos como OUTPUT, será atribuído uma variável:
const int rearMtFw = 4; // Rear Motor - FW const int rearMtBw = 7; // Rear Motor - BW const int rearMtEne = 6; // Rear Motor - enable const int frontMtLeft = 2; // Front Motor - turn Left const int frontMtRight = 3; // Front Motor - turn right const int frontMtEne = 5; // Front Motor enable
Por exemplo, se desejamos mover o carrinho para a frente, a função “moveForward()” deverá colocar o pino 4 en HIGH e o pino 7 em LOW, isso fará com que a corrente flua “no sentido horário”, como mostrado no diagrama abaixo:
O pino 6 é o “enable”, somente quando ele estiver em “HIGH”, a ponte permitirá o fluxo de corrente pelo motor. Como este pino possui característica PWM, a velocidade com que o motor girará, dependerá do valor da variável “motorSpeed”, no pino 6 (valor de 0 255).
A função também deverá garantir que o motor frontal “gire livremente”, e para isso o pino 5, que é o pino de “enable” deverá estar em LOW (o status dos pinos 2 e 3 não importam, uma vez que o enable está el LOW). O LED vermelho, que funciona como “luz de ré”, deverá sempre estar apagado quando o carrinho se move para a frente:
void moveForward() // rear motor FW { analogWrite(rearMtEne, motorSpeed); digitalWrite(rearMtFw, HIGH); digitalWrite(rearMtBw, LOW); digitalWrite(frontMtEne, LOW); digitalWrite(ledRed, LOW); delay(5); }
por analogia, é obvio que para o carrinho “mover para trás”, basta que o motor gire na direção contrária. Para isto, o pino 4 deverá estar em LOW e o pino 7 em HIGH. Note que nesse caso a “luz de ré”, deverá estar acesa. A função neste caso será:
void moveBackward() // rear motor BW { analogWrite(rearMtEne, motorSpeed); digitalWrite(rearMtFw, LOW); digitalWrite(rearMtBw, HIGH); digitalWrite(frontMtEne, LOW); digitalWrite(ledRed, HIGH); delay(5); }
O mesmo raciocínio pode ser utilizado para o motor frontal, somente que nesse caso, não existe controle de velocidade. Colocando o pino 2 (enable) em HIGH habilita o motor a “tentar girar”, para um lado ou para outro dependendo do status dos pinos 2 e 3:
void moveLeft() // front motor left { digitalWrite(frontMtEne, HIGH); digitalWrite(frontMtLeft, HIGH); digitalWrite(frontMtRight, LOW); digitalWrite(ledRed, LOW); delay(10); } //************************************// void moveRight() // front motor right { digitalWrite(frontMtEne, HIGH); digitalWrite(frontMtLeft, LOW); digitalWrite(frontMtRight, HIGH); digitalWrite(ledRed, LOW); delay(10); }
Para parar o carrinho, basta colocar todas as saídas da ponte relativas ao motor traseiro em LOW, o que “travará” o eixo do motor (o motor frontal basta o enable estar em LOW):
void moveStop() //turn off rear motor { analogWrite(rearMtEne, LOW); digitalWrite(rearMtFw, LOW); digitalWrite(rearMtBw, LOW); digitalWrite(frontMtEne, LOW); digitalWrite(ledRed, LOW); delay(5); }
No link abaixo, você poderá encontrar o código completo para o Arduino:
Conclusão
O carrinho está devidamente raqueado e pronto para ganhar o mundo! Agora o céu é o limite! Comece, por exemplo instando sensores para evitar obstáculos, um HC-04 (ultra-som) funcionará bem, como vimos no caso do “Mars Rover” tupiniquim. Crie um novo comando e envie o “caracter” via texto (ou use o botão Man/Auto: caracter “m”, para o robô executar outras fincões (buzina, por exemplo).
Outra idéia interessante é melhorar a “dirigibilidade” do carrinho. O motor DC frontal poderia ser substituído por um servo de 180o que movimentaria o conjunto frontal de maneira linear, obtendo-se assim ângulos de virada variáveis. A foto ao lado é de um exemplo que encontrei a web. Não é exatamente o mecanismo de meu carrinho, mas mas mostra como poderia ficar.
That’s all folks!
Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica e dos robôs!
Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook