Теория работы частотомера

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

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

Код: Выделить всё

//----------------------------------------------------------------------------

//Модуль измерения частоты сигнала

//----------------------------------------------------------------------------

#include "Main.h"
#include "Count.h"

//--------------------------- Константы: -------------------------------------

#define COMPL_TM 10 //время на завершение измерения, * T_SYS
#define PRESCALER 4 //коэффициент деления входного прескалера

enum { ST_STOP, ST_START, ST_COUNT, ST_COMPL, ST_READY };

//--------------------------- Переменные: ------------------------------------

static char State;     //текущее состояние частотмера
static int  Interval;  //длительность интервала, * T_SYS
static bool Ready;     //флаг готовности частотомера
static long Count_N;   //количество входных периодов
static char Count_M;   //количество переполнений опорного счетчика
static unsigned int Tb, Te; //захваченные в начале и в конце значения
static long Freq;      //измеренная частота

//-------------------------- Прототипы функций: ------------------------------

#pragma vector = TIMER1_CAPT_vect
__interrupt void Capture(void);   //прерывание по захвату
#pragma vector = TIMER1_OVF_vect
__interrupt void Overflow(void);  //прерывание по переполнению
void Count_Clear(void);           //очистка счетчиков
void Get_Freq(void);              //вычисление частоты

//---------------- Инициализация модуля измерения частоты: -------------------

void Count_Init(void)
{
  //запрещение аналогового компаратора:
  ACSR = (1 << ACD);
  //разрешение таймера 1, CK/1:
  TCCR1B = (1 << CS10);             
  //очистка отложенных прерываний:
  TIFR = (1 << TOV1) | (1 << ICF1);
  //разрешение прерываний по захвату и переполнению:
  TIMSK |= (1 << TOIE1) | (1 << TICIE1);
  
  Interval = 100;  //начальный интервал измерения
  State = ST_STOP; //счет остановлен
}

//----------------------- Процесс измерения частоты: -------------------------

void Count_Exe(bool t)
{
  static int IntervTm = 0;
  if(t)
  {
    if(IntervTm) IntervTm--;
  }
  Ready = 0;                            //сброс флага готовности
  switch(State)
  {
  case ST_COUNT: if(!IntervTm)          //если интервал закончился,
                 { IntervTm = COMPL_TM; //загрузка интервала завершения счета
                   State = ST_COMPL; }  //процесс завершения счета
                 break;
  case ST_COMPL:
  case ST_START: if(IntervTm) break;    //если интервал не закончился, ждем,
                 State = ST_READY;      //иначе прекращаем ожидание
                 Count_Clear();         //частота равна нулю
  case ST_READY: Get_Freq();            //вычисление частоты
                 Ready = 1;             //установка флага готовности
  case ST_STOP:  Count_Clear();         //очистка счетчиков
                 IntervTm = Interval;   //загрузка нового интервала
                 State = ST_START;      //запуск измерения
                 break;
  }
}

//------------------------ Прерывание по захвату: ----------------------------

#pragma vector = TIMER1_CAPT_vect
__interrupt void Capture(void)
{
  switch(State)
  {
  case ST_START:        //фаза запуска измерения
    {
      Tb = ICR1;        //захват начала интервала
      if(!(Tb & 0x8000) && (TIFR & (1 << TOV1)))
        Count_M--;      //коррекция, если переполнение было до захвата
      State = ST_COUNT; //следующая фаза - фаза счета
      break;
    }
  case ST_COUNT:        //фаза счета
    {
      Count_N++;        //счет периодов входного сигнала
      break;
    }
  case ST_COMPL:        //фаза завершения измерения
    {
      Te = ICR1;        //захват конца интервала
      if(!(Te & 0x8000) && (TIFR & (1 << TOV1)))
        Count_M++;      //коррекция, если переполнение было до захвата
      Count_N++;        //счет последнего периода
      State = ST_READY; //следующая фаза - фаза готовности
      break;
    }
  }
}

//---------------------- Прерывание по переполнению: -------------------------

#pragma vector = TIMER1_OVF_vect
__interrupt void Overflow(void)
{
  if(State == ST_COUNT || State == ST_COMPL)
    Count_M++; //счет переполнений
}

//--------------------------- Очистка счетчиков: -----------------------------

void Count_Clear(void)
{
  Count_N = 0;
  Count_M = 0;
  Tb = 0;
  Te = 0;
}

//-------------------------- Вычисление частоты: -----------------------------

void Get_Freq(void)
{
  long m = (long)Count_M  * 65536L + Te - Tb; //интервал
  if(m)
    Freq = (long long)Count_N * (F_CLK * 1E8 * PRESCALER) / m ;
      else Freq = 0;
  if(Freq > 99999999) Freq = 99999999; //ограничение частоты
}

