====== Sensor de distância de infra-vermelhos ======
//Conhecimento necessário:
[HW] [[pt:hardware:homelab:digi]],
[AVR] [[pt:avr:adc]], \\
[LIB] [[pt:software:homelab:library:adc]], [LIB] [[pt:software:homelab:library:module:lcd_graphic]], [LIB] [[pt:software:homelab:library:module:sensor]]//
===== Teoria =====
[{{ :examples:sensor:ir_distance:sensor_ir_distance_gp2y0a21yk_picture.jpg?240|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.
[{{ :examples:sensor:ir_distance:sensor_ir_distance_principle.png?240|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 =====
[{{ :examples:sensor:ir_distance:sensor_ir_distance_graph.png?240|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.
[{{ :examples:sensor:ir_distance:sensor_ir_distance_gp2y0a21yk_graph_calculation.png?400|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
* d - distância em centímetros.
* k - constante de correcção (encontrada por tentativa e erro).
* ADC - valor de tensão digitalizado.
* a - membro linear (o valor é determinado pela equação da linha de tendência).
* b - membro livre (o valor é determinado pela equação da linha de tendência).
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
#include
#include
#include
#include
#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);
}
}
/*
===== Materiais extra =====
* {{:examples:sensor:ir_distance:ir_distance.ods|Gráfico do sensor Sharp GP2Y0A21YK}}
* [[http://www.acroname.com/robotics/info/articles/irlinear/irlinear.html|Linearizing Sharp Ranger Data]]
*/