roboforum.ru

Технический форум по робототехнике.

Как подключить к МК пищалку?

Re: Как подключить к МК пищалку?

Duhas » 16 июн 2010, 00:04

переводы от GAW идеальны для вставки в диплом ) так экономят время )

Re: Как подключить к МК пищалку?

Kozinaka » 17 июн 2010, 09:40

По-русски оно быстрее и понятнее читать, но теперь я в курсе, что при неполадках стоит в оригинал залезть. Английский, увы, на уровне "save-load-new-game", не всегда я переведу компетентней, чем добый человек с gaw.

Возвращаясь к теме:

Я разобрался, но может будет полезно тем, кто занимается подобным: при навешивании генерации ноты на таймер-счётчик в режиме CTC нужно при смене частоты обязательно обнулять счётный регистр!

Весь вечер вчера и утро сегодня потратил чтобы разобраться. Какие-то комбинации нот работают корректно, а в каких-то появляются паузы в десяток миллисекунд! Причём даже в этих комбинациях бага появляется нестабильно. Фишка оказалась в том, что при переходе от более низкой частоты (большое значение регистра сравнения) к более высокой иногда переключение регистра сравнения происходит в тот момент, когда счетный регистр находится в значении ПОСЛЕ нового порога. В таком случае счётчик прежде чем выйти на штатный режим должен переполниться - у меня счетчик двухбайтный, время на переполнение ловится на слух как неприятная пауза.

Re: Как подключить к МК пищалку?

boez » 17 июн 2010, 17:54

А про это даже в русском переводе написано:
Однако, задание значения вершины счета близкого к значению нижнего предела счета, когда счетчик работает без предделения или с малым значением предделения, необходимо выполнять с особой осторожностью, т.к. в режиме СТС нет двойной буферизации. Если значение, записанное в OCRnA или ICRn, меньше текущего значения TCNTn, то сброс счетчика по условию совпадения наступит, когда он достигнет максимального значения (0xFFFF), затем перейдет в исходное состояние 0x0000 и достигнет нового значения OCRnA или ICRn. Во многих случаях возникновение такой ситуации не желательно.

Re: Как подключить к МК пищалку?

Kozinaka » 17 июн 2010, 18:10

А я даже это читал перед тем как столкнуться с багой. Именно благодаря этому тексту я ликвидировал багу через несколько часов отладки, а не через несколько дней.
:D

Секвенсор на двух таймерах, работающий из текстовой нотации вида "C#1:4 A2:8-E2:8 C#:8 и т.д.", вобщем-то, собрал, сегодня буду работать над эффектом вибрато (плавно "качать" частоту несколько раз в секунду) и слайдами (плавном переходе от ноты к ноте, причём желательно не линейно, а по параболе).

Re: Как подключить к МК пищалку?

Kozinaka » 18 июн 2010, 09:21

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

Поменял режим с CTC на быструю ШИМ (WGM33:0 = 0b1111), т.к. по даташиту в нём у OCR3A двойная буферизация - типа значение OCR3A применяется только после сброса счетчика. Но эффекта не заметил - то же дёрганье, сбоку.
:(

Re: Как подключить к МК пищалку?

boez » 18 июн 2010, 11:57

Да, тут ситуация непонятная, даташит явственно рекомендует использовать для твоего случая Fast PWM с OCRnA в качестве периода и режим Toggle на выходной ноге. Проверь, действительно ли у тебя WGM33:0 = 0b1111, может напутал чего?

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

Re: Как подключить к МК пищалку?

Kozinaka » 18 июн 2010, 23:26

Вот код инициализации (по совету blindman'а пользуюсь именами разрядов):
Код: Выделить всёРазвернуть
   //Таймер 3 (отсчёт частоты звука)
   //Быстрая ШИМ, OC3A переключается при сбросе таймера
   TCCR3A = 0x00 | 1<<COM3A0 | 1<<WGM31 | 1<<WGM30;
   TCCR3B = 0x00 | 1<<WGM33| 1<<WGM32;
Работать работает, но попадаются прежние неприятные паузы при смене частоты, которые ликвидируются, если обнулять счетчик (TCNT3 = 0x00).

Чуть-чуть поковыряюсь ещё, и сделаю как ты советуешь. :) Буду использовать программный буфер и включать прерывание при необходимости сменить частоту звука.

Добавлено спустя 3 часа 22 минуты 38 секунд:
Сделал двойную буферизацию программно - не помогло. Полез выяснять, обнаружил такую штуку - пока у меня вызывается обработчик прерывания переполнения таймера-счётчика его значение уже успевает уплыть больше чем на половину периода! Вот встал на брейкпоинте:
Why.jpg

:shock: Это нормально, доктор?
Счетчик у меня с предделителем 8 работает, значит прошло 2480 тактов процессора, прежде чем запустился мой обработчик прерывания и я считал значения двух регистров.

Добавлено спустя 15 минут 49 секунд:
На данный момент решил проблему без прерываний, дешевой и сердитой проверкой на "убегание" после изменения значения регистра сравнения:
Код: Выделить всёРазвернуть
   //Установка значения счётного регистра
   OCR3A = nFreq;
   //Проверка на "перепрыгивание" предела
   nCounter = TCNT3;
   if(nCounter >= nFreq) {
      //Cброс счетчика
      TCNT3 = 0x00;
   }

Re: Как подключить к МК пищалку?

blindman » 19 июн 2010, 06:12

Kozinaka, ты бы код полностью выложил - а то так общей картины не видно.

Re: Как подключить к МК пищалку?

Kozinaka » 19 июн 2010, 09:04

Стараюсь не захламлять форум. :)

Вложил архивчик с проектом в AVR Studio и Proteus(подпапочка proteus). Код разделен на модули, все что к пищалке buzzer.h/buzzer.c. Обработчик прерывания по переполнению: buzzer.c/buzzer_change_freq(), ну а дальше - я довольно дотошно всё комментами описываю.

Buzzer.zip
(162.26 КиБ) Скачиваний: 0

Re: Как подключить к МК пищалку?

blindman » 19 июн 2010, 09:53

В том, что счетчик сильно убегает до того, как вызвано прерывание - ничего удивительного. У тебя в прерывании от нулевого таймера вызывается монструозная функция parse_note, да не один раз, да в цикле. И еще и оптимизация отключена. Пока отрабатывается это прерывание, возникает прерывание от третьего таймера, но оно не будет обработано до тех пор пока не закончится прерывание от нулевого таймера.

Оптимизацию включить, убедиться что обработчик прерывания от нулевого таймера укладывается в 1мс и частоту ноты устанавливать в нем, прерывание от третьего таймера убрать.

Re: Как подключить к МК пищалку?

Kozinaka » 19 июн 2010, 23:20

О, спасибо за рекомендации и столь серьёзное внимание к моему коду! :Yahoo!:

Оптимизация отключена в режиме debug - для нормальной отладки, чтобы в переменные глядеть. А в режиме release оптимизация конечно включена на полную.

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

Прерывание переполнения таймера 3 я убрал сразу, просто вернул обратно когда выложил исходник, чтобы сразу в коде можно было попробовать глюку с запоздалым вызовом прерывания. Кстати, ещё раз спасибо, про очередь из прерываний знал только теоретически - не думал, что это про меня.

Нет идей по поводу - почему не работает двойная буферизация? :sorry:

Re: Как подключить к МК пищалку?

blindman » 20 июн 2010, 09:02

Двойная буферизация вряд ли не работает - скорее проблема именно в долгой обработке прерываний. Я бы сделал так: парсер крутится в главном цикле, и пишет в кольцевой буфер по 2 значения - частота и время. В прерывании от таймера достаем частоту и время из буфера, устанавливаем новую частоту, и переставляем таймер, чтобы следующее срабатывание было по истечении нужного интервала времени. Частоту генерируем 3-м таймером, интервал отсчитываем первым (если он занят, можно и 8-битным, но тогда длинные интервалы программно отрабатывать). Прерывание будет очень простым:
Код: Выделить всёРазвернуть
ISR(SIG_OUTPUT_COMPARE1A) {
   /*
     здесь достаем freq и time  из буфера
   */


   OCR3A = freq;
   OCR1A += time;
}

Re: Как подключить к МК пищалку?

Kozinaka » 20 июн 2010, 09:31

Насколько я понимаю, основной недостаток такого решения - необходимость работы парсера в главном цикле. Получится как у yak-40: либо Валли "мурку" играет, либо Валли едет.

Таймер отсчёта времени не обязан иметь супер плоский обработчик прерывания, ведь он своей работой не тормозит генерящий таймер, а если считать им не весь интервал, а только миллисекунды, как сейчас, то годится любой, что байтовый, что двухбайтовый счетчик (кроме засады с предделителем 128, конечно).

А что такое кольцевой буфер?

Re: Как подключить к МК пищалку?

blindman » 20 июн 2010, 09:56

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

Глянул еще раз - у тебя там вычисления с плавающей точкой - это-то зачем? Вычислить заранее целочисленные значения для 12 нот самой низкой октавы, по октавам переходить делением на 2.

[[en:Ring buffer]]

Re: Как подключить к МК пищалку?

Kozinaka » 20 июн 2010, 11:01

Не, не, октавы я как раз сдвигами (от первой октавы в обе стороны) меняю, после вычисления целочисленной частоты ноты.
:)

Плавающая точка только в вычислении порога таймера (fFreq - герцы, nFreq - такты), формула из даташита:
Код: Выделить всёРазвернуть
nFreq = F_CPU / ((fFreq * 4/*транспозиция*/)*2*8/*предделитель*/);

Хм.. Пока писал, понял, что можно просто все показатели увеличить на 100, тогда частоты можно задавать целочисленно, а не "369.99"!

Добавлено спустя 5 минут 27 секунд:
В лоб нельзя. Ля первой октавы тогда 44000, это не умещается в двухбайтовый int. Умножу-ка на 10, а последний разряд округлю, в сотую герца ухо не слышит.


Rambler\'s Top100 Mail.ru counter