Ferramentas do usuário

Ferramentas do site


cursos:introrobotica:2017-1:grupo05:tp3

Trabalho Prático 3 - Robótica móvel (navegação e controle)

1. Objetivo:

O Trabalho Prático 3 - Robótica Móvel (navegação e controle) teve como premissa a familiarização com o problema de localização, desenvolvimento de um sistema de odometria básica utilizando sensores do tipo shaft-encoding e implementação de técnicas básicas de navegação e controle. As tarefas a serem desenvolvidas são:

1.1. Localização: Através do uso de um sensor utilizando LDR's em montagem diferencial, o robô deverá ser capaz de alinhar com a fonte de luz mais próxima presente no campo de prova.

1.2. Odometria e controle: Uso de sensores break-beam para a construção de shaft-encoders. Implementeção de um controlador PD (Proporcional e Derivativo) para controlar a velocidade do robô Realização de um caminho pré-determinado através de um menu de opções (reta, quadrado, triângulo), onde o comprimento da reta e do lado das figuras geométricas deverá ser escolhido no menu.

1.3. Navegação (line-following): O robô deverá seguir as linhas marcadas no campo da competição, utilizando no máximo dois sensores ópticos (óptico-reflexivo ou LDR).

2. Mecânica:

Grande parte da composição mecânica do robô foi herdada do trabalho anterior (http://homepages.dcc.ufmg.br/~doug/cursos/doku.php?id=cursos:introrobotica:2017-1:grupo05:tp2), sendo alterado somente algumas partes como: inserção dos sensores óptico-reflexivos para a navegação (line-following), eliminação do sensor de detecção de objetos e inserção do sensor de luz polarizada montado na forma diferencial. As imagens abaixo ilustram a montagem mecânica do robô:

img_20170607_163453246_hdr_1.jpg img_20170607_163512978_hdr_2.jpg img_20170607_163542810_hdr_3.jpg
LDR diferencial Sensores óptico_reflexivos Sensor break-beam

3. Eletrônica embarcada

A eletrônica embarcada foi a mesma utilizada no trabalho prático anterior (http://homepages.dcc.ufmg.br/~doug/cursos/doku.php?id=cursos:introrobotica:2017-1:grupo05:tp2), com a ressalva das alterações necessárias para a inserção de novos sensores: sensores opto-reflexivos e break-beam.

3.1. Localização:

Para resolver a tarefa de alinhar o robô com a fonte de luz mais próxima, foi feita uma montagem utilizando dois sensores LDR e filtros polarizadores. Sua configuração final segue abaixo:

3.1.1. LDR Diferencial

Divisor de tensão O sensor LDR é um resistor cuja resistência varia de acordo com a intensidade da luz que incide sobre ele. Seu funcionamento típico é: à medida que a intensidade da luz aumenta, a sua resistência diminui. Dessa forma, na escuridão, o LDR possui uma resistência máxima, e na luz muito brilhante, sua resistência é mínima. Já um LDR diferencial nada mais é do que dois sensores LDR ligados em série, com um ponto de medição inserido entre estes sensores.

Para a montagem física dos sensores, os LDRs foram posicionados separados por uma parede de lego. Em frente a cada sensor LDR havia um filtro polarizador.

//LDR// Diferencial

Diferente do trabalho anterior, agora ambas as resistências (R1 e R2) do circuito são variáveis. Os resistores correspondem aos LDRs e o valor de suas resistências variam de acordo com a intensidade da luz. Ao montar um divisor de tensão, obtém-se a equação correspondente exibida acima:

Através da equação, observa-se que a tensão de saída (V_LDR) é diretamente proporcional à resistência (R2) do sensor LDR. Ou seja, a tensão de saída será maior com um índice de luminosidade incidente menor. O circuito do divisor de corrente segue ao lado:

3.2. Filtro Polarizador

Esse tipo de filtro funciona como uma fenda para uma direção certa. Ou seja, o filtro polarizador deixa passar a parte da onda que oscila num determinado plano. A figura abaixo demonstra o que foi citado anteriormente:

Filtro Polarizador A luminária utilizada no projeto emite uma luz polarizada. Dessa forma, só passa luz pelo filtro caso as ondas provenientes da luz estejam alinhadas a um ângulo de 0, 180 ou 360 graus. Caso a diferença de fase seja de 90 ou 270 graus a passagem de luz é nula. Dessa forma, o filtro tinha a função de controlar a intensidade de luz recebida pelos sensores LDR.

4. Software Embarcado

Assim como nos trabalhos anteriores, todo o software embarcado foi composto em C/C++ utilizando o framework Arduino para uma placa microcontrolada base do tipo Arduino Mega2560. As subseções abaixo descrevem a implementação de cada tarefa sob a perspectiva do software.

4.1 Localização – Identificação da fonte de luz polarizada:

Para identificar a fonte de luz mais pŕoxima, o robô faz um giro de 360 graus (em torno de seu eixo Normal) armazenando os valores de entrada dado pelos LDRs. O menor valor lido após esse movimento de rotação é onde a fonte de luz mais próxima está. A localização (ângulo correspondente medido pelos encoders) foi sendo armazenada à medida que uma entrada menor era recebida. Feito isso, o robô voltava para a posição armazenada (posição da luz mais pŕoxima). O algoritmo correspondente segue abaixo:

// Condicao de parada
// Verifica se os motores atingiram o num de voltas 
// necessaria para o ang requisitado (360)
if((leftEncCount>=ligthLeftEncoder)&&(rightEncCount>=ligthRightEncoder)){
  getOutLp = 1; // Sai do loop
}
 
// Gira o robo 360 graus para a direita
leftMotor->run(FORWARD);
leftMotor->setSpeed(leftMotorSpeed);
rigthMotor->run(BACKWARD);
rigthMotor->setSpeed(rigthMotorSpeed);
 
// Faz a leitura dos encoderes
leftEncState = digitalRead(leftEncoder);
rightEncState = digitalRead(rigthEncoder);
 
// Verifica borda de descida do encoder esquerdo
if(leftEncState == HIGH) {
  if(oldLeftEncState == LOW) {
    leftEncCount++;
  }
}else { //Verifica borda de subida
  if(oldLeftEncState == HIGH) {
    leftEncCount++;
  }
}
 
// Verifica borda de descida do encoder direito
if(rightEncState == HIGH) {
  if(oldRightEncState == LOW) {
    rightEncCount++;
  }
}else { //Verifica borda de subida
  if(oldRightEncState == HIGH) {
    rightEncCount++;
  }
}
 
// Faz a leitura do sensor ldr
ldrInputValue = analogRead(ldr);
 
// Verifica se o ponto luminoso eh maior
// O ponto luminoso ocorre qnd o ldr faz uma leitura pequena
if(ldrInputValue < minLdrValue) {
  minLdrValue = ldrInputValue;
  ligthLeftEncoder = leftEncCount;
  ligthRightEncoder = rightEncCount;
}
 
oldRightEncState = rightEncState;
oldLeftEncState = leftEncState;

Segue abaixo o vídeo da versão final da localização da luz polarizada:

4.2. Odometria e Controle

Foram utilizados sensores break-beam para construir shaft-encoders. Foi implementado um controlador do tipo PD para controlar a velocidade do robô. Além disso, o robô é capaz de realizar um determinado caminho com uma distância selecionada através do menu (Reta, Quadrado, Triângulo).

Os Sensores break-beam foram usados para medir a variação (rotação) do eixo da roda. Dessa forma era possível obter: quão rápido as rodas estão girando e o número total de rotações. Um disco perfurado foi colocado sobre o eixo, entre o par de emissor-detector. À medida que o eixo girava, os furos no disco cortam o feixe de luz na velocidade do giro. As rotações foram contadas a partir do número de bordas de subida e descida. A montagem do encoder segue abaixo:

Montagem do encoder

A distância agora é controlada pelo valor retornado pelos encoders do motor direito e esquerdo. Primeiramente foi necessário medir quantas bordas de subida e descida os encoderes retornavam para uma volta de 360 graus das rodas. O valor final retornado pelo encoder foi obtido de forma empírica (foram feitas várias medidas para obter o melhor valor correspondente).

Considerando que a roda tem 8cm de diâmetro, a distância translacional do robô correspondia a 25,13cm (d = 2*pi*R = 25,13cm). O valor de bordas retornado pelos encoderes foi 22. Através de uma regra de três simples, foi obtido o ganho (= 0.48) que deveria ser multiplicado pelas distâncias requisitadas (dadas em centímetro).

O mesmo foi feito para descobrir o valor correspondente do número de rotação do encoder para o ângulo em graus. Nesse caso, foi medido quantas bordas os encoders retornavam para um giro de 360 graus do robô (em torno de seu eixo Normal). O algoritmo utilizado para resolver o problema segue abaixo:

// Quantas voltas o encoder deve dar para atingir a distancia necessaria
distRightMotor = 0.48*dist;
distLeftMotor = 0.48*dist;
 
while (getOut != 1) {
  // Verifica se os motores atingiram o num de voltas necessaria para a dist requisitada
  if((leftEncCount>=distLeftMotor)&&(rightEncCount>=distRightMotor)) {
    getOut = 1;
  }
 
  // Caso seja terminado
  if(getOut == 1) {
    leftMotor->run(RELEASE);
    rigthMotor->run(RELEASE);
    Serial.println("esq");
    Serial.println(leftEncCount);
    Serial.println("dir");
    Serial.println(rightEncCount);
    break;
  }
 
  // Gira as rodas 360 graus, ou seja, 25,13cm de translacao
  leftMotor->run(FORWARD);
  leftMotor->setSpeed(leftMotorSpeed);
  rigthMotor->run(FORWARD);
  rigthMotor->setSpeed(rightMotorSpeed);
 
  // Faz a leitura dos encoderes
  leftEncState = digitalRead(leftEncoder);
  rightEncState = digitalRead(rigthEncoder);
 
  // Verifica borda de descida do encoder esquerdo
  if(leftEncState == HIGH) {
    if(oldLeftEncState == LOW) {
      leftEncCount++;
    }
  }else { //Verifica borda de subida
    if(oldLeftEncState == HIGH) {
      leftEncCount++;
    }
  }
 
  // Verifica borda de descida do encoder direito
  if(rightEncState == HIGH) {
    if(oldRightEncState == LOW) {
      rightEncCount++;
    }
  }else { //Verifica borda de subida
    if(oldRightEncState == HIGH){
      rightEncCount++;
    }
  }
 
  oldRightEncState = rightEncState;
  oldLeftEncState = leftEncState;
}

Por fim, o controle da velocidade foi obtido de forma empírica. Através de vaŕios testes, foi atribuído um ganho Kp que era multiplicado pelo erro (diferença entre o setpoint e a saída). O ganho ke também foi obtido de forma empírica e multiplicado pela variação do erro (diferença entre o erro anterior e o erro atual). O proporcional e o derivativo são somados e atribuídos à saída. Segue abaixo o vídeo da versão final da odometria e controle:

Vídeos - Odometria e Controle:

4.4. Navegação (line-following):

O algoritmo de navegação implementado foi o de seguidor de linha simples, utilizando dois sensores óptico-reflexivos como fonte de sinal de detecção da linha. Para o controle da velocidade dos motores foi utilizado um controlador do tipo PD (Proporcional e Derivativo). O controlador do tipo PD obtém dos sensores break-beam a velocidade a qual o robô desloca-se e a partir desse valor, juntamente com os valores das constantes proporcional e derivativa, efetua o ajuste na alimentação dos motores através do valor da largura de pulso (PWM) aplicada a cada um deles. Desta forma, é possível o robô realizar trajetória em linha reta mesmo tendo motores com taxas de rotação de eixo diferentes – caso comum encontrado na prática. A correção da trajetória para seguir a linha traçada é dada pelos sensores ópticos, quando um dos sensores detecta o traçado, implica que é necessário o aumento da velocidade do motor contrário para a correção da trajetória (correção esta efetuada através do ajuste da alimentação do motor, via alimentação por modulação do tipo larguar de pulso (PWM)). Abaixo, segue trecho do código fonte que implementa o algoritmo de navegação:

//Navegação (line-following)
// ...
 
//Atribui ao Setpoint de cada sensor um valor médio
setPointR = (blackSurfaceR - whiteSurfaceR)/2 + whiteSurfaceR;
setPointL = (blackSurfaceL - whiteSurfaceL)/2 + whiteSurfaceL;
 
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Kp = ");
 
Kp = 1;
 
leftMotor->run(FORWARD);
leftMotor->setSpeed(60);
rigthMotor->run(FORWARD);
rigthMotor->setSpeed(72);
 
while(1){
  //Leitura dos sensores					
  rightValue = analogRead(rightSensor);
  leftValue = analogRead(leftSensor);
 
  //Erro = Setpoint - leitura
  correctionR = Kp * (setPointR - rightValue);
  correctionL = Kp * (setPointL - leftValue);
 
  //Move para frente
  if(rightValue < setPointR && leftValue < setPointL){
    leftMotor->run(FORWARD);
    leftMotor->setSpeed(60);
    rigthMotor->run(FORWARD);
    rigthMotor->setSpeed(72);
  }
  //Move para direita
  else if(rightValue > setPointR && leftValue < setPointL){
    leftMotor->run(FORWARD);
    if(60 + correctionR <= 255){
      leftMotor->setSpeed(60 + correctionR);
    }
    else{
      leftMotor->setSpeed(255);
    }
    rigthMotor->run(BACKWARD);
    rigthMotor->setSpeed(72);
  }
  //Move para esquerda
  else if(rightValue < setPointR && leftValue > setPointL){
    rigthMotor->run(FORWARD);
    if(72 + correctionL <= 255){
      rigthMotor->setSpeed(72 + correctionL);
    }
    else{
      rigthMotor->setSpeed(255);
    }
    leftMotor->run(BACKWARD);
    leftMotor->setSpeed(60);
  }
  //Move também para esquerda, caso ambos sobre a linha preta
  else if(rightValue > setPointR && leftValue > setPointL){
    rigthMotor->run(FORWARD);
    if(72 + correctionL <= 255){
      rigthMotor->setSpeed(72 + correctionL);
    }
    else{
      rigthMotor->setSpeed(255);
    }
    leftMotor->run(BACKWARD);
    leftMotor->setSpeed(60);
    }
  }

Abaixo, vídeo exibindo a navegação por line-following do robô:

Conclusão:

O trabalho prático proporcionou melhor entendimento dos conceitos apresentados na disciplina de Introdução à Robótica, através da implementação de um robô móvel capaz de realizar as tarefas de localização, odometria e controle e navegação (line-following).

O problema de localização foi resolvido através do uso de um sensor de luz utilizando sensores do tipo LDR montados em uma configuração diferencial, assim, o robô foi capaz de alinhar-se com a fonte de luz mais próxima presente no campo de prova. A odometria e controle foi realizada utilizando sensores do tipo break-beam para construir os shaft-encoders. Um controlador do tipo PD (Proporcional e Derivativo) foi implementado para controlar a velocidade do motor. A tarefa de navegação (line-following) foi feita utilizando dois sensores óptico-reflexivos posicionados nas extremidades do robô. Assim, pôde-se controlar o sentido de delocamento do robô de forma que o mesmo pudesse seguir o trajeto determinado por uma linha demarcada no campo de prova. Tal qual especificado no escopo do trabalho, as tarefas a serem executadas foram selecionadas através de um menu.

Referências:

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

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki