5 впечатляющих проектов с ультразвуковыми датчиками для Arduino

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Arduino-энтузиасты
  • Люди, интересующиеся электроникой и программированием
  • Начинающие разработчики, ищущие новые проекты для реализации

    Ультразвуковые датчики открывают для Arduino-энтузиастов целую вселенную возможностей! 🚀 Эти невероятные устройства превращают простую плату в "зрячего" робота, персональную охранную систему или даже музыкальный инструмент. Я собрал пять по-настоящему впечатляющих проектов, которые вы сможете реализовать буквально за выходные. От автомобильного парктроника до бесконтактного музыкального инструмента — каждый проект снабжен детальными схемами и готовым кодом. Пристегните ремни — мы погружаемся в мир ультразвуковой магии на Arduino!

Погружение в проекты с ультразвуковыми датчиками и Arduino можно сравнить с изучением программирования на Python — вы начинаете с основ и быстро переходите к созданию впечатляющих приложений. На курсе Обучение Python-разработке от Skypro вы изучите не только базовые принципы программирования, но и научитесь создавать веб-приложения, которые могут взаимодействовать с вашими Arduino-проектами через API. Представьте управление вашим роботом или считывание данных с ультразвуковых датчиков через элегантный веб-интерфейс!

Как работают ультразвуковые датчики в проектах Arduino

Ультразвуковые датчики работают по принципу эхолокации, напоминая технологию, которую используют летучие мыши для навигации в темноте. 🦇 Датчик отправляет звуковые волны частотой выше 20 кГц (за пределами человеческого слуха) и измеряет время, которое требуется для возвращения эха после отражения от объекта.

Наиболее популярным ультразвуковым датчиком для Arduino является HC-SR04, который имеет четыре вывода:

  • VCC — питание (+5В)
  • Trig — вывод запуска (отправляет ультразвуковой импульс)
  • Echo — вывод эха (получает отраженный сигнал)
  • GND — заземление

Принцип работы с HC-SR04 в проектах Arduino прост: мы отправляем короткий импульс на вывод Trig, а затем измеряем, сколько времени сигнал на выводе Echo находится в высоком состоянии. Это время прямо пропорционально расстоянию до объекта.

Алексей Соколов, преподаватель робототехники

Помню свой первый опыт с ультразвуковым датчиком HC-SR04 и Arduino. Я был уверен, что всё просто: подключил, загрузил код — и готово. Но когда начал тестирование, датчик выдавал странные значения: то 2 см, когда перед ним ничего не было, то бесконечность, когда объект находился прямо перед ним.

После нескольких часов отладки я обнаружил две проблемы: во-первых, я использовал слишком длинные провода, что вызывало помехи; во-вторых, датчик был направлен на глянцевую поверхность, которая отражала сигнал в сторону от приёмника.

Вот что я усвоил: при работе с ультразвуковыми датчиками всегда используйте короткие провода, надежное питание и учитывайте, что некоторые поверхности (особенно мягкие, пористые или расположенные под углом) могут поглощать или неправильно отражать ультразвуковые волны.

Для корректного измерения расстояния используется формула:

Расстояние (см) = (Время в микросекундах × 0.034) / 2

Здесь 0.034 — это скорость звука в сантиметрах за микросекунду, а деление на 2 необходимо, потому что измеренное время включает путь сигнала туда и обратно.

Параметр HC-SR04 US-100 JSN-SR04T
Диапазон измерения 2-400 см 2-450 см 20-600 см
Точность ±3 мм ±1 мм ±2 мм
Угол измерения 15° 15° 20°
Водонепроницаемость Нет Нет Да
Рабочее напряжение 3.3-5В

Базовый код для работы с ультразвуковым датчиком на Arduino выглядит следующим образом:

cpp
Скопировать код
#define TRIG_PIN 9
#define ECHO_PIN 10

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

void loop() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  long duration = pulseIn(ECHO_PIN, HIGH);
  float distance = (duration * 0.034) / 2;
  
  Serial.print("Расстояние: ");
  Serial.print(distance);
  Serial.println(" см");
  
  delay(500);
}

Теперь, когда мы разобрались с основами, давайте перейдем к пяти захватывающим проектам! 🛠️

Пошаговый план для смены профессии

Парктроник для автомобиля: создаем систему на Arduino

Многие автолюбители сталкиваются с проблемой парковки в тесных городских условиях. Парктроник на Arduino — отличное решение, которое можно сделать своими руками за вечер. Такая система поможет определить расстояние до препятствия и предупредит вас звуковым сигналом или визуальным индикатором.

Для создания парктроника нам понадобятся:

  • Arduino Nano или UNO
  • 1-4 ультразвуковых датчика HC-SR04
  • Пьезодинамик
  • RGB светодиод или светодиодная лента
  • Резисторы: 220 Ом (для светодиодов)
  • Макетная плата и провода
  • Корпус (можно использовать контейнер от конфет или напечатать на 3D-принтере)
  • Источник питания (можно использовать автомобильный адаптер 12В→5В)

Схема подключения для простого варианта с одним датчиком:

  1. Соедините VCC датчика с 5В на Arduino
  2. Подключите GND датчика к GND Arduino
  3. Trig вывод датчика к D9 на Arduino
  4. Echo вывод датчика к D10 на Arduino
  5. Пьезодинамик подключите к D8 через резистор 100 Ом
  6. RGB светодиод: красный к D3, зеленый к D5, синий к D6 (через резисторы 220 Ом)

Михаил Петров, автолюбитель и Arduino-энтузиаст

После того как я поцарапал бампер на новой машине, паркуясь в своем гараже, решение пришло само собой — создать парктроник на Arduino. Купил все компоненты, потратив меньше 1000 рублей, и потратил вечер пятницы на сборку.

Самым сложным оказалось не программирование или сборка схемы, а установка системы в автомобиле. Я разместил датчики в заднем бампере (просверлил отверстия точно по размеру датчиков), а Arduino с пищалкой и светодиодами установил в салоне. Для питания использовал разъем прикуривателя.

Первая поездка с самодельным парктроником была волнительной. Когда система запищала при приближении к стене гаража, я ощутил невероятное удовлетворение. За год использования парктроник ни разу не подвел — ни одной царапины! Теперь планирую добавить систему камеры заднего вида и вывести изображение на небольшой дисплей.

Код для парктроника:

cpp
Скопировать код
#define TRIG_PIN 9
#define ECHO_PIN 10
#define BUZZER_PIN 8
#define RED_PIN 3
#define GREEN_PIN 5
#define BLUE_PIN 6

// Пороговые значения для предупреждений
const int SAFE_DISTANCE = 150; // в см
const int WARNING_DISTANCE = 100;
const int DANGER_DISTANCE = 50;

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
}

void loop() {
  long duration, distance;
  
  // Отправка ультразвукового импульса
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  // Получение эха и расчет расстояния
  duration = pulseIn(ECHO_PIN, HIGH);
  distance = (duration * 0.034) / 2;
  
  Serial.print("Расстояние: ");
  Serial.print(distance);
  Serial.println(" см");
  
  // Логика работы парктроника
  if (distance > SAFE_DISTANCE) {
    // Безопасное расстояние – зеленый цвет, нет сигнала
    setColor(0, 255, 0);
    noTone(BUZZER_PIN);
  } else if (distance > WARNING_DISTANCE) {
    // Предупреждающее расстояние – синий цвет, редкие гудки
    setColor(0, 0, 255);
    beepPattern(500, 500); // 0.5с звук, 0.5с пауза
  } else if (distance > DANGER_DISTANCE) {
    // Опасное расстояние – желтый цвет, частые гудки
    setColor(255, 255, 0);
    beepPattern(200, 200); // 0.2с звук, 0.2с пауза
  } else {
    // Критическое расстояние – красный цвет, непрерывный гудок
    setColor(255, 0, 0);
    tone(BUZZER_PIN, 1000);
  }
  
  delay(100);
}

// Функция управления RGB светодиодом
void setColor(int red, int green, int blue) {
  analogWrite(RED_PIN, red);
  analogWrite(GREEN_PIN, green);
  analogWrite(BLUE_PIN, blue);
}

// Функция для создания звуковых сигналов с паузами
void beepPattern(int onTime, int offTime) {
  static unsigned long previousMillis = 0;
  static bool buzzerState = false;
  
  unsigned long currentMillis = millis();
  
  if (buzzerState && (currentMillis – previousMillis >= onTime)) {
    noTone(BUZZER_PIN);
    buzzerState = false;
    previousMillis = currentMillis;
  } else if (!buzzerState && (currentMillis – previousMillis >= offTime)) {
    tone(BUZZER_PIN, 1000);
    buzzerState = true;
    previousMillis = currentMillis;
  }
}

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

Робот-обходчик препятствий с ультразвуковым "зрением"

