Trabalho Prático 1
Construção do Robô
A estrutura do robô foi feita pensando em ser o mais robusta possível. Todas as peças apresentam pelo menos 2 pontos de apoio. O apoio lateral com barras de LEGO é feito em todas as extensões verticais do robô (foto 1).
Além disso, reforçamos a base, com vigas que ajudam a fixar os motores (foto 2). Utilizamos as barras finas furadas para poder manter os motores presos utilizando abraçadeiras plásticas (foto 3).
Para segurar o pincel, utilizamos um par de garras amarelas (não inclusas no kit dacta) (foto 4). Através de elásticos, conseguimos regular a abertura da garra de modo a viabilizar o uso de pincéis de diversos diametros. Além disso, Conseguimos colocar o pincel no eixo das duas rodas melhorando a qualidade do desenho no momento que o robô gira 90 graus no próprio eixo.
Uma vez que os motores que usamos já tinham redução, não houve necessidade de construir uma caixa de redução muito complexa. Utilizamos, portanto, uma redução de 1:5 usando 1 engrenagem de 8 dentes e outra de 40 dentes (foto 5).
Inicialmente, usamos as rodas de maior raio. Essas rodas deixaram robô rápido demais e sem muito torque (travava facilmente). Além disso os erros de rotação e translação eram maiores. As rodas pequenas (foto 5) se mostraram melhores em todos esses aspectos.
Experimentos de Caracterização do Erro dos Motores
Erro de Translação (Erro lateral)
Desde o inicio do trabalho reparamos que os motores nao tem comportamento constante e uniforme. É comum que a força aplicada pelos motores às rodas varie ao longo do tempo. Para lidar com esse erro, o ideal seria utilizar técnicas de controle que aplicaria mais força a um motor de acordo com o desvio naquele instante. No entanto, durante a execução desse projeto nao tinhamos o conhecimento dessas tecnica. Portanto, iremos caracterizar o erro lateral do robô para auxiliar na escolha de uma velociadade ideal e compensar se um motor estiver mais forte que o outro.
Na figura abaixo, vemos o histograma dos erros de translação horizontais, em cm (direita é positivo e esquerda é negativo). Vemos que, nesse caso, quanto mais lenta for a potencia do robô menor o erro. No entanto, uma potencia baixa demais pode causar o travamento do motor. Para obter essas medidas, mantivemos o motor ligado por 3 segundos sob as potências assinaladas e anotamos o deslocamento em relação a reta que o robô deveria seguir.
Potência 20 | Potência 60 | Potência 100 | |
---|---|---|---|
Média | -0.4 | -0.6 | -1 |
Desvio Padrão | 1.459 | 2.260 | 2.915 |
É facil ver que quanto maior o lado do quadrado maior será o efeito desse erro pois o erro cresce conforme o tempo de autuação.
Erro de Rotação
O erro de rotação é fundamental para a execução do quadrado. Para calcular esse erro utilizamos uma vareta sob o robô e atuamos um dos motores para frente e o outro para traz por um tempo constante, para que ele girasse no próprio eixo. O tempo utilizado foi obtido através de experimentos previos que obtiveram média próxima de 90 graus.
Potência 20 | Potência 60 | Potência 100 | |
---|---|---|---|
Média | 89.1 | 89.6 | 90.4 |
Desvio Padrão | 5.721 | 3.994 | 4.274 |
Implementação do Algoritmo
Primeiramente, uma estrutura básica foi feita para o algoritmo, com a interface de LCD. A usuário pode escolher se quer que o carrinho execute um quadrado ou uma circunferência, através dos botões start e stop. Depois, caso a escolha feita seja o quadrado, pode escolher o tamanho do lado girando o potenciômetro (valores de 10 a 50 são aceitos, em cm).
Então, as funções FazQuadrado e FazCircunferencia foram esquematizadas, cada uma sendo chamada 3 vezes de acordo com a escolha. Considerando o tempo em função da distância (o lado do quadrado, por exemplo), a partir de testes foi possível obter uma constante que os relacionasse, para o movimento retilíneo e em determinada potência dos motores. Assim, para o valor de distância desejado, foi possível colocar o tempo certo que os motores ficariam ligados.
A rotação, no entanto, é algo constante. Para um valor de potência do motor, o tempo de rotação de 90º é sempre o mesmo, independente do tamanho do lado do quadrado. Esse valor foi obtido através de testes e ajustes.
Durante os ajustes das constantes do algoritmo fizemos diversas medidas. Calculamos o erro de translação para v = 20, 60 e 100, como mostrado na tabela abaixo:
Calculamos também o tempo de rotação de 90º para cada valor de potência:
No algoritmo, utilizamos as seguintes constantes para o quadrado:
- TEMPO_ROTACAO: 0.4985 (Com potência 60)
- VAR_A_Q: 1.0/12.7 (Constante que relaciona distância ao tempo, com potência 20)
Além disso, da distância (tamanho do lado) foi decrescido 1cm, pois cada curva realizada pelo robô acrescenta 0.5cm ao lado, acrescentando ao todo 1cm para cada lado.
Apesar de ser utilizada a potência 20 para o movimento em linha reta, foi feito um pequeno compensamento devido à diferença entre os motores (o que antes gerava um erro para quadrados com 30cm de lado, mas era imperceptível para quadrados de 10 ou 15cm de lado). Assim, o motor esquerdo utiliza a potência 20, enquanto o direito utiliza a potência 19.
Abaixo, vídeo da execução do quadrado:
Para a execução da circunferência, medimos qual deveria ser a diferença entre as potências para a geração de uma circunferência de raio de 30cm. Não foi possível fazer uma função para isso, dado que a função da potência do motor é complexa, e não linear (por exemplo, se dobrarmos a potência de 20 para 40, isso não significa que a distância percorrida será dobrada… o comportamento é inesperado).
Após diversas tentativas, constatamos que o melhor valor seria V=30 para o motor esquerdo e V=14 para o direito. Depois, pudemos calcular o tempo para a realização das 3 circunferências, que foi de 14.68 segundos.
Abaixo, vídeo da execução da circunferência:
Observações:
* Foi possível constatar que a potência do motor, mesmo regulada para determinado valor (como V=30, por exemplo), muda de acordo com a bateria da handyboard. Isso gera grande dificuldade, pois torna os resultados imprevisíveis. Uma realização impecável de uma tarefa em um dia, pode se tornar uma realização falha em outro, devido à isso.
* As condições ambientes, como por exemplo a superfície em que o robô anda, também afetam muito a realização da atividade
Código Fonte
#define MOTOR_ESQ 0 #define MOTOR_DIR 1 #define PI 3.14 #define VAR_A_Q (1.0/12.7) #define TEMPO_ROTACAO 0.4985 #define POTENCIA_ESQ_C 30 #define POTENCIA_DIR_C 14 int main(){ int valor,i; while(1){ printf("\n\n"); printf("Start- Quadrado Stop- Circulo"); while(1){ //rotina quadrado if(start_button()){ while(start_button()); printf("\n\n"); printf("Ajuste o lado- pressione Start"); sleep(5.0); //ajuste da distancia - valor entre 0 e 50 cm while(!start_button()){ valor = knob()*40/255 +10; printf("\n\n"); printf("lado de %d cm",valor); sleep(0.1); } while(start_button()); printf("\n\n"); printf("Iniciando..."); sleep(3.0); for(i=0;i<3;i++){ FazQuadrado((float)valor); } break; } //rotina circulo else if(stop_button()){ while(stop_button()); /*printf("\n"); printf("Ajuste o raio - pressione Start"); sleep(5.0); //ajuste da distancia - valor entre 0 e 50 cm while(!start_button()){ valor = knob()*40/255 + 10; printf("\n\n"); printf("raio de %d cm",valor); sleep(0.1); } while(start_button());*/ printf("\n\n"); printf("Iniciando..."); sleep(3.0); for(i=0;i<3;i++){ FazCircunferencia((float)valor); } break; } } } } //percorre trajetoria de um quadrado, com parametro lado em cm void FazQuadrado(float lado){ float tempo,tempoIni; int i; //relacao entre a distancia a ser percorrida e o tempo da atuao dos motores tempo = VAR_A_Q*(lado-1.0) + VAR_B_Q; //-1, pois eh o tamanho da borda tempoIni = VAR_A_Q*(lado+1.0) + VAR_B_Q; for(i=0;i<4;i++){ motor(MOTOR_ESQ,20); motor(MOTOR_DIR,19); sleep(tempo); ao(); sleep(0.5); motor(MOTOR_ESQ,60); //85 motor(MOTOR_DIR,-60); //-35 sleep(TEMPO_ROTACAO); ao(); sleep(0.5); } } //percorre trajetoria de uma circunferencia, com parametro raio em cm void FazCircunferencia(float raio){ float tempo = 14.68; /* não foi utilizado, pois não foi possível relacionar o raio */ float distancia = 2.0*PI*raio; // tempo = VAR_A_C*distancia + VAR_B_C; //de algum modo, relacionar a potencia dos motores com a distancia ou o raio //potencia nao pode ser constante, pois quanto menor o raio, maior deve ser a diferenca //de potencia entre os motores motor(MOTOR_ESQ, POTENCIA_ESQ_C ); motor(MOTOR_DIR, POTENCIA_DIR_C ); // Para raio de 10 cm; m1 = 20 m2 = 5 sleep(tempo); ao(); }