Tabela de conteúdos

Trabalho Pratico 2

Objetivo

Montagem do robô

As unicas modificações no robô foram as intalações dos sensores e a adição de um pequeno compartimento para a realização da identificação dos blocos, cujo objetivo é manter as condições de luminosidade constanstes.

Dificuldades encontradas

- Lidar com os sensores

Os sensores se mostraram um pouco ineficientes quando a superficie do objeto a ser identificado nao era liso (exemplo:Blocos fornecidos, eram muito porosos o que dificulta a reflexão da luz proveniente do emissor). Tambem apresentaram resultados ruins quando havia muito reflexão na superfie (exemplo: plista sobre a qual foi montada a trajetoria com a linha preta quando esta estava sujeita a forte iluminação artificial).

- Resolução dos problemas

A solução é tratar os sinais dos sensores por meio de algoritimos adequados a cada aplicação.

Resultados Obtidos dos testes

Apos a realização dos testes propostos obtivemos os seguintes resultados:

Iluminação constante, distância 3mm

Constante_3mm.jpg

Sem Iluminação constante, distância 3mm

Variante_3mm.jpg

Podemos observar que a variação da luminosidade causou tambem uma flutuação do sinal em torno da média e um deslocamento para baixo da média.

Curva Sinal x Distância

Sinal_x_Dist.jpg

O comportamento é não linear, mas para distâncias menores que 10mm e maiores que 3mm podemos fazer uma aproximação linear razuavel.

Regressao_4.jpg

Fizemos entao uma regressão de quarta ordem que abrange os 4 pontos.

Efeito dos motores na leitura do sensor

Motor_3mm.jpg

Os motores provocam oscilação do sinal e queda no valor médio.

Validação

Para distâncias diferentes das anteriores obtivemos 4 medidas e 4 valores calculados apartir da equação da regressão de 4 ordem mostrada em figura anterior e os respectivos erros:

* Para Dist = 4,5mm

 Medido = 11
 Calculado = -7,48
 Erro = 18,48

* Para Dist = 7,5mm

 Medido = 92,98
 Calculado = 69,94
 Erro = 23,04

* Para Dist = 10,5mm

 Medido = 171,84
 Calculado = 162,65
 Erro = 9,19

* Para Dist = 13,5mm

 Medido = 212,92
 Calculado = 206,49
 Erro = 6,43
Influência da superfície na identificação dos blocos

Cores_x_Dist.jpg

Vemos pelo gráfico que a melhor distancia é 3mm, pois propicia a maior distancia entre os sinais. Além disso vimos que penas variações na distancia podem provocar troca entre as cores. O algoritimo que utilizamos é baseado na media do sinal obtido atraves do sensor.

LISTA DE EXERCICIOS

Normalização:

1-Para os valores medidos do sensor temos:

Máximo de Luz Refletida = 6 Mínimo de Luz Refletida = 252

/*normal.c*/ int normalize (int light) { int MAX_LIGHT = 6; int MIN_LIGHT = 252;

int output = 100 - ( (light – MAX_LIGHT)*100 / (MIN_LIGHT – MAX_LIGHT) );

if (output < 0) output = 0; if (output > 100) output = 100;

return output; }

2-Utilizando a função normalize para o sensor fotoelétrico QRB1113 obtivemos os valores esperado, uma vez que foram normalizados. A faixa de valores que a função retorna é de zero a cem.

3-Quando o sensor estiver em contato com uma superfície mais refletora do que a utilizada na calibração (superfícies brancas) ou quando a superfície for menos refletora que a utilizada na calibração (superfícies pretas) o valor encontrado estará fora do range; ou seja, MAX_LITHG > valor medido ou MIN_LIGHT < valor medido.

Valores Históricos:

1-Para um array de 50 posições e uma frequência de aquisição de dados de 7,8125Hz temos:

Tempo = 50/7,8125 e Tempo = 6,4 segundos

3-/* stuck.c*/

