Table of Contents

Sensor de distância de infra-vermelhos

Conhecimento necessário: [HW] Módulo de Interface do Utilizador, [AVR] Conversor Analógico-para-Digital,
[LIB] Conversor Analógico para Digital, [LIB] LCD Gráfico, [LIB] Sensores

Teoria

Sharp GP2Y0A21YK

Para a medição da distância a um objecto, existem sensores ópticos que usam o método de medição por triangulação. A empresa “Sharp” produz sensores de distância comuns que usam o comprimento de onda dos infra-vermelho (IR) e que têm saída de tensão analógica. Os sensores feitos pela “Sharp” têm um LED IR equipado com lente, que emite um feixe de luz estreito. Depois de refletir a partir do objeto, o feixe é dirigido através de uma segunda lente a um detector de posição foto-sensível (PSD). A condutividade deste PSD depende da posição em que o feixe cai. A condutividade é convertida em tensão e se a tensão for digitalizada usando um conversor analógico-digital, a distância pode ser calculada. O caminho dos feixes reflectidos a várias distâncias diferentes é apresentado no desenho junto ao texto.

O caminho de feixes de luz até um sensor de distância IR

A saída dos sensores de distância da “Sharp” é inversamente proporcional, isto significa que, quando a distância está a crescer a saída é decrescente (o decréscimo é reduzindo gradualmente). O gráfico exato da relação entre a distância e a saída está geralmente no data-sheet do sensor. Todos os sensores têm a sua gama de medição específica onde os resultados medidos se enquadram e esta gama depende do tipo do sensor. A distância máxima medida está limitada por dois aspectos: a quantidade de luz reflectida é decrescente e a incapacidade do PSD registar pequenas mudanças na localização do raio reflectido. Ao medir os objectos que estão muito longe, a saída permanece aproximadamente a mesma como quando está à distância máxima. A distância mínima é restrita devido a uma peculiaridade dos sensores Sharp, em que a saída começa a diminuir (novamente) drasticamente a partir de um determinado ponto (dependendo do modelo de 4-20 cm). Isto significa que a um valor de saída correspondem dois valores de distância. Este problema pode ser evitado notando que o objecto não está muito próximo do sensor.

Prática

Diagrama voltagem-distância de um sensor de distância IR

O conjunto de sensores HomeLab inclui o sensor de distância IR SHARP GP2Y0A21YK. A gama de valores do sensor é de 10 cm - 80 cm. A voltagem de saída deste sensor é, de acordo com a distância medida, até 3 V. O sensor de distância pode ser ligado a qualquer ADC (conversor analógico-digital) de canal do módulo HomeLab. Com base nos exercícios de sensores anteriores, é fácil escrever um programa que mede a tensão de saída dos sensores de distância, mas, além disso, este exercício inclui a conversão desta tensão de saída para distância.

Na datasheet do GP2Y0A21YK é mostrado o gráfico da relação entre a tensão de saída e distância medida. Este gráfico não é linear, porém o gráfico de valores inversos de tensão de saída e distancia são quase, e a partir dele é bastante fácil encontrar a fórmula para a conversão de tensão em distância. Para encontrar a fórmula, os pontos do mesmo gráfico devem ser inseridos numa folha de cálculo e, em seguida, gerar um novo gráfico. Em programas de folhas e cálculo é possível calcular automaticamente a linha de tendência. De seguida, o gráfico da relação entre os valores inversos da tensão de saída corrigido do GP2Y0A21YK e o valor corrigido inverso da distância medida com linha de tendência linear é apresentado. Para simplificar, a tensão de saída está já convertida para valores de 10 bits +5 V do conversor analógico-digital com tensão de comparação.

O gráfico da linearização dos valores do ADC e distância

Como pode ser visto no gráfico, a linha de tendência (azul) sobrepõe-se com bastante precisão aos pontos do gráfico. Tal sobreposição é conseguida através da ajuda da constante de correcção. Esta constante de correcção é descoberta usando o método de tentativa e erro - muitas variáveis ​​são testadas até ser encontrada a que faz o gráfico de linha de tendência sobrepor-se o mais possível. Esta constante de correcção do presente gráfico é +2; isto significa que, para todas as distâncias reais é adicionado o valor 2. Desta forma, o gráfico é muito semelhante para a linha de tendência linear e uma generalização pode ser feita e dizer-se que a relação entre a distância e a tensão é a seguinte:

