Curso Robótica – #7 – LineFollower 

Durante a sétima parte do curso de robótica, vamos lidar com LineFollower. As competições organizadas para estas construções podem ser chamadas de corridas da F1 World Robots!

Desta vez, os robots serão capazes de dirigir de forma completamente autónoma numa pista especial colada à fita de isolamento preta comum!

 

O que são LineFollower?

LineFollower, como o nome sugere, são construções que seguem a linha  que marca o curso.

Um exemplo de um LineFollower:

Construção da linha seguidora

A rota em que as corridas acontecem é geralmente determinada por uma linha preta (15-20 mm de largura), que é colocada sobre um fundo branco. Uma verso reversa também possível, isto uma linha branca sobre um fundo preto – no entanto, esta variante no momento rara.

Para construir uma pista em casa, você precisará de:

  • substrato : a variante ideal é painéis móveis de MDF/HDF branco. No entanto, no início, um papelão branco terá um bom desempenho. Como último recurso, pode haver até painéis ou outro piso duro e brilhante.
  • linha preta: aqui, independentemente do substrato, use fita isolante preta que funciona perfeitamente para esta aplicação.

No começo tem que começar com trilhas mais simples e pequenas. Vale a pena encontrar um pedaço de chão livre e colar a pista. Para começar, devemos começar com algo fácil – por exemplo, a partir de um retângulo com cantos arredondados ou uma elipse. Claro, isso não precisa ser feito perfeitamente – apenas o oposto.

Um exemplo da minha faixa é mostrado abaixo. Eu escolhi um piso que não tem uma cor uniforme e pode causar problemas, porque significa que se o meu robot funcionar corretamente, não há opção para outras pessoas causarem problemas!

“Track” é feito de uma única peça de fita. Pode esticar suavemente a fita, que irá formar os arcos. No entanto, não exagere na esticá-lo, porque ele pode levar a estenose e descoloração. Nós também devemos-nos lembrar de não deixar a pista colada ao chão por um tempo muito longo. Depois de vários dias colada a fita adesiva pode deixar marcas difíceis de remover!

Sensores e o princípio da detecção de linha

Antes de chegarmos à montagem do sensor, vale a pena perceber como o robot “vê a linha”. Os veículos iluminam a rota (na luz visível ou IR) e, de seguida, verificam quanta luz foi refletida pela rota. Haverá muito mais luz da rota branca do que da linha preta.

Para esta tarefa, vamos usar sensores. Desta vez é necessário colocar os jumpers, que ligam os LEDs – eles acendem a rota!

Por meio do potenciómetro embutido no sensor, é possível ajustar o brilho do díodo.

  • Porquê um LED colorido (em vez de IR)? 
    Isso torna muito mais fácil verificar se o sensor realmente funciona e onde a luz emitida pelo transmissor cai.
  • Porquê ajustar o brilho do díodo, não o divisor de tensão para o fotoresistência? 
    O efeito do ajuste é então simplesmente visível a olho nu. Os sensores deveriam ser simples e amigáveis ​​para os iniciantes, para que os problemas pudessem ser rapidamente detectados.

Conexão de sensores ao robot

No início, os sensores devem estar conectados. Desta vez eles devem “olhar para baixo”, essa é a nossa rota. Eles também devem estar próximos uns dos outros (na largura da fita isolante), que marca o caminho. Os buracos preparados à frente do robot são ideais aqui:

Os cabos podem ser convenientemente passados ​​pelos mesmos orifícios através dos quais os sinais são enviados para os motores. Obviamente, a conexão permanece inalterada (conectores ADC_L e ADC_R no eixo). Se alguém tem medo de muitos fios na vizinhança dos motores, eles podem ser pressionados contra o compensado usando um elástico regular, como mostrado abaixo:

Teste e calibração de sensores

É hora de verificar o funcionamento dos sensores na prática – temos que ensinar o robot a reagir à linha. Para isso, vamos precisar de um “pedaço da rota”, ou seja, um pedaço de papel com uma tira de fita isolante preta:

