Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 08:17:55

не сильно надеясь на результат, все же спрошу.

осваиваю модуль воспроизведения MP3 и не только по командам с USART MP3-TF-16P, вот такой:
Изображение

задумка была такая: заставил модуль что-то воспроизводить, и занимаюсь своими делами, проверяя время от времени, не закончил ли он бухтеть. как закончил - снова его пинаю, если надо. казалось бы - что сложного?

только оказалось, что модуль на команды реагирует своеобразно.
во-первых, если требуешь от него ACK-подтверждение, то он выставляет его мгновенно после приема команды. а вот результат исполнения самой команды может прийти спустя несколько сотен миллисекунд, видимо, пока он по SD-карте пошушршит...
во-вторых, на пине BUSY уровень выставляется тоже спустя некоторое время после приема команды, до конца не выяснил, какое именно, но тоже в сотнях миллисекунд измеряется.
в-третьих, о том, что он закончил играть заданный трек, модуль сообщает ДВУМЯ командами, хотя в документации об этом ни слова. т.е. приходит два одинаковых пакета.

плюс ко всему я еще запузырил кольцевые буферы на прием...

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

ну и самое смешное: послал команду "играй трек" и, как выше говорил, начинаю периодически спрашивать модуль "ты там что делаешь?". а он мне в течение нескольких сотен миллисекунд отвечает "ничего не делаю". само собой, если у меня в очереди следующий трек на воспроизведение, я его стартую - и снова та же песня. приходится ТУПО ЖДАТЬ, пока модуль ответит "я начал играть", и уж потом можно начинать периодически интересоваться, не закончил ли. если ждать ответа об окончании, то, т.к. прием буфферизирован, а модуль выдает ДВА ответа, я попадаю в ситуацию, когда начав воспроизводить ВТОРОЙ трек я тут же вижу в буфере второй ответ об окончании ПЕРВОГО, и попадаю в непонятки - то ли ВТОРОЙ уже кончился, то ли нет.

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

как разумно наладить асинхронность? может, я чего-то не понимаю в работе этого модуля? может, я, наоборот, замудрил с асинхронностью?

меня еще подобный геморрой ждет с модулем GSM: там модем тоже может неожиданно выдать ответ не тот, что я жду, а, например, сигнал о входящем звонке или СМС... и разбираться с этим тоже придется. так что надо бы определиться с общим принципиальным алгоритмом. если есть понимающие в этом люди, посоветуйте что-нибудь разумно-оптимальное.

Re: Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 08:28:34

ARV писал(а):меня еще подобный геморрой ждет с модулем GSM: там модем тоже может неожиданно выдать ответ не тот, что я жду, а, например, сигнал о входящем звонке или СМС...
Уж не M590 ли? А то я себе такой прикупил, но даже еще в руках не держал.

Re: Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 10:18:40

Z_h_e писал(а):Уж не M590 ли?
такой тоже есть, но пока веду речь об SIM800L - жду доставку... у М590 нет звукового тракта, на сколько я понимаю...

Re: Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 18:36:03

асинхронная передача данных тем и хороша, что отвязана от таймингов. Но Вам необходимо самостоятельно запоминать состояние системы, и уметь восстанавливать состояние в случае потери соединения (или, что на первых порах вероятнее, глюков, вызванных неверной работой машины состояний).
Практически я бы начал со следующей реализации:
Пишем команду и данные в буфер передачи. Время от времени читаем буфер приёма, в ожидании нужного нам ответа. Остальную информацию аккуратно игнорируем, и чистим. Я так понимаю, что с чтением не полностью переданных кусочков данных проблем не должно возникнуть. Это такой эмулятор синхронности :)
Следующая итерация: Пишем последовательно несколько команд, и читаем буфер приёма в поисках нужных ответов. Задача чуть сложнее первой, т.к. ответы могут приходить в произвольном порядке, и чистить полученную информацию нужно аккуратно, чтобы не удалить ответ на следующую посылку.
Следующая итерация: учим софт, если нет ответа на отправленный пакет на протяжении таймаута, повторять отправку. Если нет нумерации пакетов в протоколе (или временнЫх меток каких-нибудь), придётся заново инициализировать "удалённое" устройство, чтобы очистить его состояние и буфер передачи. Иначе потерянный ответ может таки дойти, но не совсем вовремя :)
Следующая итерация: учим программу понимать сообщения, которые отправляются по инициативе "удалённого" устройства, не в ответ на команды. В случае с AT командами модему и сообщением RING - оно может "вклиниваться", например, прямо в текст сообщения, которое Вы читаете с модема. Разделить их задача, действительно, не тривиальная. Каждый раз, получая признак конца переданного сообщения, нужно проверять, ответ на Ваше сообщение закончился, или модем решил сам что-то отправить :)
На самом деле, в задачах, подобных Вашей, чаще всего асинхронный обмен данными пытаются использовать для обмена синхронизированными сообщениями: отправить команду play, дождаться ответа ok, поллить запросами состояния, если не busy - отправить следующую команду play. Это неверный подход к программированию такой задачи. Правильно было бы отправить команду play, если за время меньше таймаута пришёл ok - забыть про плеер, пока он не пришлёт сообщение, что проиграл трек. Или не закончится таймаут, выставленный для воспроизведения.
Я отлично помню ощущение потери контроля над происходящим, и связанную с этим панику :) но на самом деле ничего страшного, со временем привыкаешь :)
IMO топик был бы более уместен в соседней теме про "периферию"

