Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Частотомер


Автор: Семен78 31.3.2008, 14:02
Хочу мерить частоту оборотов на двигателе -  железо готово(опрос LPT)  - набираюсь мыслей по софту:
 В MFC    -  Edit box  и   Кнопка на которой  наввешу :
  таймер  1 сек . который
 запускает бесконечный цикл с опросом порта  и  записью единичек ....
  Ну и надеюсь видеть цифру новую каждую сек.  
 Вопрос -  как  закончить цикл при наступлении следующей команды от таймера?  
  

Автор: korian 31.3.2008, 14:11
Цитата(Семен78 @  31.3.2008,  13:02 Найти цитируемый пост)
запускает бесконечный цикл с опросом порта  

это необходимо делать?
вообще лучше расскажите, что надо сделать, не опираясь на реализацию, а то так не понятно...

самый простой вариант, когда программа просто опрашивать порт каждую секунду:
на диалог ставим Edit
при инизиализации диалога, инициализируем таймер, устанавливаем обновление 1 сек.
в функции таймера, читаем порт и выводим данные в edit

Автор: Семен78 31.3.2008, 14:23
крутится вал около 10 -20 тыс.  оборотов в секунду    -   на валу метка для датчика который  висит на LPT. 
  надо точно мерить частоту вращения не пропуская ни одного оборота  -   
полагаю что частота выполнения бесконечного цикла с опросом порта много выше чем частота вала 

Автор: Andrey44 31.3.2008, 14:25
korian, поддерживаю твое мнение. Бесконечный цикл не нужен. 
Тогда это надо делать в другом потоке. Самый лучший вариант - таймер.

Автор: korian 31.3.2008, 14:37
Цитата(Семен78 @  31.3.2008,  13:23 Найти цитируемый пост)
полагаю что частота выполнения бесконечного цикла с опросом порта много выше чем частота вала

предположение не совсем верное.

Цитата(Семен78 @  31.3.2008,  13:23 Найти цитируемый пост)
на валу метка для датчика который  висит на LPT

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

Цитата(Семен78 @  31.3.2008,  13:23 Найти цитируемый пост)
надо точно мерить частоту вращения не пропуская ни одного оборота  

этого сделать средствами Windows нельзя, т.к. любой поток/процесс может замереть на неопределенное время и соответсвенно потерять часть данных.
вообщем-то это нельзя сделать средствами компа на базе x86, т.к. он не является системой реального времени.
если это не настолько критично, т.е. иногда можно пропускать куски данных, то можно попробывать реализовать, но никто не гарантирует, когда будет пропущен кусок и какого размера он будет.

где-то это уже обсуждалось... щас попробую найты ссылку, почитаете подробнее.

Автор: Семен78 31.3.2008, 14:46
что то типа  этого ?
Код

void CMy7Dlg::OnButton1() 
{
    // TODO: Add your control notification handler code here
    SetTimer(1, 1000, NULL);
}
void CMy7Dlg::OnTimer(UINT nIDEvent) 
{
    // TODO: Add your message handler code here and/or call default
                   r=0; // Счетчик оборотов
    while(nIDEvent == 1)
{
         int c=Inp32(0x378);
                      if(c=1) {r++}
 }
                             UpdateData(false);
            
CDialog::OnTimer(nIDEvent);
}



Добавлено через 7 минут и 50 секунд
ну вобщем как уж получится  -  хочу попробовать  
 возможно ли  оценить погрешность ?   как же работают всякие  виртуальные приборы где важна точность?

Автор: korian 31.3.2008, 14:57
Цитата(Семен78 @  31.3.2008,  13:46 Найти цитируемый пост)
что то типа  этого ?

нет не так.
необходимо создавать дополнительный поток, который будет считать частоту.
основной поток будет брать данный из дополнительного и выводить их по таймеру или по Event'у из дополнительного потока.
но еще раз повторяю, что есть большая вероятность терять куски данных.

