Частотомер на микроконтроллере

06/03/2011 - 19:00

   Введение

  В одной из предыдущих статей, посвященных изучению микроконтроллеров AVR, на примере проекта частотомера мы рассмотрели использование 16-ти разрядного таймера/счетчика Т1 и прерывания по событию захват. В качестве дополнения к этому материалу, предлагаю улучшенную версию частотомера. В этом проекте тоже используется блок захвата и дополнительно еще задействован тактовый вход 8-ми разрядного таймера. 
    Недостатки старого проекта заключались в маленьком диапазоне измеряемых частот (~сотни киллогерц), что было связано со способом измерения периода сигнала. 
   Вы, наверное, помните, что в прерывании по событию захват счетный  регистр 16-ти разрядного таймера обнулялся, а захваченное значение, соответствующее количеству импульсов тактового генератора микроконтроллера, укладывающихся в один период входного сигнала,  сохранялось в переменной. На основе этого значения и выполнялись расчеты. 
   При повышении частоты входного сигнала микроконтроллер не успевал обрабатывать прерывания, пропускал их, и показания частотомера начинали резко расходиться с действительностью.   
   В новом проекте вычисление частоты выполняется по нескольким периодам входного сигнала и без постоянного использования прерывания по событию захват. Это уменьшает накладные расходы микроконтроллера и позволяет измерять значительно большие частоты — в идеале до 1/2 Fcpu (частоты тактирования микроконтроллера). 
   Итак, перейдем к описанию нового проекта частотомера. 

   Схема


   Входной сигнал подается на вход схемы захвата таймера Т1 и счетный вход таймера Т0. Для того чтобы таймер Т0 тактировался от внешнего сигнала, он должен быть соответствующим образом настроен.  

   Структура проекта

   Проект состоит из 4-ех программных модулей. 
bcd.c – содержит функцию  для вывода двоичных чисел на дисплей 
timer.c – содержит функцию инициализации таймеров T0 и Т1, обработчики прерываний, функцию захвата значений счетных регистров таймеров и программных счетчиков и, наконец, функцию вычисления частоты. 
lcd_lib.c – это библиотека для работы с символьным дисплеем.
main.c -  основная программа.

   Метод измерения частоты

   Частота входного сигнала измеряется методом временных ворот. Суть метода заключается в подсчете количества импульсов измеряемого и опорного сигналов за определенный промежуток времени. 
   Для подсчета количества импульсов измеряемого сигнала используется счетный вход аппаратного таймера. В качестве опорного сигнала используется тактовый сигнал микроконтроллера.   
   Интервал времени, в течение которого выполняются подсчеты импульсов, отмеряется с помощью схемы захвата аппаратного таймера Т1 и программной задержки. 
   Формула для расчета частоты по методу временных ворот такая:
 
Fx = Fo * (M/N),
 
где Fx – частота входного сигнала, Fo – частота опорного сигнала, M – количество импульсов входного сигнала за время измерения, N – количество импульсов опорного сигнала за время измерения.

  Алгоритм программы

     В проекте используются два таймера — 8-ми разрядный таймер/счетчик Т0 и 16-ти разрядный Т1. Таймер T1 подсчитывает количество тактовых импульсов микроконтроллера (baseImp), укладывающихся в определенный временной интервал, а таймер Т0 считает импульсы измеряемого сигнала (mesurImp).
   Временной интервал, в течение которого выполняются подсчеты импульсов, порядка одной секунды. Поскольку за это время оба таймера успевают много раз переполнится, в программе используются дополнительные программные счетчики (timer0, timer1). Это 16-ти разрядные переменные, которые  инкрементируются в прерываниях таймеров Т0 и Т1. 
    Общий вид циклограммы работы таймеров представлен на рисунке ниже.

Циклограмма работы таймеров Т0 и Т1
 
Алгоритм программы выглядит следующим образом.
 
1. Выполняется инициализация таймеров и дисплея
2. Микроконтроллер ожидает установки флага схемы захвата таймера Т1, или, выражаясь простым языком, ловит передний фронт измеряемого сигнала. 
3. Дождавшись установки флага (момент Capture1 на рисунке), микроконтроллер сохраняет значения счетных регистров таймеров Т0 и Т1, а также значения программных счетчиков. 
4. Вызывается программная задержка длительностью в одну секунду. Оба таймера продолжают работать. 
5. По окончанию задержки микроконтроллер ожидает установки флага схемы захвата 
6. Дождавшись установки флага (момент Capture2 на рисунке), микроконтроллер сохраняет значения счетных регистров Т0 и Т1 и значения программных счетчиков. 
7. Вычисляется значение частоты и выводится на дисплей 
8. Возврат на шаг номер 2.
 
   Несколько слов о вычислении частоты. 
 Для расчета количества  импульсов опорного сигнала используется следующая формула. 
 
  //количество переполнений программного счетчика
  saveTimer12 = saveTimer12 – saveTimer11;
 
  //количество импульсов опорного сигнала
  baseImp = (icr12 + (unsigned long)saveTimer12*65536) – icr11;
 
