Tutorial · Iniciante · 20 min
Matriz de sensores infravermelhos para robô seguidor de linha
Transforme uma fileira de sensores de reflectância infravermelha em um único erro de posição, com calibração, leitura analógica e média ponderada.
O desempenho de um robô seguidor de linha depende do erro usado para comandar sua direção. Esse valor vem de uma fileira de sensores de reflectância infravermelha apontados para o piso: a linha tem uma cor, o fundo tem outra, e os sensores informam quanto da luz infravermelha é refletida. Este guia transforma essa fileira bruta de leituras em uma única posição da linha contínua e suave — o erro sobre o qual o controlador atua.
Como um sensor de reflectância vê a linha
Cada sensor combina um LED infravermelho com um fototransistor. O LED projeta luz para baixo; o fototransistor mede a reflexão. Uma linha preta fosca reflete pouca luz infravermelha (leitura baixa); o fundo mais claro reflete mais (leitura alta). Passe a matriz por uma pista preta sobre fundo branco e cada sensor oscilará entre um valor “sobre a linha” e um valor “fora da linha”.
Dois fatores fazem esses valores brutos variarem de uma execução para outra: a altura do sensor acima da superfície e a luz ambiente. Por isso nunca fixe limiares no código — calibre. Os mesmos sensores apontados para a borda de um anel, em vez de uma linha, tornam-se um detector de borda, em que uma leitura perdida custa a partida ao robô.
Sensores analógicos ou digitais
- Sensores analógicos fornecem um valor contínuo (por exemplo, 0–1023 em um ADC do Arduino). Você sabe a que distância a linha está de cada sensor, o que permite calcular uma posição suave e comandar a direção proporcionalmente.
- Sensores digitais informam apenas ligado/desligado depois de um limiar interno. São mais simples de conectar, mas perdem a informação intermediária, então o controle fica mais grosseiro.
Para o seguimento proporcional de linha — o tipo que se ajusta com um controlador PID — use leituras analógicas. É essa a abordagem que o simulador de robô seguidor de linha modela.
Calibre primeiro
Antes de uma execução, passe cada sensor sobre a linha e sobre o fundo e registre o valor mínimo e o valor máximo de cada sensor. Depois normalize cada leitura obtida em tempo real para 0–1000 em relação à sua própria faixa:
// Per-sensor calibration captured during a sweep.
int minv[N], maxv[N];
int normalized(int raw, int i) {
long span = maxv[i] - minv[i];
if (span <= 0) return 0; // sensor never saw contrast
long v = (long)(raw - minv[i]) * 1000 / span; // 0 (background) … 1000 (line)
return constrain(v, 0, 1000);
}
Calibrar cada sensor cancela o brilho desigual dos LEDs e pequenas diferenças de altura ao longo da barra. Assim, a resposta de um único sensor não desloca silenciosamente toda a estimativa.
Das leituras a uma única posição da linha
Agora reduza a matriz a uma única posição com uma média ponderada pela reflectância. Dê a cada sensor uma posição fixa (…−2, −1, 0, +1, +2… ao longo da barra) e pondera esse valor pela leitura normalizada. O resultado é a posição da linha em relação ao centro da barra — positiva de um lado, negativa do outro e zero quando a linha está exatamente no centro.
// Sensor positions across the bar, e.g. { -2000,-1000,0,1000,2000 }.
long readLinePosition() {
long weighted = 0, total = 0;
for (int i = 0; i < N; i++) {
int v = normalized(analogRead(pins[i]), i);
weighted += (long)v * position[i];
total += v;
}
if (total == 0) return lastPosition; // line lost — reuse last direction
lastPosition = weighted / total;
return lastPosition; // 0 = centered, sign = which side
}
Dois detalhes tornam isso robusto:
- Divida pela soma das leituras, não pela quantidade de sensores, para que uma linha fraca e uma linha forte sejam mapeadas para a mesma escala de posição.
- Quando todos os sensores perderem a linha (
total == 0), reutilize a última posição conhecida em vez de retornar zero. Isso mantém a última direção de correção do robô, em vez de fazê-lo sair em linha reta de uma curva fechada.
Quantos sensores?
Cinco é um bom ponto de partida — suficiente para perceber direção e magnitude, mantendo a matemática fácil de verificar. Três funcionam em baixa velocidade; robôs de competição usam oito ou mais para obter maior resolução em alta velocidade. O principal ganho de mais sensores é uma estimativa de posição mais suave em curvas fechadas.
A rotina completa de calibração
“Calibre primeiro” é fácil de dizer e fácil de executar de forma inadequada. Esta é a rotina inteira, incluindo a proteção que impede que um canal inativo estrague a estimativa:
const int N = 8;
const int PIN[N] = {A0, A1, A2, A3, A4, A5, A6, A7};
int minv[N], maxv[N];
void calibrate(unsigned long durationMs) {
for (int i = 0; i < N; i++) { minv[i] = 1023; maxv[i] = 0; }
const unsigned long start = millis();
while (millis() - start < durationMs) {
for (int i = 0; i < N; i++) {
const int v = analogRead(PIN[i]);
if (v < minv[i]) minv[i] = v;
if (v > maxv[i]) maxv[i] = v;
}
}
// A channel that never saw contrast would turn noise into huge normalised
// values and drag the whole estimate toward itself.
for (int i = 0; i < N; i++) {
if (maxv[i] - minv[i] < 50) {
Serial.print(F("channel dead or never crossed the line: "));
Serial.println(i);
}
}
}
Passe a matriz pela linha durante toda a janela de calibração. Um robô parado registra a mesma leitura como mínimo e máximo, produzindo uma amplitude zero e fazendo com que o sensor não contribua para nada. Girar o robô no lugar sobre a linha por três segundos é o movimento padrão, e funciona porque cada canal cruza a fita.
Recalibre no início de cada execução, não uma única vez durante a montagem. A luz ambiente muda, a distância do sensor ao piso muda conforme o pacote de baterias se desloca e a fita acumula poeira. Esse é o motivo mais comum para um robô seguidor de linha funcionar em uma mesa e falhar em outra.
Eliminando a luz ambiente
A luz do sol contém muito infravermelho de 940 nm, e o fototransistor não consegue distingui-lo da reflexão do seu próprio emissor. Um robô que funciona em ambientes internos e falha perto de uma janela está exatamente nessa situação.
Se os emissores da sua matriz puderem ser desligados — a maioria tem um pino LEDON ou CTRL — a solução é completa e custa uma leitura adicional por canal:
int ambientSubtracted(int i) {
digitalWrite(LEDON, LOW);
delayMicroseconds(200); // let the phototransistor settle
const int dark = analogRead(PIN[i]); // ambient only
digitalWrite(LEDON, HIGH);
delayMicroseconds(200);
const int lit = analogRead(PIN[i]); // ambient + our emitter
return lit - dark; // just our emitter
}
Tudo o que for constante no ambiente é cancelado exatamente. O custo é o dobro do tempo de amostragem, o que pesa em um robô seguidor de linha rápido — mas converte um sensor pouco confiável em confiável, e é a técnica usada por matrizes comerciais.
Isso também traz um segundo benefício importante: com os emissores desligados entre leituras, a corrente média deles cai bastante. Os emissores de uma matriz de 8 canais podem consumir 100–200 mA continuamente, o que em um pacote pequeno representa uma parte significativa do orçamento.
Perdendo a linha e reencontrando-a
O caso total == 0 merece mais atenção do que costuma receber, porque é nele que um robô seguidor de linha falha visivelmente com mais frequência.
Retornar zero é a implementação óbvia e errada: zero significa “perfeitamente centralizado”, então o robô segue em frente à velocidade máxima — para longe da linha que acabou de perder, que quase certamente estava curvando.
Retornar a última posição faz o robô continuar girando na direção para onde a linha foi. Essa única mudança é a diferença entre um robô que se recupera de uma curva fechada e outro que sai da pista.
Uma versão mais completa adiciona um tempo limite, para que um robô realmente perdido pare em vez de ficar em espiral:
long lastPosition = 0;
unsigned long lostSince = 0;
long readLinePosition() {
long weighted = 0, total = 0;
for (int i = 0; i < N; i++) {
const int v = normalized(analogRead(PIN[i]), i);
if (v > 100) { // ignore channels clearly on the floor
weighted += (long)v * POSITION[i];
total += v;
}
}
if (total == 0) {
if (lostSince == 0) lostSince = millis();
if (millis() - lostSince > 1500) stopMotors(); // genuinely lost
return lastPosition; // keep turning the way we were
}
lostSince = 0;
lastPosition = weighted / total;
return lastPosition;
}
O limiar v > 100 também importa. Sem ele, oito canais que registram um pequeno valor de fundo diferente de zero arrastam a média ponderada para o centro da matriz, independentemente de onde a linha esteja — o resultado é um robô que acompanha bem uma linha forte e mal uma linha apagada.
A distância ao piso determina o contraste
Sensores de reflectância têm uma faixa ideal estreita, e essa é a variável mecânica que mais frequentemente se disfarça de problema de software.
| Distância do sensor ao piso | O que aparece na amplitude da calibração |
|---|---|
| 1–3 mm | Maior amplitude, mas a matriz raspa em qualquer irregularidade do piso |
| 3–8 mm | A faixa utilizável. A maioria das matrizes especifica cerca de 3 mm |
| 8–15 mm | A amplitude diminui visivelmente; a normalização começa a amplificar o ruído |
| > 15 mm | Praticamente sem leitura na maioria das superfícies |
Duas consequências decorrem disso. Monte a matriz rigidamente — uma matriz em um suporte flexível muda de altura quando o robô acelera, o que altera as leituras, e o laço de controle interpreta essa alteração como se a linha tivesse se movido. E monte a matriz nivelada, porque uma matriz inclinada dá a cada canal uma altura efetiva diferente e, portanto, uma calibração diferente; isso aparece como um robô que acompanha bem em uma direção e mal na outra.
Quantos sensores, de forma quantificada
| Canais | Resolução de posição em uma linha de 19 mm | Adequado para |
|---|---|---|
| 3 | Essencialmente esquerda / centro / direita | Entender a ideia |
| 5 | ~4 regiões discretas, suaves entre elas | Um primeiro robô seguidor de linha em uma pista suave |
| 8 | ~7 regiões | Pistas rápidas, curvas fechadas, detecção de junções |
| 12–16 | Fina | Robôs de competição em alta velocidade |
O número que importa mais do que a contagem é a largura da matriz em relação à linha. Para o seguimento comum de uma linha, a matriz precisa ser larga o suficiente para que pelo menos um sensor fique sobre o piso, junto a cada borda da linha — aproximadamente o dobro da largura da fita.
Para detecção de junções em labirintos de linhas, o requisito é mais estrito: o robô reconhece um ramo quando vê os sensores mais externos escurecerem enquanto o centro ainda está sobre a linha, portanto a matriz deve ter pelo menos três vezes a largura da fita. Uma matriz de 8 canais com espaçamento de 8 mm mede cerca de 60 mm, valor adequado para fita de 19 mm.
Solução de problemas
| Sintoma | Causa provável | Correção |
|---|---|---|
| Funciona em uma superfície e falha em outra | Calibração desatualizada ou ausente | Recalibre no início de cada execução |
| Um canal desloca a estimativa | Emissor inativo — a amplitude dele é mínima | Verifique o valor maxv − minv de cada canal e aplique a proteção |
| O robô segue em linha reta ao perder a linha | Retorna 0 ao perder a linha | Retorne a última posição |
| Acompanha fita forte e vagueia sobre fita apagada | Ruído de fundo entra na média | Adicione o limiar v > 100 |
| Falha perto de uma janela | Infravermelho ambiente | Faça a subtração com o emissor desligado ou proteja a matriz |
| A posição salta quando a linha cruza os sensores | Leituras não normalizadas por canal | Calibre cada canal em relação ao próprio valor mínimo e máximo |
| As leituras variam ao longo de uma execução longa | Queda de tensão da bateria, que faz a intensidade dos emissores diminuir | Verifique a tensão no trilho sob carga |
| Todos os canais fazem a mesma leitura | A matriz está longe demais do piso | Use 3–8 mm e depois recalibre |
| Acompanha bem em uma direção e mal na outra | Matriz não está nivelada | Cada canal tem uma altura efetiva diferente |
Para onde isso leva
Esse único valor de posição é o termo de erro. Alimente-o a um laço de controle que acelera uma roda e desacelera a outra, e você terá um robô seguidor de linha. Aprenda esse laço em ajustar um controlador PID e depois tente o conjunto completo no simulador de robô seguidor de linha.
Explore o grafo
Faz parte destas montagens
Projetos e caminhos de aprendizagem que incluem este tutorial.
Leitura complementar