Создание робота, способного самостоятельно обходить препятствия — увлекательный проект, демонстрирующий основы автономной навигации. Наш робот будет использовать ультразвуковой датчик в качестве "глаз", чтобы обнаруживать препятствия и выбирать оптимальный путь. 🤖

Для этого проекта понадобятся:

  • Arduino UNO или Nano
  • Шасси робота с двумя моторами
  • Драйвер моторов L298N
  • Ультразвуковой датчик HC-SR04
  • Сервопривод SG90 для поворота датчика (опционально)
  • Батарейный блок (6-12В)
  • Перемычки и макетная плата
Алгоритм навигации Преимущества Недостатки Сложность реализации
Простой разворот при обнаружении Легко запрограммировать, минимальные требования к оборудованию Может застрять в углах или сложных лабиринтах Низкая
Сканирование с сервоприводом Лучшее "понимание" окружения, может выбирать оптимальные пути Требует дополнительного сервопривода, сложнее в настройке Средняя
Алгоритм "правой руки" Гарантированно выйдет из любого лабиринта с одним входом/выходом Не всегда выбирает кратчайший путь Средняя
Картографирование Создает карту окружения, оптимизирует маршруты Требует дополнительной памяти и вычислительной мощности Высокая

Схема подключения:

  1. Ультразвуковой датчик: – VCC → 5В Arduino – GND → GND Arduino – Trig → D9 Arduino – Echo → D10 Arduino

  2. Драйвер моторов L298N: – IN1 → D2 Arduino – IN2 → D3 Arduino – IN3 → D4 Arduino – IN4 → D5 Arduino – ENA → D6 Arduino (ШИМ для регулировки скорости левого мотора) – ENB → D7 Arduino (ШИМ для регулировки скорости правого мотора) – 12V и GND → внешний источник питания – 5V → не подключаем, если используем внешнее питание для Arduino – GND → GND Arduino (общий контур заземления)

  3. Сервопривод (опционально): – Красный провод → 5В Arduino – Коричневый/Черный → GND Arduino – Оранжевый/Желтый → D11 Arduino (ШИМ сигнал)

Базовый код для робота-обходчика препятствий:

cpp
Скопировать код
#include <Servo.h>

// Пины ультразвукового датчика
#define TRIG_PIN 9
#define ECHO_PIN 10

// Пины сервопривода
#define SERVO_PIN 11

// Пины драйвера моторов
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5
#define ENA 6
#define ENB 7

// Константы
#define MIN_DISTANCE 30 // Минимальное безопасное расстояние в см
#define MOTOR_SPEED 150 // Скорость моторов (0-255)

Servo servoMotor; // Создаем объект сервопривода

void setup() {
  Serial.begin(9600);
  
  // Настраиваем пины ультразвукового датчика
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  
  // Настраиваем пины драйвера моторов
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  
  // Подключаем сервопривод
  servoMotor.attach(SERVO_PIN);
  servoMotor.write(90); // Устанавливаем в среднее положение
  
  // Начальная пауза для подготовки
  delay(2000);
}

void loop() {
  int distance = measureDistance();
  Serial.print("Расстояние: ");
  Serial.print(distance);
  Serial.println(" см");
  
  if (distance > MIN_DISTANCE) {
    moveForward(); // Если путь свободен, едем вперед
  } else {
    stopMotors(); // Останавливаемся
    delay(500);
    
    // Сканируем пространство
    int leftDistance = lookLeft();
    delay(500);
    int rightDistance = lookRight();
    delay(500);
    servoMotor.write(90); // Возвращаем сервопривод в центр
    
    // Выбираем направление с большим свободным пространством
    if (leftDistance > rightDistance) {
      turnLeft();
    } else {
      turnRight();
    }
  }
}

// Функция измерения расстояния
int measureDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  long duration = pulseIn(ECHO_PIN, HIGH);
  int distance = (duration * 0.034) / 2;
  
  return distance;
}

// Функция взгляда налево
int lookLeft() {
  servoMotor.write(180); // Поворачиваем сервопривод влево
  delay(500); // Ждем, пока сервопривод повернется
  int distance = measureDistance(); // Измеряем расстояние
  return distance;
}

// Функция взгляда направо
int lookRight() {
  servoMotor.write(0); // Поворачиваем сервопривод вправо
  delay(500); // Ждем, пока сервопривод повернется
  int distance = measureDistance(); // Измеряем расстояние
  return distance;
}

// Функции управления движением
void moveForward() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, MOTOR_SPEED);
  analogWrite(ENB, MOTOR_SPEED);
}