No começo, vamos começar com um teste simples. Tudo o que precisa de fazer é exibir informações sobre o valor lido pelo ADC. Eu sugiro, por enquanto, cuidar apenas de um sensor:

#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 165
 
#define R_LINE_SENSOR A0
#define L_LINE_SENSOR A1
#define BUZZER 10
#define LED 13
 
void setup() {
  //Konfiguracja pinow od mostka H
  pinMode(L_DIR, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);
 
  //Konfiguracja pozostalych elementow
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, 0); //Wylaczenie buzzera  
  pinMode(LED, OUTPUT); 
  digitalWrite(LED, 0); //Wylaczenie diody
 
  Serial.begin(9600);
}
 
void loop() {
  int odczytLewy = analogRead(L_LINE_SENSOR);
 
  Serial.print("Lewy czujnik: ");
  Serial.println(odczytLewy);
  delay(250);
}
 
void leftMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //Kierunek: do przodu
    analogWrite(L_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //Kierunek: do tyłu
    analogWrite(L_PWM, V); //Ustawienie predkosci    
  }
}
 
void rightMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0); //Kierunek: do przodu
    analogWrite(R_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1); //Kierunek: do tyłu
    analogWrite(R_PWM, V); //Ustawienie predkosci    
  }
}
 
void stopMotors() {
  analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
  analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}

Tudo depende das configurações dos sensores e do substrato no qual eles são testados. O mais importante é fazer a diferença entre as leituras feitas na superfície preta e branca visível. Já 50-100 unidades de ADC são suficientes para trabalhos futuros.

Em caso de problemas na obtenção de leituras apropriadas, deve começar com o ajuste do brilho com o qual o díodo acende. É claro que, para isso, usamos um potenciómetro embutido no sensor. Além disso, vale a pena proteger os fotoresistências com um pedaço de tubo termoencolhível.

Aplicá-lo (e apertá-lo delicadamente por aquecimento) nas fotoresistências deve aumentar a diferença entre as leituras. Esse tratamento também imunizará o robot contra fatores externos (por exemplo, a luz solar, que, ao passar pela janela, iluminará uma parte adicional da rota).


No meu caso, notei os seguintes valores (média para os dois sensores):

  • sensor acima da linha: 930
  • sensor fora da linha: 680

Implementação de um comparador simples

Agora o valor ADC deve ser selecionado manualmente, a partir do qual reconheceremos que o sensor detectou a linha. O robot irá se mover, por isso não podemos definir limites rígidos. As leituras do sensor mudam o tempo todo, por isso é melhor definir um valor limite.

Com base nas informações que eu havia anotado anteriormente, decidi que cada caso acima de 850 deveria ser identificado como uma linha preta. Depois de escolher o valor limite, é melhor adicionar imediatamente a constante apropriada ao programa:

#define GRANICA 850#

Por conveniência, vamos agora adicionar duas funções que retornarão informações sobre o estado dos sensores. É melhor assumir que 1 é uma linha e 0 está faltando. As funções, portanto, atuam como comparadores.

As funções retornam apenas 1 (verdadeiro) ou 0 (falso):

boolean leftSensor() {
   if (analogRead(L_LINE_SENSOR) > GRANICA) { //Jesli czujnik widzi linie, to
    return 1; //Zwroc 1
  } else { //Jesli czujnik nie jest nad linią, to
    return 0; //Zwroc 0
  } 
}
 
boolean rightSensor() {
   if (analogRead(R_LINE_SENSOR) > GRANICA) { //Jesli czujnik widzi linie, to
    return 1; //Zwroc 1
  } else { //Jesli czujnik nie jest nad linią, to
    return 0; //Zwroc 0
  } 
}

Agora é necessário verificar se ambos os sensores funcionam corretamente. Para este propósito, no loop(), perguntamos aos sensores se eles vêem a linha. Para que o teste seja “mais móvel” além do UART, usaremos o sinal sonoro (para o sensor esquerdo) e o díodo (para o sensor direito).

O programa inteiro pode ser assim:

#define GRANICA 850
 
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 165
 
