====== GRUPO 3 - Breakway Builders - TP 1 ======
===== Membros da Equipe =====
* Douglas Martins
* Elerson Rubens
* Rodrigo Maffra
* Roger Melo
===== Introdução =====
O objetivo deste trabalho é a familiarização dos alunos com a montagem lego e os principais meios de controle cinemático de um robô móvel. Para isso o grupo tem como tarefa a construção de um robô que execute ações específicas conforme descrito na tarefa.
===== Tarefas a serem realizadas =====
- Montar o HandyBug similar ao 9645 ([Martin] pg. 30-51)
- Controle PD - Utilizar os sensores break-beam para construir shaft-encoders. Fazer a montagem mostrada na Figura 5.9. Seção 5.2.3, exercícios 1 e 4.
- Montar uma caneta , marcador, etc. de tal forma que possa marcar a trajetória descrita pelo robô.
- Medir o erro de translação - Atuar os motores por um tempo constante e medir a distância percorrida para V = 20, 60 e 100.
- Medir o erro de rotação - Atuar os motores de forma que o robô gire 90 graus e medir o erro obtido para V = 20, 60 e 100.
- **Tarefas a serem apresentadas**:
* Fazer o robô realizar uma trajetória quadrada de 30 cm x 30 cm por 3 vezes consecutivas.
* Fazer o robô realizar uma trajetória circular de raio 30 cm por 3 vezes consecutivas.
===== Montagem do Robô =====
Foram realizadas diversas montagens até chegar ao modelo final apresentado na figura abaixo.
* Versão 1: foi feita antes da disponibilização do TP1, sem se basear na montagem 9645([Martin] pg. 30-51). O robô apresentou diversos problemas que impossibilitaram o prosseguimento com aquele modelo.
* Versão 2: A partir da disponibilização do TP1, o grupo começou a seguir o modelo proposto pelo trabalho. Tiveram que ser realizadas algumas modificações no projeto 9645, pois o projeto não comportava bem a montagem do motor que não pertencia ao lego. Além disso foram realizadas um aumento ao invés de uma redução na montagem das coroas, a fim de dar mais velocidade ao carro. O carro comportou-se bem, mas a inclusão dos shaft-encoders nos obrigou a realizar algumas modificações no projeto.
{{:cursos:introrobotica:2011-2:grupo03:versao2.jpg|}}
* Versão 3: Com a disponibilização dos shaft-encoders, houve a necessidade de realizar uma modificação na montagem, a fim de obter um controle mais preciso, e para isso foram realizadas duas modificações principais: A primeira modificação consistiu na redução da velocidade do robô, com a troca das coroas, que possibilitaram correções mais amenas; A segunda modificação ocorreu no posicionamento dos shaft-encoders para leitura de velocidade, antes realizada diretamente no eixo da roda e depois sobre o eixo principal no qual o motor atuava, aumentando assim o número de rotações por minuto e conseqüentemente, tornando mais fina a calibragem passada para a programação do robô.
* Versâo 4: Por fim, houve a necessidade de inserir a caneta entre os eixos dos motores de forma que a mesma fique no centro de rotação do robô. Esse trabalho ja estava previsto, mas devido a falta de encaixe entre caneta e lego, tivemos que realizar algumas adaptações no carro com a finalidade de inserir e prender a caneta no carro.
{{:cursos:introrobotica:2011-2:grupo03:versao3.jpg|}}
===== Programação do Robô =====
A partir da versão 2 da montagem do robô iniciamos a sua programação. Como o trabalho prático requeria a realização de duas formas geométricas ( circulo e quadrado) fizemos dois programas diferente que no final foram condensados em um unico programa com uma interface amigável para realizar a escolha do programa a ser rodado.
Código:
#use "quad2.ic"
#use "circ2.ic"
//#use "cmucamlib.ic"
void main()
{
char a[3][16]={"Menu: Quad","Menu: Circ","Menu: Sair"};
printf("Press START\n");
while(!start_button());
printf("rode o knob para selecionar programa\n");
sleep(1.0);
while(1) {
int sel;
printf("rode o knob para selecionar programa\n");
sleep(1.0);
sel = select_string(a,3);
if(sel==0) quad();
else if(sel==1) circ();
else if(sel >=2 ) break;
}
printf("Terminou\n");
}
==== Controle de PD ====
O controle desenvolvido para o trabalho tenta manter cada uma das rodas a uma velocidade predeterminada.
==== Progroma do Círculo ====
O programa do circulo tem um objetivo simples: manter uma determinada velocidade em uma roda e manter uma velocidade 64% (exatamente 9/14) menor na roda interna a fim de fazer o robô realizar uma trajetoria circular. A programação apresentou um ótimo resultado. Após isso, tivemos apenas que calcular a distância que o robô deveria percorrer para realizar três voltas.
Código:
/* circle handyBoard program created by group 3 - robotics introduction - dcc - ufmg*/
#include sencdr5.icb
#include sencdr6.icb
#define CSLEEP 50L
//valor inicial de power
#define CPOWER0 68
#define CPOWER1 38
//velocidade dos motores para curva de 90 graus
#define CVELPD0 14
#define CVELPD1 9
// proporcao para curvaa de 90 graus
#define CPROP 0.64285
//constantes PD
#define Ckd 1.0
#define Ckp 0.2
//costantes de erro
#define Cerr 1.0
//tamanho do circulo
#define QFIM 13959 // 4653*3
void circ() {
int velocidade0,velocidade1;
int count0,count1;
int power0,power1;
float dif;
encoder5_counts=0;
encoder6_counts=0;
while(!start_button());
while (1) {
//calcula a velocidade
velocidade0 = encoder6_velocity;
velocidade1 = encoder5_velocity;
//calcula o power do motor0
if(velocidade0 != CVELPD0)
{ power0 -= (int) Ckd*(velocidade0 - CVELPD0) ;
}
//calcula o power do motor1
if(velocidade1 != CVELPD1)
{ power1 -= (int) Ckd*(velocidade1 - CVELPD1);
}
//calcula a proporcao entre os counts ate o momento
if(encoder5_counts != 0) {
dif = ((float) encoder6_counts)/((float)encoder5_counts);
}else
{
dif = CPROP;
}
//altera power pela porporcao do erro
if(dif - CPROP > Cerr)
{ power0 -= (int)(Ckp*(dif - CPROP));
}
else if(dif - CPROP < -Cerr)
{ power1 -= -(int)(Ckp*(dif - CPROP)) ;
}
printf("pw0 %d vel %d",power0,encoder6_velocity);
printf("pw1 %d vel %d %d\n",power1,encoder5_velocity,(int)(dif));
motor(0,power0);
motor(1,power1);
//mantem countX atualizado
count0 = encoder6_counts;
count1 = encoder5_counts;
msleep(CSLEEP);
if(count0 >= QFIM) break;
if(stop_button()) break;
}
printf("c0 %d c1 %d",count0,count1);
off(0);
off(1);
}
==== Programa do Quadrado ====
Houve maior dificuldade no desenvolvimento do programa que faz um quadrado, uma vez que há a necessidade de o robô mudar sua direção de 90º. A programação foi desenvolvida, porém pequenos erros na mudança de direção fizeram com que a trajetória do quadrado não fechasse conforme planejado. Apesar disso, a execução da trajetória assemelha-se muito a um quadrado.
Código:
/*square handyBoard program created by group 3 - robotics introduction - dcc - ufmg*/
#include sencdr5.icb
#include sencdr6.icb
#define QSLEEP 20L
//valor inicial de power para 90 graus
#define QNOVPOWER0 6.0
#define QNOVPOWER1 -6.0
//valor inicail de power para reta
#define QPOWERRETA0 6.0
#define QPOWERRETA1 6.0
//vlocidade curva 90 graus
#define QVELPD0 8
#define QVELPD1 -8
//vlocidade reta
#define QVELRETA0 8
#define QVELRETA1 8
//constantes PD
#define Qkd 0.3 //0.3
#define Qkp 0.04 // 0.07
//erro a ser considerado
#define Qerrcd 0.0 //0
#define QPROP 0.0
//constantes para inecia
#define QcountsAcel 100.0
#define QcountsDacel 30
//tamanho quadrado
#define QLADO 1284
// tamnho para curva 90 graus
#define QARETO 375 //375
//funcao que desenha quadrado
void quad() {
int velocidade0,velocidade1;
int count0,count1,countAux0,countAux1,i;
int sair = 0;
float power0,power1;
float dif;
encoder5_counts=0;
encoder6_counts=0;
while(!start_button());
count0 = 0;
count1 = 0;
for(i = 0; i < 12; i++)
{
//inicia reta
power0 = QPOWERRETA0;
power1 = QPOWERRETA1;
//faz anda reto
while (1) {
//calcula a velocidade
velocidade0 = encoder6_velocity;
velocidade1 = encoder5_velocity;
power0 -= controleMotor(velocidade0,QVELRETA0);
power1 -= controleMotor(velocidade1,QVELRETA1);
printf("pw0 %f vel %d",power0,encoder6_velocity);
printf("pw1 %f vel %d %d\n",power1,encoder5_velocity,(int)(dif));
//calcula erro jah cometido
dif = (float) (count0 - count1);
//ajusta power de acordo com erro
if(dif - QPROP > Qerrcd)
{
power1 += (Qkp*(dif - QPROP));
// power0 -= (int)(kp)*dif + erro0;
}
else if(dif - QPROP < -Qerrcd)
{
power0 += -(Qkp*(dif - QPROP)) ;
//power1 += (int)(kp)*dif - erro1;
}
motor(0,(int)power0);
motor(1,(int)power1);
//manrtem o numero de counts atualizado
count0 += encoder6_counts - countAux0 ;
count1 += encoder5_counts - countAux1;
countAux0 = encoder6_counts;
countAux1 = encoder5_counts;
// completou lado quagrado
if((count0 + count1) >= QLADO) break;
msleep(QSLEEP);
if(stop_button() || sair == 1){ sair = 1; break;}
}
off(0);
off(1);
msleep(200L);
//inicia a curva
power0 = QNOVPOWER0;
power1 = QNOVPOWER1;
count0 = 0;
count1 = 0;
//faz 90 graus
while (1) {
//pega a velocidade
velocidade0 = encoder6_velocity;
velocidade1 = encoder5_velocity;
//pega o power necessario para a velocidade de destino
power0 -= controleMotor(velocidade0,QVELPD0);
power1 -= controleMotor(-velocidade1,QVELPD1);
printf("pw0 %f vel %d",power0,encoder6_velocity);
printf("pw1 %f vel %d %d\n",power1,encoder5_velocity,(int)(dif));
//ativa os motores
motor(0,(int)power0);
motor(1,(int)power1);
//mantem o numero de rotacoes atualizadas
count0 += encoder6_counts - countAux0 ;
count1 += encoder5_counts - countAux1;
countAux0 = encoder6_counts;
countAux1 = encoder5_counts;
//completou 90 graus
if((count0 + count1) >= QARETO) break;//
msleep(QSLEEP);
if(stop_button() || sair == 1){ sair = 1; break;}
}
off(0);
off(1);
msleep(200L);
// mantem o erro de rotacao
if(count0 > count1)
{
count1 = count0 - count1;
count0 = 0;
}else
{
count0 = count1 - count0;
count1 = 0;
}
if(stop_button() || sair == 1) break;
}
}
//faz o controle dos motores utilizando a velociadade
float controleMotor(int velocidadeMotor,int velocidadeObjMotor)
{
float power;
//faz om que motor mantenha um certa velocidade
if(velocidadeMotor != velocidadeObjMotor)
{
power = Qkd*((float)(velocidadeMotor - velocidadeObjMotor));
}
return power;
}
===== Montagem da Caneta =====
A montagem da caneta foi realizada de forma que a mesma ficou entre os eixos dos motores do robô e próximo ao seu centro de rotação. A montagem exigiu uma remodelagem de algumas peças do robô além do redimencionamento da caneta, mas foi realizada com sucesso.
===== Apresentação =====
A apresentação ocorreu sem maiores problemas. O objetivo de fazer uma trajetoria circular e outra quadrada foram realizadas pelo robô. As imagens a seguir ilustram os resultados obtidos.
{{:cursos:introrobotica:2011-2:grupo03:apresentacao.jpg|}}
Vídeo da apresentação:
[[http://www.youtube.com/watch?v=_EOfrhQGVLY]]
===== Tarefas Complementares =====
==== Exercícios 1 e 4 ====
=== Exercício 1 ===
{{:cursos:introrobotica:2011-2:grupo03:grafico1.jpg|}}
Esse exercício consistiu na implementação de um controle PD, de forma a igualar os resultados obtidos no livro.
=== Exercício 4 ===
A principal dificuldade encontrada em manter o robô em linha reta esteve na calibragem do controle. Sendo que o fator que mais afetou nossa calibragem foi a localização dos sensores. Quando os sensores estavam localizados na roda diretamente tivemos dificuldades devido ao baixo valor da velocidade que era capturada, mudamos então a localização desses sensores de forma que esses ficassem diretamente nos motorores, conseguindo, assim, um controle mais acurado para nossos propósitos.
==== Medição do erro de translação ====
{{:cursos:introrobotica:2011-2:grupo03:errostranslacao4.png|}}
Os gráficos e tabelas acima foram obtidos medindo, para cada valor de velocidade(20%,60% e 100% da velocidade), a distância percorrida pelo robô em um determinado tempo. Para realizar essas medidas foram feitos três experimentos para cada valor de tempo, sendo a média obtida plotada nos gráficos. Nesses gráficos é apresentado também a regressão linear da média obtida nos experimentos, mostrando assim que o valor esperado estava próximo do valor obtido nas medições. A equação produzida pela regressão linear representa a formula d = v*t.
==== Medição do erro de rotação ====
{{:cursos:introrobotica:2011-2:grupo03:rotacao2.png|}}
Nesse experimento o objetivo era medir o erro de translação com o robô em diferentes velocidades. Assim, o robô deveria rodar em cima do eixo principal 90º. A tabela acima mostra os resultados obtidos para a média de três experimentos para cada velocidade (20%,60% e 100% da velocidade).
==== Conclusão ====
O objetivo de familiarização com os lego e a handyboard foi atingido com sucesso. Durante o processo de aprendizagem tivemos a chance ter contato com uma parte mais prática do curso, e mesmo com diversas dificuldades, conseguimos realizar todas as tarefas propostas para o trabalho.