Re: Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 19:34:10

AAX писал(а):Это неверный подход к программированию такой задачи. Правильно было бы отправить команду play, если за время меньше таймаута пришёл ok - забыть про плеер, пока он не пришлёт сообщение, что проиграл трек.
вот и смотрите, что получается: я отправляю команду PLAY, плейер мне немедленно (т.е. стартовый бит его ответа начинается ровно по концу стопового бита принимаемой команды) отвечает OK. только этот ОК абсолютно не означает, что он НАЧАЛ ИГРАТЬ. очень может быть, что указанный файл не будет найден, и тогда спустя время поиска файла он мне выдаст сообщение с ошибкой. спустя неизвестно какое время. при этом плейер вполне может продолжать принимать другие команды, например, управления громкостью, отчечать на них ОК и т.п. и потом нежданно приходит ошибка. очень неприятный момент.
но еще неприятнее тот момент, который вы, видимо, не заметили: если файл есть, то плейер начнет его воспроизводить (и выставит аппаратно уровень на пине BUSY) не сразу после ОК, а опять-таки спустя неизвестно какое время. в моих экспериментах это время достигало 600-800 миллисекунд. и в течение всего того времени на запрос состояния плейер будет отвечать СВОБОДЕН, т.е. честно уведомлять, что еще ничего не воспроизводит! как отследить эту ситуацию, если надо воспроизвести два или более файлов последовательно? понимаете, о чем я? 800 милисекунд - это чертовски много по меркам МК, за это время я минимум 50-60 раз успеваю послать запрос состояния. и получается, что моя программа уверена, что файл УЖЕ ОТЫГРАЛ, РАЗ ПЛЕЙЕР СВОБОДЕН. неприятно. и я заранее никак не могу узнать, как долго файл будет воспроизводиться по-настоящему...

конечно, все это как-то можно разруливать. в частности, я поначалу именно дожидался НУЖНОГО ответа на каждую команду, чем убивал весь смысл асинхронного обмена.

сейчас я решил делать некую машину состояний с флагами... это более-менее решает проблему с плейером, но насколько это применимо к модему - еще не думал...

предложенное вами более менее понятно, хотя выглядит достаточно сложным. не хотелось бы погружаться в подобные дебри... неужели ничего проще нет?

Re: Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 20:02:06

я отправляю команду PLAY, плейер мне немедленно (т.е. стартовый бит его ответа начинается ровно по концу стопового бита принимаемой команды) отвечает OK. только этот ОК абсолютно не означает, что он НАЧАЛ ИГРАТЬ.
точно. Это означает, что плеер услышал команду. Теперь Вам нужно его оставить в покое, пока он не сообщит о конце воспроизведения, ну, или об ошибке.
при этом плейер вполне может продолжать принимать другие команды, например, управления громкостью, отчечать на них ОК и т.п.
в этом смысл организации асинхронной связи, это отлично! :)
но еще неприятнее тот момент, который вы, видимо, не заметили: если файл есть, то плейер начнет его воспроизводить (и выставит аппаратно уровень на пине BUSY) не сразу после ОК, а опять-таки спустя неизвестно какое время. в моих экспериментах это время достигало 600-800 миллисекунд. и в течение всего того времени на запрос состояния плейер будет отвечать СВОБОДЕН, т.е. честно уведомлять, что еще ничего не воспроизводит! как отследить эту ситуацию, если надо воспроизвести два или более файлов последовательно? понимаете, о чем я?
заметил, понимаю. Именно по этому я говорил, что нужно самостоятельно запоминать состояние. Это Вы ещё про корректные жизненные ситуации, а бывают "несчастные случаи", типа кратковременного отключения питания, когда плеер ушёл в ресет, а МК этого не заметил, и продолжает "разговаривать" с ним, как с живым :) По этому нужно ещё и корректность ответов анализировать. И приведение системы в известное состояние предусматривать. Это не обязательно будет та же процедура, что при начальной инициализации.
сейчас я решил делать некую машину состояний с флагами... это более-менее решает проблему с плейером, но насколько это применимо к модему - еще не думал...
лучше сразу перейти к машине состояний со списками, с произвольным доступом. Чтоб два раза не вставать :)
предложенное вами более менее понятно, хотя выглядит достаточно сложным. не хотелось бы погружаться в подобные дебри... неужели ничего проще нет?
это дебри? Даладно :) Это Вы ещё по UDP что-нибудь передавать/принимать не пробовали :) К счастью, обычно протоколы ниже уже в готовом виде. Иначе там можно голову сломать, разбираясь, когда что и куда отправляется.

