Звуки воспроизводятся одновременно

Я делаю школьный проект, который позволяет растениям «говорить». Например, когда растение находится в неидеальной среде (низкая или высокая влажность почвы, не идеальная температура или влажность и недостаточно света). В настоящее время я написал демонстрационный код для своей презентации, поскольку реальный код имеет реальные пороговые значения, и его трудно запустить мгновенно во время презентации. Проблема, с которой я столкнулся, заключается в том, что звук почти всегда прерывается другим, как я могу это остановить, к тому же все записи длятся 7 секунд или меньше.

#include <DHT.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <LiquidCrystal_I2C.h>
//----------------ДЕМО---КОД-------
#define DHTPIN 3
#define DHTTYPE DHT22
#define SOIL_MOISTURE_PIN A0
#define LIGHT_SENSOR_PIN 2
#define TEMP_THRESHOLD 25.0
#define HUMIDITY_THRESHOLD 60
#define LIGHT_THRESHOLD 1  // 1 для темного цвета, отрегулируйте по мере необходимости
#define LOWER_SM_THRESHOLD 20 // Отрегулируйте по мере необходимости
#define UPPER_SM_THRESHOLD 50 // Отрегулируйте по мере необходимости
#define LCD_ADDR 0x27  // I2C-адрес ЖК-дисплея
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#define MESSAGE_INTERVAL 20000  // 20 секунд в миллисекундах

DHT dht(DHTPIN, DHTTYPE);
SoftwareSerial mySoftwareSerial(10, 11);  // RX, TX для DFPlayer
DFRobotDFPlayerMini myDFPlayer;
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLUMNS, LCD_ROWS);

unsigned long lastTempTrigger = 0;
unsigned long lastHumidityTrigger = 0;
unsigned long lastSoilMoistureTrigger = 0;
unsigned long lastLightTrigger = 0;

void setup() {
  dht.begin();
  Serial.begin(9600);
  mySoftwareSerial.begin(9600);
  myDFPlayer.begin(mySoftwareSerial);

  myDFPlayer.volume(30);

  // Инициализируем ЖК-дисплей
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Plantastic!");
  lcd.setCursor(0, 1);
  lcd.print("System Ready");
  delay(2000);
  lcd.clear();
}

void loop() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  int lightValue = digitalRead(LIGHT_SENSOR_PIN);
  int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
  int soilMoisturePercentage = 100 - (map(soilMoistureValue, 0, 1023, 0, 100));

  if (temperature > TEMP_THRESHOLD && millis() - lastTempTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(3);  // Играем в «Too Hot»; сообщение
    lastTempTrigger = millis();
  } else if (temperature < TEMP_THRESHOLD && millis() - lastTempTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(1);  // Играем в «Слишком холодно»; сообщение
    lastTempTrigger = millis();
  }

  if (round(humidity) < HUMIDITY_THRESHOLD && millis() - lastHumidityTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(2);  // Воспроизведение «Низкая влажность»; сообщение
    lastHumidityTrigger = millis();
  }

  if (soilMoisturePercentage < LOWER_SM_THRESHOLD && millis() - lastSoilMoistureTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(6);  // Играем в «Жаждущий»; сообщение
    lastSoilMoistureTrigger = millis();
  } else if (soilMoisturePercentage > UPPER_SM_THRESHOLD && millis() - lastSoilMoistureTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(5);  // Играем в «Достаточно воды»; сообщение
    lastSoilMoistureTrigger = millis();
  }

  if (lightValue == 1 && millis() - lastLightTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(4);  // Играем «Здесь темно»; сообщение
    lastLightTrigger = millis();
  }

  // Обновляем ЖК-дисплей
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("T: ");
  lcd.print(temperature, 2);
  lcd.print(" H: ");
  lcd.print(humidity, 2);
  lcd.setCursor(0, 1);
  lcd.print("SM: ");
  lcd.print(soilMoisturePercentage);
  lcd.print("% L: ");
  lcd.print(lightValue == LIGHT_THRESHOLD ? "Dark" : "Light");

  delay(1000);
}

, 👍1

Обсуждение

Вы можете проверить, воспроизводится ли что-то, прежде чем выполнять play(), @chrisl

нет, воспроизводится первая часть звука, например, первая секунда или полсекунды, но затем она прерывается другим звуком, поэтому вы не можете слышать ее полностью, @I-like-turtles

Разве ты не можешь просто подождать, пока звук прекратится, прежде чем продолжить? Если вы потеряете итерацию из-за воспроизводимого звука, это, вероятно, не проблема (в любом случае вы обновляетесь максимум каждую секунду), @PMF

Я не говорю о пользователе, ожидающем завершения звуков. То, что вы описываете, указывает на то, что вы выполняете функцию play() до того, как закончился последний звук. У dfplayer также должна быть команда, которая вернет статус воспроизведения. Если вы вставите предложение if для каждого вызова play(), чтобы проверить, воспроизводится ли что-то, вы можете предотвратить это прерывание., @chrisl


1 ответ


Лучший ответ:

1

Существует два подхода, которые решают проблему неполного воспроизведения звука.

  1. Поместите цикл задержки после каждого вызова myDFPlayer.play(), рассчитанный на время воспроизведения звука. Вероятно, это самое простое решение. Однако добавление задержек там, где никакой другой код не может быть запущен, считается плохой формой программирования. Это также создает проблемы при добавлении новых функций в программу.
  2. Создайте конечный автомат, в котором функция цикла() не имеет задержек. Вместо этого используйте переменную для отслеживания состояния, в котором находится конечный автомат, и изменяйте эту переменную только тогда, когда условия перехода в следующее состояние выполнены. Например, ничего не делайте, пока не будет преодолен порог (сухость, свет и т. д.). В этот момент переключитесь в состояние, в котором вы воспроизводите соответствующий звук и amp; очистите этот пороговый флаг. Не выходите из этого состояния до тех пор, пока millis() не превысит длительность воспроизводимого звука. Наконец, повторите эти переходы состояний для любых других пороговых значений, которые были пересечены. Сложное поведение, связанное с тем, через какое время после повторения звука можно добавить дополнительные состояния.
,