Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Интерактивный MP3-плеер на Arduino с ультразвуковым датчиком расстояния

Компоненты и материалы

Arduino UNO×1
Последовательный MP3-плеер Catalex (требуется SD-карта и кардридер)×1
Ультразвуковой датчик HC-SR04×2
Динамик с входом 3.5 мм×1

О проекте

Использование последовательного MP3-плеера Catalex

В предыдущем уроке использовалась только библиотека SoftwareSerial.h и простые функции. Основная функция отправки команд:

void sendCommand(int8_t command, int16_t dat) {
  if (command == CMD_PLAY_WITHFOLDER || command == CMD_PLAY_WITHVOLUME) {
    Serial.println("PLAYING SONG, SLIGHTLY MOVE YOUR HEAD FOR GREAT EFFECT");
  }
  delay(20);
  Send_buf[0] = 0x7e; // стартовый байт
  Send_buf[1] = 0xff; // версия
  Send_buf[2] = 0x06; // длина команды без стартового и конечного байтов
  Send_buf[3] = command;
  Send_buf[4] = 0x00; // 0x00 = без подтверждения, 0x01 = с подтверждением
  Send_buf[5] = (int8_t)(dat >> 8); // старший байт данных
  Send_buf[6] = (int8_t)(dat);      // младший байт данных
  Send_buf[7] = 0xef; // конечный байт
  for (uint8_t i = 0; i < 8; i++) {
    mySerial.write(Send_buf[i]);
  }
  Serial.println();
}
Интерактивный MP3-плеер на Arduino с ультразвуковым датчиком расстояния

Использование ультразвукового датчика HC-SR04

Библиотеки не требуется. Функция измерения расстояния:

long measureDistance() {
  long duration, distance;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) / 29.1;
  Serial.println("distance:");
  Serial.println(distance);
  return distance; // расстояние в см
}
Интерактивный MP3-плеер на Arduino с ультразвуковым датчиком расстояния

Версия 1: Простой триггер MP3 по расстоянию

Сначала установите библиотеку SoftwareSerial.h, если её нет.

В этой версии: если объект приближается ближе 50 см — срабатывает воспроизведение аудио. Я использовал это, чтобы напугать соседей громким клипом «surprise motherfucker».

Примечание: Полный код .ino находится в вложениях проекта.

void loop() {
  if (measureDistance() < 50) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0203); // 3-я песня 2-й папки
    delay(1000); // пауза для избежания ошибок
  }
  delay(300);
}

Версия 2: Триггер по изменению расстояния (Disturbance)

Эта версия не учитывает абсолютное расстояние, а реагирует на резкое изменение показаний. Если ложные срабатывания — увеличьте порог в if(gap > 20). Новые переменные объявляются вне цикла.

int firstTime = 0;
long Distance, auxDistance, gap = 0;

void loop() {
  Distance = measureDistance(trigPin, echoPin);
  gap = abs(Distance - auxDistance);
  if (firstTime == 0) {
    auxDistance = Distance; gap = 0;
    firstTime++; delay(1000);
  }
  if (gap > 20) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0201); // 1-я песня 2-й папки
    firstTime = 0; delay(2000);
  }
  Serial.print("New Distace:"); Serial.print(Distance);
  Serial.print(" Old Distance: "); Serial.print(auxDistance); Serial.println(gap);
  delay(300);
  auxDistance = Distance;
}

Версия 3: Два датчика расстояния — определение направления движения

С двумя датчиками можно определить направление движения: программа воспроизводит «hello» или «bye» в зависимости от того, в какую сторону движется человек.

#define trigPin 13  // первый датчик
#define echoPin 12
#define trigPin2 10 // второй датчик
#define echoPin2 9
long Distance, auxDistance, gap = 0;
long Distance2, auxDistance2, gap2 = 0;
long measureDistance(int trigger, int echo) {
  long duration, distance;
  digitalWrite(trigger, LOW); delayMicroseconds(2);
  digitalWrite(trigger, HIGH); delayMicroseconds(10);
  digitalWrite(trigger, LOW);
  duration = pulseIn(echo, HIGH);
  distance = (duration / 2) / 29.1;
  return distance;
}
void loop() {
  Distance = measureDistance(trigPin, echoPin);
  Distance2 = measureDistance(trigPin2, echoPin2);
  gap = abs(Distance - auxDistance);
  gap2 = abs(Distance2 - auxDistance2);
  if (firstTime == 0) {
    auxDistance = Distance; auxDistance2 = Distance2;
    gap = 0; gap2 = 0; firstTime++; delay(2000);
  }
  if (gap > 20 && gap2 < 20) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0201);
    firstTime = 0; Serial.println("RIGHT MOVEMENT DETECTED"); delay(2000);
  }
  if (gap2 > 20 && gap < 20) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0202);
    firstTime = 0; Serial.println("LEFT MOVEMENT DETECTED"); delay(2000);
  }
  // ... отладочный вывод
  delay(300);
  auxDistance = Distance; auxDistance2 = Distance2;
}

