Юрец

Частотомер На Atmega

53 сообщения в этой теме

Юрец    9

здравствуйте!

делаю частотомер-тахометр.

использую atmega16, частота от кварца 14,7456000 MHz. таймер по прерыванию 1 сек .

в программе:

int p,i=0;

в теле таймера:

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{if (p==225) {p=0;printf(" F = %u\r\n",i);i=0;}else p++;

;}

(14,7456000 MHz / 256 / 256=225). при TCCR0=0b00000100;

теоретически таймер тикает правильно (смотрел в протеусе).

в обработчике int0, на который тикают входящие проверяемые импульсы так:

interrupt [EXT_INT0] void ext_int0_isr(void)

{i++;}

трабла в следующем:

при симуляции (подав частоту 6000Гц в протеусе) на терминале вижу:

F=5988

F=6018

F=6018

F=6017

F=6018 и т.д.

что это? глюк протеуса или ошибка в программе? или я неправильно сделал алгоритм подсчета импульсов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zenner    1

А почему бы не использовать ещё один таймер для счета импульсов ?

Если ты подашь на внешнее прерывание больше ~150кГц то программа просто застрянет в нем...

Глюки протеуса имеют место быть. Я делал частотомер до 5МГц, тоже на меге. В реале меряет 5МГц с точностью 1-2гц, в протеусе - частота скачет сильнее, намного...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
demonchik    0

Здравствуйте. Алгоритм вашей программы ясен - подсчет импульсов по прерыванию за единицу времени. а как вы включаете таймер с приходом импульса? вель нам надо его включить с приходом 1-го импульса и считать их количество... вроде верно? ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
1.А почему бы не использовать ещё один таймер для счета импульсов ?

2.Если ты подашь на внешнее прерывание больше ~150кГц то программа просто застрянет в нем...

3.Глюки протеуса имеют место быть. Я делал частотомер до 5МГц, тоже на меге. В реале меряет 5МГц с точностью 1-2гц, в протеусе - частота скачет сильнее, намного...

1.может я что-то недопонимаю, но ЗАЧЕМ?

2.фактически это алгоритм автомобильного тахометра. скажем до 8000 оборотов. 8000 * 4 цилиндра = 32кГц. пока это будет максимумом.

3.частотомер до 5МГц своя разработка? можно взглянуть на исходник (если можно, то на Си, т.к. в ассемблере не силен...)

Здравствуйте. Алгоритм вашей программы ясен - подсчет импульсов по прерыванию за единицу времени. а как вы включаете таймер с приходом импульса? вель нам надо его включить с приходом 1-го импульса и считать их количество... вроде верно? ;)

у меня получается так: прерывание по INT0 постоянно срабатывает по входящему импульсу, а таймер тикает постоянно (TIMSK=0X01 - запуск таймера при инициализации), причем обнуляя накопившееся значение каждую секунду.

можно ввести доп. переменную, скажем first_impulse=1 при подаче питания на микроконтроллер, а при первом срабатывании interrupt [EXT_INT0] void ext_int0_isr делаем так: включаем таймер, потом first_impulse=0.

фактически в автомобиле так: сперва вставляем ключ зажигания, поворачиваем, заводим. пусть между подачей питания на микроконтроллер и до момента "зеведенного двигателя" пройдет 0,5-2сек. тогда проверку на "первый импульс" для корректного отображения частоты можно и не делать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

Zenner    1
1.может я что-то недопонимаю, но ЗАЧЕМ?

2.фактически это алгоритм автомобильного тахометра. скажем до 8000 оборотов. 8000 * 4 цилиндра = 32кГц. пока это будет максимумом.

3.частотомер до 5МГц своя разработка? можно взглянуть на исходник (если можно, то на Си, т.к. в ассемблере не силен...)

1,2. Внешних прерываний у меги увы, не много. Могут куда-нибудь ещё пригодиться. А если есть свободный таймер - почему бы не использовать? Тем самым разгрузив проц для занятия чем-нибудь более полезным.

3. Да, своя. См. ЛС.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
demonchik    0

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
1,2. Внешних прерываний у меги увы, не много. Могут куда-нибудь ещё пригодиться. А если есть свободный таймер - почему бы не использовать? Тем самым разгрузив проц для занятия чем-нибудь более полезным.

3. Да, своя. См. ЛС.

спасибо! разбираюсь.

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

Zenner любезно предоставил : http://kb.3bb.ru/viewforum.php?id=5

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mazzi    38
interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{if (p==225) {p=0;printf(" F = %u\r\n",i);i=0;}else p++;

;}

Я думаю проблема в функции printf

зафиксируй полученное значение в буферной переменной и вынеси printf в основной цикл

{if (p>224) {p=0; i_view=i;i=0; flag=1;}else p++;}

а в основном цикле добавь следующую строку