где  saveTimer12, saveTimer11 — значение программного счетчика timer1 в моменты Capture2, Capture1 соответственно;   icr12,  icr12 — значение счетного регистра TCNT1 таймера Т1 в моменты Capture2, Capture1 соответственно; 65536 — емкость счетчика Т1
     
   Расчет количества импульсов входного сигнала выполняется по аналогичной формуле, только там емкость счетчика равна 256.
 
  saveTimer02 = saveTimer02 - saveTimer01;
  mesurImp = (tcnt02 + (unsigned  long)saveTimer02*256) — tcnt01;
 
   Расчет частоты входного сигнала производится по формуле:
 
  result = (16000000UL*(unsigned long long)mesurImp*10)/baseImp;
 
где 16000000 — тактовая частота микроконтроллера, а mesurImp и baseImp количество импульсов входного и опорного сигналов соответственно.
   Результат умножается на 10 для отображения одного знака после запятой. 
   
   Переменные  baseImp,  mesurImp и  result типа unsigned long. Для избежания переполнения переменных при выполнении операций умножения,  переменные приводятся к типам более высокой разрядности (unsigned long в первых двух формулах и unsigned long long в последней).  

  Частотомер на AVR – проекты

 
PS: С проектами для WinAVR и CodeVison у меня возникли некоторые проблемы. И  WinAVR и CodeVison неадекватно вели себя при использовании типа unsigned long long в формуле вычисления частоты. Не было времени разбираться в чем дело и я немного упростил формулу, пожертвовав точностью вычислений.

Комментарии   

# Crafter76 07.03.2011 05:05
А вот и косяк будет в настоящем-то устройстве... Проблема в том, что частота - это случайный процесс, и померить ее без использования дисперсии - неправильно...
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.03.2011 08:17
Материал носит обучающий характер. Мы не создаем здесь девайс на продажу.
Цитата:
Проблема в том, что частота - это случайный процесс
Объясните популярно (или дайте ссылку) почему частота случайный процесс и где написано как ее правильно измерять.
Ответить | Ответить с цитатой | Цитировать
# RA_DU_GA 10.03.2013 16:36
Человек видимо имел ввиду, что любое измерение есть процесс получения случайных величин :)
Так это уже второй вопрос - чем достовернее хочешь померить, тем просто большее количество измерений проводишь (получая децл разные результаты), сводишь в таблицу,
а там считаешь дисперсию и все прочее :)
Ответить | Ответить с цитатой | Цитировать
# den3z 17.11.2012 08:12
частота это не процесс, а физ. величина.
Ответить | Ответить с цитатой | Цитировать
# Crazy Synergetic 07.03.2011 05:25
А какова максимальная измеряемая частота???? Мне из этого поста сие совсем не ясно...
P.S. Конечно хотелось бы еще узнать какова максимальная частота измерений на практике:)))
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.03.2011 08:07
Читаем внимательно
Цитата:
в идеале до 1/2 Fcpu (частоты тактирования микроконтроллера).
Ответить | Ответить с цитатой | Цитировать
# AtMega8 07.03.2011 16:16
Ужас для начинающих..
Я вот не пойму если один счетчик подсчитывае количество импульсов измеряемого сигнала за определенный промежуток времени(то что надо), зачем тогда некая опорная частота?))
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.03.2011 21:11
Один счетчик считает импульсы входного сигнала, второй - импульсы опорной частоты укладывающийся в "определенный промежуток времени". А промежуток этот складывается из программной задержки и двух "хвостиков" - первый от Capture1 до программной задержки, второй от программной задержки до Capture2.
Ответить | Ответить с цитатой | Цитировать
# Brigadir 07.03.2011 20:37
Довольно экзотический алгоритм измерений. Pashgan, и как ты до такого додумался?
И, действительно, почему бы просто не считать кол-во входных импульсов за определенный интервал времени? В таком случае, тактовая частота МК не играла бы роли.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.03.2011 20:54
Идея не моя. Я прочитал об этом методе на форуме electronix.ru.
В идеале метод должен давать точность +-1 такт контроллера. На практике получается хуже.
Думаю на XMEGA хорошо получилось бы реализовать - там несколько 16-ти разрядных счетчиков и их можно каскадировать в 32 разрядные.
Ответить | Ответить с цитатой | Цитировать
# add 10.03.2011 05:54
Цитирую Pashgan:
Идея не моя. Я прочитал об этом методе на форуме electronix.ru.