#define R_LINE_SENSOR A0
#define L_LINE_SENSOR A1
#define BUZZER 10
#define LED 13
 
void setup() {
  //Konfiguracja pinow od mostka H
  pinMode(L_DIR, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);
 
  //Konfiguracja pozostalych elementow
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, 0); //Wylaczenie buzzera  
  pinMode(LED, OUTPUT); 
  digitalWrite(LED, 0); //Wylaczenie diody
 
  Serial.begin(9600);
}
 
void loop() {
  if (leftSensor() == 1) { //Jesli lewy czujnik widzi linie
    Serial.println("Linia pod lewym czujnikiem!");
    digitalWrite(BUZZER, 1); //Wlacz buzzer
  } else {
    digitalWrite(BUZZER, 0); //Wylacz buzzer
  }
 
  if (rightSensor() == 1) { //Jesli prawy czujnik widzi linie
    Serial.println("Linia pod prawym czujnikiem!");
    digitalWrite(LED, 1); //Wlacz LED
  } else {
    digitalWrite(LED, 0); //Wylacz LED
  }
}
 
boolean leftSensor() {
   if (analogRead(L_LINE_SENSOR) > GRANICA) { //Jesli czujnik widzi linie, to
    return 1; //Zwroc 1
  } else { //Jesli czujnik nie jest nad linią, to
    return 0; //Zwroc 0
  } 
}
 
boolean rightSensor() {
   if (analogRead(R_LINE_SENSOR) > GRANICA) { //Jesli czujnik widzi linie, to
    return 1; //Zwroc 1
  } else { //Jesli czujnik nie jest nad linią, to
    return 0; //Zwroc 0
  } 
}
 
void leftMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //Kierunek: do przodu
    analogWrite(L_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //Kierunek: do tyłu
    analogWrite(L_PWM, V); //Ustawienie predkosci    
  }
}
 
void rightMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0); //Kierunek: do przodu
    analogWrite(R_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1); //Kierunek: do tyłu
    analogWrite(R_PWM, V); //Ustawienie predkosci    
  }
}
 
void stopMotors() {
  analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
  analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}

Antes de prosseguir, certifique-se de que ambos os sensores funcionam corretamente! Para evitar muitos problemas mais tarde, precisa verificar se o GRANICA (LIMITE) atualmente configurado cumpre sua tarefa.

No momento, o correto funcionamento do programa é:

  • ambos os sensores na superfície branca – campainha e díodo desligado
  • ambos os sensores na superfície preta – campainha e díodo ligado
  • linha sob o sensor esquerdo – buzina ligada , díodo desligado
  • linha sob o sensor direito – campainha desligada, díodo ligado .

Variante 1: seguidor de linha com um sensor

Sim, eu sei que já temos 2 sensores no robot, mas vale a pena verificar como o robô rastreando a linha com um sensor se comportará. Esta tarefa é frequentemente medida por pessoas que constroem robots a partir de blocos LEGO (na maioria dos casos, existe apenas um sensor de linha).

No entanto, pode seguir a borda da linha! Se colocarmos o robot ao lado da borda esquerda da linha, o programa deve executar as seguintes operações:

  1. Se o sensor vir uma linha: vá com um arco para a esquerda,
  2. Se o sensor não pode ver a linha: vá para a direita.

Mudanças igualmente interessantes no comportamento também podem ser obtidas colocando sensores no outro lado do robot (trocando a frente das costas). Se o robot der o inverso, os sensores estarão localizados muito mais longe do eixo de tração. Graças a isso, movimentos menores das rodas são suficientes para direcionar o robot para o caminho certo.

Sumário

Espero que, após este artigo, todos saibam como o seguidor de linha acompanha a linha! Encorajo todos a testar e tentar definir a velocidade o mais rápido possível.

Os assuntos discutidos são apenas uma introdução. Para uma condução mais rápida e suave, são necessários mais sensores e algoritmos mais sofisticados. No futuro, haverá um conjunto de sensores adicionais para o nosso robot – então poderei dar um passo adiante!