Tabela de conteúdos

SAS - Seek and Shoot

Introdução

O primeiro trabalho prático requeria a construção de um robô móvel com um sistema de controle cinemático implementado. Para sua construção foi fornecido um kit de peças Lego, 2 motores elétricos e sensores break-beam. Para testar o controle cinemático, era preciso que o robô realizasse duas tarefas. Na primeira, precisaria realizar três quadrados (de lado 30cm) consecutivos e na segunda, três círculos (de raio de 30cm) consecutivos. As trajetórias deveriam ser marcadas em uma superfície.

Montagem

Para montar o robô inicialmente nos baseamos na estrutura proposta por Fred J. Martin. No entanto essa se tornou inviável quanto a disposição dos sensores e rodas. Experimentamos várias idéias visando aperfeiçoar a estrutura quanto à estabilidade, firmeza e velocidade. Pudemos perceber que as mais simples alterações em relação à qualquer um dos fatores implicavam em mudanças em toda a estrutura do robô. Na versão apresentada conseguimos um boa relação entre estabilidade e velocidade, porém, a estrutura não ficou firme como esperado. Dessa forma, pretendemos nos próximos trabalhos melhorar sua firmeza sem comprometer os demais aspectos.

Para realizar a odometria utilizamos shaft-encoders, construídos a partir de dois sensores break-beam, montados como na imagem abaixo.

No primeiro projeto realizado pelo grupo os sensores foram instalados no eixo da roda com o objetivo de captar apenas as reais rotações da roda. Esta montagem se mostrou pouco eficiente pois os sensores captavam poucas rotações devido as reduções e o resultado da velocidade de rotação do motor não era preciso o suficiente para aplicação de controle de maneira eficiente. Portanto o Shaft-Encoder foi instalado diretamente no eixo do motor para que o sensor conseguisse uma maior resolução na captura de dados. Dessa forma conseguimos obter um maior número de pulsos gerados, o que propiciou melhores condições para a realização do controle de movimentação do robô.

Para demarcar o trajeto percorrido pelo robô foi modificada uma caneta hidrocor, a qual foi colada sob uma peça lego do repositório de peças extras. Em prol de minimizar desvios no traçado da rotação do robô, esta estrutura foi afixada de forma que a ponta da caneta ficou disposta no centro dos eixos. A montagem desse módulo é ilustrada pela figura abaixo.

Implementação

Com os sensores instalados o próximo desafio era obter a relação entre o número de counts e a distância percorrida em centímetros. Como cada pulso corresponde à uma borda de descida ou subida, cada furo da roda lego utilizada (figura acima) corresponde à dois counts. Dado o raio da roda r=2,1cm, e o perímetro p=13,1943cm, e que a redução do eixo é de 1:24, temos que a cada 12 counts (um giro do motor), o robô se desloca p/24=0.5497cm.

Controle

Para fazer o controle do robô estabelecemos como objetivo a velocidade das rodas. Caso, a velocidade de uma das rodas estivesse acima ou abaixo do esperado, a potência do seu motor correspondente era diminuída ou aumentada respectivamente.

Execução do Quadrado

No caso do desenho do quadrado, o objetivo era manter as duas velocidades constantes e de mesmo módulo sempre. No primeiro gráfico observamos o número de counts de cada motor na execução do percurso, bem como a diferença entre eles. Em seguida contrastamos a potência aplicada em cada motor.

A partir da análise dos gráficos acima, podemos evidenciar o erro entre as rodas durante a execução da tarefa e a sua redução à zero ao fim da mesma. Observamos também que o erro de rotação ia se acumulando, levando o robô à não coincidir o traçado dos três quadrados. Mesmo assim o resultado obtido foi muito bom, dado que utilizamos apenas dois sensores break-beam.

Execução do Círculo

Porém, no caso do círculo, o objetivo era manter uma diferença constante entre as velocidades das duas rodas, traçando assim uma curva. Essa diferença proporcional varia de acordo com a dimensão requerida do círculo e é dada pela razão dos raios das trajetórias a serem percorridas por cada roda. Como a distância entre as rodas é de 15cm, e a caneta é colocada no centro do eixo, p = r1/r2 = (37.5/22.5) = 1.66, onde r1 e r2 são os raios das trajetórias da roda interna e externa, respectivamente, à circunferência tracejada. Os gráficos abaixo ilustram a diferença de potência aplicada nos motores e a relação entre as velocidades das rodas.

Exercícios Propostos

Exercício 1

Para a realização do exercício foi montado uma estrutura composta de um motor, uma roda e um shaft-encoder (através de um sensor break-beam).

Com a constante derivativa D=.25 valendo ¼ de P (P=1.00), observamos uma maior demora para a estabilização, dada a ocorrência de vários overshoots de pequena amplitude, como ilustrado pelos gráficos abaixo.

Quando definimos D=1.00 e P=2.00 inicialmente observamos uma maior amplitude dos overshoots, mas uma estabilização mais rápida.

Ao utilizar D=0.5 e P=1.00 a estabilização foi rápida e suave, como representado nas figuras abaixo.

Exercício 4

