Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Измерение частоты через АЦП
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
hd44780
Сделал прибор на ATMega16 - показывает напряжение, ток нагрузки, мощности разновсякие.... Сеть бытовая, 50 Гц.
Тут всё нормально работает. Спасибо участникам форума, которые ранее отвечали на мои вопросы.

Схема входного каскада - рис.

Вопрос - как можно померить частоту имея на входе АЦП поднятое на 2.5в напряжение сети 50 Гц.
Вообще-то оно совершенно не капает, ну так, интересно просто. Для полноты функционала так сказать ...

Сейчас я сделал так:
АЦП цифрует 20 раз за период (таймер 1khz = 1ms).
В обработчике прерывания написал:

// Миллисекунды
ms++;

// Проверка перехода через 0 (- -> +)
if (adcU>3)
{ // Положительная полуволна
if (isUNegative==1)
{ // Была отрицательная - переход
pulses++;

isUNegative = 0;
} // if
} // if
else // отрицательная полуволна
isUNegative = 1;

adcU - код со входа ADC1 за вычетом смещения ср. точки ADC0.
isUNegative - просто флаг, отслеживает переход синусоиды через 0.
pulses - кол-во переходов синусоиды вверх через 0.

Цикл измерений длится 0.5 сек (10 периодов).
Потом идёт обсчёт, в т.ч. и частоты:

// Частота
frequency = pulses*1000.0;
frequency/=ms;

frequency - частота в Гц, float.

pulses и ms считают постоянно, никогда не обнуляясь.

Проблема в том, что частота в итоге "плавает" где-то в интервале 49-51 Гц, хотя частотомер из осциллографа-мультиметра UT-81B показывает ровно 50 Гц. Да и сам я понимаю, что реально частота не может так гулять, она жёстко контролируется.

Читал соседнюю тему про частоту, например, эту - http://electronix.ru/forum/index.php?showt...=29796&st=0 , но у меня порт В, где все входы таймеров T0, T1 занят, там ШД дисплея HD44780 crying.gif .... Освободить могу, переведя дисплей в 4 бит режим работы с перебросом его целиком на PORTC, но я терпеть не могу 4 бит режим работы, глючный он какой-то. У меня так метеостанция работает (деваться было некуда), так там вечно на дисплее какая-то байда лезет. Библиотека для LCD там не самодельная, а стандартная, из CvAVR. Думал дисплей коцнутый, но на 8 бит работает идеально...
Отвлёкся я ...

PC6, PC7 свободны, но я не знаю, может ли TC2 считать внешние импульсы или он только под кварц часовой заточен ...

Можно, конечно, налепить внешний компаратор, счётчик, но это усложние схемы, доп. корпуса и пр....
Да и делает тот компаратор то же самое, что и мой программный счётчик...

Спасибо.

PS
Админам:
Кнопка CODEBOX не фурычит, валится ошибка -

Сообщение: Недопустимый аргумент.
Строка: 1225
Символ: 3
Код: 0
URI-код: http://electronix.ru/forum/jscripts/ips_text_editor.js

Смайлики вставляются нормально.
Браузер - IE8 со всеми обновлениями.
Винда - 2003 SP2 сервер лицензионный. Обновляется регулярно.
Оперу и пр. альтернативы не предлагать, у нас на работе запрещено biggrin.gif .
woroba
Так у Вас зазор 1mS, вот показания и плюшут. Попробуйте чаще запускать преобразования. А вообще лучше всего для этих целей использовать внешнее прерывание+таймер.
hd44780
Чаще запускать пытался, там другие проблемы были. Попробую ещё, на свежую голову.

INT0 реально освободить, попробую. Спасибо.
А туда выход какого-то компаратора сунуть? В наличии есль К554СА3. Пойдёт?
ILYAUL
QUOTE (hd44780 @ Oct 27 2011, 12:59) *
Чаще запускать пытался, там другие проблемы были. Попробую ещё, на свежую голову.

INT0 реально освободить, попробую. Спасибо.
А туда выход какого-то компаратора сунуть? В наличии есль К554СА3. Пойдёт?



