Плеко / Робототехніка
Урок 07 · Крок 1 / 10

Дальномір з OLED

Відстань до предмета показуємо числом і смугою на екрані.

  • Arduino Uno, HC-SR04, макетна плата, USB-кабель і дроти.
  • OLED 128×64 з контролером SSD1306 та інтерфейсом I²C (чотири контакти).
  • Для фізичного OLED із логікою лише 3,3 В — двонапрямний узгоджувач рівнів I²C 5↔3,3 В.
  • Лінійка та плаский картон.

Перед складанням перевір маркування екрана: SSD1306, 128×64, I²C. Для іншої моделі потрібно змінити бібліотеку або налаштування.

Перед зміною схеми від’єднай живлення. У Wokwi зупини симуляцію. Справжню схему перевір разом з учителем перед підключенням USB.

Повний код і файли проєкту

Arduino Uno показує відстань на OLED SSD1306 128×64.

#include <Arduino.h> // Основні команди Arduino.
#include <Wire.h> // Обмін даними I²C.
#include <Adafruit_GFX.h> // Текст і графічні фігури.
#include <Adafruit_SSD1306.h> // Керування дисплеєм SSD1306.

const byte TRIG_PIN = 7; // Команда датчику почати вимірювання.
const byte ECHO_PIN = 6; // Вхід тривалості відлуння.
const byte OLED_ADDRESS = 0x3C; // Адреса дисплея на шині I²C.
Adafruit_SSD1306 display(128, 64, &Wire, -1); // Екран 128×64 без окремого RESET.

float readDistanceCm() { // Повертаємо сантиметри або -1 при помилці.
  digitalWrite(TRIG_PIN, LOW); // Початковий низький рівень.
  delayMicroseconds(2); // Даємо сигналу стабілізуватися.
  digitalWrite(TRIG_PIN, HIGH); // Починаємо запуск вимірювання.
  delayMicroseconds(10); // Тримаємо імпульс 10 мікросекунд.
  digitalWrite(TRIG_PIN, LOW); // Завершуємо імпульс.
  unsigned long duration = pulseIn(ECHO_PIN, HIGH, 25000UL); // Чекаємо не довше 25 мс.
  float cm = duration / 58.0; // Час шляху звуку туди й назад переводимо в см.

  if (duration == 0 || cm < 2 || cm > 400) { // Немає надійного вимірювання.
    return -1; // Окреме значення помилки, а не нуль сантиметрів.
  }

  return cm; // Віддаємо виміряну відстань.
}

void setup() { // Підготовка датчика та екрана.
  pinMode(TRIG_PIN, OUTPUT); // TRIG надсилає імпульс.
  pinMode(ECHO_PIN, INPUT); // ECHO приймає імпульс.
  digitalWrite(TRIG_PIN, LOW); // До першого вимірювання тримаємо LOW.
  Serial.begin(115200); // Монітор порту для перевірки.
  Wire.begin(); // На Uno: SDA=A4, SCL=A5.
  Wire.beginTransmission(OLED_ADDRESS); // Перевіряємо відповідь за адресою.
  byte error = Wire.endTransmission(); // Нуль означає, що пристрій відповів.

  if (error != 0 || !display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) { // Немає екрана або пам’яті.
    Serial.println(F("OLED error: check power, A4/A5, address")); // Підказка в моніторі.

    while (true) { // Зупиняємо приклад до виправлення й перезапуску.
      delay(1000); // Не продовжуємо малювати на недоступному екрані.
    }

  }

  display.clearDisplay(); // Очищаємо графічний буфер.
  display.setTextColor(SSD1306_WHITE); // Світлі пікселі на темному тлі.
  display.display(); // Передаємо очищений буфер на екран.
}

void loop() { // Новий кадр із новим вимірюванням.
  float cm = readDistanceCm(); // Вимірюємо відстань.
  display.clearDisplay(); // Прибираємо попередні цифри та шкалу.
  display.setTextSize(1); // Малий шрифт заголовка.
  display.setCursor(0, 0); // Початок верхнього рядка.
  display.print(F("Distance")); // Латиниця підтримується стандартним шрифтом.
  display.setCursor(0, 20); // Місце для результату.

  if (cm < 0) { // Відлуння не отримано або значення поза межами.
    display.setTextSize(1); // Помилка має вміститися в ширину екрана.
    display.print(F("No echo")); // Не показуємо помилковий нуль.
  } else { // Є вимірювання.
    display.setTextSize(2); // Великі цифри.
    display.print(cm, 0); // Виводимо округлену відстань.
    display.print(F(" cm")); // Одиниця вимірювання.
    int width = map(constrain((int)cm, 0, 100), 0, 100, 0, 124); // Шкала 0–100 см.
    display.drawRect(0, 49, 128, 14, SSD1306_WHITE); // Контур шкали.
    display.fillRect(2, 51, width, 10, SSD1306_WHITE); // Заповнюємо частину шкали.
  }

  display.display(); // Лише тепер показуємо готовий кадр.
  Serial.println(cm); // Дублюємо вимірювання для діагностики.
  delay(100); // Пауза між вимірюваннями більша за 60 мс.
}

Wokwi потребує інтернету. Завантажений HTML-урок працює офлайн.