Таймери Arduino UNO — Частина 5. Вимірювання тривалості імпульсів і частоти (Input Capture)
Теорія
Режим Input Capture (ICP1)
Режим Input Capture — це спеціальна функція Timer1 у мікроконтролері ATmega328P, яка дозволяє з високою точністю фіксувати моменти приходу фронтів сигналу (зростаючого або спадаючого) на піні ICP1 (Arduino UNO — пін D8).
Коли на вхід ICP1 надходить вибраний фронт сигналу, поточне значення лічильника TCNT1 автоматично копіюється в регістр ICR1. Це дозволяє точно зафіксувати момент події без затримок, які могли б виникнути під час опитування піна у звичайному коді.
Як виміряти частоту і тривалість
- Частота розраховується за формулою:
F = F_CPU / (Prescaler * ΔTCNT), деΔTCNT— різниця між двома захватами, аPrescaler— вибраний дільник таймера. - Тривалість імпульсу можна визначити, вимірявши час між фронтами (зростаючим і спадаючим) одного імпульсу.
Input Capture корисний у завданнях, де потрібна висока точність вимірювань — наприклад, у тахометрах, аналізаторах сигналів, частотомірах.
Практика
Вимірювання частоти сигналу від датчика Холла
Приклад коду для вимірювання частоти обертання колеса з датчиком Холла:
volatile uint16_t lastCapture = 0;
volatile uint16_t period = 0;
float frequency = 0;
void setup() {
Serial.begin(9600);
pinMode(8, INPUT);
TCCR1A = 0; // Звичайний режим
TCCR1B = 0;
TCCR1B |= (1 << ICES1); // Захоплення за зростаючим фронтом
TCCR1B |= (1 << CS11); // Дільник 8
TIMSK1 |= (1 << ICIE1); // Дозвіл переривання захоплення
}
ISR(TIMER1_CAPT_vect) {
uint16_t capture = ICR1;
period = capture - lastCapture;
lastCapture = capture;
}
void loop() {
if (period > 0) {
frequency = 16000000.0 / (8.0 * period);
Serial.print("Частота: ");
Serial.print(frequency);
Serial.println(" Гц");
delay(500);
}
}
Проєкт: Тахометр на Arduino UNO
У цьому проєкті ми використовуємо Input Capture для створення тахометра, що вимірює оберти на хвилину (RPM) двигуна.
volatile uint16_t lastCapture = 0;
volatile uint16_t period = 0;
float rpm = 0;
void setup() {
Serial.begin(9600);
pinMode(8, INPUT);
TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << ICES1); // Захоплення за зростаючим фронтом
TCCR1B |= (1 << CS11); // Дільник 8
TIMSK1 |= (1 << ICIE1); // Переривання захоплення
}
ISR(TIMER1_CAPT_vect) {
uint16_t capture = ICR1;
period = capture - lastCapture;
lastCapture = capture;
}
void loop() {
if (period > 0) {
float frequency = 16000000.0 / (8.0 * period);
rpm = frequency * 60.0; // 1 імпульс на оберт
Serial.print("RPM: ");
Serial.println(rpm);
delay(500);
}
}
Такий тахометр можна застосувати у моделях автомобілів, мотоциклів, вентиляторах та інших механізмах, де потрібно вимірювати швидкість обертання.





