Введение
В данной статье объясняется, как определить местоположение объекта с помощью Arduino, двух ультразвуковых датчиков и формулы Герона для треугольников. Движущихся частей в проекте нет.
Формула Герона позволяет рассчитать площадь любого треугольника, для которого известны все стороны. Как только вы узнаете площадь треугольника, вы сможете рассчитать положение одного объекта (относительно известной базовой линии), используя тригонометрию и теорему Пифагора.
Точность отличная. При использовании распространенных ультразвуковых датчиков HC-SR04 или HY-SRF05 возможны большие области обнаружения.
Конструкция проста: всё, что вам нужно, это острый нож, два сверла, паяльник и ножовка по дереву.
Изображения:
- видеоролик, показывающий работу устройства;
- фото 1 показывает собранный эхолокатор;
- на фото 2 показан типовой дисплей. Объект отображается красной (мигающей) точкой;
- на фото 3 показана тестовая установка, используемая на видео. Было необходимо установить два ультразвуковых датчика HY-SRF05 на 50 см ниже базовой линии, чтобы полностью «осветить» зону обнаружения со звуком.
Рисунок 1 – Собранный эхолокатор на двух датчиках и Arduino
Рисунок 2 – Скриншот экрана обнаружения объектаРисунок 3 – Тестовый стенд для проверки эхолокатора на Arduino
Сборка робота для очистки пола
Смонтируйте плату Arduino на шасси робота. Убедитесь в том, что она не касается никаких металлических деталей. Хорошей идеей будет установка платы Arduino и шилда драйвера двигателей в отдельную коробку. Зафиксируйте двигатели и колеса на шасси робота с помощью болтов. Также для этой цели можно использовать эпоксидный клей или другие способы. Закрепите приспособление для сбора мусора (не знаю как точно перевести, но в оригинале оно называется Scotch Brite scrub pad) позади щетки. Чтобы закрепить все это мы использовали ось, идущую вдоль шасси робота. Также отдельно смонтируйте батареи на шасси робота – для их крепления можно использовать отдельную коробку или специальный контейнер.
Водонепроницаемый ультразвуковой датчик JSN SR-04T
JSN SR-04T представляет собой модуль водонепроницаемого ультразвукового датчика, который способен измерять расстояние на дистанциях 25-450 см с точностью 2 мм. Модуль датчика состоит из двух раздельных частей. Одна часть – это датчик, который непосредственно производит передачу и прием ультразвуковых волн, а вторая часть – это плата управления. По принципу действия JSN SR-04T очень похож на датчики парковки, которые устанавливаются в бамперах автомобилей.
Модуль датчика JSN SR-04T имеет водозащищенное исполнение датчика, отличается устойчивым функционированием в сложных условиях эксплуатации и высокой точностью измерения расстояния. Он может использоваться в системах дальнометрии, предотвращения столкновения с препятствиями, автоматизированного контроля, мониторинга движения объектов, контроля трафика, системах безопасности и искусственного интеллекта и многих других применениях.
Назначение контактов (распиновка) датчика JSN SR-04T представлены на следующих рисунке и таблице.
№ контакта | Название контакта | Назначение контакта |
1 | 5V | Напряжение питания |
2 | Trig | Входной контакт датчика. На него необходимо подать импульс длительностью 10 мкс чтобы запустить датчик в работу (чтобы он начал излучение ультразвуковой волны). |
3 | Echo | Выходной контакт датчика. После приема отраженной от препятствия ультразвуковой волны на этом контакте формируется импульс высокого уровня (high), длительность которого равна времени распространения ультразвуковой волны до препятствия и обратно. |
4 | Gnd | Общий провод (земля) |
Модуль датчика JSN SR-04T во многом похож на модуль ультразвукового датчика, но по сравнению с ним у него есть ряд преимуществ:
- в отличие от HC-SR04 у модуля JSN SR-04T непосредственно датчик не распаян на печатной плате модуля, вместо этого он закреплен на конце достаточно длинного кабеля (2,5 метра), поэтому чувствительный элемент датчика может быть удален на значительное расстояние от платы управления;
- чувствительный элемент датчика заключен в защищённый водонепроницаемый корпус, поэтому его можно размещать в жестких условиях эксплуатации и агрессивных средах.
Но несмотря на эти преимущества имеются и некоторые недостатки. К примеру, минимальное расстояние измерения у датчика JSN SR-04T составляет 20 см, в то время как у датчика HC-SR04 оно равно 2 см. Причина этого заключается в том, что JSN SR-04T имеет только один чувствительный элемент в то время как у датчика HC-SR04 их два – один используется для передачи ультразвуковых волн, а другой для приема. В результате этого чувствительному элементу датчика JSN SR-04T приходится переключаться двумя режимами (прием/передача), а на это требуется дополнительное время. Поэтому и минимальное расстояние измерения для датчика JSN SR-04T равно 20 см, а датчик HC-SR04 может измерять значительно меньшие расстояния благодаря наличию у него отдельных передатчика и приемника.
Основные технические характеристики и особенности датчика JSN SR-04T:
- рабочее напряжение: DC 5V (постоянного тока);
- ток в состоянии покоя (ожидания): 5mA;
- ток в рабочем состоянии: 30mA;
- частота ультразвуковой волны: 40 кГц;
- диапазон измерения расстояний: от 25 см до 4,5 м;
- длина кабеля: 2,5 метра.
Предисловие
Так получилось, что в университете я изучаю C/C++. Для души пробую делать небольшие проекты на Python. Я много слышал про платформу Arduino, смотрел видео на YouTube, частенько посещал Arduino Project Hub и вот мне стало интересно самому поэкспериментировать, углубясь в разработку под микроконтроллеры. Купив стартовый набор с самой платой и горстью электронных компонентов и попробовав собрать проекты из обучающей брошюры, понял, что надо двигаться дальше. Продумав саму идею следующей самоделки, отправился на просторы Google и обнаружил, что не могу найти всего, что мне нужно на одном ресурсе. Безусловно, мне несложно было посетить несколько сайтитов и блогов с информацией, но я бы сильно сэкономил время, если бы нашел все в одном месте. Так и появилась эта статья-туториал.
Схема проекта
Схема проекта ультразвуковой левитации на основе платы Arduino представлена на следующем рисунке.
Основными компонентами данной схемы являются плата Arduino, драйвер двигателей L239D и ультразвуковые датчики (преобразователи, transducer), собранные из модуля ультразвукового датчика HCSR04, который способен генерировать акустические волны с частотами от 25 до 50 кГц. На нашем сайте вы можете посмотреть все проекты, в которых ультразвуковой датчик HCSR04 использовался для определения расстояния до объектов. Но для данного проекта мы выпаяли ультразвуковые передатчики из модуля HCSR04.
В соответствии с даташитом на модуль HCSR04 его рабочая частота составляет 40 кГц. Таким образом, задачей платы Arduino в этом проекте является формирование сигналов с частотой 40 кГц для работы наших самодельных ультразвуковых датчиков (передатчиков). Эти сигналы (с контактов A0 и A1 платы Arduino) подаются на входы микросхемы драйвера двигателей L239D (ее контакты 2 и 6). Далее с помощью этих сигналов происходит управление управляющим напряжением (от 8 до 12 В), которое подается на контакт 8 микросхемы L239D, в результате этого микросхема L239D подает управляющие сигналы на ультразвуковые передатчики – мы их разместили лицом друг к другу и оставили между ними небольшое расстояние. Таким образом, акустические волны распространяются между этими двумя датчиками и позволяют объекту, размешенному между ними, парить (плавать) в воздухе.
Необходимо заметить, что микросхема L293D имеет два входа напряжения, по одному из них микросхема питается сама – на него питание подается с контакта 5v платы Arduino, а на другой контакт (8-й) Vcc2 (на него можно подавать до 36 В) подается другое напряжение, которое используется для управления выходными контактами.
Микросхема L293D имеет 2 разрешающих контакта (Enable pins), 4 контакта ввода-вывода и 4 общих контакта (ground pins). В этом проекте мы будем использовать только два входных контакта микросхемы — pin 1 (2) и pin 2 (7). Чтобы разрешить работу этих двух контактов, мы должны подать на Enable PIN 1 напряжение высокого уровня (high), поэтому в нашей схеме этот контакт подключен к контакту 16, который является контактом Vcc 1 (то есть на него подается питающее напряжение). Более подробно о принципах работы контактов данной микросхемы вы можете прочитать в даташите на L293D.
Использование конденсатора емкостью 100 нФ в представленной схеме опционально. В качестве источника питания мы используем 12V 2Amp LED driver, затем мы понижаем напряжение до 9 В с помощью микросхемы регулятора напряжения LM7809 и подаем его на 8-й контакт микросхемы L293D. В соответствии с техническими характеристиками платы Arduino Uno на ее контакт Vin можно подавать напряжение в диапазоне от 7 до 12 В, однако лучше (более безопасно) не подавать на этот контакт напряжение более 9 В.
3Получение дистанции до объекта с датчика HC-SR04
Теперь напишем скетч, определяющий расстояние до препятствия и выводящий его в последовательный порт. Сначала задаём номера выводов TRIG и ECHO – это 12 и 11 пины. Затем объявляем триггер как выход, а эхо – как вход. Инициализируем последовательный порт на скорости 9600 бод. В каждом повторении цикла loop() считываем дистанцию и выводим в порт.
const int trigPin = 12; const int echoPin = 11;void setup() { pinMode(trigPin, OUTPUT); // триггер — выходной пин pinMode(echoPin, INPUT); // эхо — входной digitalWrite(trigPin, LOW); Serial.begin(9600); // инициализация послед. порта}void loop() { long distance = getDistance(); // получаем дистанцию с датчика Serial.println(distance); // выводим в последовательный порт delay(100);} // Определение дистанции до объекта в смlong getDistance() { long distacne_cm = getEchoTiming() * 1.7 * 0.01; return distacne_cm;} // Определение времени задержкиlong getEchoTiming() { digitalWrite(trigPin, HIGH); // генерируем 10 мкс импульс запуска delayMicroseconds(10); digitalWrite(trigPin, LOW); // определение на пине echoPin длительности уровня HIGH, мкс: long duration = pulseIn(echoPin, HIGH); return duration;} Функция getEchoTiming() генерирует импульс запуска. Она как раз создаёт тот 10-микросекундный импульс, который является триггером для начала излучения дальномером звукового пакета в пространство. Далее она запоминает время от начала передачи звуковой волны до прихода эха.
Функция getDistance() рассчитывает дистанцию до объекта. Из школьного курса физики мы помним, что расстояние равно скорость умножить на время: S = V×t Скорость звука в воздухе 340 м/сек, время в микросекундах мы знаем (переменная duration). Чтобы получить время duration в секундах, нужно разделить его на 1 000 000. Так как звук проходит двойное расстояние – до объекта и обратно – нужно ещё разделить результат пополам. Вот и получается, что расстояние до объекта S = 34000 см/сек × duration / 1 000 000 сек / 2 = 1,7 см/сек / 100, что мы и написали в скетче.
Операцию умножения микроконтроллер выполняет быстрее, чем операцию деления, поэтому :100 я заменил на эквивалентное ×0,01.
Подключение датчика HC SR04
С подключением датчика не должно возникнуть никаких проблем. Достаточно с помощью проводников соединить пин на питание с источником или МК, а ввод и вывод, соответственно, присоединить непосредственно к МК. Воспользуйтесь схемой ниже для сборки схемы:
У самого сенсора SR04 следующие характеристики от которых вам стоит отталкиваться:
- Напряжение для питания – 5В.
- Работает в цепях с силой тока 15 мА.
- Если датчик не используется, то для поддержания его в пассивном состоянии всё ещё требуется до 2 мА.
- Угол обзора у модуля небольшой, всего 15 градусов.
- Разрешение сенсора – 3 десятых см.
- А вот угол для измерений составляет уже приятные 30 градусов.
Также на датчике имеются четыре вывода по стандарту 2.54 мм. В них входит контакт для питания с положительным напряжением +5В, пины для ввода и вывода сигнала и заземление.
В конечном варианте выглядеть устройство должно примерно таким образом:
4Калибровка ультразвукового дальномера
После небольшого опыта использования данного прибора, выявилось, что измеренное расстояние отличается от действительного, причём чем больше расстояние от датчика до цели, тем больше отклонение. В связи с этим возникла необходимость в корректировке показаний дальномера.
Для этого я измерил на всём рабочем диапазоне датчика (от 0 до 400 см) расстояния и составил таблицу из двух столбцов: реальное расстояние и показания датчика. По этим данным построил график:
График отклонения показаний ультразвукового дальномера
Здесь зелёным цветом показан график для идеального дальномера, как должно быть, а красным – реального, который в моём случае занижает показания.
Зависимость получилась линейная. Прекрасно! Из курса геометрии мы помним, что уравнение прямой, проходящей через две точки: (x − x1)/(x2 − x1) = (y − y1)/(y2 − y1)
Подставив вместо x1, 2 и y1, 2 значения из таблицы и упростив выражение, я получил уравнение для графика измерений ультразвукового дальномера: y = 0,97x + 0,27
В уравнении прямой коэффициент 0,97 возле «икс» является тангенсом угла наклона прямой к оси абсцисс. Назовём его tg(α). Можно посчитать, что угол наклона прямой равняется 44,13 градусам (арктангенс от 0,97), а в идеальном случае он должен быть равен 45 градусам (и уравнение прямой идеального дальномера очень простое: y = x, то есть каждому измеренному числу соответствует точно такое же реальное расстояние). Постоянная 0,27 – это смещение графика относительно нуля по оси ординат.
Посмотрим на следующий рисунок. Видны два прямоугольных треугольника, приподнятые над осью OX. Один из катетов, назовём его h, треугольника с углом α равен измеренному дальномером расстоянию Rизм за вычетом константы b, равной 0,27. Катет другого треугольника равен реальному расстоянию Rреал. У обоих треугольников катеты h равны. Зная длину катета h и тангенс угла α (равный 0,97), мы узнаем реальное расстояние Rреал, поделив, длину катета h на tg(α),
Последовательность коррекции показаний ультразвукового дальномера
Таким образом, для того чтобы скорректировать ошибку при измерениях дальномера, нужно следовать формуле: Rреал = (Rизм − b) / tg(α) = (Rизм − 0,27) / 0,97 Обратите внимание, что это выражение можно было получить из предыдущего уравнения, выразив x через y. В вашем случае коэффициент и константа, естественно, будут отличаться
Эту коррекцию следует внести в скетч для Arduino. После этого ультразвуковой дальномер на датчике HC-SR04 будет показывать расстояние более точно
В вашем случае коэффициент и константа, естественно, будут отличаться. Эту коррекцию следует внести в скетч для Arduino. После этого ультразвуковой дальномер на датчике HC-SR04 будет показывать расстояние более точно.
Напоследок приведу видеодемонстрацию работы готового ультразвукового дальномера (до калибровки).
Шаг 5: установка программного обеспечения
Установите следующее программное обеспечение в этом порядке:
Arduino IDE
Скачайте и установите Arduino IDE (интегрированную среду разработки) с сайта https://www.arduino.cc/en/main/software, если она еще у вас не установлена.
Скетч Arduino
Скачайте и откройте в Arduino IDE файл «dual_sensor _echo_locator.ino«, загрузите его в свою Arduino Uno R3.
Закройте Arduino IDE, но USB кабель оставьте подключенным.
Скетч Processing
Скопируйте содержимое прикрепленного файла, “dual_sensor_echo_locator.pde” в Processing «Sketch».
Теперь нажмите вверху слева кнопку «Run»… На вашем экране должен появиться графический экран.
Технические характеристики Arduino Sensorshield
Самое главное преимущество данного шилда заключается в том, что вы сможете подключить огромное количество датчиков с максимальной удобностью и при этом заняв максимально маленькое место на Arduino. Подключение шилда к ардуино воспроизводится стандартным способом, а именно накладывается всеми контактами на плату микроконтроллера, сделав гибрид, который мы назовем — «бутерброд».
Шилд можно использовать для подключения следующих устройств
- SD card
- 32 servo controller
- RB URF для ультразвуковых датчиков
- 12864 LCD последовательный и параллельный интерфейс
- APC220 wireless RF
- Bluetooth
- I2C
Ниже приведена схематическая распиновка платы Sensorshield, она вам поможет понять, в какие пины вам необходимо соединить тот или иной датчик.
Суть проекта
Мне хотелось сделать дальномер. Во-первых, из-за того, что у меня был ультразвуковой датчик и надо было научиться с ним взаимодействовать. Во-вторых, я хотел выводить всю информацию на OLED-дисплей. В статьях, которые я находил, либо рассказывалось про работу с дисплеем и датчиком по отдельности, либо они являлись частью совершенно другого проекта. Я собрал все необходимое тут и надеюсь, что это сможет как-то помочь другим.
Что понадобится?
-
Любая плата Arduino (у меня Uno);
-
Ультразвуковой дальномер HC-SR04;
-
OLED-дисплей на 0,96 дюймов;
-
Соединительные провода;
-
Макетная плата.
Скачивание и установка необходимого программного обеспечения
Программную среду Arduino IDE можно скачать по этой ссылке, хотя если вы читаете этот материал наверняка она у вас уже есть. Arduino IDE требует драйвера для взаимодействия с платой Arduino. Обычно этот драйвер устанавливается автоматически как только вы подключаете плату Arduino к вашему компьютеру. Но если у вас возникла проблема с этим шагом, то найти ее решение вы можете в полном руководстве по плате Arduino Uno на нашем сайте.
Программную среду Processing IDE можно скачать по этой ссылке. Processing представляет собой отличную программную среду с открытым исходным кодом, хорошо подходящую для многих DIY (сделай сам) проектов. Она имеет несколько режимов работы. В режиме “Java Mode” мы можем создать в ней оконное приложение для операционной системы Windows (.EXE files), в режиме “Android mode” – мобильное приложение для Android (.APK files), в режиме “Python mode” можно писать программы на языке Python. В данной статье мы не будем подробно описывать работу с данной программной средой (для этой цели в сети есть специализированные сайты), но будет приведен текст программы в ней для нашего проекта, который вы можете использовать если не хотите изучать данную программную среду.
Код
1 #include <Servo.h> // подключение библиотеки Servo 2 3 #define SERVO 9 // вывод для подключения сигнального провода серводвигателя 4 #define IR 0 // аналоговый вывод для подключения сигнального провода ИК-датчика расстояния 5 #define LED1 3 // вывод для подключения LED1 6 #define LED2 5 // вывод для подключения LED2 7 #define LED3 6 // вывод для подключения LED3 8 #define LED4 11 // вывод для подключения LED4 9 10 Servo myServo; // создаем объект класса Servo 11 int dist1 = ; // переменная для хранения дистанции в первой позиции 12 int dist2 = ; // переменная для хранения дистанции в второй позиции 13 int dist3 = ; // переменная для хранения дистанции в третьей позиции 14 int dist4 = ; // переменная для хранения дистанции в четвертой позиции 15 16 void setup() 17 { 18 myServo.attach(SERVO); // подключаем объект серводвигателя к контакту SERVO (т.е. 9-му) 19 pinMode(LED1, OUTPUT); // Конфигурируем вывод LED1(т.е. 3-ий) как выход 20 pinMode(LED2, OUTPUT); // Конфигурируем вывод LED2(т.е. 5-ий) как выход 21 pinMode(LED3, OUTPUT); // Конфигурируем вывод LED3(т.е. 6-ий) как выход 22 pinMode(LED4, OUTPUT); // Конфигурируем вывод LED4(т.е. 11-ий) как выход 23 } 24 25 void loop() 26 { 27 // Осуществляем перемещение вала серводвигателя по 4 позициям 28 dist1 = readDistance(15); // Измеряем расстояния с помощью ИК-датчика при перемещении вала серводвигателя на 15 градусов 29 analogWrite(LED1, dist1); // Регулируем яркость светодиода LED1 30 delay(300); // Задержка перед следующим измерением 31 32 dist2 = readDistance(65); // Измеряем расстояния с помощью ИК-датчика при перемещении вала серводвигателя на 65 градусов 33 analogWrite(LED2, dist2); // Регулируем яркость светодиода LED2 34 delay(300); // Задержка перед следующим измерением 35 36 dist3 = readDistance(115); // Измеряем расстояния с помощью ИК-датчика при перемещении вала серводвигателя на 115 градусов 37 analogWrite(LED3, dist3); // Регулируем яркость светодиода LED3 38 delay(300); // Задержка перед следующим измерением 39 40 dist4 = readDistance(165); // Измеряем расстояния с помощью ИК-датчика при перемещении вала серводвигателя на 165 градусов 41 analogWrite(LED4, dist4); // Регулируем яркость светодиода LED4 42 delay(300); // Задержка перед следующим измерением 43 } 44 45 int readDistance(int pos) 46 { 47 myServo.write(pos); // перемещаем вал сервопривода на 'pos' градусов 48 delay(600); // задержка 49 int dist = analogRead(IR); // чтение данных с ИК-датчика расстояния 50 dist = map(dist, 50, 500, , 255); // преобразование к необходимому диапазону 51 return dist; // возврат значения расстояния, измеренного в текущей позиции вала серводвигателя 52 }
Подключение HC-SR04 к Arduino и вывод на LCD1602
Чтобы не использовать компьютер для вывода информации, мы будем вывести данные о расстоянии на ЖКИ, в моём случае — это LCD1602 (два ряда по 16 символов). Лучше всего использовать PCF8574 — I2C модуль для LCD на базе HD44780. Подробнее в статье Подключение LCD1602 к Arduino по I2C (HD44780/PCF8574).
Схема подключения LCD1602 и HC-SR04 к Arduino
Подключение HC-SR04 к Arduino:
Arduino Pro Mini | HC-SR04 |
---|---|
VCC | Vcc |
13 | Trig |
12 | Echo |
GND | Gnd |
Подключение LCD1602 к Arduino:
Arduino Pro Mini | LCD I2C модуль |
---|---|
GND | GND |
5V | VCC |
A4 | SDA |
A5 | SCL |
Пример скетча
#include <LiquidCrystal_I2C.h>
/*
Включяем библиотеку для работы с HC-SR04
*/
#include <hcsr04.h>
#define ECHO_PIN 12
#define TRIG_PIN 13
#define TIMEOUT 30000
/*
Устанавливаем ЖК-дисплей по адресу 0x27, 16 символов и 2 строки
*/
LiquidCrystal_I2C lcd(0x27, 16, 2);
/*
Создаём экземпляр класса HCSR04
*/
HCSR04 hcsr04(TRIG_PIN, ECHO_PIN, TIMEOUT);
void setup() {
hcsr04.begin();
/*
Инициализируем ЖК-дисплей
*/
lcd.init();
/*
Включаем подсветку дисплея
*/
lcd.backlight();
}
void loop() {
float cm, inch;
int mm;
/*
Получаем расстояние в миллиметрах
*/
mm = hcsr04.getDistanceMm();
/*
Даём сонару чуть-чуть отдохнуть
*/
delay(30);
/*
Получаем расстояние в сантиметрах. Тип возвращаемых данных float
*/
cm = hcsr04.getDistanceCmFloat();
/*
Даём сонару чуть-чуть отдохнуть
*/
delay(30);
/*
Получаем расстояние в дюймах. Тип возвращаемых данных float
*/
inch = hcsr04.getDistanceInchFloat();
/*
Отправляем полученные данные на LCD
*/
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(mm);
lcd.print(«mm «);
lcd.setCursor(8, 0);
lcd.print(cm);
lcd.print(«cm»);
lcd.setCursor(0, 1);
lcd.print(inch);
lcd.print(«inch»);
delay(500);
}
1 |
#include <LiquidCrystal_I2C.h> LiquidCrystal_I2Clcd(0x27,16,2); HCSR04hcsr04(TRIG_PIN,ECHO_PIN,TIMEOUT); voidsetup(){ hcsr04.begin(); /* Инициализируем ЖК-дисплей lcd.init(); /* Включаем подсветку дисплея lcd.backlight(); } voidloop(){ floatcm,inch; intmm; /* Получаем расстояние в миллиметрах mm=hcsr04.getDistanceMm(); /* Даём сонару чуть-чуть отдохнуть delay(30); /* Получаем расстояние в сантиметрах. Тип возвращаемых данных float cm=hcsr04.getDistanceCmFloat(); /* Даём сонару чуть-чуть отдохнуть delay(30); /* Получаем расстояние в дюймах. Тип возвращаемых данных float inch=hcsr04.getDistanceInchFloat(); /* Отправляем полученные данные на LCD lcd.clear(); lcd.setCursor(,); lcd.print(mm); lcd.print(«mm «); lcd.setCursor(8,); lcd.print(cm); lcd.print(«cm»); lcd.setCursor(,1); lcd.print(inch); lcd.print(«inch»); delay(500); } |