void turnLeft() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, MOTOR_SPEED);
  analogWrite(ENB, MOTOR_SPEED);
  delay(700); // Время поворота (настройте экспериментально)
  stopMotors();
}

void turnRight() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  analogWrite(ENA, MOTOR_SPEED);
  analogWrite(ENB, MOTOR_SPEED);
  delay(700); // Время поворота (настройте экспериментально)
  stopMotors();
}

void stopMotors() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
}

Для улучшения навигационных способностей робота можно добавить несколько ультразвуковых датчиков или заменить сканирование с поворотом сервопривода на более сложные алгоритмы картографирования. Также стоит рассмотреть добавление инфракрасных датчиков линии для следования по маршруту или движения вдоль стен.

Умная система измерения уровня жидкости в баке

Измерение уровня жидкости в резервуарах — задача, с которой прекрасно справляются ультразвуковые датчики. Они позволяют создать бесконтактную систему мониторинга, которую можно применить для контроля уровня воды в аквариуме, топлива в баке или любой другой жидкости. 💧

Для создания такой системы потребуются:

  • Arduino Nano или UNO
  • Водонепроницаемый ультразвуковой датчик JSN-SR04T (можно использовать HC-SR04 в пластиковом корпусе для не очень влажных условий)
  • LCD дисплей 16x2 с I2C модулем
  • Зуммер для сигнализации
  • RGB светодиод для индикации
  • Резисторы: 220 Ом (3 шт. для RGB светодиода)
  • Макетная плата и провода
  • Источник питания 5В

Особенность этой системы в том, что ультразвуковой датчик размещается над резервуаром и измеряет расстояние до поверхности жидкости. Чем меньше расстояние до дна резервуара, тем выше уровень жидкости.

Схема подключения:

  1. Ультразвуковой датчик JSN-SR04T: – VCC → 5В Arduino – GND → GND Arduino – Trig → D9 Arduino – Echo → D10 Arduino

  2. LCD дисплей с I2C: – VCC → 5В Arduino – GND → GND Arduino – SDA → A4 Arduino – SCL → A5 Arduino

  3. Зуммер: – "+" → D8 Arduino – "-" → GND Arduino

  4. RGB светодиод: – Красный → D3 через резистор 220 Ом – Зеленый → D5 через резистор 220 Ом – Синий → D6 через резистор 220 Ом – Общий катод → GND Arduino

Код для системы измерения уровня жидкости:

cpp
Скопировать код
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// Настройка пинов
#define TRIG_PIN 9
#define ECHO_PIN 10
#define BUZZER_PIN 8
#define RED_PIN 3
#define GREEN_PIN 5
#define BLUE_PIN 6

// Настройка дисплея (адрес, столбцы, строки)
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Параметры бака
const int TANK_DEPTH = 30; // Глубина бака в см
const int SENSOR_HEIGHT = 5; // Высота установки датчика над верхним краем бака
const int TOTAL_DISTANCE = TANK_DEPTH + SENSOR_HEIGHT; // Общее расстояние от датчика до дна

// Пороговые значения для предупреждений
const int LOW_LEVEL = 20; // % – предупреждение о низком уровне
const int HIGH_LEVEL = 80; // % – предупреждение о высоком уровне

void setup() {
  Serial.begin(9600);
  
  // Настройка пинов
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  
  // Инициализация дисплея
  lcd.init();
  lcd.backlight();
  lcd.print("Система готова");
  delay(2000);
  lcd.clear();
}

