Таймери Arduino UNO — Частина 4. Використання таймерів для керування сервоприводами
Теорія
Чому сервоприводи потребують ШІМ 50 Гц
Стандартні сервоприводи для моделювання керуються імпульсами тривалістю від 1 мс до 2 мс, що повторюються кожні 20 мс (частота 50 Гц). Тривалість імпульсу визначає кут повороту:
- 1 мс — мінімальне положення (приблизно 0°).
- 1,5 мс — середнє положення (90°).
- 2 мс — максимальне положення (180°).
Таймери мікроконтролера дозволяють генерувати такі імпульси з високою точністю, що особливо важливо під час керування декількома сервоприводами одночасно.
Використання Timer1 для генерації сигналу
На Arduino UNO (ATmega328P) Timer1 — це 16-бітний таймер, який ідеально підходить для генерації низькочастотного точного сигналу. У режимі Fast PWM або Phase Correct PWM можна встановити частоту 50 Гц і регулювати тривалість імпульсу через регістри OCR1A або OCR1B.
Відмінність Servo.h від ручного налаштування таймера
Бібліотека Servo.h спрощує роботу з сервоприводами, автоматично налаштовуючи таймер і забезпечуючи підтримку декількох каналів. Однак:
- Вона займає частину ресурсів таймера (зазвичай Timer1).
- Має фіксовану частоту оновлення.
- Може конфліктувати з іншими задачами, що використовують той самий таймер.
Ручне налаштування дає повну свободу, дозволяє оптимізувати код і використовувати лише потрібні ресурси.
Практика
Рух сервопривода без бібліотеки Servo.h
void setup() {
pinMode(9, OUTPUT); // OC1A
// Налаштування Timer1 для Fast PWM, частота 50 Гц
TCCR1A = (1 << COM1A1) | (1 << WGM11); // Вивід на OC1A, режим Fast PWM (ICR1 — TOP)
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); // Дільник 8
ICR1 = 39999; // 16 МГц / 8 / 50 Гц - 1 = 39999
OCR1A = 3000; // ~1.5 мс (середнє положення)
}
void loop() {
OCR1A = 2000; // Поворот в один бік (~1 мс)
delay(1000);
OCR1A = 4000; // Поворот в інший бік (~2 мс)
delay(1000);
}
Проєкт: Двовісний поворотний модуль камери
У цьому проєкті ми керуємо двома сервоприводами — по осях X та Y, створюючи поворотний механізм для камери.
void setup() {
pinMode(9, OUTPUT); // OC1A — вісь X
pinMode(10, OUTPUT); // OC1B — вісь Y
// Налаштування Timer1 для Fast PWM, 50 Гц
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
ICR1 = 39999;
OCR1A = 3000; // X у центр
OCR1B = 3000; // Y у центр
}
void loop() {
// Панорамування
for (int pos = 2000; pos <= 4000; pos += 50) {
OCR1A = pos;
delay(20);
}
for (int pos = 4000; pos >= 2000; pos -= 50) {
OCR1A = pos;
delay(20);
}
// Нахил
for (int pos = 2000; pos <= 4000; pos += 50) {
OCR1B = pos;
delay(20);
}
for (int pos = 4000; pos >= 2000; pos -= 50) {
OCR1B = pos;
delay(20);
}
}
Таким чином, ми отримуємо плавний і точний контроль над положенням камери без використання додаткових бібліотек, що зменшує навантаження на мікроконтролер та покращує сумісність з іншими модулями.