//----------------- Установка интервала измерения частоты: -------------------

void Count_SetT(int t)
{
  State = ST_STOP;
  Interval = t;
}

//--------------------- Чтение готовности частотомера: -----------------------

bool Count_Ready(void)
{
  return(Ready);
}

//----------------------- Чтение измеренной частоты: -------------------------

long Count_GetF(void)
{
  return(Freq);
}

//----------------------------------------------------------------------------
Реклама
Аватара пользователя
Ghost in shell
Держит паяльник хвостом
Сообщения: 936
Зарегистрирован: Пн июн 15, 2009 06:01:38
Откуда: USSR

Re: Теория работы частотомера

Сообщение Ghost in shell »

А почему 5 периодов входного сигнала?
Если порекомендуете число получше, я сделаю.
Нужно измерять столько, сколько укладывается в заданный интервал измерения.
Это как? Зачем мерять с привязкой к времени, если можно к количеству измеряемых импульсов и опорной частоте?
Не знаю, что это за язык, на С непохоже. Впрочем, я с макросами не работал.
А для измерения длительности этого количества периодов, нужно использовать функцию захвата таймера.
А на какой параметр настраивать захват? На какое-то количество измеряемых импульсов? Возможно, так правильнее, но что в лоб, что по лбу.
Кот гуляет сам по себе, но вблизи холодильника.
Реклама
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

Ghost in shell писал(а):Если порекомендуете число получше, я сделаю.
Нет какого-то определенного числа. Это число зависит от измеряемой частоты.
Ghost in shell писал(а):Это как? Зачем мерять с привязкой к времени, если можно к количеству измеряемых импульсов и опорной частоте?
Если интервал измерения будет постоянный (а не постоянное число входных периодов), то и относительная погрешность измерения будет тоже постоянной. Что и требуется. Я же давал ссылки на теорию метода. Да и в сети материала полно насчет "Reciprocal Counting". Если Вам лень прочитать, то никогда не будете уметь строить хорошие частотомеры.
Ghost in shell писал(а):Не знаю, что это за язык, на С непохоже.
Мой пример на Си. Это фрагмент программы устройства стабилизации частоты лазера путем регулировки температуры резонатора.
Ghost in shell писал(а):А на какой параметр настраивать захват? На какое-то количество измеряемых импульсов? Возможно, так правильнее, но что в лоб, что по лбу.
Из исходника всё ясно. Начинаем процесс измерения. Захватываем текущее значение таймера - это время начала измерения Tb. При следующих событиях захвата увеличиваем на единицу число входных импульсов Count_N. При этом параллельно считаем количество переполнений таймера Count_M. Когда желаемое время измерения истечет, производим последний захват. Он даст время окончания измерения Te. Частота вычисляется по формуле А = Count_N * F_CLK / (Count_M * 65536 + Te - Tb). Если не использовать захват, я не знаю, как точно измерить длительность импульсов входной частоты.
Аватара пользователя
Ghost in shell
Держит паяльник хвостом
Сообщения: 936
Зарегистрирован: Пн июн 15, 2009 06:01:38
Откуда: USSR

Re: Теория работы частотомера

Сообщение Ghost in shell »

Ничегонеработает
Спасибо за пояснения. Но вопросы есть:
При следующих событиях захвата увеличиваем на единицу число входных импульсов Count_N
Проблема в том, что в PIC16 таймер захватывает или 4-й, или 16-й импульс (точнее, его передний фронт). Что же считаем в Count_N: события захвата, или входные импульсы?
F_CLK - опорная частота? 65536 - это значение переполнения таймера? Результат получаем в герцах?
Кот гуляет сам по себе, но вблизи холодильника.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

Ghost in shell писал(а):Проблема в том, что в PIC16 таймер захватывает или 4-й, или 16-й импульс (точнее, его передний фронт).
Увы, с архитектурой PIC не знаком, хотя всё это кажется весьма странным. А почему схема захвата не может срабатывать по каждому фронту входного сигнала? Там что, прескалер на входе? Если так, то просто нужно будет результат измерения частоты умножить на коэффициент деления этого прескалера.
Ghost in shell писал(а):Что же считаем в Count_N: события захвата, или входные импульсы?
В моем случае это одно и то же.
Ghost in shell писал(а):F_CLK - опорная частота?
Да, это частота, на которой работает таймер.
Ghost in shell писал(а):65536 - это значение переполнения таймера?
Верно. Это "емкость" 16-разрядного счетчика.
Ghost in shell писал(а):Результат получаем в герцах?
Результат получаем в тех единицах, в которых задана константа F_CLK. Поскольку я использовал целочисленную арифметику, то в формулу добавил масштабирующий коэффициент (см. мой исходник), чтобы получить результат в сотых долях герца (так нужно было в том проекте). В общем случае можно масштаб выбрать любой, ну или вообще считать во float.
Реклама
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: Теория работы частотомера