Удачного творчества!

Программный код

Версия 1 — Простой триггер по расстоянию Arduino

// Javier Muñoz 10/11/2016, javimusama@hotmail.com
#include <SoftwareSerial.h>
#define ARDUINO_RX 5  // к TX MP3-модуля
#define ARDUINO_TX 6  // к RX MP3-модуля
#define trigPin 13
#define echoPin 12
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);

static int8_t Send_buf[8] = {0};
#define NEXT_SONG 0X01
#define PREV_SONG 0X02
#define CMD_PLAY_W_INDEX 0X03
#define VOLUME_UP_ONE 0X04
#define VOLUME_DOWN_ONE 0X05
#define CMD_SET_VOLUME 0X06
#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22
#define CMD_SEL_DEV 0X09
#define DEV_TF 0X02
#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B
#define CMD_RESET 0X0C
#define CMD_PLAY 0X0D
#define CMD_PAUSE 0X0E
#define CMD_PLAY_WITHFOLDER 0X0F
#define STOP_PLAY 0X16
#define PLAY_FOLDER 0X17
#define SET_CYCLEPLAY 0X19

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  delay(500);
  sendCommand(CMD_SEL_DEV, DEV_TF);
  delay(200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  if (measureDistance(trigPin, echoPin) < 50) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0203);
    delay(1000);
  }
  delay(300);
}

void sendCommand(int8_t command, int16_t dat) {
  delay(20);
  Send_buf[0] = 0x7e; Send_buf[1] = 0xff; Send_buf[2] = 0x06;
  Send_buf[3] = command; Send_buf[4] = 0x00;
  Send_buf[5] = (int8_t)(dat >> 8); Send_buf[6] = (int8_t)(dat);
  Send_buf[7] = 0xef;
  for (uint8_t i = 0; i < 8; i++) {
    mySerial.write(Send_buf[i]);
    Serial.print(Send_buf[i], HEX);
  }
  Serial.println();
}

long measureDistance(int trigger, int echo) {
  long duration, distance;
  digitalWrite(trigger, LOW); delayMicroseconds(2);
  digitalWrite(trigger, HIGH); delayMicroseconds(10);
  digitalWrite(trigger, LOW);
  duration = pulseIn(echo, HIGH);
  distance = (duration / 2) / 29.1;
  Serial.println("distance:"); Serial.println(distance);
  return distance;
}

Версия 2 — Триггер по изменению расстояния Arduino

// Javier Muñoz 10/11/2016
#include <SoftwareSerial.h>
#define ARDUINO_RX 5
#define ARDUINO_TX 6
#define trigPin 13
#define echoPin 12
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);

static int8_t Send_buf[8] = {0};
// ... (те же define, что в версии 1)

int firstTime = 0;
long Distance, auxDistance, gap = 0;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  delay(500);
  sendCommand(CMD_SEL_DEV, DEV_TF);
  delay(200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  Distance = measureDistance(trigPin, echoPin);
  gap = abs(Distance - auxDistance);
  if (firstTime == 0) {
    auxDistance = Distance; gap = 0; firstTime++; delay(1000);
  }
  if (gap > 20) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0201);
    firstTime = 0; delay(2000);
  }
  Serial.print("New Distace:"); Serial.print(Distance);
  Serial.print(" Old Distance: "); Serial.print(auxDistance); Serial.println(gap);
  delay(300);
  auxDistance = Distance;
}

void sendCommand(int8_t command, int16_t dat) {
  if (command == CMD_PLAY_WITHFOLDER || command == CMD_PLAY_WITHVOLUME) {
    Serial.print("PLAYING SONG, SLIGHTLY MOVE YOUR HEAD FOR GREAT EFFECT");
  }
  delay(20);
  Send_buf[0] = 0x7e; Send_buf[1] = 0xff; Send_buf[2] = 0x06;
  Send_buf[3] = command; Send_buf[4] = 0x00;
  Send_buf[5] = (int8_t)(dat >> 8); Send_buf[6] = (int8_t)(dat);
  Send_buf[7] = 0xef;
  for (uint8_t i = 0; i < 8; i++) mySerial.write(Send_buf[i]);
  Serial.println();
}