уф, а я уж читая, подумал что ссылки на первоисточник не будет)))
Ответить | Ответить с цитатой | Цитировать
# TarasH 30.08.2011 11:35
Цитирую Pashgan:
Идея не моя. Я прочитал об этом методе на форуме electronix.ru.
В идеале метод должен давать точность +-1 такт контроллера. На практике получается хуже.
Думаю на XMEGA хорошо получилось бы реализовать - там несколько 16-ти разрядных счетчиков и их можно каскадировать в 32 разрядные.



http://electronix.ru/forum/index.php?showtopic=29796&view=findpost&p=234466
Ответить | Ответить с цитатой | Цитировать
# Technician 09.03.2011 03:23
Отличная статья! Именно то, чем занимаюсь сейчас. Всвязи с этим есть несколько вопросов:
1. Можно ли величину программной задержки в 1 секунду снизить хотя бы до 0,5 секунды? Мне необходимо реализовать ПИД алгоритм для контроля частоты вращения двигателя, и за секунду частота может сильно "уплыть"
2. Необходимо измерять частоту одновременно с 2х устройств. Можно ли после получения стартовых Мнач и Nнач и завершающих пар Мкон и Nкон для одной частоты подключить к МК мультиплексором другую частоту?(идея с форума electronix.ru).
Ответить | Ответить с цитатой | Цитировать
# Pashgan 09.03.2011 22:18
1. Можно
2. Не пробовал, но думаю, что можно
Ответить | Ответить с цитатой | Цитировать
# Гость 12.03.2011 05:42
Здравствуйте. Статья понравилась. Несколько дополнений, если можно
-в выражение вычисления частоты правильнее вводить точно измеренное значение Fcpu генерации системы
резонатор+контроллер.
-согласно выражения определения абсолютной погрешности метода A_ERR>=Fx/(Fcpu *Tизмер.) десятые доли будут измеряться правильно до частоты Fx
Ответить | Ответить с цитатой | Цитировать
# Гость 12.03.2011 05:47
будут измеряться правильно до частоты Fx
Ответить | Ответить с цитатой | Цитировать
# Валентин 13.03.2011 17:46
Фух, с трудом но освоил. Спасибо за статью, очень благодарен!
Ответить | Ответить с цитатой | Цитировать
# kitekat 06.04.2011 03:48
В файлах timer.c есть описка в инициализации таймера Т1, а именно - вместо операции сдвига - знак "меньше" : TCCR1B=(0
Ответить | Ответить с цитатой | Цитировать
# Pashgan 17.09.2011 21:11
Да, мой косяк. Но по счастливой случайности на правильность работы он не влияет.
Ответить | Ответить с цитатой | Цитировать
# Zorkiy 23.08.2011 04:27
В статье, к данному методу вычисления частоты не сказано главное преимущество данного метода, это точность вычисления, которая составляет при измерении, ну к примеру сигнала частотой 1МГц, за время измерения 0,1 сек дать точность до 0,01 Гц и более. То есть с помощью данного метода за 0,1сек вы можете измерить сигнал 7999999,99Гц!!! Каким еще методом можно этого добиться?! Стандартным методом подсчета сигнала для такой точности понадобится считать 100сек!, а здесь измеряйте частоту хоть непрерывно, каждые 0,01сек или чаще.
Книга, где описываются алгоритмы: Касаткин А.С. Обработка сигналов частотных датчиков. – М.: Энергия, 1966. – 120 с.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 17.09.2011 21:10
Мне не удалось добиться такой точности
Ответить | Ответить с цитатой | Цитировать
# John Walker 20.09.2011 14:55
Цитирую Pashgan:
Мне не удалось добиться такой точности


У меня этот алгоритм работает так, как заявлено автором с сайта electronix.ru
Ответить | Ответить с цитатой | Цитировать
# DM 01.10.2011 05:37
Сначала я тоже считал кол-во входных импульсов за определенный интервал времени, но при низких частотах-от 10 до 100 гц-быстродейств ие моего девайса уже будет никакой, поэтому я решил чситать время между импульсами,так уже нормально, импульсы поступают на вход внешнего прерывания, а таймер считает время между прерываниями.Пр остейший код- 3 строки.
Код: // External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
a=1; // при поступлении импульса
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
tik++; if(a){chast=tik; tik=0; a=0;} //измеряем время между импульсами
}