Сообщение clawham »

можно и другой вариант использовать!
не знаю как ПИКи ...а АВР при вызове прерывания всегда тормозит на 11 тактов
этим и можно воспользоваться

запускаем таймер на системной частоте, делаем ему прерывание по переполнению, где инкрементируем дополнительный счетчик переполнений

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

ну и сбрасываете флаг результат готов

а если частота перевалила за 1000 герц то вы вырубаете внешние прерывания, запускаете таймер на прерывание каждую 1/6 секунды и запускаете тот счетный таймер не от системного генератора работать а от внешнего события тактоваться
в каждом прерывании по 1/6 секунде вы записываете(снимаете) значение таймера тактующегося исследуемым сигналом и запоминаете его в ФИФО буффере (для красивого и плавного счета достаточно 12 значений)

когда конец буффера налезет на начало - выставляете флажек - результаты счета готовы и в основном цикле программы суммируете значения всех жлементов массива, делите на 2(если 12 элементов на каждый по 1/6 секунды)и минусуете 12 -=> и получаете частоту в герцах ...

вот собственно и всё...
при замере малых частот удобно было бы высчитывать промежуточный результат например от последнего импульса известно - частота была 0.1 герц ... вы ждали 10 секунд а импульса нет следовательно частота уже будет ниже 0.1 герц - берете и рассчитывете частоту не от реальной длительности между предпоследним и последним импульсами а системную частоту делите на текущее время прошедшее от последнего импульса ... время измеряется в системных тиках...
результат или серым шрифтом или морганием выводим на экран показывая что частота падает...
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Реклама
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: Теория работы частотомера

Сообщение clawham »

П.С. конечно же все вычисления нужно проводить во флоатах если не известно заранее диапазона частот...НО
помните что флоат коварная весч и я например столкнулся с тем что к числу 16000000000 в флоате нельзя прибавить 1
сколько бы раз не писалось float a+=1; в а всегда будет одно и то же ибо чтоб оно смогло записаться нужно прибьавлять уже не 1 а 2-3-4
для числа 4600000000чтоб его увеличить и запомнить в флоате нужно прибавлять не менее 10-ти....вот атк вот...аккуратнее...
встати лонгинт тоже всего 4600000000 число может запомнить....мне например и этой размерности не хватало...
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

clawham

Опять двадцать пять. Не первый раз уже встречаю упорное нежелание использовать метод Reciprocal Counting, который применяется во всех современных частотомерах. Уверен, что Вы просто не понимаете, как работает этот метод. Никакого анализа измеряемой частоты не нужно. Задаете желаемый измерительный интервал - и всё. Относительная погрешность измерения для любой частоты будет постоянной. А то, что Вы предлагаете, не даст точности. Без применения захвата нельзя точно померить период, так как задержка обработки прерывания не постоянна, она зависит от типа выполняющейся команды на момент возникновения прерывания. Я уже молчу о других прерываниях.
Аватара пользователя
Ghost in shell
Держит паяльник хвостом
Сообщения: 936
Зарегистрирован: Пн июн 15, 2009 06:01:38
Откуда: USSR

Re: Теория работы частотомера

Сообщение Ghost in shell »

Прочитал я
Метод "обратного отсчета" (измерения периода) описан у Хоровца и Хилла в Искусстве схемотехники.
У меня в трехтомнике это Том.3. раздел 15.10, стр.294-294.
(ежели кому надо, дам линки на книги.)
"входной сигнал (или некоторая его часть) используется для стробирования часов." Там же: "Число периодов измерения выбирают так, чтобы измерения занимали удобный отрезок времени". Так чем стробировать? Мутно сие...
А почему схема захвата не может срабатывать по каждому фронту входного сигнала?
Может. А зачем тогда захват вообще? Просто считаем импульсы.
Итак:
А = Count_N * F_CLK / (Count_M * 65536 + Te - Tb)
где:
Tb - значение таймера в начале измерения
Tе - значение таймера в конце измерения
Count_N - события захвата, или входные импульсы
Count_M - количество переполнений таймера
F_CLK - частота, на которой работает таймер.
65536 - значение переполнения таймера, его "емкость".
А - результат получаем в тех единицах, в которых задана константа F_CLK.

Период машинного цикла для Fosc = 4 MHz равен 1 микросекунде. А как время измерения выбирать? МК-то эквигинетально. У меня предвидятся обороты от 10 до 1000 в мин. И результат хочется в об/мин. А умножаем на 1.000.000 (перевод в секунды) и на 60 (перевод в минуты)?
Кот гуляет сам по себе, но вблизи холодильника.
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