void loop() {
  // Измерение расстояния
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  long duration = pulseIn(ECHO_PIN, HIGH);
  float distance = (duration * 0.034) / 2; // Расстояние в см
  
  // Проверка на корректность измерения
  if (distance <= 0 || distance > TOTAL_DISTANCE + 10) {
    Serial.println("Ошибка измерения!");
    lcd.clear();
    lcd.print("Ошибка измерения!");
    setColor(255, 0, 0); // Красный – ошибка
    beep(3); // Тройной сигнал об ошибке
    delay(1000);
    return;
  }
  
  // Расчет уровня жидкости
  int level_cm = TOTAL_DISTANCE – distance; // Уровень в см
  if (level_cm < 0) level_cm = 0;
  
  float level_percent = ((float)level_cm / TANK_DEPTH) * 100.0;
  if (level_percent > 100) level_percent = 100;
  
  // Вывод информации на дисплей
  lcd.clear();
  lcd.print("Уровень: ");
  lcd.print((int)level_percent);
  lcd.print("%");
  
  lcd.setCursor(0, 1);
  lcd.print("Высота: ");
  lcd.print(level_cm);
  lcd.print(" см");
  
  // Визуальная и звуковая индикация
  if (level_percent < LOW_LEVEL) {
    // Низкий уровень – красный
    setColor(255, 0, 0);
    if (level_percent < 10) beep(1); // Сигнал при очень низком уровне
  } else if (level_percent > HIGH_LEVEL) {
    // Высокий уровень – синий
    setColor(0, 0, 255);
    if (level_percent > 90) beep(2); // Двойной сигнал при очень высоком уровне
  } else {
    // Нормальный уровень – зеленый
    setColor(0, 255, 0);
  }
  
  // Отладочная информация в Serial Monitor
  Serial.print("Расстояние до поверхности: ");
  Serial.print(distance);
  Serial.println(" см");
  
  Serial.print("Уровень жидкости: ");
  Serial.print(level_cm);
  Serial.print(" см (");
  Serial.print(level_percent);
  Serial.println("%)");
  
  delay(1000); // Пауза между измерениями
}

// Функция установки цвета RGB светодиода
void setColor(int red, int green, int blue) {
  analogWrite(RED_PIN, red);
  analogWrite(GREEN_PIN, green);
  analogWrite(BLUE_PIN, blue);
}

// Функция для звукового сигнала
void beep(int times) {
  for (int i = 0; i < times; i++) {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);
    delay(200);
  }
}

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

Интерактивная музыкальная установка без касаний

Создание бесконтактного музыкального инструмента на основе ультразвуковых датчиков — это проект, который понравится как музыкантам, так и любителям экспериментов с электроникой. 🎵 Такая установка позволяет создавать музыку, просто перемещая руки в пространстве перед датчиками.

Для создания интерактивной музыкальной установки понадобятся:

  • Arduino UNO или Mega (предпочтительнее Mega из-за большего количества пинов)
  • 2-5 ультразвуковых датчиков HC-SR04
  • Пьезодинамик или активная колонка (для лучшего звучания)
  • Макетная плата и провода
  • Резисторы: 220 Ом (для пьезодинамика)
  • Кнопки или переключатели для выбора режимов (опционально)
  • RGB светодиоды для визуальных эффектов (опционально)
  • Корпус для установки (можно использовать деревянную коробку или напечатать на 3D-принтере)

Основная идея: каждый датчик контролирует определенный параметр звука. Например:

  • Датчик 1: высота ноты (ближе рука — выше нота)
  • Датчик 2: громкость звука
  • Датчик 3: тембр или тип инструмента
  • Датчик 4: эффекты (вибрато, тремоло)
  • Датчик 5: ритм или темп

Для простого варианта с двумя датчиками схема подключения будет следующей:

  1. Ультразвуковой датчик 1 (контроль высоты): – VCC → 5В Arduino – GND → GND Arduino – Trig → D2 Arduino – Echo → D3 Arduino

  2. Ультразвуковой датчик 2 (контроль громкости): – VCC → 5В Arduino – GND → GND Arduino – Trig → D4 Arduino – Echo → D5 Arduino

  3. Пьезодинамик или звуковой модуль: – "+" → D8 Arduino – "-" → GND Arduino (через резистор 220 Ом для пьезодинамика)

Базовый код для музыкальной установки:

cpp
Скопировать код
// Пины для первого датчика (контроль высоты)
#define TRIG_PIN1 2
#define ECHO_PIN1 3

// Пины для второго датчика (контроль громкости)
#define TRIG_PIN2 4
#define ECHO_PIN2 5

// Пин для пьезодинамика
#define BUZZER_PIN 8

// Параметры для генерации звука
int minDistance = 10; // Минимальное расстояние в см
int maxDistance = 60; // Максимальное расстояние в см
int minFreq = 100; // Минимальная частота в Гц
int maxFreq = 2000; // Максимальная частота в Гц

// Музыкальная гамма для дискретного режима
int notes[] = {262, 294, 330, 349, 392, 440, 494, 523}; // До, Ре, Ми, Фа, Соль, Ля, Си, До

// Режимы работы
#define MODE_CONTINUOUS 0 // Непрерывное изменение частоты
#define MODE_DISCRETE 1 // Дискретные ноты (гамма)
int currentMode = MODE_CONTINUOUS;

