Оглавление:
- Шаг 1. Подсчет частот по старинке
- Шаг 2: Взаимный путь
- Шаг 3: Оборудование и его схема
- Шаг 4: Код
- Шаг 5: точность и прецизионность
Видео: Частотомер высокого разрешения: 5 шагов (с изображениями)
2024 Автор: John Day | [email protected]. Последнее изменение: 2024-01-30 11:48
В этом руководстве показан обратный частотомер, способный измерять частоты быстро и с разумной точностью. Он сделан из стандартных компонентов и может быть изготовлен за выходные (у меня это заняло немного больше времени:-))
РЕДАКТИРОВАТЬ: код теперь доступен в GitLab:
gitlab.com/WilkoL/high-resolution-frequency-counter
Шаг 1. Подсчет частот по старинке
Старый школьный способ измерения частоты сигнала состоит в том, чтобы использовать логический элемент И, подавать измеряемый сигнал в один порт, а сигнал с точным временем задержки в 1 секунду - на другой порт и подсчитывать выходной сигнал. Это довольно хорошо работает для сигналов с частотой от нескольких кГц до ГГц. Но что, если вы хотите измерить низкочастотный сигнал с хорошим разрешением? Допустим, вы хотите измерить частоту сети (здесь 50 Гц). Используя старый метод, вы увидите постоянное значение 50 на вашем дисплее, если вам повезет, но более вероятно, что вы увидите переключение дисплея с 49 на 50 или с 50 на 51. Разрешение составляет 1 Гц, и все. Вы никогда не увидите 50,002 Гц, если не захотите увеличить время стробирования до 1000 секунд. Это более 16 минут для одного измерения!
Лучший способ измерить низкочастотные сигналы - измерить их период. Возьмем, к примеру, сеть, период 20 миллисекунд. Возьмите тот же логический элемент И, подайте на него, скажем, 10 МГц (импульсы 0,1 мкс) и ваш сигнал на другой порт, и на выходе получится 200000 импульсов, поэтому время периода составляет 20000,0 мкс, и это переводится обратно в 50 Гц. Когда вы измеряете всего 199650 импульсов, частота составляет 50,087 Гц, это намного лучше, и время измерения составляет всего одну секунду. К сожалению, это плохо работает с более высокими частотами. Возьмем, к примеру, сейчас мы хотим измерить 40 кГц. При той же входной частоте 10 МГц, что и эталон, мы теперь измеряем всего 250 импульсов. При подсчете всего 249 импульсов расчет дает 40161 Гц, а при 251 - 39840 Гц. Это неприемлемое разрешение. Конечно, увеличение опорной частоты улучшает результаты, но есть предел того, что вы можете использовать в микроконтроллере.
Шаг 2: Взаимный путь
Решением, которое работает как для низких, так и для высоких частот, является обратный частотомер. Я попытаюсь объяснить его принцип. Вы начинаете со времени измерения, которое составляет примерно 1 секунду, оно не обязательно должно быть очень точным, но это разумное время для измерения. Подайте этот сигнал с частотой 1 Гц на D-триггер на D-входе. На выходе (ах) пока ничего не происходит. Подключите сигнал, который вы хотите измерить, ко входу CLOCK D-триггера.
Как только этот сигнал переходит с НИЗКОГО на ВЫСОКИЙ, выход D-триггера передает состояние входа D на выход (Q). Этот восходящий сигнал используется для начала отсчета входного сигнала, а также опорного тактового сигнала.
Таким образом, вы подсчитываете ДВА сигнала в одно и то же время: сигнал, который вы хотите измерить, и опорные часы. Эти опорные часы должны иметь точное значение и быть стабильными, нормальный кварцевый генератор подойдет. Значение не очень важно, если это высокая частота и его значение хорошо известно.
Через некоторое время, скажем, через несколько миллисекунд, вы снова сделаете D-вход D-триггера низким. При следующем вводе ЧАСОВ выход Q следует за состоянием входа, но больше ничего не происходит, потому что микроконтроллер настроен так, чтобы реагировать только на сигнал RISING. Затем, по истечении времени измерения (примерно 1 секунда), вы устанавливаете D-вход HIGH.
Опять же, за следующим входом ЧАСОВ следует выход Q, и этот сигнал RISING запускает микроконтроллер, на этот раз для завершения счета обоих счетчиков.
Результат - два числа. Первое число - это количество импульсов, отсчитываемых от эталона. Поскольку мы знаем опорную частоту, мы также знаем время, которое потребовалось для подсчета этих импульсов.
Второе число - это количество импульсов входного сигнала, который мы измеряем. Поскольку мы начали именно с НАРАЩАЮЩИХСЯ фронтов этого сигнала, мы очень уверены в количестве импульсов этого входного сигнала.
Теперь это просто расчет для определения частоты входного сигнала.
Например, допустим, у нас есть эти сигналы, и мы хотим измерить f-вход. Опорная частота составляет 10 МГц, генерируется кварцевым генератором. f_input = 31,416 Гц f_reference = 10000000 Гц (10 МГц), время измерения составляет прибл. 1 секунда
За это время мы насчитали 32 импульса. Теперь один период этого сигнала занимает 1 / 31,416 = 31830,9 мкс. Таким образом, 32 периода заняли 1,0185892 секунды, что чуть больше 1 секунды.
За эти 1,0186 секунды мы также посчитаем 10185892 импульса опорного сигнала.
Это дает нам следующую информацию: input_count = 32 reference_count = 10185892 f_reference = 10000000 Гц
Формула для вычисления результирующей частоты следующая: freq = (input_count * f_reference) / ref_count
В нашем примере это: f-input = (32 * 10000000) / 10185892 = 31,416 Гц
И это хорошо работает как для низких, так и для высоких частот, только когда входной сигнал приближается (или даже превышает) к опорной частоте, лучше использовать стандартный "стробированный" способ измерения. Но тогда мы могли бы просто добавить к входному сигналу делитель частоты, так как этот обратный метод имеет одинаковое разрешение для любой частоты (снова до эталона). Таким образом, независимо от того, измеряете ли вы 100 кГц напрямую или делите его на внешний делитель 1000x, разрешение остается одинаковым.
Шаг 3: Оборудование и его схема
Я сделал несколько таких частотомеров. Давным-давно я сделал один с ATMEGA328 (тот же контроллер, что и в Arduino), позже с микроконтроллерами ARM от ST. Последний был сделан на STM32F407 с тактовой частотой 168 МГц. Но теперь мне стало интересно, что, если я сделаю то же самое с * гораздо * меньшим * размером. Я выбрал ATTINY2313, у которого всего 2 Кбайт флэш-памяти и 128 байт ОЗУ. У меня есть дисплей MAX7219 с 8 семисегментными дисплеями на нем, эти дисплеи доступны на Ebay всего за 2 евро. ATTINY2313 можно купить примерно за 1,5 евро, остальные детали, которые я использовал, стоят всего центов за штуку. Самой дорогой была, наверное, пластиковая коробка проекта. Позже я решил заставить его работать от литий-ионного аккумулятора, поэтому мне нужно было добавить стабилизатор напряжения (LDO) 3,3 В, модуль зарядки аккумулятора и сам аккумулятор. Это несколько увеличивает цену, но я думаю, что его можно построить менее чем за 20 евро.
Шаг 4: Код
Код был написан на C с помощью Atmel (Microchip) Studio 7 и запрограммирован в ATTINY2313 с использованием OLIMEX AVR_ISP (клон?). Откройте (main.c) в zip-файле ниже, если вы хотите следовать приведенному здесь описанию.
ИНИЦИАЛИЗАЦИЯ
Сначала ATTINY2313 был настроен на использование внешнего кварцевого резонатора, поскольку внутренний RC-генератор бесполезен для каких-либо измерений. Я использую кристалл 10 МГц, который настраиваю на правильную частоту 10 000 000 Гц с небольшим переменным конденсатором. Инициализация заботится о настройке портов на входы и выходы, настройке таймеров, разрешении прерываний и инициализации MAX7219. TIMER0 настроен для подсчета внешних часов, TIMER1 - внутренних часов, а также для захвата значения счетчика на переднем фронте ICP, поступающего от D-триггера.
В последнюю очередь я буду обсуждать основную программу, а затем перейдем к процедурам прерывания.
TIMER0_OVF
Поскольку TIMER0 считает до 255 (8 бит), а затем возвращается к 0, нам нужно прерывание для подсчета количества переполнений. Это все, что делает TIMER0_OVF, просто посчитайте количество переполнений. Позже это число совмещается со значением самого счетчика.
TIMER1_OVF
TIMER1 может подсчитывать до 65536 (16 бит), поэтому прерывание TIMER1_OVF также подсчитывает количество переполнений. Но это еще не все. Он также уменьшается со 152 до 0, что занимает около 1 секунды, а затем устанавливает выходной контакт, идущий на вход D триггера. И последнее, что делается в этой подпрограмме прерывания, - это уменьшение счетчика тайм-аута с 765 до 0, что занимает около 5 секунд.
TIMER1_CAPT
Это прерывание TIMER1_CAPT, которое запускается каждый раз, когда D-триггер посылает ему сигнал по нарастающему фронту входного сигнала (как объяснено выше). Логика захвата заботится о сохранении значения счетчика TIMER1 в момент захвата, оно сохраняется, как и счетчик переполнения. К сожалению, TIMER0 не имеет функции захвата ввода, поэтому здесь читается его текущее значение и текущее значение счетчика переполнения. Переменная сообщения устанавливается в единицу, чтобы основная программа сообщала ей, что это новые данные.
Далее следуют две функции для управления MAX7219.
SPI
Хотя в чипе есть универсальный последовательный интерфейс (USI), я решил не использовать его. Дисплей MAX7219 должен управляться через SPI, и это возможно с помощью USI. Но битбэнговый SPI настолько прост, что я не нашел времени на то, чтобы сделать это с помощью USI.
MAX7219
Протокол для настройки MAX7219 также довольно прост, если вы прочитали его руководство. Для каждой цифры требуется 16-битное значение, состоящее из 8 бит для номера цифры (от 1 до 8), за которым следуют 8 бит для числа, которое необходимо отобразить.
ГЛАВНАЯ ПРОГ
Последнее, что нужно объяснить основной программе. Он работает в бесконечном цикле (while (1)), но на самом деле что-то делает только тогда, когда есть сообщение (1) из подпрограммы прерывания или когда счетчик тайм-аута опустился до нуля (нет входного сигнала).
Первое, что нужно сделать, когда переменная message установлена в единицу, - это сбросить счетчик тайм-аута, ведь мы знаем, что сигнал присутствует. D-триггер сбрасывается, чтобы подготовить его к следующему триггеру, который произойдет по истечении времени измерения (подождите-секунду).
Числа, зарегистрированные в прерывании захвата, складываются, чтобы получить счетчик ссылок и счетчик входной частоты. (мы должны убедиться, что ссылка никогда не может быть равна нулю, поскольку мы разделим ее позже)
Далее идет расчет фактической частоты. Я определенно не хочу использовать числа с плавающей запятой на микроконтроллере всего с 2 кбайт флеш-памяти и только 128 байт оперативной памяти. Я использую целые числа. Но частоты могут быть вроде 314,159 Гц с несколькими десятичными знаками. Поэтому я умножаю входную частоту не только на опорную частоту, но и на множитель, а затем добавляю число к месту, где должна располагаться десятичная точка. Когда вы это сделаете, эти числа станут очень большими. Например. при входной частоте 500 кГц, опорной частоте 10 МГц и множителе 100 это дает 5 x 10 ^ 14, что действительно огромно! Они не подходят для 32-битного числа, поэтому я использую 64-битные числа, которые будут до 1,8 x 10 ^ 19 (что отлично работает на ATTINY2313)
И последнее, что нужно сделать, это отправить результат на дисплей MAX7219.
Код компилируется примерно в 1600 байт, поэтому он умещается во флеш-память размером 2048 байт, доступную в ATTINY2313.
Регистры предохранителей должны выглядеть так:
РАСШИРЕННЫЙ 0xFF
ВЫСОКИЙ 0xDF
НИЗКИЙ 0xBF
Шаг 5: точность и прецизионность
Точность и аккуратность - два разных зверя. Точность здесь составляет семь цифр, а фактическая точность зависит от оборудования и калибровки. Я откалибровал 10 МГц (5 МГц на контрольной точке) с помощью другого частотомера, у которого есть осциллятор с привязкой к GPS.
И работает неплохо, самая низкая частота, которую я пробовал, - 0,2 Гц, максимальная - 2 МГц. Это на месте. Выше 2 МГц контроллер начинает терять прерывания, что неудивительно, если вы знаете, что при входном сигнале 2 МГц TIMER0 генерирует более 7800 прерываний в секунду. И ATTINY2313 должен делать и другие вещи, прерывания от TIMER1, еще 150 прерываний в секунду и, конечно же, выполнять вычисления, управляя дисплеем и D-триггером. Когда вы посмотрите на реальное устройство, вы увидите, что я использую только семь из восьми цифр дисплея. Я делаю это по нескольким причинам.
Во-первых, вычисление входной частоты - это деление, оно почти всегда будет иметь остаток, который вы не видите, поскольку это целочисленное деление. Во-вторых, кварцевый генератор не имеет температурной стабилизации.
Конденсаторы, которые настраивают его на правильную частоту 10 МГц, керамические, очень чувствительные к перепадам температуры. Кроме того, в TIMER0 нет встроенной логики захвата, и всем функциям прерывания требуется некоторое время для выполнения своей работы. Я думаю, что семи цифр достаточно.
Рекомендуемые:
Простой частотомер с использованием Arduino: 6 шагов
Простой счетчик частоты с использованием Arduino: в этом уроке мы узнаем, как сделать простой счетчик частоты с помощью Arduino. Посмотрите видео
Частотомер с Arduino: 8 шагов (с изображениями)
Счетчик частоты с Arduino: это простой и дешевый счетчик частоты на базе Arduino стоимостью менее 4 долларов, он очень полезен для измерения небольших цепей
Веб-камера высокого разрешения: 9 шагов (с изображениями)
Веб-камера высокого разрешения: в течение нескольких лет я использовал веб-камеру на базе RPi (с модулем PiCam). Создаваемые изображения были в порядке, но затем наступил момент, когда качество меня больше не устраивало. Решил сделать веб-камеру высокого разрешения. Следующие части
Генерация ШИМ-сигнала высокого разрешения для сервоприводов RC с устройствами STM32: 3 шага
Генерация ШИМ-сигналов высокого разрешения для сервоприводов RC с устройствами STM32. В настоящее время я создаю передатчик / приемник RC на основе радиочастотного чипа SX1280. Одна из целей проекта состоит в том, чтобы я хотел получить 12-битное разрешение сервоприводов от стиков до сервоприводов. Отчасти потому, что современные цифровые сервоприводы имеют 12-битное разрешение
Как снять свой независимый фильм в метро Нью-Йорка, когда у вас нет разрешения: 12 шагов
Как снять свой независимый фильм в метро Нью-Йорка, когда вы не можете позволить себе разрешения: это простое руководство для начинающих независимых режиссеров, которые мечтают снять эту волшебную сцену в прекрасной системе метро Нью-Йорка, но которые не может позволить себе тысячи долларов, необходимых для получения разрешения на легальную стрельбу