Ftek=(2600/(chast/12))*60; //переводим в об/мин
Ответить | Ответить с цитатой | Цитировать
# Roger 25.02.2012 11:20
Цитирую DM:

Код: // External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
a=1; // при поступлении импульса
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
tik++; if(a){chast=tik; tik=0; a=0;} //измеряем время между импульсами
}

Ftek=(2600/(chast/12))*60; //переводим в об/мин

Поясните формулу?И с какой частотой у вас прерывание TIM0_OVF
Ответить | Ответить с цитатой | Цитировать
# pitato 19.10.2011 07:15
pitato/ Здравствуйте. А как перевести программу на ATMEGA16? Не могу найти 8535.
Ответить | Ответить с цитатой | Цитировать
# Dmitrii 01.12.2011 20:42
Как должны быть прошиты fuze bits?
Ответить | Ответить с цитатой | Цитировать
# GM 04.12.2011 12:56
Ещё один вариант программы частотомера на си http://electronix.ru/forum/index.php?showtopic=77251&st=30
Ответить | Ответить с цитатой | Цитировать
# Слава 25.12.2011 18:16
Скажите пожалуйста, а фьюз биты как выставить?
Ответить | Ответить с цитатой | Цитировать
# Слава 25.12.2011 18:17
Некоректно спросил, какие выставить и в какие состояния?
Ответить | Ответить с цитатой | Цитировать
# SeNiMal 05.11.2012 16:18
В схеме проекта Proteus к данной статье показано подсоединение генератора частоты к ножкам PD6(ICP1) и PB0(T0). Разве недостаточно подключить генератор только к PD6(ICP1)?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.11.2012 21:12
Недостаточно. В этом алгоритме вычисления частоты используется и вход захвата таймера Т1 и тактовый вход таймера Т0. Объяснение алгоритма в статье.
Ответить | Ответить с цитатой | Цитировать
# SeNiMal 07.11.2012 07:22
Спасибо! Разобрался.
Ответить | Ответить с цитатой | Цитировать
# TRON 20.11.2012 23:25
Не понял смысла в дополнительных программных счетчиках, которые заполняются при прерываниях. Они физически получается в микроконтроллер е не существуют? И как их указать в программе?
Объясните пожалуйста чайнику).
Ответить | Ответить с цитатой | Цитировать
# Pashgan 23.11.2012 21:16
Разрядности аппаратных счетчиков не хватает для подсчета числа импульсов. Поэтому используются дополнительные переменные, которые считают число переполнений аппаратных таймеров. Физически они существуют только в виде ячеек оперативной памяти. Указываются (объявляются) как обычные переменные.
Ответить | Ответить с цитатой | Цитировать
# DmAlex 06.01.2013 13:07
Спасибо автору за статью и ее разжевывание.
У себя большие частоты от 32кГц до 4Мгц я не мерил и естественно не знаю погрешность измерений, но когда измерял частоту в 4096Гц с ds1307 погрещность у меня составила 1,5%(4030 - 4110). Возможно при больших частотах измерений она будет составлять меньше.
Ответить | Ответить с цитатой | Цитировать
# Vadis 25.03.2013 12:00
Запустил этот частотомер на Mege128 на 7.3728 мгц. Возникли вопросы с точностью результатов, в проекте протеуса в приложении частота считается точно, но если перемножить показания счетчиков по формуле то видна ошибка в 4 гц на 4 кГц то есть одна тысячная, когда я повторил алгоритм то получил ту же ошибку, она вполне компенсируется но проблеа в том что у меня она постоянна до 60 кГц. На частотах выше она возрастает до 100 Гц. в общем случае у меня частотомер работал до частоты в 2 МГц. Думаю как оптимальнее скомпенсировать ошибку.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 25.03.2013 20:48
Надо разобраться откуда она берется. У меня не удалось добиться заявленной точности метода. Может я где-то допустил ошибку.
Ответить | Ответить с цитатой | Цитировать
# Vadis 25.03.2013 12:07
Да и забыл сказать большое спасибо за сайт и за материалы.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 25.03.2013 20:49
Пожалуйста.
Ответить | Ответить с цитатой | Цитировать
# Vadis 25.03.2013 21:29
Сегодня пытался найти закономерность, но так и не смог, частотомер является частью прибора в котором стоят еще 2 синтезатора, так что проблемы формирования эталонной частоты у меня нет, сначала делал ради освоения синтезаторов, теперь пытаюсь довести это до полноценного прибора. надеюсь доведу.
Ответить | Ответить с цитатой | Цитировать
# SeNiMal 26.03.2013 05:01
Алгоритм теоретически отличный, но на практике его мне реализовать не удалось, т.к. нет повторяемости результатов даже в Proteus. Большая полемика по этой теме шла на electronix.ru, но работающего кода так никто и не представил. Пришлось ставить медианный фильтр для отбрасывания "выбросов". Но это заказчику не понравилось. Пришлось вернуться на старый алгоритм.
Ответить | Ответить с цитатой | Цитировать
# foxit 20.04.2013 13:23
Цитирую Vadis:
Сегодня пытался найти закономерность, но так и не смог, частотомер является частью прибора в котором стоят еще 2 синтезатора, так что проблемы формирования эталонной частоты у меня нет, сначала делал ради освоения синтезаторов, теперь пытаюсь довести это до полноценного прибора. надеюсь доведу.

