Robô Seguidor de Linha




Neste tutorial você vai aprender os conceitos básicos de como fazer seu primeiro robô seguidor de linha. Robôs seguidores de linha basicamente são robôs pré-programados cuja função é, através da leitura de sensores, detectar onde existe um caminho em uma superfície (uma linha, muitas vezes feita com fita isolante) e seguir este caminho. Existem várias competições desse tipo em todas as partes do mundo, inclusive no campeonato mundial de robótica que a RoboCore organiza todos os anos.

Para começar você precisa de um robô. Nós aconselhamos o uso do Kit Falcon que temos na loja virtual. Caso esteja realmente começando e não tenha uma placa para programar seu primeiro robô, sugerimos ainda adquirir junto do kit, a placa Julieta V1.0. Esta placa possui todo o necessário para o desenvolvimento do robô. Na mesma placa você tem a parte programável do Arduino e um driver para motores, lembrando que o driver para motores é obrigatório, uma vez que se você ligar os motores diretamente nos pinos digitais do Arduino, estes pinos irão queimar, já que a corrente elétrica que os motores precisam para funcionar é maior do que a máxima corrente que os pinos do Arduino conseguem fornecer.

Após fazer a montagem do robô conforme o manual do mesmo, vamos pensar na parte da programação. É interessante que seus dois sensores estejam próximos um do outro, assim o robô ficará mais estável durante o percurso.
O objetivo que queremos buscar na programação de um robô seguidor de linha é manter sempre os dois sensores sobre a linha. A lógica básica de nossa programação será:
  • Caso os dois sensores estejam sobre a linha, ande para frente.
  • Caso um sensor esteja sobre a linha e o outro não, devemos fazer uma curva para corrigir o percurso.
Em cima destas duas premissas iremos pensar no código do robô, constantemente fazendo a leitura dos sensores e enviando o comando correto para os motores através do driver da placa. Em um percurso simples, vamos ter três possibilidades em nossos sensores: os dois estarem sobre a linha; o sensor da direita estar sobre a linha e o sensor da esquerda estar fora da linha; o sensor da direita estar fora da linha e o sensor da esquerda estar sobre a linha. Também teríamos uma quarta hipótese dos dois sensores estarem fora da linha, porém neste tutorial iremos considerar apenas as três situações, e deixar para o leitor implementar algo que julgue necessário quando houver a quarta condição.

O código a ser usado quando os dois sensores estão sobre a linha será muito simples, uma vez que precisamos mandar o robô andar pra frente, ambos os motores com a mesma velocidade. Agora vamos observar o caso a seguir, quando o robô está chegando em uma curva:

Se nada fizermos, o robô simplesmente sairá do percurso, pois estaria apenas programado para seguir uma linha reta, o que não é nada recomendado para um robô seguidor de linha. Portanto, ao chegar a uma curva, deveremos compensar a direção do robô alterando a velocidade de cada motor. Em nosso robô, como você já pôde observar, possuímos dois motores. Desta forma, quando chegarmos a uma curva para a direita, a roda de dentro da curva (roda do lado direito do robô) deverá ir mais devagar do que a roda de fora da curva, fazendo assim com que o robô consiga virar.

O conceito utilizado aqui é parecido com o conceito do diferencial presente em automóveis. Conforme a Wikipedia: "Uma das principais atuações do diferencial é no momento da curva, onde uma roda precisa girar mais do que a outra. O diferencial mantém o torque igual entre elas.". Ao virar o volante de um carro, se as duas rodas girassem com a mesma velocidade, a curva deveria ter um raio muito grande, se não tivesse, você não iria conseguir completar a curva. Claro que em automóveis existe outro fator determinante nas curvas que é o grau que cada roda fica em relação ao solo. Como aqui nossas rodas não viram, ou seja, são fixas, para efetuar uma curva é estritamente necessário fazer com que uma roda seja mais rápida que a outra.

Com este conceito, conseguimos entender como fazer com que um robô gire em torno do seu próprio eixo utilizando apenas duas rodas. Se colocarmos uma para girar para um lado, e a outra para girar para o mesmo lado, veremos o robô girando em torno do seu próprio eixo, ou você acha que para um carro andar pra frente as rodas giram pro mesmo lado? Este é um conceito que está presente no dia-a-dia de cada um de nós, mas nunca paramos para pensar. Você já parou para observar as rodas de um carro? Para o carro andar para frente, as rodas de um lado giram em um sentido, enquanto que as do outro lado do carro giram em outro. Tecnicamente, para um carro andar para frente é necessário que as duas rodas do lado esquerdo do carro girem no sentido anti-horário, e é necessário que as duas rodas do lado direito do carro girem no sentido horário. Logo: as rodas giram ao contrário e o carro anda para frente!