Добавлено через 8 минут и 16 секунд
Цитата(Семен78 @  31.3.2008,  13:46 Найти цитируемый пост)
как же работают всякие  виртуальные приборы где важна точность? 

делается это на базе устройства.
например, если нужна только частота, но не нужно ее изменение, то такое делается просто.
устройство само считает частоту.
при запросе частоты, на LPT порт подается значение частоты в данный момент времени.
если нужно знать изменение частоты, то в устройстве должен быть буфер, в котором содержится изменение частоты с нужной дискретизацией по времени. и должна быть возможность дать программе прочитать этот буфер.

Автор: korian 31.3.2008, 15:19
http://forum.ixbt.com/topic.cgi?id=26:38024 по поводу как это лучше делать в плане устройства.
ну а в программном плане (если работать с тем что есть), вам нужно наследовать класс от CWinThread. и делать опрос устройства с подсчетом частоты в OnInitInstance.
главная программа должна будет опрашивать этот поток...
и не забудьте про сихнранизацию. в этом помогут классы CCriticalSection и CSingleLock.

Автор: Семен78 31.3.2008, 15:28
Благодарю!   
 пошел теорию "грызть" ....

Автор: Lazin 31.3.2008, 15:49
Семен78, Во первых тебе нужен источник опорной частоты.
всего есть 2 способа измерения частоты: в первом у тебя опорная частота меньше чем измеряемая, во втором - опорная частота больше чем измеряемая.
описываю для первого случая...
что-бы измерять частоту, во первых нужно как-то получать управление каждый раз когда приходит импульс на LPT (как это сделать хз, с параллельным портом никогда не работал), и тупо их считать.
здесь важно что-бы не произошло переполнение переменной.  
то есть нужна переменная типа long, в которой у тебя-бы накапливалась сумма пришедших импульсов с датчика.
В качестве источника опорной частоты можно использовать таймер, например с периодом 1с (для простоты)))
при каждом срабатывании таймера рассчитываем частоту, а потом обнуляем счетчик

как то так 

Код

unsigned long lpt_cnt = 0;
double current_frequensy = 0;

void on_signal()
{
  lpt_cnt++;
}

void on_timer()
{
  current_frequensy = 1.0f/lpt_cnt;  
}


при втором методе таймер и порт меняются местами, мы считаем сколько натикало по таймеру, и при появлении сигнала, переменная, в которой содержится количество тиков таймера будет содержать количество тиков таймера прошедших между приходами 2-х соседних импульсов с датчика.  smile но это больше подходит для небольших частот...
а с потоками заморачиваться не стоит, не думаю что погрешность будет заметна...

Автор: Семен78 31.3.2008, 16:04
вот и проблемка как постоянно следить за появлением сигнала (опрашивать порт) -  для двух случаев .
  вычитал что тик таймера 55 мсек.   ( а точность вроде 10 мсек.)   а мои импульсы примерно 3 мсек.(300 имп. в сек.) 

Автор: korian 31.3.2008, 16:51
Цитата(Семен78 @  31.3.2008,  15:04 Найти цитируемый пост)
вот и проблемка как постоянно следить за появлением сигнала 

вешать сигнал надо не на данные, а на упровляющий "провод" LPT и обрабатывать соответствующие прерывание.
в Windows на уровне пользователя обрабатывать прерывания нельзя, поэтому для такого варианта надо писать драйвер (вместо потока).
что вообщем-то правильнее и обеспечит более лучшую работу (в том смысле что будет меньше или не будет вообще пропусков импульсов).

Автор: maxim1000 31.3.2008, 20:40
не уверен, но, вгозможно, одна из линий LPT предназначена для индикации передачи данных
т.е. можно повесить на неё сигнал и просто читать из LPT (обычным ReadFile)
в зависимости от того, сколько байт получится читать в секунду, можно посчитать частоту
обработкой прерывания будет заниматься драйвер LPT, тчо лучше, чем обычное приложение

P.S.
естественно, это всё при том условии, что есть такой сигнал и стандартный драйвер ведёт себя соответствующим образом