A principal dificuldade encontrada em manter o robô em uma trajetória retilínea na calibração dos parâmetros do motor (o tempo de reação dos motores e constantes de ganho propocional e derivativo). Outro fator decisivo foi a produção de pulsos para aumentar a resolução e precisão na atuação. Inicialmente os sensores foram instalados no eixo da roda com o objetivo de captar apenas as reais rotações da roda. Esta montagem se revelou ineficiente já que os sensores captavam poucas rotações devido as reduções e o resultado da velocidade de rotação do motor não era preciso o suficiente para aplicação de controle de maneira eficiente. Portanto o Shaft-Encoder foi instalado diretamente no eixo do motor para que o sensor conseguisse uma maior resolução na captura de dados. Dessa forma conseguimos obter um maior número de pulsos gerados, o que propiciou melhores condições para a realização do controle de movimentação do robô.

Conclusão

Neste trabalho foi construído um robô móvel dotado de um controle cinemático utilizando os modelos de controle proporcional-derivativo (PD). Descrevemos os passos da montagem e as dificuldades encontradas bem como os resultados da execução das tarefas.

Código Fonte

#include sencdr5.icb
#include sencdr6.icb
 
 
#define counts_30cm 623
#define counts_circle37 4950
#define angle_90 237
#define angle_10 26
 
int main(){
 
    int v0 = 60;
    int v1 = 50;
    int D, P, tmp0, D1, P1, tmp1, i, function;
 
    printf("\n\nEscolha a funcao no knob");
    function = 0;
    while(!stop_button()){
        while(!start_button()){
            if(knob() < 128){
                if(function != 1){
                    printf("\n\nFuncao selecionada: Quadrado");    
                    function = 1;
                }
            } else {
                if(function != 2){
                    printf("\n\nFuncao selecionada: Circulo");    
                    function = 2;
                }
            }
        }
 
        switch(function){
            case 1:
              squares(3);
            break;
            case 2:
              circle(3);
            break;
        }
        off(0);off(1); 
    }
 
 
    return 0;
}
 
void turn_10(){
    int P,v0,v1;
    v0 = 50;
    v1 = 50;
 
    encoder5_counts = 0; 
    encoder6_counts = 0;
 
    while(1){
        P = (encoder5_counts - encoder6_counts);
        if(P<0) {
            v0 -= 1;
            v1 += 1;
        }
        if(P>0) {
            v0 += 1;
            v1 -= 1;
        }
        motor(1, (int)v1);           
        motor(0, -(int)v0);
 
        if(stop_button())break;
 
        printf("\n\nc0: %d c1: %d", encoder6_counts, encoder5_counts);
 
        if(encoder5_counts > angle_10 || encoder6_counts > angle_10) break;
 
        msleep(50L);          
    }
 
 
 
}
 
/** Desenha o numero de quadrados passado como parametros.*/
void squares(int n){
    int i;
    for(i=0; i<n*4; i++){
        goAhead(counts_30cm);
        off(0);off(1);
        sleep(.2);
        turn_90();
        off(0);off(1);
        sleep(.2);      
    }
}
 
/** Gira o robo sobre o eixo 90 graus.*/
void turn_90(){
    int P,v0,v1;
    v0 = 50;
    v1 = 50;
 
    encoder5_counts = 0; 
    encoder6_counts = 0;
 
    while(1){
        P = (encoder5_counts - encoder6_counts);
        if(P<0) {
            v0 -= 1;
            v1 += 1;
        }
        if(P>0) {
            v0 += 1;
            v1 -= 1;
        }
        motor(1, (int)v1);           
        motor(0, -(int)v0);
 
        if(stop_button())break;
 
        if(encoder5_counts > angle_90 || encoder6_counts > angle_90) break;
 
        msleep(50L);          
    }
 
 
}
 
/** Anda em linha reta pela distancia passada como parametro, em counts */
void goAhead(int distance){
    int P,v0,v1;
    int goal, i;
    v0 = 50;
    v1 = 50;
 
    encoder5_counts = 0; 
    encoder6_counts = 0;
    goal = 0;
    while(!goal){
        P = (encoder5_counts - encoder6_counts);
 
        if(P<5) {
            v0 -= 1;
            v1 += 1;
        }
        if(P>5) {
            v0 += 1;
            v1 -= 1;
        }
 
        motor(1, (int)v1);           
        motor(0, (int)v0);
 
        if(stop_button())break;
 
        //Checa se a distancia foi atingida.
        for(i=0; i< 6; i++){
            if(encoder5_counts > distance || encoder6_counts > distance){
                goal = 1;
                break;
            }
            msleep(50L);
        }
    }
}
/** Desenha o numero de circulos de 30cm de raio passado como parametro. */
void circle(int n){
    int v0,v1, acum, i;
 
    v0 = 0;
    v1 = 0;
 
    for(i=0; i<n; i++){
 
        encoder5_counts = 0; 
        encoder6_counts = 0;
        acum = 0;
 
        while(acum < counts_circle37){
            if(encoder6_counts > 6){
                v0 -= 1;
            }
            if(encoder6_counts < 6){
                v0 += 1;
            }
            if(encoder5_counts > 10){
                v1 -= 1;
            }
            if(encoder5_counts < 10){
                v1 += 1;
            }
 
            motor(1, (int)v1);           
            motor(0, (int)v0);
 
            if(stop_button())break;
 
            acum += encoder5_counts;
 
            encoder5_counts = 0; 
            encoder6_counts = 0;
 
            msleep(100L);          
        }
    }   
}

Referências

MARTIN, Fred G.Robotic Explorations: An Introduction to Engineering Through Design. Prentice Hall; ISBN: 0-130-89568-7.