Vamos começar então fazendo com que nosso robô gire em torno do próprio eixo. Analise o código a seguir e envie para sua placa após entender o que ele faz:


Para controlar os motores de nosso robô, seja usando a placa Julieta, seja usando uma placa Arduino com o Shield Motor Driver 2x2A da RoboCore, basicamente você precisa de dois comandos por motor. São eles os comandos de sentido de rotação e velocidade. O comando de sentido de rotação pode ter dois valores, HIGH ou LOW. A velocidade pode assumir qualquer valor em um range de 0 a 255, sendo que se você colocar a velocidade 0, o driver de motores irá enviar para o motor a tensão de 0V, logo o motor irá ficar parado; e se você colocar 255, o driver irá enviar para o motor a tensão máxima da bateria que estiver alimentando o circuito (se for um pack com 6 pilhas AA, por exemplo, ao colocar 255 na programação o driver irá enviar a tensão de 1,5 x 6 = 9V).

O que vemos no código acima é primeiro a chamada de pinos, sendo que, conforme as trilhas da placa, os pinos digitais 5 e 6 servem para informar a velocidade dos motores A e B, respectivamente, e os pinos digitais 7 e 8 servem para informar o sentido de rotação dos mesmos. Por se tratarem de pinos digitais, no setup do código devemos informar que todos serão saídas. No loop informamos que os dois motores deverão possuir o mesmo sentido de rotação com a mesma velocidade, assim esperamos que o robô gire em torno do próprio eixo. Caso seu robô não esteja girando em torno do próprio eixo, desligue o robô e inverta os dois fios de ligação de um dos motores.

Agora que você entendeu como esse código funciona tente alterar o código para que o robô ande para frente durante 1 segundo, depois pare, ande de ré durante 1 segundo, e depois pare novamente, fechando um loop. Como podemos fazer isso? Simples, alterando o sentido de rotação e implementando o código para que pare e ande para trás. Dê uma olhada em uma sugestão de resposta para esse problema:


Se você entendeu o primeiro código, esse deve ter sido fácil. Se não entendeu, sem problemas, você está aqui para aprender! Antes do loop nada mudou. Os primeiros comandos no loop são parecidos com os que tinhamos no código anterior, porém alteramos um dos sentidos de rotação para que o robô andasse em linha reta. Depois colocamos um delay de 1 segundo (para que ele ande em linha reta durante 1 segundo) e zeramos as velocidades dos dois motores. Assim o robô fica parado (independente do sentido de rotação que está setado), e como temos um delay de 1 segundo após o comando de zerar a velocidade, ele fica parado durante 1 segundo. Então invertemos os dois sentidos de rotação e voltamos a colocar uma certa velocidade nos motores. Como invertemos os sentidos de rotação que tínhamos inicialmente, o robô vai andar para trás. O restante agora fica fácil de entender!

Ótimo, já sabemos controlar os motores da forma que quisermos, seja para andar pra frente, seja para andar pra trás. Pra fazer curvas, como vimos no texto acima, basta alterarmos as velocidades dos motores, diminuindo a velocidade de um lado e aumentando do outro, o robô passará a fazer uma curva. Caso queira uma curva brusca, você pode zerar a velocidade de um dos lados e aumentar a do outro, e se quiser algo ainda mais brusco você pode até mudar o sentido de rotação de um dos lados (porém nesse caso, com o "tranco" no motor, a energia na bateria tende a se esgotar mais rapidamente).

Agora que já sabemos controlar os motores, vamos deixá-los de lado por alguns instantes e vamos entender como faremos a leitura dos sensores, já que quem vai mandar se nosso robô anda pra frente ou pros lados será a leitura dos mesmos.

Os sensores de refletância que você encontra na RoboCore são do tipo analógicos com três pinos (OUT - VCC - GND). Para ligá-los basta usar os pinos da Julieta na ordem correta (tome cuidado para não inverter a ordem de ligação, isso poderá danificar o sensor). Se você já usou o Kit Iniciante ou o Kit Avançado para Arduino da RoboCore, você já está craque em fazer leituras em sensores analógicos. Considerando que um dos nossos sensores está ligado no pino analógico 3 e o outro sensor está no pino analógico 4, vamos começar fazendo a leitura deles com a placa. Neste momento é interessante você ter uma superfície branca e colar nela um pouco de fita isolante preta, para fazermos as leituras.

Grave o seguinte código na placa, após ter ligado os sensores nos pinos corretamente:


Esse código basicamente informa para a placa onde estão ligados os dois sensores de linha, cria duas variáveis para armazenar os valores lidos e mostra no monitor serial tais valores. Após gravar o código, abra o monitor serial e coloque os dois sensores sobre a linha preta. Você deve estar vendo algo próximo a isso:

Passe alguns segundos observando os dados no monitor serial do Arduino sem mexer no robô. Observando os dados lidos, chegue a uma conclusão de qual será sempre o valor mínimo se os dois sensores estiverem sobre a linha. Pelo que vemos na imagem acima, com os dois sensores sobre a linha temos sempre valores acima de 700 em ambos sensores (esses valores podem mudar dependendo de fatores do ambiente, como iluminação). Agora faça o seguinte: mude um pouco a posição que o robô está, deixando um sensor sobre a linha e outro fora da linha. Na leitura de valores você deve estar observando algo desse tipo:


Veja que nesse caso o sensor 1 continua sobre a linha, então seu valor continua por volta dos 800. Já o sensor 2, que saiu da linha, passou a apresentar valores menores que 50, e é justamente com essa diferença de valores lidos que iremos fazer com que nosso robô saiba qual é a hora de fazer as curvas. Agora mova seu robô para o outro lado, para que o sensor que saiu da linha volte a ficar sobre a linha e o sensor que estava sobre a linha fique fora. Você irá notar que os valores de leitura irão inverter.

Com esta leitura, e apenas três rotinas condicionais, conseguiremos fazer nosso primeiro robô seguidor de linha e você verá que é bastante intuitivo. Vamos pensar então em quais serão as três possíveis condições em um circuito simples de seguidor de linha:
  1. Se os dois sensores estiverem sobre a linha, devemos andar pra frente
  2. Se o sensor da esquerda sair da linha, o robô deve fazer a curva para a direita
  3. Se o sensor da direita sair da linha, o robô deve fazer a curva para a esquerda
O fato do sensor sair da linha vai acontecer toda vez que houver uma curva, e esperamos que o robô automaticamente saiba fazer a curva e retornar para à linha. Pensando no código por partes, vamos começar com o que queremos fazer se os dois sensores estiverem sobre a linha. Neste caso o robô deve ir pra frente, vimos como fazer isso no começo desse tutorial. Vamos ter algo assim:


Talvez a única coisa que não seja fácil entender só de olhar o trecho de código acima seja o que existe dentro dos parêntesis da rotina if, e é isso que vamos entender agora. Uma rotina if serve para que o código execute determinadas tarefas caso algo aconteça. Neste caso, queremos que nosso robô ande para frente tanto quando o valor do sensor 1 for maior que 700, como quando o valor do sensor 2 for, também, maior que 700. Para contemplar essas duas condições, nós usamos dois símbolos &. Estes dois símbolos informam para a condição que o código só deve entrar nela se as duas condições forem atendidas. Não iremos usar neste projeto, porém vale ressaltar que se você quisesse que uma OU outra condição fosse atendida, você deveria usar os símbolos || ao invés de &&. Com o código acima, portanto, se a leitura dos dois sensores forem maiores que 700, ou seja, se os dois sensores estiverem sobre a linha, nosso robô andará para frente.

Para fazer as curvas as condicionais são muito semelhantes, veja a seguir:


Com estas duas condicionais conseguimos contemplar a hora que os sensores saem da linha, ou seja, quando chegamos às curvas. O primeiro contempla quando o sensor 1 sai da linha, então diminuimos a velocidade do motor da direita para que o robô corrija sua trajetória e, similarmente, fazemos o próxima condicional para que o robô faça a curva para o outro lado.

Agora, para termos o código completo do nosso primeiro robô seguidor de linha, basta juntar toda a programação vista acima. O código final ficará assim:


Grave o código acima no seu robô e teste em uma pista! Caso seu robô fique "tremendo" você pode ter colocado os sensores muito afastados um do outro, para corrigir isso aproxime o máximo possível os dois. Caso continue tremendo, o problema pode estar no valor de 700 que colocamos como "valor de gatilho" acima. Sendo assim, altere o 700 para o valor que melhor representar o limiar de quando os sensores estão sobre a linha.

A melhor parte de fazer um robô é testar os conceitos. Com este código básico sugerimos que você mexa em todos os parâmetros até chegar no código em que o robô faz o percurso da melhor maneira possível. Mexa na velocidade quando ele anda pra frente, mexa na velocidade quando está fazendo a curva, inverta o sentido de rotação pra ver como fica uma curva feita mais bruscamente, e por aí vai!

Este código é o mais básico possível para fazer um robô seguidor de linha, sendo assim ele não é muito eficiente e poderia ficar muito melhor. Para fazer curvas com o mínimo de perda de velocidade possível, poderia ser usado um algoritmo com PID. Para algo como aprendizado automático, poderia ser usada lógica Fuzzy. Caso a pista tenha cruzamentos ou curvas 90º, poderia ser usado mais sensores de linha na frente do robô. O código mostrado aqui é apenas um pontapé inicial nesta maravilhosa arte de fazer robôs seguidores de linha!

Não deixe de comentar o que achou nos comentários do tutorial abaixo.