Микроконтроллеры | Частотомер на AVR |
|
---|---|---|
Заново просматривал теорию по поводу метода захвата, изложеную GM, на electronix.ru. Немогу понять почему число подсчитываемых импульсов входной частоты М точное число, а N гуляет +/-1. У меня полуячается что гуляют оба. ИЗМЕРЕНИЕ ЧАСТОТЫ С ПОМОЩЬЮ АВР МИКРОКОНТРОЛЛЕРА 1) Введём определения 2) Формула вычисления частоты Fx = Fо*М/N (поскольку очевидно, что То*N=Тх*М за Тизм). 3) Формула для Fx применима как к варианту с "воротами", так и к варианту со схемой захвата. При использовании схемы захвата М является точным числом, а N "гуляет" в пределах (-1,+1). При использовании "ворот" N является точным числом, а М "гуляет" в пределах (-1,+1). Вот всё, что нам нужно знать из теории для измерения частоты. 4) Применим наши знания на практике. Выберем период измерения Тизм примерно равным одной секунде. (Примерно потому, что Тизм должен быть ТОЧНО кратен М*Тх). Пусть Fx=170 кГц, а Fо=16МГц. Тогда М=170000, а N=16000000. Вычислим частоту по нашей формуле Fxвыч = Fо*М/N=16000000*170000/16000000=170000 Гц. Итак, Fx = Fо*М/(N±1)=170000±0.010625 Гц. Что нам и требовалось показать. Относительная погрешность составит 6*10^(-8). Можно добавить 10^(-8) нестабильности опоры, если требуется уточнить погрешность. Кстати, для варианта с "воротами" Fx = Fо*(М±1)/N=170000±1 Гц, как и было сказано. 5) Перейдём теперь к реализации алгоритма на микроконтроллере. В принципе, всё и так уже ясно, просто поставим точки над ϊ и чёрточки на t(. Сколько нам нужно захватов таймера, чтобы вычислить частоту? Два - один для захвата начала секундного интервала, и второй для захвата конца того же интервала. Пусть захват работает по прерыванию. При захвате, т.е. при положительном фронте импульса входной частоты, содержимое таймера перепишется в регистр ICR. Прекрасно, в этом же прерывании запомним в регистрах или в памяти два числа – количество импульсов Мнач и Nнач, запрещаем прерывание и выходим из него (замечу в скобках, схема захвата "молотит" по-прежнему, но прерывания запрещены), оно нам понадобится только через секунду, займёмся другими делами, скажем, расчетом частоты предыдущего цикла. Через примерно секунду работы (или вынужденного безделья, можно по таймеру) ОПЯТЬ разрешаем прерывания от схемы захвата. Как только оно произойдёт, опять запоминаем два числа – количество импульсов Мкон и Nкон, запрещаем прерывание по захвату и выходим из него, вычисляем М=Мкон-Мнач, N=Nкон-Nнач. Вот так это всё и работает. Я, конечно многого не упомянул. Все переменные для расчета должны быть соответствующей разрядности, как минимум 32, умножение надо делать до деления, чтобы не потерять точность, вычисление частоты можно вести непрерывно, достаточно просто после вычисления частоты переписать переменные Мнач=Мкон, Nнач=Nкон. Обязателен учёт переполнения таймеров. |
|
|
Y@rik: Заново просматривал теорию по поводу метода захвата, изложеную GM, на electronix.ru. Не могу понять, почему число подсчитываемых импульсов входной частоты М точное число, а N гуляет +/-1 Насколько я помню вашу программу, вы М получаете по прерыванию. Если это так, то у вас может быть такая ситуация, пришёл фронт входного импульса, возникло прерывание захвата, пока прерывание, написанное на си, доходило до чтения М, возникал новый захват, и вы считывали не М, а М+1 или даже М+2. Ну сами посудите, для 1 МГц входной частоты фронты идут через 1 мкс или 8 машинных циклов (МЦ). А у вас вход в прерывание не менее 0-1-2 МЦ (на завершение текущей команды) ПЛЮС 4 МЦ(на сохранение СчК) ПЛЮС 2 МЦ (на переход на подпрограмму) = 7-8 МЦ. Вывод: обеспечьте равные задержки как для начала цикла измерения, так и для конца. Например, чтобы исключить неравномерность от завершения текущей команды, надо бы чтобы программа в моменты прерываний шла по однотактным командам, скажем по нопам. |
|
|
GM: Просто вам надо силой воли отказаться от прерываний. Что можно сделать. Пусть пока прерывания захвата приходят с частотой 1 МГц, т.е. каждые 8 МЦ. В си-программе открываете ваш ключ разрешения захвата, скажем, на 1 мс. Что произойдёт? Прилетит порядка 1000 фронтов, последний останется в ICR1 и его можно использовать для вычисления N. Далее, надо определить содержимое счётчика0, соответствующее последнему фронту. Навскидку так например, читаете 4 раза содержимое счётчика0, закрываете ключ, ещё 4 раза читаете и смотрите, где произошли изменения, простая логика и М у вас в кармане. Будет работать и на 4 МГц, и даже на си. Ну и всё, остальную часть вы знаете. Попробывал, как Вы и говорили реализовать программу без прерывания, кажется работает. Так как я пишу на СИ, есть вопрос, если эти сохранения сделать вставками ассеблерных команд в тело Си программы, сохранение лучше проводить в регистры или в ОЗУ. Мене кажется, что лучше будет в регистры (т.к. сохранение происходит за 1 такт). |
|
|
Возьмите МК с двумя схемами захвата, я вам уже говорил на электрониксе, и пишите всё на си, если вам это си так полюбилось. И будет вам щастье, и программа у вас будет белая и пушистая, как у меня норвежская лесная кошка(. С регистрами поаккуратней, шут его знает, как компилер ими распоряжается... |
|
|
Сразу записывать в регистры попробывал, пока программа работает . Пробывал подставлять значения сохранненых регистров в формулу вычисления частоты, получается, что частота не зависит от того, какую пару сохранненых регистров я возьму Т0_1, Т0_2 и т.д. для вычисления М1 и М2. GM: Возьмите МК с двумя схемами захвата, я вам уже говорил на электрониксе, и пишите всё на си, если вам это си так полюбилось. |
|
|
Y@rik: Но мне не понятно как можно детектировать, что за время открытия ключа, допустим 1мс прошел хоть один импульс Y@rik: Я уже спрашивал у Вас, какие контроллеры имеют 2 схемы захвата, кроме мега128 - да и дороговата она у нас |
|
|
Кстати я тут тоже столкнулся с проблемой реализации частотомера. У меня диапазон изменения входной частоты 50 Гц - 500 кГц нужно измерять с точностью хотя-б +/-1 Гц и временем измерения 0,1 сек не более. Параллельно ведя обширную "переписку" по UART. Контроллер ATMEGA8 при тактовой 12 МГц. Таймеры 0 и 1 свободны. Сейчас тактирую измеряемой частотой таймер 1, а время отмеряю таймером 0 по прерываниям. Работает, но нельзя-ли как-то поизящнее. Импульсы имеют скважность близкую к 2. ЗЫ ищу примеры реализации ПИД регулятора на ассемблере AVR (Элм Ченовскую уже изучал). ЗЫ номер 2 - на 2 недели правда ухожу в загул. |
|
|
Абсолютная погрешность моего метода равна ±(Fx/Fo)*(1/Tизмерения)=±(0.5/12)*(1/0.1)=±0.4Гц за 0.1с или можете уменьшить время измерения в два раза, до 50мс, точность будет ±0.8Гц. Почитайте на электрониксе, я там новый способ статистической обработки предложил для этого метода. |
|
|
Сделал частотомер реализован по етому алгоритму на Мега8. В протеусе(7.4 SP3) симулируется норьмально. Диапазон 0.3гц - 1мгц. В железе не проверял. Может кому пригодится. |
|
|
Интересное решение входного ключа, но там у вас глитч присутствует на выходе, поэтому возможна систематическая ошибка и нестабильность работы. Также в вашей программе есть ошибки, например, здесь MovfStart = ICR1; // Запоминаем начальное состояние М счетчика вы почему-то игнорируете Movf, а счётчик переполняется каждые 4 мс и в цикле ожидания первого импульса вполне может быть перенос из таймера в Movf. |
|
|
Форум про радио — сайт, посвященный обсуждению электроники, компьютеров и смежных тем. pro-radio.online | Обратная связь |
© 2003—2024 |