Глиф Учебники

Как сделать задержку без delay — millis

Справочник · Arduino · 1 минута чтения

Шаблон «делать что-то раз в N миллисекунд», который не останавливает скетч:

Arduino
const unsigned long INTERVAL = 1000;   // каждые 1000 мс
unsigned long previous = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (millis() - previous >= INTERVAL) {
    previous = millis();
    Serial.println("Прошла секунда");  // ваше действие
  }
  // остальной код выполняется без остановки
}

millis() — сколько миллисекунд прошло с запуска платы. Скетч на каждом проходе loop проверяет, прошёл ли интервал с прошлого раза; если нет — сразу идёт дальше. Поэтому кнопки, датчики и команды из монитора порта обрабатываются всё время, а не после окончания паузы.

Однократная задержка после события

Например, нажали кнопку — светодиод горит 5 секунд и гаснет, а кнопку можно нажать снова в любой момент:

Arduino
const int BUTTON = 2;
const unsigned long ON_TIME = 5000;

unsigned long startTime = 0;
bool ledOn = false;

void setup() {
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if (digitalRead(BUTTON) == LOW) {      // нажали — включить и запомнить время
    digitalWrite(LED_BUILTIN, HIGH);
    ledOn = true;
    startTime = millis();
  }
  if (ledOn && millis() - startTime >= ON_TIME) {   // прошло 5 секунд — выключить
    digitalWrite(LED_BUILTIN, LOW);
    ledOn = false;
  }
}

Пока кнопка нажата, отсчёт всё время начинается заново, — так работает свет на лестнице с датчиком движения.

Несколько интервалов

Каждому делу — своя переменная «время прошлого раза»:

Arduino
unsigned long lastSensor = 0, lastDisplay = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  unsigned long now = millis();
  if (now - lastSensor >= 2000) {       // раз в 2 секунды
    lastSensor = now;
    Serial.println("Чтение датчика");
  }
  if (now - lastDisplay >= 500) {       // раз в полсекунды
    lastDisplay = now;
    Serial.println("Обновление экрана");
  }
}

Частые ошибки

Подробный разбор, почему вычитание переживает переполнение, — в уроке millis вместо delay.