Если ты хочешь измерять расстояние с помощью ультразвукового датчика HC-SR04 и видеть результат на дисплее — например, для робота-исследователя, парктроника или просто ради интересного проекта — эта задача решается за один вечер. Главное правильно собрать схему и не наделать ошибок в коде, из-за которых датчик будет показывать ерунду.
Ниже — пошаговое руководство: от подключения проводов до рабочего скетча. Всё проверено на практике.
Что понадобится
Минимальный набор деталей:
- Arduino (Uno, Nano или любая совместимая плата)
- Ультразвуковой датчик HC-SR04
- LCD-дисплей 16×2 с интерфейсом I2C (именно I2C — об этом ниже)
- Соединительные провода (мама-мама или мама-папа — зависит от платы)
- Макетная плата — опционально, но удобно
Почему LCD именно с I2C: обычный 16×2 без адаптера требует 6 пинов Arduino. С I2C-модулем — только 2 пина (SDA и SCL) плюс питание. Разница критическая, особенно если пинов мало.
Как устроен HC-SR04 и почему он работает
Датчик посылает ультразвуковой импульс на частоте 40 кГц, затем слушает отражённый сигнал. Время между отправкой и приёмом — это время прохождения звука туда и обратно. Зная скорость звука (~343 м/с при комнатной температуре), можно вычислить расстояние.
Формула простая: расстояние = (время × скорость звука) / 2. Делим на два, потому что звук проходит путь до объекта и обратно.
У HC-SR04 четыре вывода:
- VCC — питание 5 В
- GND — земля
- Trig — вход, на него подаём короткий импульс для запуска измерения
- Echo — выход, датчик выдаёт на него импульс, длительность которого равна времени прохождения звука
Схема подключения
Вот как всё соединять. Начну с датчика, затем дисплей.
Подключение HC-SR04 к Arduino
| HC-SR04 | Arduino |
|---|---|
| VCC | 5V |
| GND | GND |
| Trig | Пин 9 |
| Echo | Пин 10 |
Пины Trig и Echo можно менять в коде, но для первого запуска оставь так — будет проверять.
Подключение LCD 16×2 I2C к Arduino
| LCD I2C | Arduino Uno / Nano |
|---|---|
| VCC | 5V |
| GND | GND |
| SDA | A4 |
| SCL | A5 |
На Arduino Mega пины другие: SDA — 20, SCL — 21. На Leonardo: SDA — 2, SCL — 3. Проверь свою плату, если результат не появляется на дисплее — первая причина не тот пин.
Библиотеки, которые нужны
В Arduino IDE через менеджер библиотек установи:
- LiquidCrystal_I2C — самая распространённая, автор — Frank de Brabander. Ищи по названию в Library Manager.
- Для HC-SR04 отдельная библиотека не обязательна — работаем напрямую с пинами. Но если хочешь готовую обёртку, подойдёт NewPing — она корректно обрабатывает таймауты.
Рабочий скетч
Вот полный код. Скопируй, загрузи в Arduino, открой монитор порта на 9600 бод — там тоже будут показываться значения.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Адрес дисплея обычно 0x27 или 0x3F. Если не работает — запусти I2C Scanner и проверь.
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int trigPin = 9;
const int echoPin = 10;
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
lcd.setCursor(0, 0);
lcd.print("HC-SR04 Ready");
delay(1500);
lcd.clear();
}
void loop() {
long duration;
float distance;
// Отправляем 10-микросекундный импульс на Trig
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Считываем длительность с Echo
duration = pulseIn(echoPin, HIGH, 30000); // Таймаут 30 мс (~5 м)
// Если таймаут — duration будет 0
if (duration == 0) {
lcd.setCursor(0, 0);
lcd.print("Out of range ");
lcd.setCursor(0, 1);
lcd.print(" ");
} else {
// Расчёт расстояния в сантиметрах
distance = duration * 0.0343 / 2.0;
lcd.setCursor(0, 0);
lcd.print("Dist: ");
lcd.print(distance, 1);
lcd.print(" cm ");
// Дополнительно — строка состояния
lcd.setCursor(0, 1);
if (distance < 10) {
lcd.print("! CLOSE OBJECT !");
} else if (distance > 400) {
lcd.print("Beyond 400cm ");
} else {
lcd.print("Range OK ");
}
}
delay(200); // Не опрашиваем слишком часто
} Обрати внимание на таймаут в pulseIn — 30 миллисекунд. Без него скетч зависнет, если датчик ничего не обнаружил (например, объект слишком далеко или сигнал ушёл в пустоту). Это одна из самых частых причин «зависающих» проектов.
Что делать, если на дисплее пусто
Порядок проверки:
- Подстроечный потенциометр на I2C-модуле. Крути его медленно — пока не появятся чёрные квадратики. Если их нет — контраст выставлен в крайнее положение.
- Адрес дисплея. Загрузь скетч I2C Scanner (File → Examples → Wire → scanner) и посмотри, какой адрес показывает монитор порта. Подставь его в
LiquidCrystal_I2C lcd(0x27, 16, 2);вместо 0x27. - Питание. Если дисплей подключён к 3.3V вместо 5V — он может не запуститься. Проверь напряжение мультиметром.
- Провода. Переткни SDA и SCL. Если провода длинные больше 20 см — могут быть помехи, укороти для теста.
Частые ошибки, из-за которых ничего не работает
- Перепутаны Trig и Echo. Датчик не запускает измерение, на Echo тишина. Проверь пины по схеме.
- Нет делителя напряжения на Echo. У HC-SR04 выход Echo — 5 В. У Arduino это обычно не проблема, но если у тебя 3.3В-плата (ESP32, Due) — без делителя напряжения пин может сгореть. Делитель: 1 кОм от Echo к пину, 2 кОм от пина к GND.
- Слишком близкий объект. HC-SR04 не измеряет расстояние ближе ~2 см. Ближе — эхо возвращается быстрее, чем датчик успевает переключиться из режима передачи в режим приёма.
- Мягкие или наклонные поверхности. Велосипедная шина, шторы, поролон — звук поглощается или отражается в сторону. Датчик выдаёт 0 или случайные значения. Это не поломка, это физика.
- Забыли подсветку.
lcd.backlight()без вызова — дисплей выглядит пустым, хотя данные на нём есть. Посмотри под углом — увидишь символы.
Какой LCD выбрать
Если только начинаешь — бери 16×2 с I2C-модулем на базе PCF8574. Это самый распространённый и дешёвый вариант. Вот что стоит учитывать:
| Параметр | LCD 16×2 I2C | LCD 20×4 I2C | OLED 0.96″ I2C |
|---|---|---|---|
| Символов | 16 × 2 | 20 × 4 | 16 × 2 (или 21 × зависит от шрифта) |
| Интерфейс | I2C | I2C | I2C |
| Подсветка | LED, синяя/зелёная | LED | Сам экран — LED матрица |
| Читаемость при ярком свете | Средняя | Средняя | Хорошая |
| Потребление | ~20 мА с подсветкой | ~30 мА | ~15 мА |
| Удобство для проекта | Достаточно для расстояния + статус | Можно вывести больше данных | Компактный, но дороже |
Для задачи «показать расстояние» 16×2 хватает за глаза. 20×4 берут, когда нужно одновременно показывать минимальное/максимальное расстояние, статус системы или единицы измерения с переключением.
Сценарии выбора под свою задачу
Делаешь простой дальномер для мастерской. Бери 16×2 I2C, код выше — и работает. Минимум проводов, всё понятно.
Делаешь робот с объездом препятствий. Датчик на сервоприводе, сканирует влево-вправо. На LCD выводи расстояние + направление. Тут удобнее 20×4 — помещается больше информации.
Делаешь парктроник для гаража. LCD вообще не нужен — достаточно светодиодов и бипера. Но если хочешь именно дисплей — бери OLED, он читается при любом освещении.
Работаешь с ESP32 вместо Arduino. Схема та же, но учти: на ESP32 SDA — GPIO 21, SCL — GPIO 22. И обязательно делитель напряжения на Echo (5В → 3.3В).
Как улучшить точность
HC-SR04 из коробки даёт точность ±3 мм при идеальных условиях. На практике разброс больше. Вот что реально помогает:
- Не опрашивай датчик слишком часто. Между измерениями нужно минимум 50–60 мс, иначе предыдущее эхо накладывается на новое.
- Усредняй показания. Сделай 3–5 измерений, отбрось максимальное и минимальное, остальные усреднь. Разброс уйдёт.
- Учитывай температуру. Скорость звука меняется: при 0°C это ~331 м/с, при 20°C — ~343 м/с, при 30°C — ~349 м/с. Для домашних условий разница незаметна, но если работаешь на улице зимой — добавь датчик температуры и корректируй расчёт.
- Фиксируй датчик жёстко. Висящий на проводах, болтающийся на макетке — он сам себе создаёт помехи.
Итог
Собрать дальномер на HC-SR04 с выводом на LCD — задача на 30 минут, если знаешь порядок действий. Ключевые моменты:
- Подключай LCD через I2C — экономишь пины и провода.
- Всегда ставь таймаут в
pulseIn— иначе скетч зависнет при потере сигнала. - Если дисплей пустой — сначала проверь контраст и адрес I2C, потом всё остальное.
- Для мягких и наклонных поверхностей датчик врёт — это не баг, это особенность ультразвука.
Начни с приведённого выше кода — он рабочий. Когда заработает — добавляй свои фильтры, усреднение, переключение единиц измерения. Это уже детали.
