Зависание про выполнении attachInterrupt() с функцией audioZero.end(); AudioZero.play();

Zhivotnikov.mikhail
Offline
Зарегистрирован: 26.02.2021

Всем привет, натолкните на мысль пожалуйста..

Задача - при нажатии кнопки начать проигрывать музыку с SD карты (сделано).

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

attachInterrupt(0, pressButton, RISING),

pressButton() {

audioZero.end();

file myFile = SD.open("2.wav");

AudioZero.play(myFile);

}

Но вот беда исполняя этот код плата как будто виснет, перестает работать монитор порта.. только после ресета оживает. Подозреваю что эта функция слишком сложна для attachInterrupt() так как возможно тоже использует прерывание в себе, но как тогда быть?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Можно встречный вопрос: а зачем Вы пытаетесь решить эту задачу через использование прерываний? Да еще, насколько я понял, даже не пытаясь подавить дребезг?

Zhivotnikov.mikhail
Offline
Зарегистрирован: 26.02.2021

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

По поводу первого вопроса, это первое, что пришло в голову так как задача не доиграть файл до конца, а потом считать состояние кнопки и выполнить новое условие, а именно прервать проигрывание файла если кнопка будет нажата, хоть в середине мелодии.. 

Поэтому и решил через прерывание.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

"Прервать воспроизведение файла" и "аппаратное прерывание" - это никак не связанные вещи, хоть и образованы от однокоренных слов.

Обычно проигрывание музыки осуществляется путем запуска файла на воспроизведение и циклического опроса состояния - закончился или еще нет. По завершении - запускается на проигрывание следующий. Это - стандартная ситуация. Иногда, чтобы ее "облегчить" с точки зрения неопытного программиста делается дополнительная блокирующая функция, чтобы не нужно было осуществлять опрос.

Я не знаю, является ли AudioZero.play(myFile); блокирующей или нет. Если нет - просто ввести в дополнению к опросу статуса воспроизведения опрос состояния кнопки. Если да - найти в библиотеке неблокирующую функцию и использовать именно ее.

b707
Offline
Зарегистрирован: 26.05.2017

Zhivotnikov.mikhail пишет:

но как тогда быть?

переписать функцию AudioZeroPlay() в неблокирующем варианте, чтобы одновременно с воспроизведением музыки оставалась возможность проверить кнопку и прервать проигрывание в любой момент

Upper
Offline
Зарегистрирован: 23.06.2020

b707 пишет:

Zhivotnikov.mikhail пишет:

но как тогда быть?

переписать функцию AudioZeroPlay() в неблокирующем варианте, 

По некоторым признакам мне кажется, что ТС - троль и ответ ему не особо нужен. Но если я ошибаюсь, то переписать функцию в неблокирующем варианте ему явно не по силам. Довольно легко модифицировать - оставив блокирующей, но добавив глобальный флаг, проверяя который функция сможет завершить выполнение. И этот Флаг на сброс устанавливать в прерывании. 

Zhivotnikov.mikhail
Offline
Зарегистрирован: 26.02.2021

Спасибо за совет поковыряю функцию, посмотрю что там можно сделать

Zhivotnikov.mikhail
Offline
Зарегистрирован: 26.02.2021

Смысл понял, но не знаю как реализовать, нужно порыться в инете.. спасибо за подсказки 

Zhivotnikov.mikhail
Offline
Зарегистрирован: 26.02.2021

Разобрался с этой задачей, решил сделать как посоветовал "Upper" через глобальный флаг.

Выкладываю пример, может кому пригодится:

1. создал глобальную переменную в библиотеке AudioZero, volatile bool __StopFlag = true;

2. дописал в функции "void AudioZeroClass::play(File myFile)" проверку этой переменной в цикле "While" и устанавливаю значение переменной true в конце функции.

3. объявил переменную extern bool __StopFlag как внешнюю.

4. Функция обращения к прерыванию -  attachInterrupt(buttonInt, pressButton, RISING);

5. функция запускается по прерыванию -

void pressButton(){

  __StopFlag = false;
}
 
 
Ниже, на всякий случай, код функции Play из библиотеки AudioZero
 
 
void AudioZeroClass::play(File myFile) {
while (myFile.available() && __StopFlag == true) {
if (!__StartFlag)
    {
      myFile.read(__WavSamples, __NumberOfSamples);
      __HeadIndex = 0;
  
  /*once the buffer is filled for the first time the counter can be started*/
      tcStartCounter();
      __StartFlag = true;
    }
    else
    {
      uint32_t current__SampleIndex = __SampleIndex;
      
      if (current__SampleIndex > __HeadIndex) {
        myFile.read(&__WavSamples[__HeadIndex], current__SampleIndex - __HeadIndex);
        __HeadIndex = current__SampleIndex;        
      }
      else if (current__SampleIndex < __HeadIndex) {
        myFile.read(&__WavSamples[__HeadIndex], __NumberOfSamples-1 - __HeadIndex);
        myFile.read(__WavSamples, current__SampleIndex);
        __HeadIndex = current__SampleIndex;
      }
    }
}
myFile.close();
__StopFlag = true;
}