long measureDistance(int trigger, int echo) {
  long duration, distance;
  digitalWrite(trigger, LOW); delayMicroseconds(2);
  digitalWrite(trigger, HIGH); delayMicroseconds(10);
  digitalWrite(trigger, LOW);
  duration = pulseIn(echo, HIGH);
  distance = (duration / 2) / 29.1;
  return distance;
}

Версия 3 — Два датчика, определение направления Arduino

// Javier Muñoz 10/11/2016
#include <SoftwareSerial.h>
#define ARDUINO_RX 5
#define ARDUINO_TX 6
#define trigPin 13
#define echoPin 12
#define trigPin2 10
#define echoPin2 9
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);

static int8_t Send_buf[8] = {0};
// ... (те же define)

int firstTime = 0;
long Distance, auxDistance, gap = 0;
long Distance2, auxDistance2, gap2 = 0;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  delay(500);
  sendCommand(CMD_SEL_DEV, DEV_TF);
  delay(200);
  pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT);
  pinMode(trigPin2, OUTPUT); pinMode(echoPin2, INPUT);
}

void loop() {
  Distance = measureDistance(trigPin, echoPin);
  Distance2 = measureDistance(trigPin2, echoPin2);
  gap = abs(Distance - auxDistance);
  gap2 = abs(Distance2 - auxDistance2);
  if (firstTime == 0) {
    auxDistance = Distance; auxDistance2 = Distance2;
    gap = 0; gap2 = 0; firstTime++; delay(2000);
  }
  if (gap > 20 && gap2 < 20) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0201);
    firstTime = 0; Serial.println("RIGHT MOVEMENT DETECTED"); delay(2000);
  }
  if (gap2 > 20 && gap < 20) {
    sendCommand(CMD_PLAY_WITHFOLDER, 0X0202);
    firstTime = 0; Serial.println("LEFT MOVEMENT DETECTED"); delay(2000);
  }
  Serial.println("\\\\\\\\\\\\\\\\\\\\\\\\");
  Serial.print(" New Distace:"); Serial.print(Distance);
  Serial.print(" Old Distance: "); Serial.print(auxDistance);
  Serial.print(" GAP "); Serial.println(gap);
  Serial.print("New Distace2:"); Serial.print(Distance2);
  Serial.print(" Old Distance2: "); Serial.print(auxDistance2);
  Serial.print(" GAP2 "); Serial.println(gap2);
  Serial.println("\\\\\\\\\\\\\\\\\\\\\\\\");
  delay(300);
  auxDistance = Distance; auxDistance2 = Distance2;
}

void sendCommand(int8_t command, int16_t dat) {
  if (command == CMD_PLAY_WITHFOLDER || command == CMD_PLAY_WITHVOLUME) {
    Serial.print("PLAYING SONG, SLIGHTLY MOVE YOUR HEAD FOR GREAT EFFECT");
  }
  delay(20);
  Send_buf[0] = 0x7e; Send_buf[1] = 0xff; Send_buf[2] = 0x06;
  Send_buf[3] = command; Send_buf[4] = 0x00;
  Send_buf[5] = (int8_t)(dat >> 8); Send_buf[6] = (int8_t)(dat);
  Send_buf[7] = 0xef;
  for (uint8_t i = 0; i < 8; i++) mySerial.write(Send_buf[i]);
  Serial.println();
}

long measureDistance(int trigger, int echo) {
  long duration, distance;
  digitalWrite(trigger, LOW); delayMicroseconds(2);
  digitalWrite(trigger, HIGH); delayMicroseconds(10);
  digitalWrite(trigger, LOW);
  duration = pulseIn(echo, HIGH);
  distance = (duration / 2) / 29.1;
  return distance;
}

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

Производственный процесс

  1. Построение доступной беспроводной сети датчиков для дома
  2. Датчик CO2 K30: мониторинг качества воздуха в реальном времени на Arduino
  3. Цифровой стадиометр на Arduino: отслеживание роста лазерным датчиком VL53L0X
  4. Интеграция ёмкостного сканера отпечатков DFRobot с Arduino или ESP8266
  5. Как воспроизводить аудио с Arduino UNO и DFPlayer Mini – Пошаговое руководство
  6. Веб-управляемый MP3-плеер на Arduino: Воспроизведение аудио через браузер
  7. Сенсорная башня на Arduino Cloud: Мониторинг температуры, движения и газа
  8. Умный водяной пистолет с датчиком движения на Arduino Nano
  9. Arduino UNO + WiFi Shield: реальный график температуры в вебе через Serial
  10. Компактный радар на Arduino Nano с HC-SR04 и дисплеем 1.8"