Тема этого урока — оптический датчик измерения расстояния. Такие датчики встречаются как в робототехнике, так и в бытовой жизни (например, сушилки для рук, элементы «умного дома», реагирующие на движение, тоже имеют датчик расстояния 🙂 ). Для урока взят датчик SHARP 2Y0A21 с диапазоном измерения 10-80 см.
Список необходимых компонентов
Для выполнения всех экспериментов в данном уроке, кроме самого датчика, потребуются: Ардуино-совместимый контроллер и немного проводов вилка-розетка. Необходимые компоненты можно добавить в корзину прямо здесь, и затем оформить заказ в нашем интернет-магазине.
Принцип работы оптического датчика измерения расстояния
Часто, можно услышать неправильное мнение, что оптические датчики расстояния работают по принципу акустических — измеряют время прохождения луча от датчика до препятствия. Конечно, подобные датчики тоже существуют, но чаще всего оптические дальномеры работают совсем по другому принципу, основанному на относительно простой геометрии.
Принцип работы оптического датчика Sharp заключается в том, что лазерный луч отражается от препятствия и попадает на матрицу в разные её места, в зависимости от того, на каком расстоянии D произошло отражение .
где G — расстояние на матрице до тени;
F — расстояние от матрицы до линзы;
L — расстояние от луча до матрицы.
Перед нами обычный прямоугольный треугольник, так что расстояние до объекта D определяется по формуле D = (FE)/G.
Выход датчика нелинеен. Зависимость показаний датчика от расстояния имеет следующий вид:
Излом в начале первого графика объясняется тем, что датчик не способен обнаруживать объекты на малых расстояниях. Также, у разных типов датчиков будут разные минимальное и максимальное расстояния.
Подключение датчика к Ардуино
Датчик Sharp аналоговый, а значит его можно подключить к одному из входов АЦП Ардуино. В нашем случае, подключаем к A0.
SHARP 2Y0A21 | GND | VCC | OUT |
Arduino Uno | GND | +5V | A0 |
Принципиальная схема:
Внешний вид макета:
Программа
Считывать полученное значение с датчика мы будем при помощи функции analogRead. Функция analogRead возвращает нам целое число от 0 до 1023 и чтобы узнать уровень напряжение на выходе сенсора, нам нужно домножить это число на 5 и поделить на 1023. Подробно про АЦП можно прочитать в одном из предыдущих уроков — Аналого-цифровые преобразования — АЦП.
Чтобы не совершать лишние операции в программе, заменим 5/1023 на 0.0048828125. В итоге получим вот такую несложную программу:
float V; // переменная для хранения значения АЦП
float dist; // переменная для хранения вычисленного расстояния
void setup() {
Serial.begin(9600); // старт последовательного порта
}
void loop() {
// считываем значение сенсора и переводим в напряжение
V = analogRead(A0)0.0048828125;
dist = 65pow(V, -1.10); // вычисляем расстояние
Serial.println(dist); // выдаём результат в порт
delay(1000);
}
Формула dist = 65*pow(V, -1.10) — на самом деле является функцией, которая отражает зависимость напряжения на выходе датчика от расстояния. Ту самую зависимость, которая изображена на графике выше.
Заливаем программу на Ардуино, запускаем монитор последовательного порта и подносим руку к сенсору. В результате, мы должны увидеть на мониторе примерное расстояние до объекта:
// так более или менее работает
// в приведенном выше примере исчезли знаки умножения
// аппроксимация, вероятно, от другого датчика (тоже Sharp)
// фильтрация нужна обязательно
float V;
float distance_;
float filtered_val;
unsigned int tick=0;
void setup()
{
Serial.begin(9600);
filtered_val= analogRead(A0);
}
void loop()
{
filter();
V = filtered_val*0.0048828125;
distance_ = 29.988*pow(V, -1.173); // Guillaume Rico
if(tick%10==0)
{
Serial.print(filtered_val);
Serial.print(«\t»);
Serial.println(distance_);
}
tick++;
delay(50);
}
float filter()
{
filtered_val= analogRead(A0)/32. + 0.96875*filtered_val; // analogRead(A0)/32. +31/32*filtered_val
}