RPM-метр для компьютерного куллера
Написал на WinAVR программу для ATMega8 для измерения частоты вращения двух компьютерных куллеров. Реализовано измерение оборотов кратное 60 об/мин, но хотелось бы измерить частоту вращения, кратную 10 об/мин, а как это сделать - не пойму. В своей программе использую прерывание по входу INT0 и INT1 для подсчета количества импульсов, пришедших от таходатчика куллера. Период подсчета импульсов - 1 секунда, устанавливаю при помощи таймера TCCR0, таймер TCCR1 выполняет функции двух ШИМ.
- Реклама
Лучше проводить анализ данных по прерываниям поочередно, т.е. секунду мониторим ИНТ0, ИНТ1 отключен в это время, потом наоборот. Несколько непонятно, как у Вас реализовано измерение частоты, откуда берется такая кратность? Стандартные подходы: либо считаем кол-во импульсов за единицу времени, либо время, за которое приходит N импульсов. На Форуме есть примеры реализации и того, и другого, поищите. Можно без проблем измерять обороты с точностью до 1.
Оптимизм х (Опыт + Знания) = const
То, что я видел, было реализовано для одного куллера и используя вход ICP1, или так же как и в моем случае - с дискретностью 60 об/мин.
Я считаю 31250 прерываний, частота микроконтроллера 8 МГц без предделителя. Кусок кода (для одного куллера):
Я считаю 31250 прерываний, частота микроконтроллера 8 МГц без предделителя. Кусок кода (для одного куллера):
Код: Выделить всё
SIGNAL (SIG_INTERRUPT0)
{
count_pulses_1++;
}
//When overflow occurs
SIGNAL (SIG_OVERFLOW0)
{
//TCNT0=0xFD;
i++;
if (i==31250)
{
//PORTD ^=0x01;
rpm_1=60*(unsigned int)count_pulses_1;
i=0;
count_pulses_1=0;
}
}
- Сообщения: 459
- Зарегистрирован: Вс июн 01, 2008 12:16:38
У вас алгоритм подсчета импульсов за определенное время, в этом случае чтобы добиться дискретности показаний 10 об/мин, нужно увеличить время счета в 6 раз (умножить константу для i во втором прерывании на 6), а в формуле для rpm_1 уже использовать 10, соответственно показания будут обновляться раз в 6 секунд.Andergrin писал(а):То, что я видел, было реализовано для одного куллера и используя вход ICP1, или так же как и в моем случае - с дискретностью 60 об/мин.
Я считаю 31250 прерываний, частота микроконтроллера 8 МГц без предделителя. Кусок кода (для одного куллера):Код: Выделить всё
SIGNAL (SIG_INTERRUPT0) { count_pulses_1++; } //When overflow occurs SIGNAL (SIG_OVERFLOW0) { //TCNT0=0xFD; i++; if (i==31250) { //PORTD ^=0x01; rpm_1=60*(unsigned int)count_pulses_1; i=0; count_pulses_1=0; } }
Как мне кажется для низкой частоты такой алгоритм неоптимален, лучше измерять период следования импульсов а затем вычислять частоту или число оборото в минуту.
Пробую разные варианты, и что-то меня сейчас смущает, так это таймер TCCR0, а точнее его регистр TCNT0. Я установил тактирование от внутреннего генератора 8 МГц без предделителя, и записываю в TCNT0 число 255, как я понимаю после одного такта генератора он переполняется. По появлению 1 в регистре TIFR, записываю 1 или 0 в порт, на виртуальном осциллографе получаю прерывание периодом 5,22 мск, хотя по идее должно быть 0,125 мск. Так и должно быть, или я что-то делаю не так?
- Реклама
- Сообщения: 459
- Зарегистрирован: Вс июн 01, 2008 12:16:38
Лучше бы код выложили, ибо не понятно как вы записываете в таймер число: в прерывании или нет? останавливаете при этом таймер или нет? и т. п. Для генерирования временных отсчетов не кратных 256 (ну или 65356 для 2х байтного таймера) лучше использовать режим СТС (Clear Timer on Compare) и регистр сравнения. Как говорит даташит в таймере 0 нет такой возможности, поэтому предлагаю рассмотреть возможность использования таймера1 или таймера2, если он будет работать на измерения.Andergrin писал(а):Пробую разные варианты, и что-то меня сейчас смущает, так это таймер TCCR0, а точнее его регистр TCNT0. Я установил тактирование от внутреннего генератора 8 МГц без предделителя, и записываю в TCNT0 число 255, как я понимаю после одного такта генератора он переполняется. По появлению 1 в регистре TIFR, записываю 1 или 0 в порт, на виртуальном осциллографе получаю прерывание периодом 5,22 мск, хотя по идее должно быть 0,125 мск. Так и должно быть, или я что-то делаю не так?
З. Ы. У таймера0 есть предделитель как он сконфигурирован? может быть в этом причина такого периода?
Здравствуйте.Andergrin писал(а):То, что я видел, было реализовано для одного куллера и используя вход ICP1, или так же как и в моем случае - с дискретностью 60 об/мин.
Позвольте не согласиться с Вами. С помощью ICP можно очень точно и быстро измерить скорость вращения.
Посмотрите веточку http://www.radiokot.ru/forum/viewtopic.php?t=12082
Допустим, что необходимо измерить скорость вращения двух источников; для этого есть следующие возможности
- задействовать INT0 и INT1 примерно так как в схеме
- время измерения скорости вращения 0.25 сек
и ограничения
- таймер Т1 используется для формирования ШИМ в пределах 0...10'000 импульсов Fclk=8МГц
Далее, назначаем регистры-счетчики
-счетчик числа переполнений таймера Т1 250'000:10000*0.125=200, свидетельствующий об окончании времени измерения
- счетчик числа периодов (Nx1) измеряемой скорости вращения 1
- счетчик числа периодов (Nx2) измеряемой скорости вращения 2
- регистр А1 памяти начального состояния Т1 в момент начала измерения скорости 1
- регистр А2 памяти начального состояния Т1 в момент начала измерения скорости 2
- регистр А11 памяти конечного состояния Т1 в момент окончания измерения скорости 1
- регистр А22 памяти конечного состояния Т1 в момент окончания измерения скорости 2
Далее разрешаем прерывания INT0, INT1, ICP, по прерываниям заносим значения А1,А2 и запрещаем прерывание ICP до окончания времени измерения. После окончания времени измерения вновь разрешаем прерывание ICP для получения значений А11, А22. Прерывания INT0, INT1 наращивают значения Nx1,Nx2 соответственно.
Далее, пользуясь алгоритмом приведенным в веточке получаем результаты.
Пример:
S1=6789.012 об/мин А1=357
S2=7654.321 об/мин А2=7531
после измерения должно получиться
S1'=6789.015 об/мин
S2'=7654.324 об/мин
Подчеркнутые цифры- погрешность метода.
Наконец то соорудил таки алгоритм измерения частоты оборотов с шагом 1 об/мин. Пока что сделал только один канал, на таймере TCCR2, но без труда можно реализовать второй канал на таймере TCCR0. Частота тактового генератора 8 МГц, установлен предделитель на 8, тоесть период одного такта таймера составляет 1 мкс. По переполнению таймера содержимое переменной i увеличивается на единицу и одержанное значение умножается на 256 (количество тактов переполнения таймера, которое отвечает 256 мкс). После поступления тахосигнала от куллера переходим в оброботчик прерываний по INT0, присваиваем переменной n текущее значение счетчика TCNT2, и проводим вычисление периода импульса по формуле T(мкс)=i*256мкс+TCNT2. Остается только вычислить количество оборотов по формуле N=60000000(мкс)/T(мкс)
Исходники и пример работы в Протеусе прилагаются.
Исходники и пример работы в Протеусе прилагаются.
- Вложения
-
- rpm.rar
- (67 КБ) 224 скачивания
- Сообщения: 459
- Зарегистрирован: Вс июн 01, 2008 12:16:38
Я бы еще для полного счастья в обработчике внешнего прерывания 0 ставил бы флаг что данные обновились, а переменную count_1 и переменную b вычислял бы в основном цикле, после того как флаг проходил бы проверку на истинность. Цель данных преобразований - сделать обработчики прерываний как можно короче. Возможно в данном проекте это и не актуально, но все-же.Andergrin писал(а):Наконец то соорудил таки алгоритм измерения частоты оборотов с шагом 1 об/мин. Пока что сделал только один канал, на таймере TCCR2, но без труда можно реализовать второй канал на таймере TCCR0. Частота тактового генератора 8 МГц, установлен предделитель на 8, тоесть период одного такта таймера составляет 1 мкс. По переполнению таймера содержимое переменной i увеличивается на единицу и одержанное значение умножается на 256 (количество тактов переполнения таймера, которое отвечает 256 мкс). После поступления тахосигнала от куллера переходим в оброботчик прерываний по INT0, присваиваем переменной n текущее значение счетчика TCNT2, и проводим вычисление периода импульса по формуле T(мкс)=i*256мкс+TCNT2. Остается только вычислить количество оборотов по формуле N=60000000(мкс)/T(мкс)
Исходники и пример работы в Протеусе прилагаются.
- Сообщения: 459
- Зарегистрирован: Вс июн 01, 2008 12:16:38
Нет вы не поняли, TIFR это регистр флагов прерываний от таймеров, его трогать не надо, тем более, что записью единицы в нужный бит вы не выставляете, а наоборот сбрасываете соответствующий флаг.(загляните в даташит). Я имел ввиду, что нужно организовать программный флаг, который выставлять и сбрасывать самому. Данные пересчитывать значения только после установки флага, после пересчета значений флаг сбрасывать.Andergrin писал(а):Выставлял TIFR |=0x40, а вот если count_1 перенести из обработчика прерываний в главную функцию то в результате отображается "хаотично" изменяющиеся данные, а когда переменная count_1 в обработчике прерываний - все нормально. А точность тут достаточная, десятые я все равно не отображаю.
Собственно, я это и хотел сделать, чтоб после появления внешнего прерывания сразу начинался счет сначала, чтоб к следующему прерыванию получить новые корректные данныеsmac писал(а):Нет вы не поняли, TIFR это регистр флагов прерываний от таймеров, его трогать не надо, тем более, что записью единицы в нужный бит вы не выставляете, а наоборот сбрасываете соответствующий флаг.(загляните в даташит)
- Сообщения: 459
- Зарегистрирован: Вс июн 01, 2008 12:16:38
Флаг прерывания от таймера или регистра стравнения автоматически сбрасываетя при обслуживании запроса прерывания, т. е. при входе в обработчик прерывания.Andergrin писал(а): Собственно, я это и хотел сделать, чтоб после появления внешнего прерывания сразу начинался счет сначала, чтоб к следующему прерыванию получить новые корректные данные
Вариант прошивки для измерения частоты оборотов от двух источников
- Вложения
-
- rpm.rar
- (61.87 КБ) 246 скачиваний