Расскажите подробнее про ваш прибор
Ответить | Ответить с цитатой | Цитировать
# Vadis 20.04.2013 20:56
В общем то тайны не делаю, задача была освоение синтезаторов, в результате получилась неплохая заготовка которой чуть не хватает до полезного прибора, причем если павел не будет возражать т можно его опубликовать здесь, я готов предоставить черновик(чистов ик статьи + исходники и фото) вкратце что получилось, проц авр64 + dds AD9834 + DDS AD9850 + индикатор 16x2 + Энкодер + частотомер отсюда, тестовый прототип на протеусе, сейчас я это собрал в конструктив, на очереди управления уровнем сигнала DDS (уже решено) ну и отображение уровня на индикаторе, + интерфейс с компом, это пока откладывается, хотя сложностей нет, просто некогда.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 22.04.2013 19:53
Цитата:
причем если павел не будет возражать т можно его опубликовать здесь
Я только за.
Ответить | Ответить с цитатой | Цитировать
# foxit 25.04.2013 11:35
Цитирую Pashgan:
Цитата:
причем если павел не будет возражать т можно его опубликовать здесь

Я только за.
Ждем появления интересной статьи!
Ответить | Ответить с цитатой | Цитировать
# foxit 21.04.2013 03:43
Цитирую Vadis:
если павел не будет возражать т можно его опубликовать здесь, я готов предоставить черновик(чистовик статьи + исходники и фото)


+1
Ответить | Ответить с цитатой | Цитировать
# Vadis 25.04.2013 18:36
Статья в процессе написания, но фотки смогу сделать когда дома появлюсь те после 10го
Ответить | Ответить с цитатой | Цитировать
# Pashgan 19.08.2013 21:55
Сорвалась статья (
Ответить | Ответить с цитатой | Цитировать
# Novomatik 28.09.2013 10:07
Для чего выводы DOWN UP и ENTER на принципиальной схеме? Их использование в программе я не нашел, они лишние?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 28.09.2013 20:04
Да. Рисуя эту схему, взял одну из старых и забыл убрать эти цепи.
Ответить | Ответить с цитатой | Цитировать
# _lex 12.11.2014 13:22
хочу сделать частотомер для 220В на stm8. Будет ли нормально работать вход с обвязкой как http://www.atmel.com/images/doc2508.pdf , или надо ставить защитные диоды и снаружи?
Ответить | Ответить с цитатой | Цитировать
# Nikolayyyy 07.09.2015 20:46
Так как счетчик Т1 не асинхронный, накопится погрешность из-за схемы захвата входного сигнала, проще взять 4 8битных двоичных счетчика + регистр сдвига, запускать все это от высокоточного секундного генератора, в паузе перегонять данные из счетчиков по 2 проводному послед. интерфейсу в микроконтроллер .
Ответить | Ответить с цитатой | Цитировать
# ptol 27.09.2015 22:12
Запустил на Mega8(кварц на 14.7456МГц) Работает отлично правда только до 2МГц, оно и понятно, т.к. система захвата съедает 2,5такта (это по даташиту). Проверить на точном генераторе пока не было возможности, но показания стабильны. Программу писал сам на асемблере (моя певая на асемблере). Результатом доволен. Алгоритм отличный
Ответить | Ответить с цитатой | Цитировать
# Boussel 10.04.2016 10:48
Уважаемый админ, подскажите, почему прошивка cymometer.hex из chastotomer-pro teus на частоте 10 кГц считает правильно(часто та-0009999.7, число тиков-16013131) , а прошивка из chastotomer-cv- avr считает с погрешностью (частота-000996 2.9, число тиков-16021335) ?
Ответить | Ответить с цитатой | Цитировать
# plotik 07.10.2016 10:09
bcd.c +48 для чего?
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий

Защитный код
Обновить