void STUCKROBOT() { int valores[50]; int i = 0; float x; while(1)

{
 If(i!=0)
 {
    x = analog(2);
    if( x != valores( i – 1 ) ) { i = 0; }
    valores( i ) = x;
    if( i == 49) { printf(“stucked”); }
 }      
 else{ valores( i ) = analog(2); }
 i++;
 sleep(0.1);
}

}

O programa compara o valor lido com o último valor do buffer, caso seja igual armazena na posição corrente do buffer, caso seja diferente armazena na primeira posição do buffer. Se o buffer encher indica que todos os valores são iguais e que o robô está parado.

Codigo Fonte

funcoes.ic

/*Variavel global*/ int vetCont; int vetCont2;

/* * * Funcionalidades * * */

int calibraCor(int cor) {

  float media, desvio;
  calculaDados();
  media = calculaMedia();
  MEDIA_COR[cor] = media;
  
  return 1;

}

int calibraPretoBranco() {

  
  float sensorLocomocao[2][2];
  printf("Calibrar preto  nos sensores.\n");
  while(!start_button());
  while(start_button());
  calculaDadosPretoBranco(PRETO, sensorLocomocao);
  
  printf("Calibrar branco nos sensores.\n");
  while(!start_button());
  while(start_button());
  calculaDadosPretoBranco(BRANCO, sensorLocomocao);
  
  calculaMediaPretoBranco(sensorLocomocao);
  
  FUNCAO_ATIVA = 0;
  

}

int identificaCor() {

  int  melhor_cont, i;
  float media, melhor, temp;
  
  calculaDados();
  media = calculaMedia();   
  melhor = 256.0;
  
  for(i = 0; i < 4; i++)
    {
      temp = (media - MEDIA_COR[i]);
      if(temp < 0.0) {
          temp = temp*-1.0;
      }
      if (temp < melhor)
        {
          melhor = temp;
          melhor_cont = i;
      }
  }
  
  if (melhor_cont == VERDE)
    printf("Verde.\n");
  else if (melhor_cont == VERMELHO)
      printf("Vermelho.\n");
    else if (melhor_cont == AZUL)
        printf("Azul.\n");
      else if (melhor_cont == AMARELO)
          printf("Amarelo.\n");
        
        sleep(5.0);
  beep();
  return 1;

}

/* * * Locomocao * * */

int locomocao() {

  
  int tarefa_caminhar;
  int tarefa_matar;
  
  FUNCAO_ATIVA = 1;
  andarReto();
  tarefa_caminhar = start_process(caminhar());
  tarefa_matar = start_process(parar());
  
  while(FUNCAO_ATIVA);
  kill_process(tarefa_caminhar);
  kill_process(tarefa_matar);
  ao();
  
  return 1;

}

void caminhar() {

  
  while(1) {
      //Se sensor esquerdo entrar numa faixa branca vira pra esquerda
      if(((float)analog(PORTA_SENSOR_ESQ)) < MEDIA_PRETO_BRANCO[SENSOR_ESQ] &&
         ((float)analog(PORTA_SENSOR_DIR)) < MEDIA_PRETO_BRANCO[SENSOR_DIR]) {
          virarEsquerda();
      }
      
      //Se sensor direito entrar numa faixa preto vira pra direita
      if(((float)analog(PORTA_SENSOR_DIR)) > MEDIA_PRETO_BRANCO[SENSOR_DIR] &&
         ((float)analog(PORTA_SENSOR_ESQ)) > MEDIA_PRETO_BRANCO[SENSOR_ESQ]) {
          virarDireita();
      }
      
      //Se sensor direito entrar numa faixa preto vira pra direita
      /*if(((float)analog(PORTA_SENSOR_DIR)) > MEDIA_PRETO_BRANCO[SENSOR_DIR] &&
         ((float)analog(PORTA_SENSOR_ESQ)) < MEDIA_PRETO_BRANCO[SENSOR_ESQ]) {
          virarDireita();
      }*/
      
      //Se sensor direito entrar numa faixa preto vira pra direita
      if(((float)analog(PORTA_SENSOR_DIR)) < MEDIA_PRETO_BRANCO[SENSOR_DIR] &&
         ((float)analog(PORTA_SENSOR_ESQ)) > MEDIA_PRETO_BRANCO[SENSOR_ESQ]) {
          andarReto();
      }
  }    

}

void virarEsquerda() {

  motor(MOTOR_ESQ, (int)(-1*POTENCIA_MOTOR_ESQ));
  motor(MOTOR_DIR, POTENCIA_MOTOR_DIR);   

}

void virarDireita() {

  motor(MOTOR_ESQ, POTENCIA_MOTOR_ESQ);
  motor(MOTOR_DIR, (int)(-1*POTENCIA_MOTOR_DIR));   

}

void andarReto() {

  motor(MOTOR_ESQ, POTENCIA_MOTOR_ESQ);
  motor(MOTOR_DIR, POTENCIA_MOTOR_DIR);   

}

/* * * * Funcoes auxiliares * */

float calculaMedia() {

  
  int i;
  int m = 0;
  for(i = 0; i < vetCont; i++) {
      m += VET_DADOS[i];
  }
  return ((float) m / (float) vetCont);

}

float calculaMediaPretoBranco(float sensorLocomocao[][]) {

  MEDIA_PRETO_BRANCO[SENSOR_ESQ] = (sensorLocomocao[SENSOR_ESQ][PRETO] + sensorLocomocao[SENSOR_ESQ][BRANCO])/2.0;
  MEDIA_PRETO_BRANCO[SENSOR_DIR] = (sensorLocomocao[SENSOR_DIR][PRETO] + sensorLocomocao[SENSOR_DIR][BRANCO])/2.0;

}

int calculaDados() {

  
  int tarefa_dados;    
  tarefa_dados = start_process(adquirirDadosCor());
  
  sleep(5.0);
  beep();
  kill_process(tarefa_dados);
  
  return 1;

}

void adquirirDadosCor() {

  vetCont = 0;
  printf("Aguarde...\n");
  while(1)
    {
      VET_DADOS[vetCont++] = analog(PORTA_SENSOR_COR);
      sleep(0.1);
  }

}

void calculaDadosPretoBranco(int cor, float sensorLocomocao[][]) {

  int i;
  int m = 0;
  int tarefa_dados;    
  tarefa_dados = start_process(adquirirDadosPretoBranco());
  
  sleep(5.0);
  beep();
  kill_process(tarefa_dados);
  
  
  m = 0;
  for(i = 0; i < vetCont; i++) {
      m += VET_DADOS[i];
  }
  sensorLocomocao[SENSOR_ESQ][cor] = ((float) m / (float) vetCont);
  
  m = 0;
  for(i = 0; i < vetCont2; i++) {
      m += VET_DADOS2[i];
  }
  sensorLocomocao[SENSOR_DIR][cor] = ((float) m / (float) vetCont2);
  
  

}

void adquirirDadosPretoBranco() {

  vetCont = 0;
  vetCont2 = 0;
  printf("Aguarde...\n");
  while(1)
    {
      VET_DADOS[vetCont++] = analog(PORTA_SENSOR_ESQ);
      VET_DADOS2[vetCont2++] = analog(PORTA_SENSOR_DIR);
      sleep(0.1);
  }

}

void parar() {

  
  while(!stop_button());
  while(stop_button());
  FUNCAO_ATIVA = 0;

}

menu.ic

#define MOTOR_ESQ 1 #define MOTOR_DIR 3 #define TEMPO_30_CM 2.0 #define TEMPO_90_GRAUS 1.15 #define VERDE 0 #define VERMELHO 1 #define AZUL 2 #define AMARELO 3 #define PRETO 0 #define BRANCO 1 #define PORTA_SENSOR_COR 4 #define PORTA_SENSOR_ESQ 2 #define PORTA_SENSOR_DIR 6 #define SENSOR_ESQ 0 #define SENSOR_DIR 1