if (flag) {
   flag=0;
   printf("F=%u\r\n",i_view);
}

и будет тебе счастье :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
и будет тебе счастье :-)

попробовал так, как вы советовали.

получаю:

F=5988

F=6028

F=6028

F=6028

F=6028

F=6029

F=6028

F=6028

F=6028

F=6028

F=6028 и т.д.

все больше склоняюсь к тому, что это глюк протеуса.

Изменено пользователем Юрец

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mazzi    38
и будет тебе счастье :-)

попробовал так, как вы советовали.

все больше склоняюсь к тому, что это глюк протеуса.

Возможно. Я протеусом не пользуюсь, всё делаю в железе и симуляторе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
Возможно. Я протеусом не пользуюсь, всё делаю в железе и симуляторе.

в каком? не vmlab случайно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
А не проще использовать функцию захвата таймера, перевести в обратный код и преобразовать в десятичное значение. Все это делается в основном цикле. Внешнее прерывание будет освобождено "про запас"..

имеете ввиду использовать внешнее прерывание таймера по нарастающему фронту? при его появлении запускать другой таймер, и считать кол-во импульсов его?

есть пример для ознакомления?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mazzi    38
в каком? не vmlab случайно?

AVR Studio

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я имею ввиду использовать вход ICP и функцию захвата таймера/счетчика. При возникновении прерывания по данному входу (фронт/спад конфигурируются) достаточно прочитать состояние таймера и вычесть из него предыдущее. Получится измерение периода, правда результат будет получаться обратнопропорциональный. Потребуется перевести полученный результат в обратный код, а так как счетчик работает в двоичном коде, то для читаемости результата потребуется преобразовать двоичный в десятичный. Но все это уже можно делать в основном цикле не нагружая прерывания. 

  • Одобряю 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
Я имею ввиду использовать вход ICP и функцию захвата таймера/счетчика. При возникновении прерывания по данному входу (фронт/спад конфигурируются) достаточно прочитать состояние таймера и вычесть из него предыдущее. Получится измерение периода, правда результат будет получаться обратнопропорциональный. Потребуется перевести полученный результат в обратный код, а так как счетчик работает в двоичном коде, то для читаемости результата потребуется преобразовать двоичный в десятичный. Но все это уже можно делать в основном цикле не нагружая прерывания. 

спасибо!

Вас понял.

з.ы. а случайно нет кода на си - не хочется изобретать велосипед (а то пока разберусь)...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Goodefine    95

Чего то непонятно, в чем нашли проблему.

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{if (p==225) {p=0;printf(" F = %u\r\n",i);i=0;}else p++;
;}

В соответствии с Вашим алгоритмом проверки и инкрементирования счетчика р, таймер на самом деле оттикает 226 интервалов (на один больше чем константа в условии, в этом легко убедится, заменив 225 на, скажем на число 2 - будет три цикла. ). Это и дает погрешность в плюс 26-27. Поэтому и в проверку надо ставить число не единицу меньше. Т.е. 224. И будет не 6028, а гораздо более точное значение. А сам алгоритм далеко не лучший по точности...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
А сам алгоритм далеко не лучший по точности...

а какой лучше? (хотя-бы теорию)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zenner    1

А чем Вам собственно не понравился подсчет импульсов за секунду с помощью ещё одного таймера?

Захват - херня ИМХО. Больно уж низкое разрешение получим(т.к. этот режим не юзал - предполагаю что минимум два такта, а это много.).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
А чем Вам собственно не понравился подсчет импульсов за секунду с помощью ещё одного таймера?

Захват - херня ИМХО. Больно уж низкое разрешение получим(т.к. этот режим не юзал - предполагаю что минимум два такта, а это много.).

тупо держу перед собой даташит на мегу16. пытаюсь вникнуть в регистры таймеров. пока дается с трудом.

я совсем замучил google своими поисками "даташит на мегу16 на русском"... пока безрезультатно...

p.s. все пытаюсь воткнуться в программу.

Изменено пользователем Юрец

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zenner    1

Вот эта книга есть что-то похожее на даташит. На русском.

Там описание всей периферии можно найти...Ну или почти всей...

1000472731.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    9
Вот эта книга есть что-то похожее на даташит. На русском.

Там описание всей периферии можно найти...Ну или почти всей...

большое СПАСИБО!

скачал. разбираюсь.

а пока вопрос по программе: однократный положительный импульс на вход Т1 вызывает однократный "тик" таймера, или все-таки запускает его счет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zenner    1

