Ferramentas do usuário

Ferramentas do site


cursos:introrobotica:2018-1:grupo03:tp3

Aprendendo a trabalhar com Sensores

Introdução

O terceiro trabalho prático consistiu na construção de sensores. Eles foram:

  • Um ldr diferencial
  • Dois encoder's
  • Dois ópticos reflexivos

Em caráter especial o professor permitiu o uso de um encoder industrial para fazer a parte de odometria do trabalho, uma vez que não estavam sendo encontrados os materiais necessários para confeccioná-los. Além disso foi pedido a implantação de um controle PID.

Materiais

Robô

  • Lego
  • Arduino Mega 2560 (com respectivo cabo)
  • 2 motores DC
  • Alicate de corte
  • Alicate de bico
  • Fios
  • Ferro de solda
  • Solda
  • Termo Retrátil
  • Abraçadeira
  • Cola quente

LDR Diferencial

  • Plaquinhas
  • Resistências
  • Trimpots
  • Solução de percloreto de ferro
  • LDR
  • Filtro polarizador

Ópticos reflexivos

  • 2 sensores TCRT5000
  • 2 Resistências de 330Ω
  • 2 Resistências de 12KΩ
  • Fios
  • Ferro de Solda
  • Termoretratil
  • Solda de estanho
  • Alicate

Encoder

  • Enconder Rotativo P17 da GBK robotics

Procedimentos

A montagem do robô foi dividida em 4 etapas:

  • Consertar os problemas do TP2;

- Um dos problemas do TP2 era o menu, que era sempre necessário reiniciar o arduíno para usar outra função, tendo isso em mente, a nova implementação visa não ser necessário ter que reiniciar, e se precisar, não precisar que calibre ou demais contra-tempos.

  • Encoder e PID;

Na etapa de confecção do Controle PID primeiramente realizou-se um estudo detalhado sobre os motores através dos enconders que possibilitou a determinação de uma zona de tensão que seria vantajosa para a movimentação do robô e a caracterização de cada um dos dois motores que possibilitou determinar a diferença entre eles auxiliando a determinação das ações de controle. Apos isso inicio-se a confecção do controlador PID que determinava as atuações do robô para que esse se movesse com regularidade em 3 percursos diferentes : Reta,Triângulo e Quadrado com o valor de lado de tamanho determinado pelo usuário através de um seletor no display.

  • Seguidor de Linha;

O código do seguidor de linha seguiu a seguinte lógica:

  1. Se 0 0 : Virar 90º para a esquerda;
  2. Se 0 1 : Virar levemente para a esquerda;
  3. Se 1 0 : Virar levemente para a direita;
  4. Se 1 1 : Seguir reto;

O código embora aparentemente bom demonstrou não ter tanta autonomia para o robô.

  • LDR diferencial;

O LDR diferencial foi construído em cima de uma plaquinha que de cobre que depois foi corroída com uma solução de percloreto de ferro fazendo assim um circuito impresso. Os LDR's foram colocados dentro de um suporte para led de modo a entrar focar mais a entrada de luz, evitando interferências externas. Para refinar as leituras foram colocados dois trimpots e os ldrs colocados com um, a resistência na horizontal e outro na vertical, de modo que os filtros polarizadores direcionassem a luz para a resistência na posição correspondente. Sobre o código, a ideia a principio era fazer uma função recursiva que refinasse o alinhamento do sensor com a luz. Uma vez que essa ideia foi mal sucedida, a ideia passou a ser algo como: enquanto os valores não se encontram dentro das faixas da luz polarizadas,gire.

Documentação do código

A função para localizar, dada a entrada do LDR e uma variável pra receber a leitura do sensor, utiliza, como supracitado de parâmetros de comparação previamente estabelecidos e segue a lógica de enquanto não forem encontrados os parâmetros o robô fica rotacionando.

