Модуль SD карты и динамик + Arduino MEGA2560

Даниил224030

✩✩✩✩✩✩✩
20 Июн 2024
1
0
Приветствую всех, разрабатываю проект - драм машину на базе Arduino MEGA 2560 и у меня возникли некоторые сложности.
Принцип работы устройства заключается в том, что Arduino Mega 2560 считывает сигнал с сенсорных кнопок и воспроизводит звуки с помощью динамика, хранящиеся на SD карте.

Ключевая проблема заключается в том, что динамик (универсальный динамик на 4ом) воспроизводит разные сгенерированные звуки, SD карта инициализируется, но они по какой-то невиданной причине не взаимодействуют друг с другом, хотя в Serial Monitor все процессы протекают ровно и никаких ошибок и затыков там нет.
Файлы хранятся на карте памяти в разрешении wav, 8 бит, 8кгц, моно (пробовал и 16 бит, и 16кгц, убирал нумерацию файлов). На данный момент файл записан как "sound" и он хранится на отформатированной карте памяти 2gb.

P.s.это мой первый проект на базе Arduino, поэтому отнеситесь пожалуйста к моему вопросу с пониманием, заранее благодарю вас!


photo_2024-06-20_20-28-30.jpg


C++:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <TMRpcm.h>

#define SD_ChipSelectPin 53
#define SpeakerPin 3

#define ENCODER_S1 7
#define ENCODER_S2 8
#define ENCODER_KEY 6

TMRpcm audio;
LiquidCrystal_I2C lcd(0x27, 16, 2);

const int sensorPins[9] = {2, 3, 4, 5, 9, 10, 11, 12, 13};
int pattern = 0;
int bpm = 120;
int volume = 5;
bool adjustVolume = false;
volatile long lastEncoderPosition = 0;

void listFiles() {
  File root = SD.open("/");
  while (true) {
    File entry = root.openNextFile();
    if (!entry) {
      // no more files
      break;
    }
    Serial.print("File: ");
    Serial.println(entry.name());
    entry.close();
  }
}

void playSound(int soundNum) {
  String soundFile = "sound" + String(soundNum) + ".wav";
  Serial.print("Attempting to play sound: ");
  Serial.println(soundFile);
  if (SD.exists(soundFile)) {
    Serial.println("File exists, playing...");
    audio.play(soundFile.c_str());  // Преобразование String в const char*
  } else {
    lcd.setCursor(0, 1);
    lcd.print("File Missing ");
    Serial.println("File Missing");
  }
}

void setup() {
  Serial.begin(9600);  // Для отладки
  lcd.begin(16, 2);  // Укажите количество столбцов и строк
  lcd.backlight();
  lcd.print("DIY Drum Machine");

  for (int i = 0; i < 9; i++) {
    pinMode(sensorPins[i], INPUT);
  }

  pinMode(SpeakerPin, OUTPUT);
  audio.speakerPin = SpeakerPin;

  lcd.setCursor(0, 1);
  lcd.print("Initializing SD");
  Serial.println("Initializing SD card...");

  // Попытка инициализации SD карты с несколькими попытками
  bool sdInitSuccess = false;
  for (int attempt = 0; attempt < 5; attempt++) {
    if (SD.begin(SD_ChipSelectPin)) {
      sdInitSuccess = true;
      break;
    }
    delay(500); // Задержка перед повторной попыткой
  }

  if (!sdInitSuccess) {
    lcd.setCursor(0, 1);
    lcd.print("SD Init Fail  ");
    Serial.println("SD Initialization Failed");
    return;
  }

  lcd.setCursor(0, 1);
  lcd.print("SD Init Success");
  Serial.println("SD Initialization Success");

  // Дополнительные настройки для TMRpcm
  audio.setVolume(volume);  // Установить начальный уровень громкости
  audio.quality(1);    // Повышенное качество звука

  // Список файлов на SD карте для отладки
  listFiles();

  // Настройка энкодера
  pinMode(ENCODER_S1, INPUT);
  pinMode(ENCODER_S2, INPUT);
  pinMode(ENCODER_KEY, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCODER_S1), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(ENCODER_S2), updateEncoder, CHANGE);
}

void loop() {
  // Обработка сенсорных кнопок
  for (int i = 0; i < 9; i++) {
    if (digitalRead(sensorPins[i]) == HIGH) {
      Serial.print("Sensor pin ");
      Serial.print(sensorPins[i]);
      Serial.println(" activated.");
      playSound(i + 1);
      lcd.setCursor(0, 1);
      lcd.print("Sound: ");
      lcd.print(i + 1);
      delay(1000); // Задержка для предотвращения слишком частого считывания
    }
  }

  // Обработка нажатия кнопки энкодера
  if (digitalRead(ENCODER_KEY) == LOW) {
    adjustVolume = !adjustVolume; // Переключение между режимами регулировки громкости и BPM
    if (adjustVolume) {
      lcd.setCursor(0, 0);
      lcd.print("Volume: ");
      lcd.print(volume);
      lcd.print("   "); // Очищаем остаточные символы
    } else {
      lcd.setCursor(0, 0);
      lcd.print("BPM: ");
      lcd.print(bpm);
      lcd.print("   "); // Очищаем остаточные символы
    }
    delay(300); // Задержка для устранения дребезга кнопки
  }

  // Обновление значения BPM или громкости в зависимости от текущего режима
  if (adjustVolume) {
    audio.setVolume(volume);
  } else {
    int newBpm = map(lastEncoderPosition, -1023, 1023, 60, 180);
    if (newBpm != bpm) {
      bpm = newBpm;
      lcd.setCursor(0, 0);
      lcd.print("BPM: ");
      lcd.print(bpm);
      lcd.print("   "); // Убираем возможные остаточные символы
      Serial.print("Updated BPM: ");
      Serial.println(bpm);
    }
  }

  delay(100); // Задержка для улучшения читаемости
}
void updateEncoder() {
  int s1State = digitalRead(ENCODER_S1);
  int s2State = digitalRead(ENCODER_S2);
  if (s1State != s2State) {
    lastEncoderPosition++;
    if (adjustVolume && volume < 7) {
      volume++;
      Serial.print("Volume increased to: ");
      Serial.println(volume);
      lcd.setCursor(0, 0);
      lcd.print("Volume: ");
      lcd.print(volume);
      lcd.print("   "); // Очищаем остаточные символы
    }
  } else {
    lastEncoderPosition--;
    if (adjustVolume && volume > 0) {
      volume--;
      Serial.print("Volume decreased to: ");
      Serial.println(volume);
      lcd.setCursor(0, 0);
      lcd.print("Volume: ");
      lcd.print(volume);
      lcd.print("   "); // Очищаем остаточные символы
    }
  }

  if (!adjustVolume) {
    lcd.setCursor(0, 0);
    lcd.print("BPM: ");
    lcd.print(bpm);
    lcd.print("   "); // Очищаем остаточные символы
  }
}