142 lines
4.0 KiB
C++
142 lines
4.0 KiB
C++
#include <SoftwareSerial.h>
|
||
#include <DFPlayerMini_Fast.h>
|
||
|
||
const int dfRx = 10;
|
||
const int dfTx = 11;
|
||
const int trigPin = 3;
|
||
const int echoPin = 4;
|
||
|
||
SoftwareSerial dfSerial(dfRx, dfTx);
|
||
DFPlayerMini_Fast player;
|
||
|
||
bool objectDetected = false;
|
||
bool isPlaying = false;
|
||
bool trackStarted = false;
|
||
|
||
unsigned long lastStartTime = 0;
|
||
unsigned long accumulatedTime = 0;
|
||
const unsigned long trackDuration = 3966000; // - подставить длину записанного трека на sd-карте, в миллисекундах
|
||
|
||
const int detectionDistance = 100;
|
||
const int stableCountThreshold = 5;
|
||
int stableCounter = 0;
|
||
|
||
int currentVolume = 30;
|
||
int targetVolume = 30;
|
||
unsigned long lastVolumeStepTime = 0;
|
||
const unsigned long volumeStepInterval = 100;
|
||
|
||
void setup() {
|
||
pinMode(trigPin, OUTPUT);
|
||
pinMode(echoPin, INPUT);
|
||
Serial.begin(9600);
|
||
dfSerial.begin(9600);
|
||
|
||
delay(1500);
|
||
player.begin(dfSerial);
|
||
player.volume(currentVolume);
|
||
Serial.println("🎬 DFPlayer готов, жду объект перед датчиком");
|
||
}
|
||
|
||
long measureDistance() {
|
||
digitalWrite(trigPin, LOW);
|
||
delayMicroseconds(2);
|
||
digitalWrite(trigPin, HIGH);
|
||
delayMicroseconds(10);
|
||
digitalWrite(trigPin, LOW);
|
||
long duration = pulseIn(echoPin, HIGH, 25000);
|
||
return duration * 0.034 / 2;
|
||
}
|
||
|
||
void setTargetVolume(int vol) {
|
||
targetVolume = constrain(vol, 0, 30);
|
||
}
|
||
|
||
void updateVolume() {
|
||
unsigned long now = millis();
|
||
if (now - lastVolumeStepTime >= volumeStepInterval) {
|
||
if (currentVolume < targetVolume) {
|
||
currentVolume++;
|
||
player.volume(currentVolume);
|
||
} else if (currentVolume > targetVolume) {
|
||
currentVolume--;
|
||
player.volume(currentVolume);
|
||
}
|
||
lastVolumeStepTime = now;
|
||
}
|
||
}
|
||
|
||
void loop() {
|
||
unsigned long now = millis();
|
||
long distance = measureDistance();
|
||
|
||
// сглаживание дребезга
|
||
if (distance > 0 && distance < detectionDistance) {
|
||
if (stableCounter < stableCountThreshold) stableCounter++;
|
||
} else {
|
||
if (stableCounter > 0) stableCounter--;
|
||
}
|
||
bool currentlyDetected = stableCounter >= stableCountThreshold;
|
||
|
||
// если трек играет — накапливаем время
|
||
if (isPlaying) {
|
||
accumulatedTime += now - lastStartTime;
|
||
}
|
||
lastStartTime = now;
|
||
|
||
// объект появился
|
||
if (currentlyDetected && !objectDetected) {
|
||
if (!trackStarted) {
|
||
// первый запуск
|
||
player.play(1);
|
||
Serial.println("▶️ Объект вернулся → трек с начала (первый запуск)");
|
||
trackStarted = true;
|
||
accumulatedTime = 0;
|
||
}
|
||
else if (accumulatedTime >= trackDuration) {
|
||
// доиграл во время паузы
|
||
player.pause();
|
||
delay(100);
|
||
player.play(1);
|
||
Serial.println("▶️ Объект вернулся → трек заново (доиграл)");
|
||
accumulatedTime = 0;
|
||
}
|
||
else {
|
||
// продолжить с места
|
||
player.resume();
|
||
Serial.println("▶️ Объект вернулся → продолжаю с места");
|
||
}
|
||
setTargetVolume(30);
|
||
isPlaying = true;
|
||
objectDetected = true;
|
||
lastStartTime = millis();
|
||
}
|
||
|
||
// объект ушёл — гасим громкость
|
||
if (!currentlyDetected && objectDetected) {
|
||
setTargetVolume(0);
|
||
Serial.println("🚶 Объект ушёл → гашу громкость");
|
||
objectDetected = false;
|
||
}
|
||
|
||
// пауза после гашения
|
||
if (!objectDetected && isPlaying && currentVolume == 0) {
|
||
player.pause();
|
||
Serial.println("⏸ Громкость догорела → пауза");
|
||
isPlaying = false;
|
||
}
|
||
|
||
// если трек доиграл во время воспроизведения — перезапуск
|
||
if (isPlaying && accumulatedTime >= trackDuration) {
|
||
player.pause();
|
||
delay(100);
|
||
player.play(1);
|
||
Serial.println("🔁 Трек доиграл → перезапуск");
|
||
accumulatedTime = 0;
|
||
lastStartTime = millis();
|
||
}
|
||
|
||
updateVolume();
|
||
delay(30);
|
||
}
|