void orienta(int ldrDifValor,int ldrDif){
 while(ldrDifValor<(valor_comp_V+30) && ldrDifValor>(valor_comp_H+30)){
 motor1->run(BACKWARD);
 motor1->setSpeed(80);
 motor2->run(FORWARD);
 motor2->setSpeed(80);
 delay(1000);
 motor1->run(RELEASE);
 motor2->run(RELEASE);
 ldrDifValor = analogRead(ldrDif);
 lcd.print(ldrDifValor);
 delay(1000); 
 lcd.clear();
 if(ldrDifValor<100){
  lcd.print("Erro");
  break;
 }
}

O código do Menu é composto por 3 funções, onde elas são:

  • void Menu()
  • void Caminhos()
  • void Comprimentos(int a)

A função Menu() é feita para ser chamada apenas uma vez no loop(), onde internamente ela tem um while(1) para não necessitar de voltar no Loop, para uma implementação mais fácil. A função Menu() tem as opções para serem selecionadas: Localizacao, Caminhos, Seguidor Linha, e calibração; quando é selecionado Localizacao e Seguidor Linha, é chamado a função que faz essa determinada ação, e quando chamado Caminhos, se chama a função Caminhos(), que também faz parte do Menu. O código do Menu() é:

 void Menu(){
   lcd.clear(); 
   delay(500);
   int x=4, ant=3;
   int botao;
   while(1){ 
   botao = analogRead(0);
   if (x<= 0 || x>= 8) x=4;  
    if (x!=ant){
     switch(x%4){
      case 0:
      lcd.setCursor(0,0);lcd.print("  Localizacao   ");
      lcd.setCursor(0,1);lcd.print("<-            ->");
      break;
    case 1:
      lcd.setCursor(0,0);lcd.print("    Caminhos    ");
       lcd.setCursor(0,1);lcd.print("<-           ->");
      break;
    case 2:
      lcd.setCursor(0,0);lcd.print(" Seguidor Linha ");
       lcd.setCursor(0,1);lcd.print("<-          ->");
      break;
    case 3:
      lcd.setCursor(0,0);lcd.print("   Calibracao   ");
       lcd.setCursor(0,1);lcd.print("<-          ->");
      break;
     }
 }
 ant=x;
  if(botao >= 400 & botao < 600 ) // Reconfigurar os valores para o valor de esquerda
     x--;
   else if(botao >= 0 & botao < 100) // Reconfigurar os valores para o valor de direita
     x++;
   else if((botao >= 600 & botao < 800)||(botao >= 200 & botao < 300)) {// Foi apertado select ou down
    
    if      ((x%4+1) == 1) {// Foi selecionado a primeira função do robô: Localização
      /***********************************************************/
      //COLOQUE AQUI A FUNÇÃO QUE CHAMA A EXECUÇÃO DA LOCALIZAÇÃO
      /***********************************************************/
      lcd.print("Entrou");
      ldrDifValor = analogRead(ldrDif);
      lcd.print(ldrDifValor);
      orienta(ldrDifValor,ldrDif);
      motor1->run(RELEASE);
      motor2->run(RELEASE);
      lcd.print("Parou");
      lcd.clear(); 
    }        
    else if ((x%4+1) == 2) 
    Caminhos();  //Foi selecionado a segunda função do robô: de fazer caminhos diversos     
    else if ((x%4+1) == 3){ //Foi selecionado a terceira função do robô: Seguidor de linha.
     /********************************************************************/
     //COLOQUE AQUI A FUNÇÃO QUE CHAMA A EXECUÇÃO DO MODO SEGUIDOR DE LINHA
     /********************************************************************/     
      lcd.clear();
      while(1){
        leitura();
      }
    }    
    else if ((x%4+1) == 4){ //Foi selecionado a quarta função do robô: Calibrar os sensores.
    /*********************************************/
    //COLOQUE AQUI A FUNÇÃO QUE CHAMA A CALIBRAÇÃO
    /*********************************************/      
    lcd.clear();lcd.setCursor(0,0);lcd.print("Ainda nao feito");} // APÓS COLOCAR A FUNÇÃO, APAGUE ISSO  
   }     
delay(250);
 }
 }

A função Caminhos() é complementar ao menu, onde tem internamente um while(1), para a execução ficar somente na função. A função Caminhos tem na sua interface a opção de escolher a opção: Reta, Triângulo e Quadrado, e se, em qualquer momento, for apertado para cima, chama de volta a função Menu(). Se selecionado qualquer uma das opções, uma variável recebe o valor que corresponde ao caminho a ser executado, e chama a função Comprimentos(int a), passando como parâmetro o valor que corresponde ao caminho a ser seguido. O código da função caminhos é:

 void Caminhos(){
   lcd.clear();
   delay(500);
   int i;
   int x=3, ant=2;  
   int  botao;
   while(1){
    botao = analogRead(0);
   if (x<= 0 || x>= 6) x=3;   
    if (x!=ant){
  switch(x%3){
    case 0:
      lcd.setCursor(0,0);lcd.print("      Reta      ");
       lcd.setCursor(0,1);lcd.print("<-          ->");
       i=0;
      break;
    case 1:
      lcd.setCursor(0,0);lcd.print("   Triangulo    ");
       lcd.setCursor(0,1);lcd.print("<-          ->");
       i=1;
      break;
    case 2:
      lcd.setCursor(0,0);lcd.print("    Quadrado    ");
       lcd.setCursor(0,1);lcd.print("<-          ->");
       i=2;
      break;
        }
    }
    ant=x;
   if(botao >= 400 & botao < 600 ) x--; // Reconfigurar os valores para o valor de esquerda    
   else if(botao >= 0 & botao < 50) x++;// Reconfigurar os valores para o valor de direita     
   else if(botao >= 50  & botao < 150) Menu();  // Foi apertado up   
   else if((botao >= 600 & botao < 800)||(botao >= 200 & botao < 300)) Comprimentos((i+1)); // Foi apertado 
 select ou down
   delay(250);
   }
  }  

A função Comprimentos(int a), também é complementar ao menu, e tem em sua interface selecionar o comprimento do lado da figura geométrica selecionada na função Caminhos(), anteriormente. Foi pensado em criar com uma interface amigável, onde foi feito uma miniatura do lado impresso na tela do arduíno, seguido do comprometimento mostrado em número. O código da função Comprimentos é:

 void Comprimentos(int a){
lcd.clear();
delay(500);
int x=30, y=30, z=30;
int botao;
while(1){
  botao=analogRead(0);
  if (a == 1){ // Comprimento da reta   
      lcd.setCursor(0,0);
      lcd.print("Comprimento Reta");
      lcd.setCursor(0,1);
      lcd.print("v__________| ");
      lcd.print(x);
      lcd.print("  ");
      if(x <= 0) x = 0;
      if(x>=179) x=179;
      lcd.setCursor((int(x/15)),1);
      lcd.print("v");
      if     (botao >= 400 & botao < 600 ) x--; // Reconfigurar os valores para o valor de esquerda
      else if (botao >= 0   & botao <  50 ) x++; // Reconfigurar os valores para o valor de direita
      else if(botao >= 50  & botao < 150) Caminhos(); // Foi apertado up
      else if((botao >= 600 & botao < 800)||(botao >= 200 & botao < 300)) {// Foi apertado select ou down      
      /*******************************************************************************************/
      //COLOQUE AQUI A CHAMADA DA FUNÇÃO DA RETA! USE O PARAMETRO 'x' QUE É O COMPRIMENTOS DA LINHA.
      /*******************************************************************************************/       
      MoverControladoReta(x);
      ResetarPID();      
  //       while(not((botao >= 400 & botao < 600 )||(botao >= 0   & botao <  50 )))botao=analogRead(0); // Pode        
 ser excluido apos incluir a função, só serve para travar.       
      delay(100);
      }
  }
  else if (a==2){ // Comprimento dos lados do triangulo      
     lcd.setCursor(0,0);lcd.print("Lado Triangulo");
     lcd.setCursor(0,1);lcd.print("v__________| ");lcd.print(x);lcd.print("  ");
     if(x <= 0) x = 0;
     if(x>=179) x=179;
     lcd.setCursor((int(x/15)),1);lcd.print("v");
     if     (botao >= 400 & botao < 600 ) x--; // Reconfigurar os valores para o valor de esquerda
     else if (botao >= 0   & botao <  50 ) x++; // Reconfigurar os valores para o valor de direita
     else if(botao >= 50  & botao < 150) Caminhos(); // Foi apertado up
     else if((botao >= 600 & botao < 800)||(botao >= 200 & botao < 300)){ // Foi apertado select ou down         
 /***********************************************************************************************************/
        //COLOQUE AQUI A CHAMADA DA FUNÇÃO DO QUADRADO! USE O PARAMETRO 'x' QUE É O COMPRIMENTOS DO LADO DO       
 QUADRADO.        
 /***********************************************************************************************************/
      MoverControladoReta(x);
       ResetarPID();
      MoverControladoAngulo(90);
       ResetarPID();
      MoverControladoReta(x);
       ResetarPID();
      MoverControladoAngulo(140);
       ResetarPID();
      MoverControladoReta(x+((40*x)/100));
       ResetarPID();
     //while(not((botao >= 400 & botao < 600 )||(botao >= 0   & botao <  50 )))botao=analogRead(0);;} // Pode ser 
    excluido apos incluir a função, só serve para travar.
 delay(100);
   
    }
    
    

O código do Seguidor de Linha é representado abaixo:

void pretobranco(){
  Serial.print("Leitura2");
  lcd.print("ESQUERDA");
  Serial.println();
  //MoverControladoAngulo(90);
  motor1->run(FORWARD);
  motor2->run(FORWARD); 
  motor1->setSpeed(35);
  motor2->setSpeed(60);   
 }
 void brancopreto(){
  Serial.print("Leitura3");
  lcd.print("Direita");
  Serial.println();
  //MoverControladoAngulo(-90);
  motor1->run(FORWARD);
  motor2->run(FORWARD); 
  motor1->setSpeed(60);
  motor2->setSpeed(35); 
 }
 void brancobranco(){
  Serial.print("Leitura1");
  lcd.print("RETO");
  Serial.println();
  motor1->run(FORWARD);
  motor2->run(FORWARD); 
  motor1->setSpeed(60);
  motor2->setSpeed(60); 
 }
 void leitura(){
  while(1){
  Serial.print(digitalRead(S2));
  Serial.print(digitalRead(S1));
  if(digitalRead(S1) == 0 && digitalRead(S2) == 0){   //VIRA PRA ESQUERDA 90º
  int i=0;
  Serial.print("Leitura0");
  lcd.print("Direita");
  Serial.println();
  motor1->run(RELEASE);
  motor2->run(RELEASE);  
  delay(800);
   Serial.print("Andou pra frente");
  while(i != 200){
  motor1->run(FORWARD); //Vai um pouco pra frente (vai estar lendo só branco)
  motor2->run(FORWARD); 
  motor1->setSpeed(56.4);
  motor2->setSpeed(60);  
    if(digitalRead(S1) == 1 && digitalRead(S2) == 1){
      i++;
    }
  }
  i=0;
  motor1->run(RELEASE);
  motor2->run(RELEASE);
  delay(800);
   Serial.print("fez angulo");
   MoverControladoAngulo(90);
   Serial.print("andou pra tras");
  motor1->run(BACKWARD);  //Volta um pouco pra trás;
  motor2->run(BACKWARD); 
  motor1->setSpeed(60);
  motor2->setSpeed(60);
  delay(1300);
  Serial.print("proximo");
  motor1->run(RELEASE);
  motor2->run(RELEASE);
  delay(800);
  ResetarPID(); 
  }
   //vai linha reta
   if(digitalRead(S1) == 1 && digitalRead(S2) == 1){ // SEGUE RETO
    brancobranco();    
   }
   //vai para esquerda
   if(digitalRead(S1) == 1 && digitalRead(S2) == 0){ //VIRA PRA ESQUERDA
  pretobranco();  
   }
   //vai para direita
   if(digitalRead(S1) == 0 && digitalRead(S2) == 1){ //VIRA PRA DIREITA
    brancopreto();
   }
   }
 }

Resultados

LDR Diferencial(25%) O LDR diferencial durante os testes com a sala vazia foi bem sucedido em sua orientação com as luzes polarizadas. Entretanto o uso de um dispositivo para a calibração e o estabelecimento de parâmetros, foi questionado, uma vez que com base nesses valores a decisão do robô fica pre-estabelecida tirando sua autonomia e a análise das leituras in loco e menos sensíveis a incertezas do próprio circuito, pessoas e flutuações de luminosidade. A sugestão de alteração envolve a construção de um elaborado algoritmo de derivação. Que a partir das variações das leituras tente fazer com que a leitura se aproxime ao maior ou menor valores detectados pelo sensor. Ou seja, seriam necessárias duas voltas para que o robô fosse capaz de cumprir sua missão. Outra ideia seria fazer as leituras enquanto elas forem menores que o máximo, por exemplo, e uma vez que as leituras antes com um valor maior que o anterior passarem a ser menores, sabemos que passamos do ponto de alinhamento, sendo necessária assim um retorno do robô e garantido seu alinhamento

Problemas encontrados

  • Acumulo de problemas TP2;
  • Sombra;
  • Testes in loco;
  • Pouco tempo;
  • A edição da wiki não funciona simultaneamente;
  • Os problemas supracitados no LDR diferencial que ficou sujeito a falhas e flutuações do ambiente;
  • Peso do Robô;
  • Tamanho do Robô que levou a erros no seguidor de linha;
  • Interferência negativa dos desenvolvedores na automaticidade do projeto;
  • Problemas de bateria e gasto energético que persistiram do ultimo TP mesmo apos modificações;

Pontos a melhorar

Um dos principais pontos a melhorar é a implementação efetiva da característica característica do projeto, pois durante a realização do TP3 ainda existia grande influencia dos projetistas na tomada de decisão do robô fazendo a eficiência do mesmo ser reduzida. Outro ponto a se melhorar é as proporções do robô que causaram diversas variações na apresentação do projeto, além da massa o robô possui uma largura e um comprimento muito próximos do limite suportado pelo ambiente de teste.

Portifólio

  • Gráfico da ação de controle sobre os dois motores, sendo o vermelho 10 vezes a saída para o motor 2 para distinguir do azul que é a saída para o motor 1:

  • Estudo do motor 1 (Azul e Laranja): esse estudo mostra a variação do numero de pulso com a tensão fornecida em relação a um mesmo intervalo de tempo.

  • Estudo do motor 2 (Branco e Verde): esse estudo mostra a variação do numero de pulso com a tensão fornecida em relação a um mesmo intervalo de tempo.

cursos/introrobotica/2018-1/grupo03/tp3.txt · Última modificação: por 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki