ATmega16 - измерение частоты: внешнее прерывание и расчет

Обсуждаем контроллеры компании Atmel.
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

ATmega16 - измерение частоты: внешнее прерывание и расчет

Сообщение GhostAnton »

Делаю небольшой много функциональный прибор, необходимо сделать тахометр и спидометр, уже битых несколько дней пытаюсь понять как это реализовать на atmega16 и cvavr. Использую внешнее прерывание int0, не понимаю как сделать измерение.... Нашел много информации, но во многих случаях очень поверхностно все описано а брать готовое решение не хочу, есть желание разобраться как это работает, как это реализуется программно. Сниматься показания планируются с 1 цилиндрового 4-х тактного двигателя, максимальная частота 10000 оборотов, измерения хочу выводить раз в секунду.

Очень прошу Вас помочь разобраться в этом. Прошу прощения за столь глупую просьбу, но контроллерами недавно начал увлекаться.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение pyzhman »

Светодиод зажигать по кнопке можешь? Мигать светиком с частотой 0,7 Гц можешь? Скважность 1/4 мигания можешь? Время между двумя нажиманиями кнопки измерить можешь?
Docendo discimus
codenamehawk
Вымогатель припоя
Сообщения: 528
Зарегистрирован: Вт фев 09, 2010 17:52:26

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение codenamehawk »

Пока не ясно на чем застряли. А так ищите код частотомера и разбирайтесь как он работает.
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение GhostAnton »

pyzhman писал(а):Светодиод зажигать по кнопке можешь? Мигать светиком с частотой 0,7 Гц можешь? Скважность 1/4 мигания можешь? Время между двумя нажиманиями кнопки измерить можешь?

Этого я не умею, прошу помощи разобраться с моментами которые вы описали, по кнопке зажигать светодиод от внешнего прерывания я могу, а вот раотать с частотами просто не понимаю.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение pyzhman »

Хех. Тогда для начала тренируемся с выводом инфы на дисплей. Задаем в переменной число(будущий ваш тахометраж) и выпуливаем на экран.
много функциональный прибор

Бонапартовские замашки однако при таком раскладе.
Docendo discimus
Аватара пользователя
Coolish
Опытный кот
Сообщения: 785
Зарегистрирован: Сб фев 27, 2010 21:45:37
Откуда: Ростов-на-Дону
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение Coolish »

Для работы с интервалами времени используют таймеры.

Чтоб сделать прерывание таймера в CVAVR, есть мастер генерации кода. Сначала нужно указать, на какой частоте работает контроллер - вкладка Chip, она определяется кварцем. Без кварца, по умолчанию, будет 1 Мгц, но стабильность этой частоты, а значит, и результатов измерений, привязанных к ней, не гарантируется.

После установки тактовой частоты контроллера, в мастере можно включить любой из трёх таймеров, выставить предделитель. Мастер показывает вместо значения предделителя сразу значение тактовой частоты, поступающей на таймер.
Для примера возьмём Timer1, заводскую частоту 1 МГц и сделаем прерывание, которое будет срабатывать каждую секунду.
Включаем таймер, Clock Source: System Clock. Выставляем предделитель 64, при котором частота таймера станет 1000000/64 = 15625 Гц (Clock Value: 15,625 kHz). Далее, выставляем в регистре сравнения OCR1A значение 15625, для чего пишем в поле Comp.A его шестнадцатеричное представление- 3D09. Режим таймера устанавливаем Mode: CTC TOP OCR1A. Далее ставим галку Interrupt On: Compare A Match

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

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

// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// Place your code here

}

Для проверки можно в него запихнуть включение и отключение светодиода.

Решение, которое я описал, весьма "грязное" по причине отсутствия понимания действий, но может помочь увидеть что-то работающее и получить стимул разбираться дальше - читать учебники по AVR.
Сделать хотел грозу, а получил КоЗу
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение GhostAnton »

pyzhman писал(а):Хех. Тогда для начала тренируемся с выводом инфы на дисплей. Задаем в переменной число(будущий ваш тахометраж) и выпуливаем на экран.
много функциональный прибор

Бонапартовские замашки однако при таком раскладе.

Выводить на экран я могу, это не проблема, у меня уже есть кое-какие наработки
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение GhostAnton »

Coolish писал(а):Для работы с интервалами времени используют таймеры.

Чтоб сделать прерывание таймера в CVAVR, есть мастер генерации кода. Сначала нужно указать, на какой частоте работает контроллер - вкладка Chip, она определяется кварцем. Без кварца, по умолчанию, будет 1 Мгц, но стабильность этой частоты, а значит, и результатов измерений, привязанных к ней, не гарантируется.

После установки тактовой частоты контроллера, в мастере можно включить любой из трёх таймеров, выставить предделитель. Мастер показывает вместо значения предделителя сразу значение тактовой частоты, поступающей на таймер.
Для примера возьмём Timer1, заводскую частоту 1 МГц и сделаем прерывание, которое будет срабатывать каждую секунду.
Включаем таймер, Clock Source: System Clock. Выставляем предделитель 64, при котором частота таймера станет 1000000/64 = 15625 Гц (Clock Value: 15,625 kHz). Далее, выставляем в регистре сравнения OCR1A значение 15625, для чего пишем в поле Comp.A его шестнадцатеричное представление- 3D09. Режим таймера устанавливаем Mode: CTC TOP OCR1A. Далее ставим галку Interrupt On: Compare A Match

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

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

// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// Place your code here

}

Для проверки можно в него запихнуть включение и отключение светодиода.

Решение, которое я описал, весьма "грязное" по причине отсутствия понимания действий, но может помочь увидеть что-то работающее и получить стимул разбираться дальше - читать учебники по AVR.


Спасибо, с этим немного понятно, такое сравнение в 16 меге можно делать только таймером1, в 0 и 2 таймерах таких настроек нет, у меня таймер1 используется для генерации звука, другими двумя таймерами этого реализовать я так понимаю что нельзя?

Правильно ли я понимаю, для того чтоб прерывание сработало раз в секунду мне необходимо установить компареА равную частоте с предделителем кот орую я выбра?
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение clawham »

Давайте сначала уясним что такое частота?
чем отличается сигнал 1 килогерц и 2 килогерца?

ответ прост - временем между импульсами
частота - это величина обратная времени 1/время = частота
1/частоту= время

потому есть два варианта измерения частоты :
1) посчитать кол-во импульсов исследуемого сигнала за единицу времени(например секунду - тогда результат будет в герцах)
2) посчитать время между двумя импульсами исследуемого сигнала(тогда частота =1/время между импульсами)

всё это могут и должны считать таймеры....например таймер можно заставить отрабатывать секундные интервалы(как - неважно...можно подобрать кварц чтоб по предделителям было подходящее значение) а второй таймер заставить тактоваться от внешней ножки...в прерывании первого таймера(секунд) считываем показания второго таймера(что он успел насчитать) и это и есть частота...проблем нет - всё точно...но...частот меньше 1 герца не увидеть...промежуточных частот тож не увидеть

второй способ проще
в прерывании смотрим - если таймер не запущен то обнуляем его, запускаем на макс частоте процесора и выходим из прерывания
когда потом прийдёт второе прерывание и мы увидим что таймер запущен - останавливаем его, считываем сколько он там наклацать успел, и делаем простой расчет:
F=Fcpu/Tcnt
тоесть мы частоту проца(в герцах) делим на то что натикал таймер...
тут есть одна особенность - таймер умеет считать только до 256 или до 65535 а дальше начнет сначала - потому надо настроить прерывание по переполнению в котором мы будем считать сколько раз таймер переполнялся...тогда во втором приходе прерывания мы возьмём то что в самом таймере есть и прибавим вол-во прерываний таймера умноженное на 256(или 65535 если таймер 16-тибитный используется)
достоинство метода - суперточное измерение низких частот с любым возможным колвом дробной части...это бывает важно для спидометра...вы же не хотите видеть на экране скорость 6, 12, 18, 24, 30 и так далее...вам захочется видеть промежуточные значения...
недостаток метода - скорость обновления напрямую зависит от времени импульсов...тоесть если вы едите 1 км/ч с датчиком выдающим 1 импульс на км то вы и увидите значение скорости только через километр(в лучшем случае)...ну если вдаваться в подробности то есть методы увидеть промежуточные результаты....