Автор: Семен78 31.3.2008, 23:20
похоже это тема не для раздела новичков  -  (казалось бы научить комп. посчитать импульсы ..... smile 

   думаю может  легче и точнее такой вариант: 
  собираю схемку - генератор секундных импульсов с кварцем (часовым)  и  через доп. логику  ограничиваю подачу считываемых импульсой  секундной полосой .
  запускаю таймер на бесконечный цикл опроса порта  каждые 1.5 сек.    и второй таймер который через 1 комп. тик(55 мсек.) будет killtimer( предыдущий)  - вот тока как их сопрячь по фазе  и чтоб результат  обновлять...?

Автор: korian 31.3.2008, 23:48
очень не плохой вариант предложил maxim1000,
похожий сигнал у ECP Parallel LPT должен быть полюбому.
осталость изучить как к нему прикрутиться правильно.
а дальше...
на таймере в программе читаем LPT порт.
частота = количество прочитаных байт / (текущее время - предыдущее время чтения)
при таком подходе, при 10-20кГц, пропусков поидее быть не должно.

Автор: Lazin 1.4.2008, 08:49
млин, да наверняка можно сделать так, что-бы система вызывала твой callback при наступлени события от LPT порта, с ком портом такое прокатывает.

постоянно опрашивать порт - бредовая идея, ты так ничего не посчитаешь, при некоторых соотношениях частоты опроса и частоты сигнала у тебя будет 0-я частота. Если так делать, то частота опроса должна быть на порядок больше частоты сигнала.. но это очень неэффективно с точки зрения производительности системы.

Кстати, операционная система не предназначена, для того что-бы из нее делали частотомер )), может стоит использовать какой, нибудь контроллер, для измерения частоты?

Автор: Семен78 1.4.2008, 10:26
на LPT  в регистре контроля глянул  -   строб импульс данных или разрешение аппаратного прерывания?
  но не понимаю какая разница с какой линии читать биты .   
  а про метод  чтения  если правильно уловил  :    запускаем цикл на  чтение порта с подсчетом битов  пока не на считает фиксированную цифру ,
 при этом до и после цикла  некой функцией извлекаем системное время  ,  вычисляем разность и от туда частоту ....?

Автор: korian 1.4.2008, 10:43
Цитата(Семен78 @  1.4.2008,  09:26 Найти цитируемый пост)
но не понимаю какая разница с какой линии читать биты 

Цитата(Семен78 @  1.4.2008,  09:26 Найти цитируемый пост)
запускаем цикл на  чтение порта с подсчетом битов  пока не на считает фиксированную цифру 

не так. этим будет заниматься процессор на уровне прерываний. 1 импульс - одно прерывание. считать их будет Windows в ввиде байтов.
сами значения байтов нам не важны, главное их количество. Драйвер для LTP порта уже существует, необходимо только правильно падать сигнал, чтобы комп считал, что вы ему передали байт инфы (за один такт передачи по ECP LPT передается байт).
потом стандартными функциями CreateFile("LPT"....) ReadFile читаем байты. Накопленные байты винда сама буферезирует, так что нам просто на таймере надо читать LPT порт. Никаких циклов не надо.
главное читать достаточно часто, т.к. у буфера поидее есть придел  smile 

Автор: Семен78 1.4.2008, 11:46
Цитата(Lazin @  1.4.2008,  08:49 Найти цитируемый пост)
может стоит использовать какой, нибудь контроллер, для измерения частоты? 

   это резервный вариант  будет 

Автор: xvr 1.4.2008, 12:09
Цитата(korian @ 31.3.2008,  23:48)
очень не плохой вариант предложил maxim1000,
похожий сигнал у ECP Parallel LPT должен быть полюбому.
осталость изучить как к нему прикрутиться правильно.

Для того, что бы Винда открыла порт как ECP, он должен определится как ECP в процессе PnP, а для этого надо, что бы то, что подключается к LPT порту понимало PnP протокол из IEEE 1284 и умело отвечать, что оно ECP устройство. Действо сие гораздо сложнее, чем подключить 1 провод к LPT. 
В общем, подключение к ECP будет сложнее, чем сделать частотомер на каком нибудь МК и скидывать инфу из него по COM порту (например)