Re: Буфферизированный асинхронный обмен по USART и задержки

Пн дек 17, 2018 22:44:18

AAX писал(а):лучше сразу перейти к машине состояний со списками, с произвольным доступом.
ну так как бы об этом и сказал... просто нет четкого понимания, какие состояния у модуля плейера - документация немного странноватая, не все понятно сразу. разбираюсь.
AAX писал(а):Это Вы ещё по UDP что-нибудь передавать/принимать не пробовали
так вроде бы там пакеты маркируются, и по этому маркеру можно понять, что к чему. типа послал пять пакетов, получил четыре ответа, но каждый ответ промаркирован номером пакета, на который он послан. и можно вычислить, какой пакет без ответа остался, и его повторить. может, не совсем так, но вроде того что-то, как я понимаю...
а здесь - не так.


в общем, что-то стало получаться с состояниями... вопросы пока остаются, но уже все дышит. спасибо за советы :)

P.S. хоть это к теме отношения не имеет, но обнаружил такое чудо: модуль после завершения воспроизведения wav-файла с номером 0470 не посылает STAY :( и моя машина состояний зависает в состоянии PLAY. при этом если другой файл путем переименования назвать 0470 - STAY приходит. то ли на SD-карте у меня какая-то беда с файловой системой, то ли это баг прошивки модуля... то ли само содержимое файла какое-то странное.

Re: Буфферизированный асинхронный обмен по USART и задержки

Вт дек 18, 2018 14:44:09

AAX писал(а):лучше сразу перейти к машине состояний со списками, с произвольным доступом.
ну так как бы об этом и сказал...
не со зла, просто это такой стандартный путь - флаги, очередь, список :) И мне кажется, что лучше этот путь пройти, ибо сказано, что "...опыт, сын ошибок трудных...", но не "...опыт, сын гугления до потери сознания..."
P.S. хоть это к теме отношения не имеет, но обнаружил такое чудо: модуль после завершения воспроизведения wav-файла с номером 0470 не посылает STAY :( и моя машина состояний зависает в состоянии PLAY. при этом если другой файл путем переименования назвать 0470 - STAY приходит. то ли на SD-карте у меня какая-то беда с файловой системой, то ли это баг прошивки модуля... то ли само содержимое файла какое-то странное.
т.е. переименование этого файла из 0470 в 0740 решает проблему? или дело не в названии вовсе, а в структуре файла? mp3, особенно id3, очень бардачный формат, пишут, кто во что горазд. Вполне возможно, что в прошивке плеера какая-то ошибка, какие-то редкие краевые условия не учтены

Re: Буфферизированный асинхронный обмен по USART и задержки

Вт дек 18, 2018 18:27:49

AAX писал(а):т.е. переименование этого файла из 0470 в 0740 решает проблему?
не совсем так. проблему решает переименование, например, 0011.wav в 0470.wav. не знаю, что было не так, но пока решил проблему тупой заменой 0470.wav на 0470.mp3 - пришлось переконверировать, естественно.
AAX писал(а):стандартный путь - флаги, очередь, список
да оно-то понятно... но все кажется, что есть способ и проще.

Добавлено after 5 minutes 8 seconds:
:( 0278.wav тоже не посылает STAY :(

что за хрень?!
сам дурак :oops:

Re: Буфферизированный асинхронный обмен по USART и задержки

Чт дек 20, 2018 03:38:20

так вроде бы там пакеты маркируются, и по этому маркеру можно понять, что к чему. типа послал пять пакетов, получил четыре ответа, но каждый ответ промаркирован номером пакета, на который он послан. и можно вычислить, какой пакет без ответа остался, и его повторить. может, не совсем так, но вроде того что-то, как я понимаю...
не, в UDP вообще никакого контроля прохождения пакетов нет. ACK-и на принятые пакеты есть в TCP, и там все куда более заморочено.
Ответить