главное - начните а там мы Вам поможем....наработки есть готовые приборы тоже есть так что подскажем
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение GhostAnton »

GhostAnton, не надо цитировать, тем более полностью, сообщение на которое сразу за ним отвечаешь..
Форум не резиновый и читать такие темы не удобно.. Привыкай сразу и к правильному..

МитяРа..



Получается тогда следующее, чтоб посчитать 1 секунду времени при тактовой частоте процессора 8000000Гц используя Timer2 нужно таймер настроить так 8000000Гц/64 (предделитель) получаем 125000Гц и используем сброс при совпадении 125 получим 1000Гц и это будет ровняться 1мс времени работы, подсчитав 1000 таких прерываний получим ровно 1 секунду, далее для тахометра просто получим значение счетчика внешних прерываний, это и будет частота вращения в секунду *60 и получаю количество оборотов в 1 минуту, сбрасываю счетчик по внешнему прерыванию в 0 и повторяю все операции. Поправьте меня если я не правильно понял.
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение clawham »

прав! для тахометра лучше и не придумаеш....только надо считать не одну секунду а хотябы в десять раз меньший отрезок времени....потому что знать какой была скорость двигателя секунду назад неинтересно ) медленно обновляться будут показания....ну и умножать "насчитанное" надо будет не на 60 а на 600 (если отмерять не 1000 миллисекунд а 100)
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение Аlex »

умножать "насчитанное" надо будет не на 60 а на 600
Только тут один минусик появляется: дискретность показаний будет = 600, т.е. на дисплее обороты будут показываться +-600 об/мин. Об этом не стоит забывать. :roll:
ИМХО, мерить период - самый нормальный вариант. Обороты можно будет считать с хорошим разрешением.
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение akl »

:cry: Неее, дискрет будет 120об/мин, т.к.
GhostAnton писал(а):...Сниматься показания планируются с 1 цилиндрового 4-х тактного двигателя, максимальная частота 10000 оборотов, измерения хочу выводить раз в секунду.
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение GhostAnton »

Аlex писал(а):мерить период - самый нормальный вариант.

Не получается правильно замерить период между импульсами, я пробую при обработке внешнего прерывания получить частоту = 1/число прерываний по 1000 гц, получаются слишком большие числа и высокие обороты не получается измерить. К каким частотам лучше всего привязаться?
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение clawham »

так так так
ещё раз
у вас мотор 10000 об/мин выдаёт?
это сколько в секунду(герц) с датчика? что есть датчик? прерыватель зажигания?

10000 об /мин это 166 герц если импульс с каждого оборота приходит
при замере периода это мелочь..у меня мега на 8 мегагерцах 2 килогерца периодами с прерыванием высчитывала нормально (+-10%) шаг

просто системный таймер надо на 8 мегагерцах запустить или 16-ти - тоесть на системной частоте проца
и не 1/число тиков таймера между импульсами а 8000000/число тиков таймера между прерываниями
вообще говоря можно и без прерывания обойтись...у таймера есть режим захвата...но ваш случай это показометр и +-5% это ничего
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение Аlex »

akl писал(а)::cry: Неее, дискрет будет 120об/мин, т.к.
Точно, там же 4 такта на оборот. Согласен, +-120 об/мин.

