Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Внутренние таймеры Arduino: точное тайминг без delay()

Компоненты и материалы

КомпонентКоличество
Arduino UNO1
Светодиод (любой)1
Резистор 220 Ом1

О проекте

Обзор

Для точного отсчёта времени нужно использовать таймеры. Функция delay() блокирует выполнение, а таймер работает на прерываниях — основной код продолжает работать.

В этом уроке разбираем TIMER0 (8-битный) — самый простой. В будущем можно рассмотреть TIMER1 и TIMER2.

Как это работает

Смотрим даташит ATmega328P. Схема таймера:

Внутренние таймеры Arduino: точное тайминг без delay()

Тактирующий сигнал (16 МГц) проходит через предделитель (prescaler), затем инкрементирует регистр TCNT0. В режиме CTC (Clear Timer on Compare) значение TCNT0 сравнивается с OCR0A. При совпадении генерируется прерывание TIMER0_COMPA_vect.

Предделитель настраивается регистром TCCR0B:

Внутренние таймеры Arduino: точное тайминг без delay()
Внутренние таймеры Arduino: точное тайминг без delay()

Формула расчёта OCR0A для нужного периода:

Внутренние таймеры Arduino: точное тайминг без delay()

Пример: прерывание каждые 1 мс (1 кГц) при 16 МГц и предделителе 64:

TCCR0A |= (1 << WGM01);        // CTC режим
OCR0A = 0xF9;                  // 249 -> 1 мс
TIMSK0 |= (1 << OCIE0A);       // разрешить прерывание
sei();                         // глобальное разрешение прерываний
TCCR0B |= (1 << CS01) | (1 << CS00); // предделитель 64

Важно: предделитель включать последним — после этого таймер стартует. Чтобы остановить — обнулить TCCR0B.

Пример: мигание встроенным LED раз в секунду

int timer = 0;
bool state = 0;

void setup() {
  pinMode(13, OUTPUT);
  TCCR0A = (1 << WGM01);       // CTC
  OCR0A = 0xF9;                // 1 мс
  TIMSK0 |= (1 << OCIE0A);     // прерывание по совпадению
  sei();                       // разрешить прерывания
  TCCR0B |= (1 << CS01) | (1 << CS00); // предделитель 64
}

void loop() {
  if (timer >= 1000) {         // 1000 мс = 1 с
    state = !state;
    timer = 0;
  }
  digitalWrite(13, state);
}

ISR(TIMER0_COMPA_vect) {
  timer++;                     // инкремент каждые 1 мс
}

Схема

Внутренние таймеры Arduino: точное тайминг без delay()

Производственный процесс

  1. Сборка Bluetooth-робота-шпиона на Arduino с управлением с телефона
  2. FlickMote: жестовое IR-пульт для умного дома на Arduino 101 и ультразвуковом датчике
  3. DIY Arduino TV-B-Gone: универсальный пульт для выключения любого телевизора
  4. Создание пользовательских LED-часов с будильником — видно с 12 метров
  5. Find Me: Умный поисковик вещей на Arduino и Bluetooth
  6. Оптимизированные решения питания для проектов на Arduino
  7. Крестики-нолики на Arduino с матрицей MAX7219 и картонным корпусом
  8. Пошаговое руководство: сборка умного четырёхногого робота на Arduino
  9. Своё рулевое управление (джойстик) для игр на Arduino
  10. Построение полнофункционального станка с ЧПУ на базе Arduino Nano R3