void setup() {
  Serial.begin(9600);
  
  // Настройка пинов ультразвуковых датчиков
  pinMode(TRIG_PIN1, OUTPUT);
  pinMode(ECHO_PIN1, INPUT);
  pinMode(TRIG_PIN2, OUTPUT);
  pinMode(ECHO_PIN2, INPUT);
  
  // Настройка пина пьезодинамика
  pinMode(BUZZER_PIN, OUTPUT);
  
  // Инициализация
  Serial.println("Интерактивная musical установка готова!");
  Serial.println("Датчик 1: контроль высоты ноты");
  Serial.println("Датчик 2: контроль громкости");
}

void loop() {
  // Измерение расстояния для первого датчика (высота ноты)
  int distance1 = measureDistance(TRIG_PIN1, ECHO_PIN1);
  
  // Измерение расстояния для второго датчика (громкость)
  int distance2 = measureDistance(TRIG_PIN2, ECHO_PIN2);
  
  // Проверка на корректность измерения
  if (distance1 < 0 || distance1 > 400 || distance2 < 0 || distance2 > 400) {
    noTone(BUZZER_PIN); // Остановка звука при ошибке
    return;
  }
  
  // Отображение данных в монитор порта
  Serial.print("Расстояние 1 (высота): ");
  Serial.print(distance1);
  Serial.print(" см, Расстояние 2 (громкость): ");
  Serial.print(distance2);
  Serial.println(" см");
  
  // Генерация звука в зависимости от режима
  if (distance1 >= minDistance && distance1 <= maxDistance) {
    // Определение частоты в зависимости от расстояния
    int frequency;
    
    if (currentMode == MODE_CONTINUOUS) {
      // Линейное отображение расстояния на частоту
      frequency = map(distance1, maxDistance, minDistance, minFreq, maxFreq);
    } else {
      // Дискретные ноты (гамма)
      int noteIndex = map(distance1, maxDistance, minDistance, 0, 7);
      noteIndex = constrain(noteIndex, 0, 7);
      frequency = notes[noteIndex];
    }
    
    // Регулировка громкости через длительность импульсов
    // (более продвинутый вариант требовал бы ШИМ или внешнего усилителя)
    if (distance2 >= minDistance && distance2 <= maxDistance) {
      tone(BUZZER_PIN, frequency);
      
      // Для демонстрации регулировки громкости через Serial
      int volume = map(distance2, maxDistance, minDistance, 0, 100);
      Serial.print("Частота: ");
      Serial.print(frequency);
      Serial.print(" Гц, Громкость: ");
      Serial.print(volume);
      Serial.println("%");
    } else {
      // Если рука вне зоны второго датчика – нет звука
      noTone(BUZZER_PIN);
    }
  } else {
    // Если рука вне зоны первого датчика – нет звука
    noTone(BUZZER_PIN);
  }
  
  delay(50); // Небольшая задержка для стабильности
}

// Функция измерения расстояния
int measureDistance(int trigPin, int echoPin) {
  // Очистка trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  
  // Отправка ультразвукового импульса
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Чтение echoPin, получение времени путешествия звукового импульса в микросекундах
  long duration = pulseIn(echoPin, HIGH, 30000); // Таймаут 30 мс
  // Если таймаут сработал, вернуть ошибку
  if (duration == 0) return -1;
  
  // Расчет расстояния
  int distance = (duration * 0.034) / 2;
  return distance;
}

Для улучшения проекта можно добавить:

  • Больше датчиков для расширения возможностей управления звуком
  • Использовать библиотеку Mozzi для генерации более качественного звука
  • Добавить LED-индикацию, соответствующую высоте и громкости звука
  • Реализовать MIDI-выход для подключения к компьютеру или синтезатору
  • Создать несколько режимов (разные музыкальные инструменты или эффекты)

Такая интерактивная музыкальная установка может стать отличным экспонатом на выставке, использоваться в образовательных целях или просто как увлекательное хобби для экспериментов со звуком.

Ультразвуковые датчики с Arduino открывают безграничные возможности для творчества и решения практических задач. От измерения расстояний и создания автоматизированных систем до разработки интерактивных музыкальных инструментов — каждый проект помогает лучше понять принципы работы с сенсорами и программирование микроконтроллеров. Начните с простого парктроника или робота, а когда освоитесь — переходите к созданию более сложных систем. Главное — экспериментируйте, не бойтесь ошибок и делитесь своими достижениями с сообществом. В этом и заключается подлинная магия самостоятельного создания электронных устройств!

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой ультразвуковой датчик является одним из самых популярных для проектов на Arduino?
1 / 5

Загрузка...