Раз выбрано внешнее тактирование - значит однократный "тик".

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сообщения

    • Да, они занижены. Ночью в мой кипящий мозг пришла мысль, что они занижены ровно в два раза, поэтому и метки выставляются. Сегодня пришлось ехать на дачу, поэтому не занимался им.
    • Для этой цели давно использую цифровой фотоапарат - фоткаю плату с разных углов и ракурсов на макросъемке (для тех, кто не знает - специальный режим для съемки с очень близкого расстояния) и увеличиваю на компьютере до читабельного размера. Программные регуляторы гаммы, яркости и контраста помогут разглядеть даже мелкие пылинки на плате. Очень удобный метод и для рассматривания элементов и срисовывания схем.    
    • Может быть такое что китайцы палево просто покарявят что бы выглядело б.у.шым и шлют шлак? https://ru.aliexpress.com/item/MJ21195-MJ21196-MJ21195G-MJ21196G-4-50-3/32913837994.html?spm=a2g0v.10010108.1000013.8.2ce03652Wy3UzB&pvid=ee79ffbd-d941-4ac9-b997-09c38395efdf&gps-id=pcDetailBottomMoreThisSeller&scm=1007.13339.90158.0&scm-url=1007.13339.90158.0&scm_id=1007.13339.90158.0 Я например один раз брал уже б.у.шные тр-ры. В принципе норм были.
    • Я брал AD823 на али по $0.4 за штуку (корпус soic-8) при партии в 10 шт - не считаю его особенно дорогим. Конечно, есть вопрос о его оригинальности, тут уверенности нет. Но по скорости нарастания выходного сигнала полностью соответствует описанию (rail-2-rail тоже выдает). Словил интересный момент - если подключать его вход к его же +Vcc, через вход течет приличный ток, ОУ нагревается и т.д. Но, опять же, по описанию на вход надо подавать на 1.2 В меньше. Для справедливости - LM358 брал за 200 рублей там же в количестве 100 шт (DIP-8). Но при его характеристиках область его применения очень ограничена. У меня три LM358 (и одна AD823) пошли на двуполярный предрегулятор - у LM358 обнаружилась неприятная особенность - если ОУ работает в режиме компаратора (т.е. его выход либо плюс, либо минус питания), то он переключается с приличной задержкой (до 50 мкс). Видимо, какие-то внутренние транзисторы входят в глубокое насыщение, из которого не могут долго выйти. Поэтому одну микросхему в предрегуляторе пришлось заменить на AD823 (пробовал LM393, но он возбуждался даже с положительной обратной связью). Я имел в виду такую ситуацию - БП переходит в режим СС, при этом его выходное напряжение становится ниже. ОУ, отвечающий за напряжение будет хотеть поднять напряжение выше и на своем выходе выдаст потенциал, соответствующий (или даже превосходящий) максимальному выходному напряжению блока. Если в этот момент нагрузка резко снижает свое потребление, схема СС отключается и выходное напряжение снова будет определяться схемой CV. Если ОУ в схеме CV медленный (или замедлен ООС), то некоторое время (пока ОУ не отреагирует) выходное напряжение будет установлено на максимально возможном для блока уровне, после чего "придет в норму". Вот этого бы не хотелось. В общем случае задача по созданию стабильного линейного БП весьма сложна. Проблему усугубляет возможность подключения к выходу конденсатора и, тем самым, значительного снижения быстродействия выходного каскада. В сочетании с "быстрым ОУ" это приведет к неминуемой генерации. В то же время медленный ОУ будет допускать вот такие скачки выходного напряжения при возврате из режима СС. Да, но такое "слитие" происходит на высокой частоте, для качественной фильтрации которой нужен, опять же, "быстрый ОУ" в линейном стабилизаторе. Конкретно в моем случае, если ОУ достаточно замедлить, пульсации от предрегулятора могут достигать 60 мВ (против 10 мВ при полном его отключении). В то же время на "быстром ОУ" пульсации незаметны даже на максимальном уровне чувствительности осциллографа (2 мВ/дел). При этом импульсы на НК у меня возникают только в одном случае, когда закрывается ключ и ток вторичной обмотки (достаточно) резко обрывается через ДК. Вы принципиально не хотите использовать ОУ?
    • Автор же признаётся сразу, что не особо в теме...
    • Да ответами и советами завалили, не то слово . Я такой эксперимент не ставил. Но сейчас включил MUX[010] и поставил перемычку между А1 и А3. Получил 1 (единицу), но не ноль. Вот только не знаю, плохо это или нет? Заодно решил поэкспериментировать. запитал микроконтроллер с ADS1115 от одного источника (USB порт компьютера), а источник опорного напряжения, который я на схеме обозначил как "Объект измерения"  от другого БП. Земли не объединил! В итоге получил неустойчивые показания, но сравнимые с показаниями контрольного мультиметра. Сейчас уже поздно, завтра попробую запитать коннтроллер от нормального блока питания. Возможно с компьютера прёт всякая хрень по питанию. Но в связи с этим вопрос. А может и не надо объединять земли питания АЦП и измеряемую цепь?