A родной занят?
hd44780
Цитата(ILYAUL @ Oct 27 2011, 12:03) *
A родной занят?


Он не занят, но у него входы на PB, а этот порт занят - ШД LCD.
ILYAUL
QUOTE
В наличии есль К554СА3
Ну тогда его выход на INT0 и запускать таймер в прерывании. Из полученных данных надо будет вычесть , переходы в прерывание выход из него. Пишите его на asm - быстрее получится. Лучше усреднять полученные значения, скажем 16 значений - один раз показания. Выбирайте усреднение кратное 2 - сдвигом поделить проще , чем формулы писать.
hd44780
Цитата(ILYAUL @ Oct 27 2011, 12:26) *
Ну тогда его выход на INT0 и запускать таймер в прерывании.


Спасибо, попробуем. Только, наверное, в выходные. Прошиву я и на работе наклепаю, но по вечерам паять темновато.
Палыч
Цитата(hd44780 @ Oct 27 2011, 11:57) *
Цикл измерений длится 0.5 сек (10 периодов).

Цикл измерений лучше заканчивать не по времени, а по числу зафиксированных периодов измеряемой величины (например, 25), подсчитывая при этом интервал времени. Начало отсчета времени необходимо привязать к началу первого периода.
_pv
Так как частота примерно известна, то
Можно Герцелем посчитать амплитуды спектра на трех чатотах в районе 50Гц.
получим три точки (x1,y1), (x2,y2), (x3,y3), где х1,х2,х3 частоты, напрмер 49, 50, 51 Гц, а y1,y2,y3-амплитуды спектра на этой частоте
через них можно провести параболу y=a*x^2 + b*x + c.
и соответственно найти коэффициенты a,b,c
Mathematica подсказывает что это будет:
LinearSolve[{{x1^2, x1, 1}, {x2^2, x2, 1}, {x3^2, x3, 1}}, {y1, y2,y3}]

a = (x2 y1 - x3 y1 - x1 y2 + x3 y2 + x1 y3 - x2 y3)/((x1 - x2) (x1 - x3) (x2 - x3)),
b = (-x2^2 y1 + x3^2 y1 + x1^2 y2 - x3^2 y2 - x1^2 y3 + x2^2 y3)/((x1 - x2) (x1 - x3) (x2 - x3)),
c = (x2^2 x3 y1 - x2 x3^2 y1 - x1^2 x3 y2 + x1 x3^2 y2 + x1^2 x2 y3 - x1 x2^2 y3)/((x2 - x3) (x1^2 - x1 x2 - x1 x3 + x2 x3))