GhostAnton, Вам нужно считать не переполнения таймера, а считывать сам таймер, затактированный от тактовой частоты МК. А его переполнения считать нужно для расширения разрядности. Кол-во переполнений - это будут старшие байты периода.
GhostAnton
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Пн ноя 21, 2011 19:07:28

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение GhostAnton »

Не совсем получается реализовать, слишком неточно получается измерение по способу

в прерывании смотрим - если таймер не запущен то обнуляем его, запускаем на макс частоте процесора и выходим из прерывания
когда потом прийдёт второе прерывание и мы увидим что таймер запущен - останавливаем его, считываем сколько он там наклацать успел, и делаем простой расчет:
F=Fcpu/Tcnt
тоесть мы частоту проца(в герцах) делим на то что натикал таймер...


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

if(TCCR0==0x00)
{ //запустим таймер
TCCR0=0x01;
TCNT0=0x00;
OCR0=0x00;
}
else
{
//остановим таймер и сделаем расчеты i - количество полных кругов таймера
TCCR0=0x00;
Count = TCNT0;
frequency = 8000000UL/(i*255+Count);
i=0;
}

Получается что когда подаю частоту 1000 гц (в моем рассматриваемом случает это 1000 оборотов) то получается 1150 при увеличении частоты погрешность достигает более 1000, каким образом сделать расчеты и подсчеты чтоб погрешность составляла 1%, для моего прибора это очень важно.
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение clawham »

погрешность? а проц тактуете от чего?

и зачем делить в прерывании?

и ксатти да...при повышении частоты падает и точность...

поэтому частоту проца повыше и постабильней

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

тоесть

заводите внешнюю переменную замеренного времени

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

а дальше во временную переменную кидаете кол-во переполнений, сдвигаете влево на 8 бит(если таймер 8 бит или на 16 если 16тибитный(что лучше)) и приплюсовываете значение сохраненное самого таймера,
при выходе из прерывания взводите битовый флаг - готов новый замер

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


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

да что я рассказываю - скачайте исходники ваттметра и сами посмотрите...
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение akl »

GhostAnton писал(а):Не совсем получается реализовать, слишком неточно получается измерение по способу
Здравствуйте. Не получается потому, что все подготовительные операции нужно делать до начала измерения, а не во время измерения. Т.е.
-запретить прерывания INT0 и переполнение Т0
-провести начальные установки
i=0
TCCR0=0; остановить таймер и
TCNT0=9; установить начальное значение Т0, компенсирующее начальную задержку, вызванную
; прерыванием от входного сигнала на INT0 и запуском Т0
TIFR=0 ;
GIFR=0 ;
- глобально разрешить все прерывания
- и вот только сейчас будет следовать
if(TCCR0==0x00)
{ //запустим таймер
TCCR0=0x01;
}
else
{
//остановим таймер и сделаем расчеты i - количество полных кругов таймера
TCCR0=0x00;
Count = TCNT0;
frequency = 8000000UL/(i*255+Count); это ошибка - нужно i*256
i=0;
}

GhostAnton писал(а):Получается что когда подаю частоту 1000 гц (в моем рассматриваемом случает это 1000 оборотов) то получается 1150 при увеличении частоты погрешность достигает более 1000, каким образом сделать расчеты и подсчеты чтоб погрешность составляла 1%, для моего прибора это очень важно.
Погрешность определения частоты таким методом определяется P[Гц]>=Fx/(Fclk*Tизм.) или для Ваших данных P[Гц]>=1000/(8'000'000*0.001)>=0.125Гц
Аватара пользователя
s_black
Мучитель микросхем
Сообщения: 411
Зарегистрирован: Вс авг 10, 2008 19:35:49
Откуда: Евпатория
Контактная информация:

Re: ATmega16 - измерение частоты: внешнее прерывание и расче

Сообщение s_black »

Топикстартеру.
А почему Вы упёрлись во внешнее прервание? Кто мешает таймером считать внешние импульсы в течении, допустим, 100 мс (ну, или сколько там нужно), подавая их на вход Т1 (Т3)?
Ответить

Вернуться в «AVR»