1 / (d + k) = a * ADC + b

onde

A distância pode ser expressa pela fórmula:

d = (1 / (a * ADC + B)) - k

Agora é possível, basicamente, calcular a distância, utilizando esta fórmula, mas isto requer cálculos com floating point, uma vez que na divisão vão ocorrer fracções. Porque o microcontrolador opera usando números inteiros, a fórmula deve ser simplificada e convertido para proporções maiores. Dividindo o quociente por um membro linear este vai parecer como se segue:

d = (1 / a) / (ADC + B / a) - k

Ao introduzir a constante de correcção na fórmula assim como o membro linear e o membro livre calculado a partir da equação de linha de tendência, a fórmula para calcular a distância será:

d = 5461 / (ADC - 17) - 2

Esta fórmula é calculável com inteiros de 16 bits e completamente adequada ao AVR. Antes de calcular, deve ser assegurado que o valor do ADC é superior a 17, de outra forma estaremo a dividir por 0 e distâncias negativas podem ocorrer.

A seguir mostra-se a função para converter os valores do ADC para centímetros, que está implementada na biblioteca do HomeLab. Os membros linear e livre, assim como a constante de correcção não estão rigidamente escritas para a função, eles são alimentados através dos parâmtros da estrutura de objetos do sensor de distância IR. Mantendo os parâmetros em separado, é fácil adicionar novos sensores de distância IR ao programa.

// The structure of the parameters of the IR distance sensors
typedef const struct
{
	const signed short a;
	const signed short b;
	const signed short k;
}
ir_distance_sensor;
 
// The object of the parameters of GP2Y0A21YK sensor
const ir_distance_sensor GP2Y0A21YK = { 5461, -17, 2 };
 
// Converting the values of the IR distance sensor to centimeters
// Returns -1, if the conversion did not succeed
signed short ir_distance_calculate_cm(ir_distance_sensor sensor,
	unsigned short adc_value)
{
	if (adc_value + sensor.b <= 0)
	{
		return -1;
	}
 
	return sensor.a / (adc_value + sensor.b) - sensor.k;
}

Para fazer a conversão, a função ir_distance_calculate_cm deve ser chamada. O primeiro parâmetro desta função é o objecto dos parâmetros do sensor de distância IR, o segundo é o valor de ADC. A função retorna a distância calculada em centímetros. Se a operação der erro (valor não natural do ADC) o valor retornado é -1. O programa seguinte demonstra a utilização do sensor de distância IR e a função de conversão. O LCD gráfico é usado, onde os resultados medidos são exibidos. Se a distância não for natural o símbolo “?” é exibido.

// The example program of the IR distance sensor of the HomeLab
// Measured results in centimeters is displayed on the LCD
#include <stdio.h>
#include <homelab/adc.h>
#include <homelab/delay.h>
#include <homelab/module/sensors.h>
#include <homelab/module/lcd_gfx.h>
 
#define ADC_CHANNEL 0
 
// Main program
int main(void)
{	
	signed short value, distance;	
	char text[16];
 
	// Robotic HomeLab II external sensors pin of Sensor module 
	//pin ex_sensors = PIN(G, 0);
	//pin_setup_output(ex_sensors);
	//pin_set(ex_sensors);
 
	// Initialization of LCD
	lcd_gfx_init();	
	lcd_gfx_clear();	
	lcd_gfx_goto_char_xy(1,2);	
	lcd_gfx_write_string("Distance sensor");
 
	// Setup of the ADC
	adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
 
	// Endless loop
	while (1)
	{
		// Reading the 4 times rounded value of output voltage
		value = adc_get_average_value(ADC_CHANNEL, 4);		
 
		// Conversing ADC value to distance
		distance = ir_distance_calculate_cm(GP2Y0A21YK, value);
 
                lcd_gfx_goto_char_xy(1,3);
 
		// Was the calculation successful?
		if (distance >= 0)
		{			
			// Conversing distance to text
			sprintf(text, "%3d cm   ", distance);
		}
		else
		{		
			// Creating the text for unknown distance
			sprintf(text, "Error   ");
		}
 
		lcd_gfx_goto_char_xy(1,3);
		lcd_gfx_write_string(text);
		sw_delay_ms(500);
	}
}