а если параболу y=a*x^2+b*x+c продиффернцировать, и приравнять нулю, то можно выяснить, что максимум у параболы находится в точке x0=-b/2a.
то есть
x0 = -(-x2^2*y1 + x3^2*y1 + x1^2*y2 - x3^2*y2 - x1^2*y3 + x2^2*y3)/(x2*y1 - x3*y1 - x1*y2 + x3*y2 + x1*y3 - x2*y3)/2
или, если немного упростить, то искомая частота будет:
x0= -((y1*(x3^2-x2^2) + y2*(x1^2-x3^2) + y3*(x2^2-x1^2))/(y1*(x2-x3)+y2*(x3-x1)+y3*(x1-x2))/2
вычислений не сильно много: Герцель - 3 умножения на отсчет для каждой частоты, т.е. 9,
да тут 6 умножений, деление и сдвиг. AVR поди справится. Тем более что последние вычисления частоты так можно вообще раз в секунду делать.




ILYAUL
QUOTE (_pv @ Oct 27 2011, 19:39) *
Можно Герцелем посчитать амплитуды спектра на трех чатотах в районе 50Гц.

Т.е три фильтра?
QUOTE (_pv @ Oct 27 2011, 19:39) *
да тут 6 умножений, деление и сдвиг. AVR поди справится. Тем более что последние вычисления частоты так можно вообще раз в секунду делать


Справится , только вот зачем.
hd44780
Во, чего я придумал - поставить туда ещё один МК - ATMega8 blink.gif w00t.gif и нагрузить её чем угодно.
Там и компаратор есть и всё остальное...
ILYAUL
QUOTE (hd44780 @ Oct 27 2011, 20:33) *
Во, чего я придумал - поставить туда ещё один МК - ATMega8 blink.gif w00t.gif и нагрузить её чем угодно.
Там и компаратор есть и всё остальное...

Поставь лучше тиньку biggrin.gif
_pv
Цитата(ILYAUL @ Oct 27 2011, 23:32) *
Т.е три фильтра?

не совсем.
я предлагаю посчитать спектр, но не полностью через Фурье потому что долго, а только в трех точках.
и по этих трем точкам найти максимум на спектре.
Цитата(ILYAUL @ Oct 27 2011, 23:32) *
Справится , только вот зачем.

Капитан Очевидность подсказывает: чтобы измерить частоту.
hd44780
Во, точно, у меня AtTiny2313 валяется ...
ILYAUL
QUOTE (_pv @ Oct 27 2011, 20:48) *
Капитан Очевидность подсказывает: чтобы измерить частоту.

Для этого есть аппаратные средства в AVR
maksimp
Если один отсчёт АЦП например больше нуля, а следующий (через 1 мс) - меньше нуля, то можно между ними провести линейную интерполяцию сигнала и более точно определить момент перехода через 0.
По таким уточнённым переходам через 0 вычисляем период, а затем - частоту.

Если не очень спешим от ждём несколько периодов и по их суммарной длине вычисляем частоту. Но тут есть лучший вариант, на основе аппроксимации зависимости "время перехода через 0" от "номер по порядку перехода через 0" с помощью прямой по методу наименьших квадратов. Тогда частота - обратная величина к наклону этой прямой.
pavel-pervomaysk
Поставить РС814 на переменку, транзистор оптопары на подтяжку +5 питания меги, заводи на прерывание меги и считай.
hd44780
Цитата(Павлик @ Oct 27 2011, 23:07) *
Поставить РС814 на переменку, транзистор оптопары на подтяжку +5 питания меги, заводи на прерывание меги и считай.


Я об этом думал ... По сути тот же компаратор.
Но у меня все замеры по 3-м каналам АЦП делаются в прерывании таймера (1 мс). Сам АЦП работет по опросу, без прерываний. Т.е. это прерывание "долгоиграющее".
Поэтому существует вероятность, что INT от оптопары или компаратора будет пропущено. В доке я что-то ничего про этот момент не нашёл sad.gif , может плохо искал.... Если есть, ткните носом плиз.

Менять алгоритм не хотелось бы (уже всё отлажено), поэтому у меня и потекли мысли в сторону 2-го камня, который спокойно посчитает эту частоту, а потом легко отдаст её основному процу по какому-нибудь SPI (жаль только, что у тини нету железного SPI, эмулировать придётся ...). Когда цикл измерений закончен и "измеряющий" таймер выключен.

Тинька даже дешевле отдельных счётчика и компаратора. По крайней мере, по местным ценам. А если ещё задуматься о способе считывания этого счётчика, 3-стаб. буферы, там тем более 2-й проц и дешевле и удобнее.
ILYAUL
QUOTE (hd44780 @ Oct 28 2011, 10:19) *
Поэтому существует вероятность, что INT от оптопары или компаратора будет пропущено. В доке я что-то ничего про этот момент не нашёл sad.gif , может плохо искал.... Если есть, ткните носом плиз.

Прерывания INTX старшие прерывания AVR и если уж они вкл. то проц их никогда не пропустит. Какая разрядность АЦП?
Вы можете посчитать сколько time уходит на одно преобразование Если укладываетесь в 20ms , то у Вас вполне остается время переключить входы и посчитать все значения на одном АЦП
hd44780
Перепаял слегка схему, освободил 5 младших ног PORTB.
Задействовал встроенный в Mega16 компаратор - AIN- - ср. точка (она же ADC0), AIN+ - вх. сигнал напряжения (ADC1), включил прерывание компаратора по нарастанию сигнала, параллельно TC2 считает миллисекунды.

Куски кода:

// Timer 2 overflow interrupt service routine
// -- Частота прерываний 1 kHz = 1 мс - 20 раз за период 50 Гц (20мс)
// -- 1000 раз в секунду
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// Reinitialize Timer 2 value
TCNT2=0x83;

// Миллисекунды
ms++;
} // timer2_ovf_isr

// Analog Comparator interrupt service routine
// Переход синусоиды вверх через 0
interrupt [ANA_COMP] void ana_comp_isr(void)
{
pulses++;
} // ana_comp_isr

Расчёт частоты:

////////////////////////////////////////////////
// Частота
frequency = pulses*1000.0;
frequency/=ms;

ms, pulses - dword, frequency - float.
ms, pulses обнуляются только при первичной инициализации по включении питания.

"Измеряющий" таймер TC0 и АЦП пока выключены, т.е. прибор меряет только частоту.
Получил результаты 50.10 ... 50.30 Гц - бегает. Заводской прибор показывает 49.98-48.99 Гц rolleyes.gif

Единствнное, что приходит в голову, это то, что переменные pulses и ms наверняка меняются, пока расчитывается частота. Когда-то я уже натыкался на это. Попробую ввести переменные-защёлки для них и кратковременный запрет прерываний.
hd44780
Переменные-защёлки не помогли.
Стабильно показывает 50.37 Гц при 49.97 по прибору.
woroba
Вам же Палыч на первой странице показал алгоритм, а вы делаете всё наоборот.
hd44780
woroba, не валите всё в одну кучу.
Замечания Палыча касаются измерения тока и напряжения.
К измерению частоты через компаратор они не относятся, хотя бы потому, что аналогового компаратора тогда не было.

Кстати - проверил внутренний компаратор основному алгоритму не мешает. Так что, К554СА3, наверное, не нужен.
DrGluck
А попробуйте пересчитать полученную погрешность измерения в свете используемого кварца на проце. У Вас же там не атомные часы подключены ? Наверняка что-нибудь из области 60 ppm ...
hd44780
Цитата(DrGluck @ Oct 31 2011, 09:44) *
А попробуйте пересчитать полученную погрешность измерения в свете используемого кварца на проце. У Вас же там не атомные часы подключены ? Наверняка что-нибудь из области 60 ppm ...


А как пересчитать? Сделать генератор и померять прибором сколько Гц он выдаст?
Кварц хрен знает какой, родом из радиобазара biggrin.gif ... На нём написано - MC 8.000 MHz.
Кстати, его корпус заземлять надо? Иногда в схемах с такое видел... У меня пока незаземлён.

Всё, что приходит в голову - ввести калибровочную константу и отнимать/прибавлять её (или делить/умножать - пока не знаю), как это делается с током и напряжением.
DrGluck
Цитата
Кварц хрен знает какой, родом из радиобазара ... На нём написано - MC 8.000 MHz.

... без комментариев sm.gif
P.S. "Пересчитать" - подразумевалось как эквивалент "А что Вас собственно удивляет ?" ...
hd44780
Наверное, введу константу. Не будешь же делать тестовый генератор под каждый кварц....

Вот только какую константу лучше - для деления/умножения или прибавления/отнимания?
Пока мне думается второе.
DrGluck
http://metrologyia.ru/

