Таймеры Arduino UNO — Часть 6. Оптимизация и нестандартные применения
Теория
Совмещение работы нескольких таймеров
В микроконтроллере ATmega328P (Arduino UNO) есть три аппаратных таймера: Timer0, Timer1 и Timer2. Каждый из них может работать в своём режиме, что позволяет одновременно выполнять несколько задач:
- Timer0 — обычно используется функциями
millis()иdelay(), но его можно перенастроить. - Timer1 — 16-битный, подходит для точных замеров времени, генерации сигналов низкой частоты, работы с сервоприводами.
- Timer2 — 8-битный, может работать на другой частоте (асинхронно), полезен для звука и ШИМ.
Совмещение работы требует аккуратного управления регистрами, чтобы конфигурации одного таймера не мешали работе других.
Оптимизация под низкое энергопотребление
Таймеры могут быть источником лишнего потребления энергии в спящем режиме. Для снижения энергопотребления можно:
- Отключать ненужные таймеры с помощью регистра
PRR(Power Reduction Register). - Использовать режимы сна микроконтроллера (
SLEEP_MODE_IDLE,SLEEP_MODE_PWR_DOWN). - Снижать частоту тактирования или увеличивать предделитель.
Подмена работы millis() и delay() своими таймерами
Функции millis() и delay() используют Timer0. Если этот таймер нужен для других задач, можно отключить стандартный обработчик и реализовать собственный счётчик времени на Timer1 или Timer2. Это позволяет полностью контролировать тайминг программы.
Практика
Секундомер с точностью 0.1 мс
volatile unsigned long ticks = 0;
ISR(TIMER1_COMPA_vect) {
ticks++; // каждые 100 мкс
}
void setup() {
Serial.begin(9600);
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS10); // CTC, делитель 1
OCR1A = 1599; // 16 МГц / 1600 = 10 000 Гц (100 мкс)
TIMSK1 = (1 << OCIE1A);
}
void loop() {
Serial.print("Время: ");
Serial.print(ticks / 10.0); // в миллисекундах с точностью 0.1 мс
Serial.println(" мс");
delay(500);
}
Звуковой генератор
void setup() {
pinMode(3, OUTPUT); // OC2B
TCCR2A = (1 << COM2B0) | (1 << WGM21); // Toggle OC2B, CTC
TCCR2B = (1 << CS20); // Без делителя
OCR2A = 113; // ~7 кГц
}
void loop() {
// Генерация звука идёт автоматически
}
Проект: Музыкальный генератор на таймерах
Этот проект воспроизводит простую мелодию, переключая частоты таймера в реальном времени.
struct Note {
uint16_t ocr;
uint16_t duration;
};
Note melody[] = {
{113, 500}, // Ля
{101, 500}, // Си
{95, 500}, // До
{85, 500}, // Ре
};
void setup() {
pinMode(3, OUTPUT);
TCCR2A = (1 << COM2B0) | (1 << WGM21); // Toggle OC2B, CTC
TCCR2B = (1 << CS20);
}
void loop() {
for (int i = 0; i < 4; i++) {
OCR2A = melody[i].ocr;
delay(melody[i].duration);
}
delay(1000);
}
Такой генератор можно использовать для создания простых звуковых сигналов, оповещений и даже музыкальных игрушек на Arduino UNO.