/*Variavel global responsavel pelo armazenamento da potencia dos motores*/

int POTENCIA_MOTOR_ESQ, POTENCIA_MOTOR_DIR; int FUNCAO_ATIVA; int VET_DADOS[100]; int VET_DADOS2[100]; float MEDIA_COR[4]; float MEDIA_PRETO_BRANCO[2];

void menu() { char menuPrincipal[5][30] = {“1- Seguir linha preta”, “2- Identificar blocos”, “3- Calibrar cores”, “4- Calibrar preto e branco”, “5- Pegar Dados”};

  
  int item, contador, retorno = 1;
  
  POTENCIA_MOTOR_ESQ = 50;
  POTENCIA_MOTOR_DIR = 50;
  
  
  while(1) {
      
      #ifdef DEBUG
        printf("Opcao escolhida: %d\n", contador);
      #endif
      
      if(start_button())  { //Caso alguma opcao tenha sido marcada
          while(start_button()); //Aguarda que tire-se o dedo do butao start
          
          if (contador == 1) {
              retorno = locomocao();
          } else if (contador == 2) {
                retorno = identificaCor();
            } else if (contador == 3) {
                  retorno = menuCalibracaoCor();
              } else if (contador == 4) {
                    retorno = menuCalibracaoPretoBranco();
                } else if (contador == 5) {
                      retorno = calculaDados();
                  }
      } else {
          if(retorno == 1) {
              imprimeMenu2(&contador, 4, menuPrincipal);
              retorno = 0;   
          } else {
              imprimeMenu(&contador, 4, menuPrincipal);
          }            
      }        
  }

}

int menuCalibracaoCor() {

  int item;
  int retorno;
  char menu[4][20] = {"1- Verde", "2- Vermelho", "3- Azul", "4- Amarelo"};
  
  while(1) {
      
      #ifdef DEBUG
        printf("loop motoresMenu\n");
      #endif
      
      if(stop_button()) {
          
          while(stop_button());
          return 1;
          
      } else if(start_button()) {
            
            while(start_button());
            
            retorno = calibraCor(item - 1);
            
            #ifdef DEBUG
              printf("Retornou de calibrar angulos\n");
            #endif
            
        } else {
            if(retorno == 1) {
                imprimeMenu2(&item, 4, menu); 
                retorno = 0;
            } else {
                imprimeMenu(&item, 4, menu);
            }
        }
      
  }

}

int menuCalibracaoPretoBranco() {

  
  int tarefa_calibra;
  int tarefa_matar_calibra;
  
  FUNCAO_ATIVA = 1;
  
  tarefa_calibra = start_process(calibraPretoBranco());
  tarefa_matar_calibra = start_process(parar());
  
  while(FUNCAO_ATIVA);
  kill_process(tarefa_calibra);
  kill_process(tarefa_matar_calibra);
  
  return 1;

}

/*Funcao chamada para imprimir a opcao do menu possibilitando a livre movimentacao entre as mesmas.*/

void imprimeMenu(int *contador, int tam, char arranjo[][]) {

  int resultado, item;
  item = (255 / tam) + 1;
  resultado = (*contador) * item;
  if (knob() > resultado) {
      //(*contador)++;
      (*contador) = (knob() / item) +1;
      printf("%s\n",arranjo[knob() / item]);
      //printf("%s\n",arranjo[((*contador)-1) % tam]);
  } else if (knob() < ((*contador)-1) * item) {
        (*contador) = (knob() / item) +1;
        printf("%s\n",arranjo[knob() / item]);
        //        (*contador)--;
        //      printf("%s\n",arranjo[((*contador)-1) % tam]);
    }

}

void imprimeMenu2(int *contador, int tam, char arranjo[][]) {

  int item;
  item = (255/tam) + 1;
  
  printf("%s\n",arranjo[knob() / item]);
  
  (*contador) = (knob() / item) +1;

}

main.ic

main apenas chama a função menu

Documentação PDF