Ghost in shell писал(а):"Число периодов измерения выбирают так, чтобы измерения занимали удобный отрезок времени"
Правильно сказано. Интервал измерения выбираем, как нам удобно. А сколько периодов входной частоты туда уместится - не имеет значения.
Ghost in shell писал(а):Так чем стробировать? Мутно сие...
Вы что, издеваетесь? Алгоритм измерения по шагам я описал тут: http://radiokot.ru/forum/viewtopic.php?p=888790#p888790
Ghost in shell писал(а):Может. А зачем тогда захват вообще? Просто считаем импульсы.
На первом и последнем импульсе захват нужен для определения Tb и Te. На всех других - не нужен, можно просто считать. Но как Вы предлагаете это делать, если не в прерывании по захвату?
Ghost in shell писал(а):А как время измерения выбирать?
Если таймер работает с периодом 1 мкс, то погрешность измерения в зависимости от интервала T будет равна T[сек]*1E-6.
Ghost in shell писал(а):У меня предвидятся обороты от 10 до 1000 в мин.
Т.е. измерение частоты от 0.167 до 16.7 Гц? Частота очень низкая, нормальные результаты будут и с простым измерением периода (погрешность будет не более 2E-5).
Ghost in shell писал(а):И результат хочется в об/мин.
Так в чем хотите, в том и получайте, всего-то выразить Fref в нужных Вам единицах.
Аватара пользователя
Ghost in shell
Держит паяльник хвостом
Сообщения: 936
Зарегистрирован: Пн июн 15, 2009 06:01:38
Откуда: USSR

Re: Теория работы частотомера

Сообщение Ghost in shell »

Интервал измерения выбираем, как нам удобно. А сколько периодов входной частоты туда уместится - не имеет значения.
А считать сей интевал как? По машинным циклам МК с помощью второго таймера? Опять же: какой временной интервал выбрать?
Вы что, издеваетесь? Алгоритм измерения по шагам я описал тут: viewtopic.php?p=888790#p888790
Вообще-то я имел в виде описание "Хоровца и Хилла". Неудивительно, что начитавшись подобного, мало кто смог применить этот метод!
На первом и последнем импульсе захват нужен для определения Tb и Te. На всех других - не нужен, можно просто считать. Но как Вы предлагаете это делать, если не в прерывании по захвату?
Ну не знаю... Можно конечно написать конвертор из 2-х байтного двоичного в десятичный формат. Захват имеет смысл только в одном случае: если у него выше приоритет перед простым счетом, т.е. результат будет точнее.
Кот гуляет сам по себе, но вблизи холодильника.
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

Ghost in shell писал(а):Ну не знаю... Можно конечно написать конвертор из 2-х байтного двоичного в десятичный формат. Захват имеет смысл только в одном случае: если у него выше приоритет перед простым счетом, т.е. результат будет точнее.
Вы успешно вынесли мой мозг. Успехов в творчестве.
Аватара пользователя
vsky
Открыл глаза
Сообщения: 63
Зарегистрирован: Пн апр 06, 2009 18:32:14

Re: Теория работы частотомера

Сообщение vsky »

Уважаемый Ничегонеработает не могли бы Вы показать логическую структуру ПЛИС из Вашего проекта http://radiokot.ru/forum/viewtopic.php?p=425206#p425206 в 74 логике (74HC590)?

заранее благодарен.
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Теория работы частотомера

Сообщение Леонид Иванович »

vsky писал(а):Уважаемый Ничегонеработает не могли бы Вы показать логическую структуру ПЛИС из Вашего проекта http://radiokot.ru/forum/viewtopic.php?p=425206#p425206 в 74 логике (74HC590)?
заранее благодарен.
Выслал в личку.
Аватара пользователя
Ghost in shell
Держит паяльник хвостом
Сообщения: 936
Зарегистрирован: Пн июн 15, 2009 06:01:38
Откуда: USSR

Re: Теория работы частотомера

Сообщение Ghost in shell »

Успехов в творчестве.
Это скорее следственные действия.
Кот гуляет сам по себе, но вблизи холодильника.
Аватара пользователя
vsky
Открыл глаза
Сообщения: 63
Зарегистрирован: Пн апр 06, 2009 18:32:14

Re: Теория работы частотомера

Сообщение vsky »

Ничегонеработает писал(а):
vsky писал(а):Уважаемый Ничегонеработает не могли бы Вы показать логическую структуру ПЛИС из Вашего проекта http://radiokot.ru/forum/viewtopic.php?p=425206#p425206 в 74 логике (74HC590)?
заранее благодарен.
Выслал в личку.
Огромное спасибо! Буду разбираться (учиться) :))
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»