hd44780
Ну и что?
Про излучение цезия-133 ( http://metrologyia.ru/?page_id=103 ) я и так знаю laughing.gif
А как мне это может помочь laughing.gif ?
Палыч
Цитата(hd44780 @ Oct 30 2011, 18:47) *
Замечания Палыча касаются измерения тока и напряжения.

Нет. Мои замечания выше касались именно подсчета частоты.
Что видно "невооруженным" глазом:
1. Запуск таймера не "привязан" к началу цикла (сброс в ноль переменной ms - это очень грубо!), поэтому таймер, скорее всего, насчитает "немного" меньше (частота получится "немного" больше).
2. ТС говорит выше о измерении за Х мс. За это время может быть зафиксиворанно только целое число периодов. "Нецелая" часть периода в расчете не участвует. Поскольку тики таймера гораздо меньше N периодов, то лучше (точнее) расчет будет за целое число периодов измеряемой величины. Т.е. окончанием измерения должно быть фиксация N периодов.


Цитата(hd44780 @ Oct 31 2011, 10:09) *
На нём написано - MC 8.000 MHz.

Кстати, посмотрите в справочной литературе: чем отличаются кварцы, на которых написано "8.000 MHz", от тех, где написано "8000 kHz"
rx3apf
Цитата(Палыч @ Oct 31 2011, 15:54) *
Кстати, посмотрите в справочной литературе: чем отличаются кварцы, на которых написано "8.000 MHz", от тех, где написано "8000 kHz"

Да ничем они не отличаются, даже и в советские времена гармониковый 8 MHz был бы экзотикой. А точность - да, там и шесть знаков после запятой на корпусе напишут, а реально 50 ppm в лучшем случае, а сколько обвязка еще даст - непредсказуемо.
hd44780
Сделал так для отладки: компаратор по приходу импульса запускает таймер, считающий миллисекунды. Кроме того, наращивает счётчик положительных полуволн.
Когда таймер насчитывает 1000мс (1 сек), он вырубает всё - и себя, и компаратор.
Потом кнопкой я запускаю процесс снова.

Результат - чаще всего равен 51 sad.gif , реже 50. Кварц кривой что ли..
Есть у меня и часовые кварцы, на 32768 Гц. Можно по нему секунду отсчитать. Но вдруг и они такие же кривые ..
_pv
Цитата(hd44780 @ Nov 5 2011, 17:24) *
Результат - чаще всего равен 51 sad.gif , реже 50. Кварц кривой что ли..
Есть у меня и часовые кварцы, на 32768 Гц. Можно по нему секунду отсчитать. Но вдруг и они такие же кривые ..

не хочу огорчать, но они тоже окажутся кривые sm.gif
если есть сигнал с частотой около 50 Гц, и если отмерить ровно секунду, то количество срабатываний компаратора за эту секунду, будет либо 49, либо 50, либо 51.
при этом ошибка измерения (можно сказать квантования) будет 20мс/1000мс = 2% = +- 1Гц.

правильнее будет считать время прошедшее за N срабатываний копмаратора. так как дискретность гораздо таймера меньше чем 20мс.
ведь даже при измерении одного периода т.е. 20 мс от кварца 32768Гц, ошибка будет всего 20мс / (1/32768) = 0.15% = 0.08Гц.

з.ы.
почему всё-таки не измерять частоту исходя из показаний АЦП как гласит изначальное название темы?
hd44780
Спасибо большое всем, получилось.

По ходу ещё 1 вопрос - я сделал, как _pv посоветовал - показывает 50.0 Гц, но гдо-то раз в 5-10 сек проскакивает значение типа 51.2 .
Интересно почему?
Может помехи пробегают? У меня там фильров нету. Напряжение идёт через обычный транс и потенциометр для подстройки. И поднимается на +2.5в средней точкой на ОУ.

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

Теперь буду всё в кучу собирать.
Палыч
Цитата(hd44780 @ Nov 6 2011, 15:05) *
Интересно почему?
Вероятно, потому, что время Вы замеряете с точностью до 1 мс....
Если Вы желате измерять частоту около 50 Гц с точностью 0.1 Гц, измеряя время с точностью 1 мс, то необходимо замерить время длительности не менее 500 периодов частоты.
hd44780
500 периодов пока не делал, это всё-таки 10 сек....
Пытался поднять частоту таймера, где-то до 100 kHz (т.е. считать не миллисекунды, а 100-тысячные доли сек) - эффекта не увидел. Мож накосячил где.

Пока тупо усреднил результаты по 8 последним замерам - нормально вроде. Правда не знаю, корректно ли это..
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.