Автор: Семен78 4.4.2008, 14:46
Нашел инструментарий работы с прерыванием от LPT: http://www.pcports.ru/xDRV_sys.php 
  Думаю зачем второй поток на чтение делать  когда таймером буду запускать  функцию работы с прерыванием...?

Автор: xvr 4.4.2008, 20:08
Цитата(Семен78 @ 4.4.2008,  14:46)
Нашел инструментарий работы с прерыванием от LPT: http://www.pcports.ru/xDRV_sys.php 
  Думаю зачем второй поток на чтение делать  когда таймером буду запускать  функцию работы с прерыванием...?

Подайте на LPT порт пачку из ~1000000 импульсов с частотой 20KHz, посчитайте, сколько импульсов пропустит этот драйвер, иначе вас ждут большие неожиданности в будущем  smile НАДЕЖНО посчитать что либо на LPT порту со скоростью до 20 KHz можно ТОЛЬКО либо под ДОС'ом либо написав СПЕЦИАЛЬНЫЙ драйвер в Windows, обычные драйвера для доступа к LPT порту (коих море) не подойдут  smile 

Автор: Семен78 4.4.2008, 23:47
Ну вот - опять подножка. 
  а какие частоты работают надежно?  может делитель в промежуток воткну.    странно как то 20khz  -  частота восприятия уха а порт не справится .   зависит ли это от рабочих частот материнки ?  через lpt  -  1 mbit  /c  проходит  вроде

Автор: korian 5.4.2008, 00:10
делайте для своего устройства интерфейс ECP LPT и используйте стандартный драйвер оси.
или как сказал xvr:
Цитата(xvr @  1.4.2008,  11:09 Найти цитируемый пост)
сделать частотомер на каком нибудь МК и скидывать инфу из него по COM порту (например)

хотя я не уверен, что тот драйвер должен пропускать импульсы.. поидее не должен, если там реально прерывание используется...
xvr, почему вы считаете, что будут пропуски?

Автор: xvr 7.4.2008, 12:17
Цитата(Семен78 @ 4.4.2008,  23:47)
Ну вот - опять подножка. 
  а какие частоты работают надежно?  

Никакие  smile Любой драйвер, принимающий что угодно от порта и отправляющих это прикладной программе будет это делать через многочисленные нырки из User Space в Kernel и обратно, т.к. не существует других легальных способов вызвать драйвер из прикладной программы и вызвать что-либо из этой прикладной программы со стороны драйвера. ЛЮБОЕ такое переключение съедает массу времени (даже если собственно прикладная программа работает с RealTime приоритетом). При этом нет НИКАКИХ ограничений снизу на время такого переключения (Windows не RealTime система). Если нужно гарантированное реагирование на сигналы из LPT порта - нужно оставаться все время в Kernel'е или User Space, т.е. только свой собственный драйвер или драйвер типа GiveIO, который дает доступ к портам напрямую из приложения (к прерываниям он доступа не дает, так что только опрос в цикле, при этом все остальное на машине будет мертво стоять).
Цитата

может делитель в промежуток воткну.    странно как то 20khz  -  частота восприятия уха а порт не справится .   
Порт справится, Windows нет.
Цитата

зависит ли это от рабочих частот материнки ?  
Нет
Цитата

через lpt  -  1 mbit  /c  проходит  вроде
Проходит, но не покидая пределов драйвера.

Добавлено через 1 минуту и 3 секунды
Цитата(korian @ 5.4.2008,  00:10)
хотя я не уверен, что тот драйвер должен пропускать импульсы.. поидее не должен, если там реально прерывание используется...
xvr, почему вы считаете, что будут пропуски?

Драйвер пропускать не будет, а вот связка драйвер+call back в пользовательском приложении может просто не успеть их все отработать

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)