Trabalho Prático 1
Objetivos
Desenvolver um dispositivo mecânico com LEGO que translade e rotacione e seja controlado apenas pela HandyBoard. O robô deve ser capaz de executar uma seqüência para 4 leds e se mover livremente durante um período exato e realizar autonomamente uma trajetória quadrada de 30cm de lado e uma trajetória circular de 25 cm de raio, ambos por 3 vezes consecutivas.
Etapas de desenvolvimento
- 07 de setembro:
Primeiro encontro para familiarização com a HandyBoard e o IteractiveC.
Foi realizado um ajuste fino da altura dos motores para que o mesmo se encaixasse de forma harmônica com as outras peças do lego.
Sobre a estrutura física:
Decidimos que a estrutura física do robô seria da seguinte forma: O robô teria um total de quatro rodas em dois eixos, como num carro. O eixo da frente seria responsável por direcionar o robô e o traseiro responsável pelo movimento de translade.Colocamos então o primeiro motor que seria responsável pelo movimento de translade.
Sobre a estrutura lógica:
Nesta etapa foi desenvolvida boa parte do código da HandyBoard incluindo o menu e o acionamento e desligamento dos motores.
- 11 de setembro:
Nesta fase começamos a implementar a tarefa relacionada aos leads e continuamos a trabalhar na estrutura física do Johnnie Walker. A tarefa de translação linear começou a ser implementada também.
- 12 de setembro:
Nesta etapa terminamos a estrutura física do Johnnie Walker e continuamos a investigar como seriam feitas as ligações dos leds e a programação da tarefa.
Sobre a estrutura física
Na Figura 1 pode-se observar a estrutura finalizada, muito embora ela tenha sido destruída dando lugar a uma estrutura completamente nova utilizando o roll-on. Nesta estrutura havia dois motores, um responsável pelo movimento de translade e outro responsável por controlar o eixo frontal, que direcionava o robô.
O motor de translade estava acoplado ao eixo traseiro, em que as rodas traseiras eram ligadas, de modo que o lado esquerdo e o lado direito sempre teriam a mesma velocidade angular. Este método garantia que o Johnnie conseguiria andar reto, mas este projeto apresentou uma falha que será abordada mais adiante.
O motor de rotação funcionava da seguinte maneira: O motor, que estava com duas reduções utilizando o sem-fim, girava uma estrutura que virava uma engrenagem e que por fim estava associada a uma cremalheira. A cremalheira estava ligada num eixo móvel, como em um carro, que direcionava as rodas frontais. As roldanas eram responsáveis pela transmissão do movimento, como está indicado na Figura 1.
- 14 de setembro:
Nesta fase começamos os testes com o robô.
Primeiramente terminamos a programação dos leads, corrigimos alguns problemas encontrados no código e começamos a testar a estrutura do robô. A programação para calibração do motor também foi terminada.
Começamos então a testar todo o conjunto que completava o Johnnie, isto é, ligamos a HandyBoard na estrutura lego e o robô movimentou-se para a frente e para trás. O motor do eixo traseiro não necessitaria de uma calibração de sincronismo dado que as rodas deste eixo estavam diretamente ligadas. Pequenas modificações na estrutura do robô mostraram-se necessárias.
A tarefa dos leads foi testada e funcionou corretamente.
- 16 de setembro:
Nesta etapa a idéia era calibrar o motor responsável por direcionar o Johnnie Walker. Porém ao começar os testes uma falha que passou despercebida tornou-se evidente. Independente da direção que colocávamos o eixo o frontal, o robô insistia em andar somente reto. Isto ocorreu devido ao fato das duas rodas do eixo traseiro estarem completamente ligadas. Desta forma, ambas sempre tinham a mesma velocidade angular, o que gerava um atrito forte quando o robô tentava fazer uma curva. Este atrito impedia que o robô fizesse a curva corretamente e o mesmo ia “quicando” para frente.
Tentamos colocar mais atrito no eixo frontal, mas foi insuficiente para que o robô fizesse a curva. Ainda que funcionasse, o atrito nas rodas traseiras era grande e culminava numa enorme resistência que desgastaria demais a roda do lego. Mostrou-se evidente a necessidade de mudar a mecânica do robô (Figura 2).
Nesta etapa também descobrimos alguns cuidados que não tomamos quanto a ligação dos leads. Não estávamos usando resistores, muito embora isto não tenha se mostrado um problema. Porém, fomos convencidos de que o uso do mesmo era necessário para que limitássemos a corrente que passava nos leads (diodos).
Segue as fotos da estrutura que deveria ser refeita.
- 17 de setembro:
Nesta fase mudamos completamente a estrutura do robô e fizemos pequenos testes com a nova estrutura, que foram bem sucedidos. Também começamos a reprogramar a parte de calibragem e de multi-tarefas do robô.
Sobre a estrutura física
Tínhamos duas opções para a estrutura física do Johnnie: Poderíamos mudar a tração do eixo traseiro para o eixo da frente ou colocar cada motor controlando uma roda do próprio eixo traseiro. Estávamos convencidos de que a primeira opção resolveria o nosso problema, porém a mecânica seria complicada e mais trabalhosa do que a exigida para a segunda opção. Optamos, portanto, pela segunda opção, que demandaria uma calibragem para a sincronia dos dois motores (Figura 3).
Segue as fotos da nova estrutura:
- 21 de setembro:
Com a estrutura do robô completamente definida, nos dedicamos nesta fase somente ao código do programa e à calibração. Foram feitos todos os testes necessários à calibração dos motores, tanto para movimento linear quanto rotacional. Realizada a calibração salvamos os valores das tabelas abaixo no programa da HandyBoard que possa realizar o movimento novamente.
Ângulo | Direita | Esquerda | Tempo |
---|---|---|---|
30 | -35 | 35 | 1.326 |
60 | -35 | 35 | 1.420 |
90 | -35 | 35 | 0.700 |
Distancia | Direita | Esquerda | Tempo |
---|---|---|---|
10 cm | 35 | 38 | 2.340 |
20 cm | 60 | 66 | 0.156 |
30 cm | 34 | 46 | 0.780 |
- 23 de setembro:
Nesta última etapa foram realizados os testes para os desenhos do quadrado e do círculo e os ajustes finais, como a finalização da estrutura dos leds.
Estrutura Física
A versão final do robô contêm 2 motores, cada um ligado a uma roda do eixo traseiro de forma independente. A parte da frente continha um roll on.
Foi necessário uma calibragem para determinar qual potência que cada motor deveria receber para que o mesmo andasse reto e fizesse uma rotação de 30, 60 e 90 graus em torno do próprio do eixo.
A Handy Board foi colocada numa estrutura feita para acomodá-la no topo do Johnnie. Um estrutura para acomodar os leds também foi feita e colocada ao lado do robô.
Estrutura Lógica
Estruturas de Dados
Para melhor organização do código, assim como para facilitar o controle de certos dados, foram criadas duas estruturas.
A primeira, Motor, é a abstração de um motor, a qual armazena a porta a qual ele se encontra ligado, bem como sua potência atual. O interesse de se armazenar a potência atual é o de facilitar a mudança de potência de forma gradativa. Além disso, evita-se o uso de variáveis globais, além de possibilitar o reuso de certas funções de forma mais eficiente.
A segunda estrutura criada, Config, possui a configuração de uma trajetória qualquer. Ela armazena a potência desejada de cada motor, além do tempo em que essas potências devem ser mantidas. Isso permite que toda trajetória seja realizada por uma só função, pois depende somente das variáveis armazenadas.
Para a calibragem e execução das tarefas, foram criadas 9 variáveis persistentes do tipo Config:
- linear10, linear20 e linear30: Armazenam as configurações para trajetórias lineares de comprimento 10, 20 e 30cm.
- angle30, angle60 e angle90: Armazenam as configurações para o robô girar em 30, 60 e 90 graus.
- circle25: Configuração para realizar um círculo de 25cm de raio.
Módulos
O código do trabalho foi dividido em vários módulos, cada um relacionado a uma tarefa ou funcionalidade específica. O método main está contido no arquivo hello.ic, bem como todos os “includes”.
hello.ic: Além de conter o main, esse módulo é responsável pela impressão do menu principal, bem como pela interação com o usuário. Assim que uma opção do menu é escolhida, uma função do módulo correspondente é chamada. Essa função é sempre no formato “startX”, sendo X a tarefa escolhida.
leds.ic: O módulo gerencia os estados das saídas digitais para os quatro leds embutidos no robô. Além disso, a função relacionada a execução da tarefa de leds também se encontra nesse módulo. A função é responsável por realizar uma sequência aleatória de funcionamento dos leds.
linear.ic: Dentro deste, encontra-se a função de execução do quadrado, a qual nada mais é do que chamar alternativamente a execução das tarefas de translação linear de 30cm e de rotação de 90 graus. Além de possibilitar ao usuário abortar a tarefa a qualquer momento, a partir do acionamento do botão “stop”.
rotation.ic: Novamente, o módulo é responsável pela realização de uma tarefa, realizar o círculo de raio de 25cm. Também é feito o controle de parada da tarefa via o botão “stop”.
thread.ic: O seguinte módulo dispara dois processos, um para funcionamento aleatório dos leds e outro para a realização de uma tarefa qualquer. São duas as condições de parada, o botão “stop” e um marcador de tempo. O marcador é setado para executar a tarefa no máximo por 30s, caso não abortada pelo usuário.
motor.ic: Possui métodos associados aos motores. Foram criadas funções para ajustar uma nova potência de um motor e de dois de forma gradativa, assim como para desligar o mesmo. Dessa forma, evita-se mudanças abruptas de velocidade. Além disso, foi criada uma função execute(), a qual é responsável por executar uma tarefa com uma potência “x” para o motor direito, uma potência “y”para o esquerdo em um intervalo “t” de tempo.
calibrate.ic: Esse módulo é responsável pelas tarefas de calibragem do motor, bem como do tempo. Utiliza-se uma variável temporária para armazenar as configurações setadas pelo usuário e permite que o mesmo faça testes com as mesmas. Caso seja de interesse do usuário, ele pode salvar tais configurações em alguma das estruturas persistentes.
time.ic: Possui uma função de sleep diferente da disponível pelo IC, a qual permite que o usuário aborte sua execução a qualquer momento. Para isso, realiza-se uma espera ocupada, ou seja, utiliza-se um while e, a cada interação, são feitos cálculos de quanto tempo já se passou desde o ínicio da chamada da função. Caso o tempo seja igual ou maior o passado, a função termina e o fluxo de controle volta para o método anterior. O mesmo ocorre caso o botão “stop” seja pressionado.
Além disso, os menus de cada tarefa são gerenciados pelo módulos associados às mesmas.
Usabilidade
A interação do usuário com o robô foi ajustada para ser feita por meio de um menu, do potenciômetro e dos botões “stop” e “start”. Cada botão tem as seguintes funções:
.start: Sempre utilizado para confirmar/executar a opção impressa no display.
.stop: Utilizado para alternar entre as opções quando no menu, para cancelar o ajuste de alguma variável durante a fase de calibragem e para abortar as tarefas a qualquer momento.
.potenciômetro: Utilizado para setar os valores associados à variáveis no menu de configuração, tempo e potência.
O menu inicial possui 6 opções:
0- Quadrado: Inicia a tarefa de realizar 3 quadrados.
1- Rotação: Execução da trajetória circular de 25 cm de raio.
2- Leds: Executa uma sequência de funcionamento aleatório dos leds.
3- Multi-tarefa: Inicia tanto uma trajetória qualquer, quanto o funcionamento dos leds.
4- Calibrar: Chama o menu de calibragem.
5- Tarefas: Chama o menu de execução de trajetórias armazenadas nas variáveis persistentes.
Além do menu principal, a calibragem possui um menu auxiliar, com 6 opções:
0- Potencia Motor Direito: Permite o ajuste da potência a ser usada no motor direito.
1- Potencia Motor Esquero: Permite o mesmo ajuste mas para o motor esquerdo.
2- Tempo: Ajuste do tempo de execução da trajetória.
3- Teste: Executa a trajetória com a configuração escolhida.
4- Salvar Config: Salva a configuração atual em uma das variáveis persistentes.
5- Voltar: Volta para o menu anterior.
Tanto a opção “Tarefas” do menu principal, quanto a opção “Salvar Config”, chamam um terceiro menu, o qual permite selecionar a variável persistente alvo. As opções são as variáveis citadas anteriormente, bem como a opção de voltar ao menu anterior.
Videos
Desafios
Encontramos os seguintes desafios nesta etapa do trabalho:
- A calibragem não era exata e a variação da carga da bateria contribuía para que esta variação se tornasse maior de maneira que uma calibragem que servia num determinado momento não serviria para um momento posterior.
- Para a primeira estrutura do robô foi desafiador encontrar uma maneira de faze-lo virar. Problema este que foi contornado alterando toda a estrutura do robô.
- Para este trabalho fizemos um ajuste fino da altura do motor. No primeiro TP isto foi um grande problema, que resolvemos neste trabalho. Além disso, travamos bem o motor e utilizamos o senfim para obter uma redução maior.
- Sincronizar os dois motores. Para a estrutura final fizemos duas tentativas. Na primeira utilizamos o recurso multitarefa do robô. Porém o overhead gerado pela troca de processos fazia com que o robô andasse um trajetória em S. A melhor opção foi Ligar os dois motores como duas instruções seguidas, cada uma ligando um motor.
Conclusão
A tarefa de calibrar os motores é difícil e trabalhosa. Várias medições devem ser feitas até ter certeza de que determinados valores são os adequados para uma determinada tarefa. Ainda assim, estes valores podem quando usados diversas vezes podem apresentar diversos resultados diferentes, com uma variação significativa entre os resultados extremos. Estes resultados também variam de acordo com a carga da bateria o que torna a tarefa ainda mais complicada.
Tal calibragem, apesar disto, contribuiu para compreender o funcionamento do motor e da HandyBoard e para obter valores que aproximados para que o robô executasse uma determinada tarefa, como a tarefa de desenhar um quadrado e um circulo.
Também percebemos que quanto menor fosse a potência e conseqüentemente menor fosse a velocidade do robô, mais reta era a linha que obtiamos e menor era a variação nas diversas medições para uma dada potência e um tempo.