Проблема с MusicShield

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем Jeane, 22 мар 2013.

  1. Jeane

    Jeane Нуб

    Всем доброго времени суток. Сразу оговорюсь: это моя первая проба пера с ардуино, так что прошу сильно не ругать за возможно тупые вопросы.
    Итак, ближе к делу. Имеем arduino uno, music shield с карточкой на 2 гига и двумя треками на ней и кнопку, подключенную ко 2-у цифровому входу. Задача: при нажатой кнопке в цикле воспроизводить один трек, при отпущенной - второй.
    Набросал пару скетчей которые как мне кажется
    Код (Text):
    // Подключаем все 3 предоставленные библиотеки
    #include <Fat16util.h>
    #include <NewSPI.h>
    #include "MusicPlayer.h"
     
    // Создаём объект для управления плейером
    MusicPlayer myplayer;
    bool State = 0;
     
    void setup() {
      Serial.begin(9600);
      myplayer.begin();
      myplayer.keyDisable(); //отключаем встроенное управление воспроизведением
      myplayer.digitalControlEnable(); //включаем возможность слушать цифровые входы
     
     
      myplayer.attachDigitOperation(2, opened, LOW);
      myplayer.attachDigitOperation(2, closed, HIGH);
      myplayer.setPlayMode(MODE_REPEAT_ONE);
      myplayer.creatPlaylist();
      myplayer.playList();
     
    }
     
    void loop() {
    }
     
     
    void opened() {
      Serial.println("OPENED");
      myplayer.playSong(1);
      delay(50);
    }
     
    void closed() {
      Serial.println("CLOSED");
      myplayer.playSong(2);
      delay(50);
     
    Код (Text):
    // Подключаем все 3 предоставленные библиотеки
    #include <Fat16util.h>
    #include <NewSPI.h>
    #include "MusicPlayer.h"
     
    // Создаём объект для управления плейером
    MusicPlayer myplayer;
    int buttonState = 0;
    const int buttonPin = 4;
     
    void setup() {
      myplayer.begin();
      myplayer.keyDisable(); //отключаем встроенное управление воспроизведением
      Serial.begin(9600);
    }
     
    void loop() {
      myplayer.setPlayMode(MODE_REPEAT_ONE);
      myplayer.creatPlaylist();
      myplayer.playList();
    buttonState = digitalRead(buttonPin);
      if ((buttonState==LOW)){
        myplayer.playSong(1);
        Serial.println("opened");
     
      }
      if ((buttonState==HIGH)){
        myplayer.playSong(2);
        Serial.println("closed");
     
     
      }
    }
    Имеем воспроизводящийся в цикле 1-й трек замолкающий при нажатии на кнопку и продолжающийся при отпускании.
    примерно вот так это выглядит в консоли

    Код (Text):
    1.MP3
    2.MP3
    Song 0 opened
     
    реакция на нажатие кнопки:
    Код (Text):
    CLOSED
    error: open file failed
     
    при отпусканни кнопки ничего не выводится.

    Помимо всего прочего это сопровождается периодическими самопроизвольными перемотками и остановками воспроизведения.

    Собственно вопрос что я не так делаю и как нужно. Буду благодарен любым советам
     
  2. TeHeBuK

    TeHeBuK Нерд

    Возможно ардуино путается когда читает треки просто потомучто они у вас названы одинаково?? Могу ошибаться особо не вникал.
     
  3. hibiki

    hibiki Гик

    для начала - выкиньте инициализацию плеера и создание плейлиста из loop и повесьте подавление дребезга на кнопку, например, библиотекой Bounce
     
  4. Jeane

    Jeane Нуб

    внёс изменения.
    Код (Text):
    // Подключаем все 3 предоставленные библиотеки
    #include <Fat16util.h>
    #include <NewSPI.h>
    #include "MusicPlayer.h"
    #include <Bounce.h>
     
    // Создаём объект для управления плейером
    int buttonState = 0;
    const int buttonPin = 2;
    Bounce bouncer = Bounce( buttonPin,5 );
    MusicPlayer myplayer;
     
     
    void setup() {
      pinMode(buttonPin,INPUT);
      Serial.begin(9600);
      myplayer.begin();
      myplayer.keyDisable();
      myplayer.setPlayMode(MODE_REPEAT_ONE);
      myplayer.creatPlaylist();
     
    }
     
    void loop() {
     
      bouncer.update ( );
      buttonState = bouncer.read();
     
      if ((buttonState==LOW)){
        myplayer.playSong(1);
        Serial.println("opened");
     
      }
      if ((buttonState==HIGH)){
        myplayer.playSong(2);
        Serial.println("closed");
     
     
      }
    }
    в таком виде в консоли видна реакция на кнопку, но выскакивает ошибка


    Код (Text):
    All songs in the root directory:
    1.MP3
    2.MP3
     
    opened
    error: open file failed
    closed
    error: open file failed
     
     
    если использовать формат с названиями треков типа
    myplayer.playSong("1.MP3");
    то включается первый трек и какая либо реакция на нажатие кнопки отсутствует
     
  5. Megakoteyka

    Megakoteyka Оракул Модератор

    myplayer.playSong("1"); ?
    Без кавычек вы передаете не строку, а число.
     
  6. Megakoteyka

    Megakoteyka Оракул Модератор

    Правильно обрабатывать нажатие кнопки так:
    Код (Text):
    if(bouncer.update() && bouncer.read() == HIGH)
    {
        ...
    }
     
    Jeane нравится это.
  7. Jeane

    Jeane Нуб

    я в курсе. я пытаюсь передавать номер трека в плейлисте, т.к. передача имени файла вызывает какой то конфликт с уже занесённым в плейлист именем.
    кстати ещё почему то при подстановке нуля компилятор расценивает его как int и выдаёт ошибку компиляции, при передаче других значений корректно распознаётся как unsigned int.
    В любом случае задать нужный трек пока не удаётся. максимум добился перехода на следующий/предыдущий и то только при отпускании кнопки.
     
  8. Jeane

    Jeane Нуб

    сейчас скетч выглядит так:
    Код (Text):
    // Подключаем все 3 предоставленные библиотеки
    #include <Fat16util.h>
    #include <NewSPI.h>
    #include "MusicPlayer.h"
    #include <Bounce.h>
     
    // Создаём объект для управления плейером
    int buttonState = 0;
    const unsigned int i=0; //номер первого трека
    const unsigned int j=1; //номер второго трека
    const int buttonPin = 2;
    Bounce bouncer = Bounce( buttonPin,100 );
    bool State =0;
    MusicPlayer myplayer;
     
     
    void setup() {
      pinMode(buttonPin,INPUT);
      Serial.begin(9600);
      myplayer.begin();
      myplayer.keyDisable();
      myplayer.setPlayMode(MODE_REPEAT_ONE);
      myplayer.creatPlaylist();
     
    }
     
    void loop() {
     
      if(bouncer.update() && bouncer.read() == LOW){
        if (State){
          Serial.println("opened");
          myplayer.playSong(i);
          State=0;
        }
      }
      if(bouncer.update() && bouncer.read() == HIGH){
        if (!State){
          Serial.println("closed");
          myplayer.playSong(j);
          State=1;
        }
      }
    }
     
    в консоли выглядит так:

    Код (Text):
    All songs in the root directory:
    1.MP3
    2.MP3
    closed
    error: open file failed
    opened
    error: open file failed
    closed
    error: open file failed
    opened
    error: open file failed
    closed
     
    т.е. почти корректно обрабатывает нажатие/отпускание кнопки, но выдаёт ошибку воспроизведения. периодически начинают произвольно сыпаться сообщения.
     
  9. Unixon

    Unixon Оракул Модератор

    Одна из playSong() принимает char*. Если передавать числовой терминал, это может быть воспринято компилятором как передача константного указателя. Передавайте номер трека через переменную или приводите аргумент к типу unsigned int явно.
     
  10. Jeane

    Jeane Нуб

    я в вышеизложенной версии скетча так и делаю
     
  11. Unixon

    Unixon Оракул Модератор

    bounce.update() что возвращает?
     
  12. Jeane

    Jeane Нуб

    ну судя по тому что условия выполняются он возвращает true
    сейчас вопрос то скорее в том как корректно выбирать нужный трек
     
  13. Megakoteyka

    Megakoteyka Оракул Модератор

    Код (Text):
    if(bouncer.update()) {
      if(bouncer.read() == HIGH) {
        // нажали
      } else
      {
        // отпустили
      }
    }
     
    Jeane нравится это.
  14. Megakoteyka

    Megakoteyka Оракул Модератор

    Попробуйте сперва отладить код, который просто запускает воспроизведение одного трека. Затем добавьте переключение на другой трек - например, через n секунд после запуска первого трека. И так далее - добавляйте мелкие кусочки кода, так проще отследить, после чего начинаются глюки.
    Опять же можно попробовать переключать треки не по номеру или имени, а функциями opNextSong и opPreviousSong, если это приемлемо для логики Вашего скетча.
     
  15. Jeane

    Jeane Нуб

    пошёл от обратного, набросал скетч со всем остальным функционалом.
    [​IMG]
    Код (Text):
    #include <Fat16util.h>
    #include <NewSPI.h>
    #include "MusicPlayer.h"
    #include <Bounce.h>
     
    // Создаём объект для управления плейером
    int doorState = 1;
    const unsigned int zero = 0;
    const int startButton = 2;
    const int doorButton = 3;
    const int yellowLED = 4;
    const int greenLED = 5;
    const int redLED = 6;
    const int relayPin = 7;
    Bounce startBounce = Bounce( startButton,20 );
    Bounce doorBounce = Bounce( doorButton,20 );
    MusicPlayer myplayer;
     
     
    void setup() {
      Serial.begin(9600);
      pinMode(startButton,INPUT);
      pinMode(doorButton,INPUT);
      pinMode(yellowLED,OUTPUT);
      pinMode(greenLED,OUTPUT);
      pinMode(redLED,OUTPUT);
      pinMode(relayPin,OUTPUT);
      //
      myplayer.keyDisable();
      myplayer.begin();
      myplayer.setPlayMode(MODE_REPEAT_ONE);
      myplayer.creatPlaylist();
     
     
    }
     
    void loop() {
        myplayer.opPlay();
      doorState=1;
      digitalWrite(greenLED,LOW);
      digitalWrite(redLED,LOW);
      digitalWrite(relayPin,LOW);
      digitalWrite(yellowLED,HIGH);
      if ( startBounce.update ( ) && startBounce.read ()){
        digitalWrite(yellowLED,LOW);
        digitalWrite(relayPin,HIGH);
    //  opPreviousSong();  // гудим
        while (!( startBounce.update ( ) && startBounce.read ())){
          if (doorState){
            if (doorBounce.read()==HIGH){
              digitalWrite(greenLED,HIGH);
              digitalWrite(redLED,LOW);
              myplayer.opPreviousSong();  // гудим
            }
            if (doorBounce.read()==LOW){
              digitalWrite(greenLED,LOW);
              digitalWrite(redLED,HIGH);
              myplayer.opNextSong();  // гудим и пищим    
            }
          }
          doorState=doorBounce.update ( );
        }
      }
    }
     
    пришлось поменять местами
    myplayer.keyDisable();
    myplayer.begin();
    т.к. похоже оно работает только в таком порядке, иначе диоды начинают светиться едва заметно.

    но с воспроизведением звука всё плохо. при использовании playList() начинается воспроизведение и больше ничего не происходит, при использовании playSong(номер трека) всё почти работает, но выкидывает в консоль ошибки при попытке открытия файла, при использовании opPlay, opNextSong(), opPreviousSong() всё работает, но на эти команды не реагирует.


    PS: удалось заставить выбирать трек при помощи doorButton и playSong("имя файла"), т.е. при нажатии startButton в зависимости от состояния doorButton включается 1-й или 2-й трек, но на этом какая либо реакция на кнопки прекращается (((
     
  16. Megakoteyka

    Megakoteyka Оракул Модератор

    Сначала опросите все кнопки, а потом начинайте логику разворачивать. а то получается так: опросили одну кнопку и свалились в цикл ожидания нажатия другой кнопки. Не надо одну и ту же кнопку несколько раз опрашивать в одном месте - сохраните в переменную и пользуйтесь ей. Добавьте отладочный вывод во все сомнительные месте - отладка пойдет гораздо веселей :)
     
  17. Jeane

    Jeane Нуб

    Вы уж определитесь.
    Не вижу каких то проблем с циклом, да и проблема совершенно не в нём. Что даст отладочный вывод, если при начале воспроизведения выполнение программы останавливается?