GrabDuck

Инфракрасный датчик расстояния [Robotic & Microcontroller Educational Knowledgepage - ...

:

Теория

Sharp GP2Y0A21YK

Для измерения расстояния до объекта существуют оптические датчики, работающие на методе триангуляции. Самые распространенные из них - это работающие на длине волны, инфракрасные (на английском языке infra-red, сокращенно IR) датчики расстояния с выходным аналоговым напряжением, производимые фирмой Sharp. У датчиков Sharp имеется IR LED с линзой, который излучает узкий световой луч. Отраженный от объекта луч направляется через другую линзу на позиционно-чувствительный фотоэлемент (на английском языке position-sensitive detector, сокращенно PSD). От местоположения падающего на PSD луча, зависит его проводимость. Проводимость преобразуется в напряжение и, к примеру, дигитализируя его аналого-цифровым преобразователем микроконтроллера, можно вычислить расстояние. Ниже приведенный рисунок показывает путь отраженного луча на различных расстояниях.

Путь светового луча IR измерителя расстояния

Выход датчика расстояния Sharp обратно пропорциональный - с увеличением расстояния это уменьшается и растет медленно. Точный график между расстоянием и выходом приведен в спецификации датчика. У датчиков, в соответствии с типом, имеется граница измерения, в пределах которой выход датчика является надежным. Измерение максимально реального расстояния ограничивают два аспекта: уменьшение интенсивности отражающегося света и невозможность PSD регистрировать изменение местоположения отображенного маленького луча. При измерении сильно отдаленных объектов, выход датчика остается приблизительно таким же, как и при измерении максимально отдаленных расстояний. Минимально измеряемое расстояние ограничено особенностями датчика Sharp, а именно - выходное напряжение на определённом расстоянии (в зависимости от датчика: 4-20 см) начинает резко падать при уменьшении расстояния. По существу это означает, что одному значению выходного напряжения соответствует два расстояния. Для предотвращения проблемы нужно избегать слишком близкого приближения объектов к датчику.

Практика

График напряжения-расстояния типичного IR измерителя расстояния Sharp

В комплекте датчиков Домашней Лаборатории есть инфракрасный измеритель расстояния Sharp GP2Y0A21YK с границей измерения 10-80 cм. Выходное напряжение датчика до 3 V в зависимости от измеряемого расстояния. Датчик подключается на модуль «Датчики» и его выходное напряжение направляется на канал 0 аналого-цифрового преобразователя AVR. На базе предыдущего задания датчиков, можно просто сделать программу, которая измеряет выходное напряжение измерителя расстояния, но вдобавок к этому целью данного задания является так же ознакомление с процессом перевода напряжения в расстояние.

В спецификации датчика GP2Y0A21YK приведен график зависимости между выходным напряжением и измеренным расстоянием. Этот график не является линейным, однако график обратной величины выходного напряжения и расстояния почти линейный, и с помощью него довольно просто найти формулу для преобразования напряжения в расстояние. Для нахождения формулы необходимо точки этого графика ввести в какую-либо программу обработки табличных данных и из них создать новый график. В программе обработки табличных данных на основе точек графика возможно автоматически вычислить линию тренда. Далее приведен график связи исправленной обратной величины между выходным напряжением GP2Y0A21YK и расстоянием вместе с линейной линией тренда. Выходное напряжение для упрощения формулы уже переведено в 10-битное значение аналогово-дигитального преобразователя с опорным напряжением +5 V.

График линеаризации расстояния и значения ADC

Как видно на графике, линия тренда (синяя) совпадает довольно точно с точками графика (красная линия). Такое совпадение достигнуто с помощью корректирующей константы расстояния. Корректирующая константа найдена методом проб и ошибок - испробованы разные числа, пока не были найдены те, при которых график покрыт линией тренда больше всего. Корректирующая константа для данного графика это +2, т.е. ко всем реальным расстояниям в графике прибавлено 2. Так как график очень похож на линейную линию тренда, можно сделать обобщение и сказать, что взаимосвязь между расстоянием и напряжением следующая:

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

где

  • d - расстояние в сантиметрах

  • k - корректирующая константа (найдена методом проб и ошибок)

  • ADC - это значение дигитализированного напряжения

  • a - линейный член (значение выходит из уравнения линии тренда)

  • b - свободный член (значение выходит из уравнения линии тренда)

Из формулы можно выразить расстояние d:

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

В принципе, этим уравнением можно вычислить расстояние, но это предполагает вычисления плавающей запятой, потому что в частном образуются дробные числа. Для микроконтроллера, оперирующего целыми числами, придется упростить формулу и перевести в большие множители. Разделив частное формулы на линейный член, получим следующий вид:

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

Введя в формулу значение корректирующей константы и полученный из уравнения линии тренда линейный и свободный член (полученный из рисунка), получим формулу для вычисления расстояния:

d = 5461 / (ADC - 17) - 2

Эта формула вычислена 16-битными целыми числами и полностью подходит для AVR. Перед вычислением придется убедиться, чтобы значение ADC было выше 17, иначе получится деление на ноль или отрицательное расстояние, что не логично.

Далее приведена записанная в библиотеке Домашней Лаборатории функция перевода значения ADC в сантиметры. Линейный и свободный член, а также корректирующая константа не вписаны жестко в функцию, но они задаются объектами параметра структуры IR датчика расстояния. Сохраняя параметры отдельно в константе, есть возможность позже просто добавить в программу новые модели IR датчиков расстояния.

 

//
// Структура параметров IR датчика расстояния
//
typedef const struct
{
	const signed short a;
	const signed short b;
	const signed short k;
}
ir_distance_sensor;
 
//
// Объект параметров датчика GP2Y0A21YK
// 
const ir_distance_sensor GP2Y0A21YK = { 5461, -17, 2 };
 
//
// Перевод значения ADC датчика расстояния IR в сантиметры
// Возвращает -1, если преобразование не удалось
//
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;
}

Для создания перевода нужно вызвать функцию ir_distance_calculate_cm первый параметр которого - это параметр объекта IR датчика расстояния, а второй - значение ADC. Функция возвращает вычисленное расстояние в сантиметрах. При неправильном расчете (т.е. при неестественном значении ADC) возвращает функция -1. Использование IR датчика расстояния и функции преобразования демонстрирует следующая программа. Используется буквенно-цифровой LCD экран, где отображаются результаты измерения. При неестественном расстоянии отображается вопросительный знак.

 

//
// Пример программы IR датчика расстояния Домашней Лаборатории.
// На LCD экране отображается измеренное расстояние в сантиметрах.
//
#include <stdio.h>
#include <homelab/adc.h>
#include <homelab/delay.h>
#include <homelab/module/sensors.h>
#include <homelab/module/lcd_alpha.h>
 
//
// Основная программа
//
int main(void)
{
	signed short value, distance;	
	char text[16];
 
	// External sensor selection
	pin ex_sensors = PIN(G, 0);
	pin_setup_output(ex_sensors);
	pin_set(ex_sensors);
 
	// Настройка LCD экрана
	lcd_alpha_init(LCD_ALPHA_DISP_ON);
 
	// Очистка LCD экрана
	lcd_alpha_clear();
 
	// Название программы
	lcd_alpha_write_string("Датчик расстояния");
 
	// Настройка ADC преобразователя
	adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
 
	// Бесконечный цикл
	while (true)
	{
		// Считывание значения выходного напряжения датчика, округленного в 4 раза
		value = adc_get_average_value(0, 4);		
 
		// Пересчет значения ADC в расстояние
		distance = ir_distance_calculate_cm(GP2Y0A21YK, value);
 
		// Возможно ли отобразить расстояние или сообщение об ошибке?
		if (distance >= 0)
		{			
			sprintf(text, "%d cm   ", distance);
		}
		else
		{
			sprintf(text, "Ошибка   ");
		}
 
		// Отображение текста в начале второй строки LCD
		lcd_alpha_goto_xy(0, 1);
		lcd_alpha_write_string(text);
 
		// Пауза
		sw_delay_ms(500);
	}
}

Дополнительные материалы