Millis arduino обнулення. Arduino delay millis і micros для організації затримки в скетчі

Якщо ви хочете «поставити на паузу» мікроконтролер, то достатньо лише ввести інструкцію затримки delay в потрібному місці програми. Але це стає справжньою перешкодою, коли ви намагаєтеся робити інші речі, наприклад, відслідковувати натискання кнопки. В цьому випадку необхідно реалізовувати своєрідну багатозадачність.



Так, це додасть трохи рядків коду в ваші програми, але це, в свою чергу, зробить вас більш досвідченим програмістом і збільшить потенціал вашого Arduino. Для цього потрібно всього лише навчитися використовувати функцію millis.


Слід розуміти, що функція delay призупиняє виконання вашої програми Arduino, роблячи її нездатною робити що-небудь ще в цей період часу. Замість того, щоб припиняти всю нашу програму протягом певного часу, ми навчимося підраховувати, скільки часу пройшло до завершення дії. Це, звичайно ж, здійснюється за допомогою функції millis () і декількох змінних друзями для зберігання наших даних. Щоб все було легко в розумінні, ми почнемо з першого навчального скетчу під назвою «Blink», але в даному випадку будемо блимати світлодіодом без затримки.


Початок цієї програми таке ж як і у будь-який інший стандартної програми для Arduino. Спочатку йде оголошення всіх потрібних змінних і ліній введення / виводу (наприклад, лінії 13 для світлодіода). Тут нам також буде потрібно змінна типу integer для зберігання поточного стану світлодіода. Вона буде встановлена \u200b\u200bв LOW, оскільки початковий стан світлодіода - вимкнено. Потім оголосимо змінну «previousMillis» типу «unsigned long». На відміну від «int» довгі змінні без знака є 32 біта, це потрібно для змінних, значення яких може стати дуже великим - як потенційне час, яке ми можемо очікувати, до тих пір, поки не буде зроблено дію. Мінлива previousMillis буде використовуватися для зберігання часу, коли останній раз блимав світлодіод. Є також тип «const long», він теж 32-розрядний, але він не змінює значення, тобто це для констант (в даному випадку для константи interval). Ми встановимо його на 1000 і використовуємо в якості часу паузи, вимірюваного в мілісекундах.


  const int ledPin \u003d 13; // визначаємо висновок світлодіода // Variables will change: int ledState \u003d LOW; // ledState використовується для визначення стану світлодіода unsigned long previousMillis \u003d 0; // збереже час, коли останній раз оновлювався світлодіод // constants won "t change: const long interval \u003d 1000; // інтервал миготіння в мімлісекундах void setup () (// настройка лінії 13 виходу pinMode (ledPin, OUTPUT);)

Потім ми переходимо в нескінченний цикл. Пам'ятайте, що замість затримки ми хочемо підрахувати, скільки часу пройшло з моменту нашого останнього миготіння, в нашому нагоди 1000 мс. Якщо зазначений час минув, настав час змінити стан нашого світлодіода.


По-перше, ми встановимо беззнаковий довгий (unsigned long) «currentMillis» рівний «millis ()», що визначає даний час в мілісекундах. Це допоможе нам з'ясувати, чи перевищила різниця між поточним часом і попереднім часом 1000 мс. Для цього ми говоримо: «Якщо поточний час мінус попередній час, коли наш світлодіод блимав, більше або дорівнює нашому призначеному значенням 1000 мс, збережіть час останнього миготіння як попереднє». Це допоможе нам згадати, скільки часу пройшло з моменту останнього миготіння в наступному обході циклу. Потім, якщо стан світлодіода LOW, Ви можете це зробити HIGH, інакше Ви можете це зробити LOW. Потім за допомогою команди digitalWrite виведіть поточний стан на світлодіод.


void loop () (unsigned long currentMillis \u003d millis (); if (currentMillis - previousMillis\u003e \u003d interval) (// зберігаємо час останньої зміни стану світлодіода previousMillis \u003d currentMillis; // якщо світлодіод вимкнений, то включимо його, і навпаки if (ledState \u003d\u003d LOW) (ledState \u003d HIGH;) else (ledState \u003d LOW;) // вихід на світлодіод digitalWrite (ledPin, ledState);))

Функція millis () дозволяє вважати час, що минув з моменту запуску поточної програми. Функція повертає значення в форматі «unsigned long» і дозволяє вважати значення до 50 днів з моменту запуску програми. По закінченні цього часу відлік почнеться заново. Нижче наведено приклад використання функції millis ():

Unsigned long time; void setup () (Serial.begin (9600);) void loop () (Serial.print ( «Час включення:«); time \u003d millis (); // запам'ятати значення часу Serial.println (time); // відправка інформації через послідовний порт delay (1000);)

У наведеному вище прикладі, кожну секунду в монітор порту відправлятиметься інформація про час, який минув з моменту запуску програми. Оскільки час вимірюється в мілісекундах, то кожне наступне значення буде відрізнятися на 1000. Точність зчитування залежить від стабільності кварцового резонатора Arduino.

Функція micros ()

Функція micros () є аналогом функції millis (), різниця полягає в точності вимірювання. За допомогою функції micros () ми отримаємо час, що минув від запуску поточної програми в мікросекундах. Лічильник підрахованих мікросекунд буде скинутий після закінчення 70 хвилин. Нижче наведено приклад використання функції micros ():

Unsigned long time; void setup () (Serial.begin (9600);) void loop () (Serial.print ( «Час з моменту запуску:«); time \u003d micros (); Serial.print (time); Serial.println ( "мкс «); delay (1000);)

Так само, як і в прикладі з функцією millis (), тут кожну секунду в монітор порту відправлятиметься інформація про измеренном часу, різниця полягає лише в тому, що в даному випадку час вимірюється в мікросекундах.

Функція delay ()

Функція delay () дозволяє призупинити виконання поточної програми на вказане в параметрі час. Синтаксис команди виглядає наступним чином:

   // команди delay (500); // затримка на 0,5 сек // команди delay (1000); // затримка на 1с

Час вказується в мілісекундах (1 сек \u003d 1000 мс). Даний параметр може мати тип «unsigned long», який знаходиться в діапазоні від 0 до 4294967295. Нижче приклад використання команди delay ():

#define ledPin 13 void setup () (pinMode (ledPin, 13);) void loop () (digitalWrite (ledPin, HIGH); // включити LED delay (500); // почекати 500ms (0,5 сек) digitalWrite ( ledPin, LOW); // вимкнути LED delay (1000); // почекати тисячі мс (1 сек))

У наведеному вище прикладі, світлодіод загоряється на 0,5 секунди, потім гасне на 1 секунду і так далі, поки харчування Arduino звучати одну.

Функція delayMicroseconds ()

Функція delayMicroseconds () є різновидом функції delay (). Різниця полягає в кількості і точності відліку часу. Функція delay () дозволяє відраховувати час з точністю до 1 мілісекунди, в той час як delayMicroseconds () з точністю до 1 мікросекунди.

Значення, яке можна вказати в параметрі, перебувати в діапазоні від 0 до 16383. Для більш довгих часових інтервалів слід використовувати функцію delay () або кілька разів використовувати delayMicroseconds ().

   #define outPin 8 void setup () (pinMode (outPin, OUTPUT); // контакт 8 як вихід) void loop () (digitalWrite (outPin, HIGH); // контакт 8 високий стан delayMicroseconds (50); // пауза 50 мікросекунд digitalWrite (outPin, LOW); // контакт 8 низький стан delayMicroseconds (50); // пауза 50 мікросекунд)

Цей приклад генерує меандр з періодом 100 мікросекунд і заповненням 50%.

Вітаю, Андрій. Вельми цікавий ваш підхід до передачі багажу знань і досвіду, вами накопиченого. Дуже допомагає в починаннях. Ну і я, починаючи освоювати arduino маю бажання прогресувати. Тим більше, що зі сторонньою допомогою у мене це виходить швидше. Отже: спершу моє завдання було зробити робота, що їде по лінії. Зробив - все відмінно. Але далі, забезпечуючи його додатковими опціями, не розумів - чому він перестав коректно реагувати на лінію. Набрів на цю статтю і зрозумів причину.

Тепер у мене до вас питання: в нижче вказаному і готовому скетчі, з огляду на проблеми з delay, чи потрібно мені всюди, де присутня ця функція перейти на millis? Якщо так, то я розумію, що скетч доведеться переробляти майже весь? І не зовсім зрозуміло, як використовувати millis в вимірі відстані? Спасибі.

// Робот з функцією проходження по білій смузі

// ********************** Установка висновків моторів *********************** *

int MotorLeftSpeed \u200b\u200b\u003d 5; // Лівий (А) мотор ШВИДКІСТЬ - ENA

int MotorLeftForward \u003d 4; // Лівий (А) мотор ВПЕРЕД - IN1

int MotorLeftBack \u003d 3; // Лівий (А) мотор НАЗАД - IN2

int MotorRightForward \u003d 8; // Правий (В) мотор ВПЕРЕД - IN3

int MotorRightBack \u003d 7; // Правий (В) мотор НАЗАД - IN4

int MotorRightSpeed \u200b\u200b\u003d 9; // Правий (В) мотор ШВИДКІСТЬ - ENB

// ********************** Установка висновків УЗ датчиків ********************** *

int trigPinL \u003d 14; // завдання номера виведення лівого trig УЗ датчика

int echoPinL \u003d 15; // завдання номера виведення лівого echo УЗ датчика

int trigPinC \u003d 10; // завдання номера виведення центрального trig УЗ датчика

int echoPinC \u003d 11; // завдання номера виведення центрального echo УЗ датчика

int trigPinR \u003d 12; // завдання номера виведення правого trig УЗ датчика

int echoPinR \u003d 13; // завдання номера виведення правого echo УЗ датчика

// ********************* Установка висновків датчиків лінії *******************

const int LineSensorLeft \u003d 19; // вхід лівого датчика лінії

const int LineSensorRight \u003d 18; // вхід правого датчика лінії

int SL; // статус лівого сенсора

int SR; // статус правого сенсора

// ********************* Установка виведення світлової та звукової сигналізації **************

int Light \u003d 2; // завдання номера виведення світлової сигналізації

int Zumm \u003d 6; // завдання номера виведення зумера

int ledState \u003d LOW; // цієї змінної встановлюємо стан світлодіода

long previousMillis \u003d 0; // зберігаємо час останнього перемикання світлодіода

long interval \u003d 300; // інтервал між включення / вимиканням світлодіода (0,3 секунди)

// ********************* Мінлива вимір дистанції датчиками *************

unsigned int impulseTimeL \u003d 0;

unsigned int impulseTimeC \u003d 0;

unsigned int impulseTimeR \u003d 0;

long distL \u003d 0; // дистанція, виміряна лівим УЗ датчиком

long distC \u003d 0; // дистанція, виміряна центральним УЗ датчиком

long distR \u003d 0; // дистанція, виміряна правим Уз датчиком

// *********************************** SETUP ************ ********************

Serial.begin (9600); // запускаємо серійний порт (швидкість 9600)

// *************** Задаємо контакти моторів ****************

pinMode (MotorRightBack, OUTPUT); // Правий (В) мотор НАЗАД

pinMode (MotorRightForward, OUTPUT); // Правий (В) мотор ВПЕРЕД

pinMode (MotorLeftBack, OUTPUT); // Лівий (А) мотор НАЗАД

pinMode (MotorLeftForward, OUTPUT); // Лівий (А) мотор ВПЕРЕД

delay (duration);

// *************** Задаємо контакти датчиків смуги **************

pinMode (LineSensorLeft, INPUT); // визначенням pin лівого датчика лінії

pinMode (LineSensorRight, INPUT); // визначенням pin правого датчика лінії

// *************** Завдання режимів висновків УЗ датчиків **********************

pinMode (trigPinL, OUTPUT); // завдання режиму роботи виведення лівого trig УЗ датчика

pinMode (echoPinL, INPUT); // завдання режиму роботи виведення лівого echo УЗ датчика

pinMode (trigPinC, OUTPUT); // завдання режиму роботи виведення центрального trig УЗ датчика

pinMode (echoPinC, INPUT); // завдання режиму роботи виведення центрального echo УЗ датчика

pinMode (trigPinR, OUTPUT); // завдання режиму роботи виведення правого trig УЗ датчика

pinMode (echoPinR, INPUT); // завдання режиму роботи виведення правого echo УЗ датчика

// *************** Задаємо контакти світлової та звукової сигналізації *************************** *****

pinMode (Zumm, OUTPUT); // завдання режиму роботи виведення зумера

pinMode (Light, OUTPUT); // завдання режиму роботи виведення світлової сигналізації

// ****************** Основні команди руху ******************

void forward (int a, int sa) // ВПЕРЕД

analogWrite (MotorRightSpeed, sa);

analogWrite (MotorLeftSpeed, sa);

void right (int b, int sb) // ПОВОРОТ ВПРАВО (одна сторона)

digitalWrite (MotorRightBack, LOW);

digitalWrite (MotorLeftBack, LOW);

digitalWrite (MotorLeftForward, HIGH);

analogWrite (MotorLeftSpeed, sb);

void left (int k, int sk) // ПОВОРОТ ЛІВОРУЧ (одна сторона)

digitalWrite (MotorRightBack, LOW);

digitalWrite (MotorRightForward, HIGH);

analogWrite (MotorRightSpeed, sk);

digitalWrite (MotorLeftBack, LOW);

void stopp (int f) // СТОП

digitalWrite (MotorRightBack, LOW);

digitalWrite (MotorRightForward, LOW);

digitalWrite (MotorLeftBack, LOW);

digitalWrite (MotorLeftForward, LOW);

// ************************** Вимірювання дистанції ******************** *

void izmdistL () // вимір дистанції лівим УЗ датчиком

digitalWrite (trigPinL, HIGH);

digitalWrite (trigPinL, LOW); // імпульс 10мс на висновок trig УЗ датчика для вимірювання відстані

impulseTimeL \u003d pulseIn (echoPinL, HIGH); // зчитування відстані з УЗ датчика

distL \u003d impulseTimeL / 58; // Перераховуємо в сантиметри

void izmdistC () // вимір дистанції центральним УЗ датчиком

digitalWrite (trigPinC, HIGH);

digitalWrite (trigPinC, LOW); // імпульс 10мс на висновок trig УЗ датчика для вимірювання відстані

impulseTimeC \u003d pulseIn (echoPinC, HIGH); // зчитування відстані з УЗ датчика

distC \u003d impulseTimeC / 58; // Перераховуємо в сантиметри

void izmdistR () // вимір дистанції центральним УЗ датчиком

digitalWrite (trigPinR, HIGH);

digitalWrite (trigPinR, LOW); // імпульс 10мс на висновок trig УЗ датчика для вимірювання відстані

impulseTimeR \u003d pulseIn (echoPinR, HIGH); // зчитування відстані з УЗ датчика

distR \u003d impulseTimeR / 58; // Перераховуємо в сантиметри

// *********************************** LOOP ************ *********************

// ********************** Режим проходження по ЛІНІЇ ********************** ***

// ********************* світлова та звукова сигналізація **************

tone (Zumm, 900); // включаємо звук на 900 Гц

tone (Zumm, 900); // включаємо звук на 800 Гц

unsigned long currentMillis \u003d millis ();

if (currentMillis - previousMillis\u003e interval) // перевіряємо не пройшов чи потрібний інтервал, якщо пройшов то

previousMillis \u003d currentMillis; // зберігаємо час останнього перемикання

if (ledState \u003d\u003d LOW) // якщо світлодіод не горить, то запалюємо, і навпаки

ledState \u003d HIGH;

digitalWrite (Light, ledState); // встановлюємо стану виходу, щоб включити або вимкнути світлодіод

// ************************ Вимірювання дистанції ********************** **

Serial.println (distL);

Serial.println (distC);

Serial.println (distR);

if (distL\u003e 50 && distC\u003e 50 && distR\u003e 50) // якщо виміряна дистанція більше 50 сантиметрів - їдемо

SL \u003d digitalRead (LineSensorLeft); // зчитуємо сигнал з лівого датчика смуги

SR \u003d digitalRead (LineSensorRight); // зчитуємо сигнал з правого датчика смуги

// ************************* Проходження по чорній лінії ******************* ****

// РОБОТ на смузі - їдемо прямо

if (SL \u003d\u003d LOW & SR \u003d\u003d LOW) // БІЛИЙ - БІЛИЙ - їдемо ПРЯМО

forward (10, 100); // ПРЯМО (час, швидкість)

// РОБОТ починає зміщуватися з смуги - підрулюємо

else if (SL \u003d\u003d LOW & SR \u003d\u003d HIGH) // ЧОРНИЙ - БІЛИЙ - поворот вліво

left (10, 100); // поворот вліво (час, швидкість)

else if (SL \u003d\u003d HIGH & SR \u003d\u003d LOW) // БІЛИЙ - ЧОРНИЙ - поворот вправо

right (10, 100); // поворот вправо (час, швидкість)

// ФІНІШ - РОБОТ бачить обома датчиками смугу

else if (SL \u003d\u003d HIGH & SR \u003d\u003d HIGH) // ЧОРНИЙ - ЧОРНИЙ - СТОП

stopp (50); // СТОП

else // якщо виміряна дистанція менше або дорівнює мінімальній - стоїмо

Перше, з чим стикається освоює Arduino новачок, це неприємну властивість функції delay () - блокування виконання програми. Безліч прикладів в інтернеті використовують цю функцію, але практичне застосування якось натякає, що краще без неї обійтися.

Як і належить починаючому, я винайшов велосипед зробив свою реалізацію неблокірующіх затримки. Завдання стояло так:

  • Забезпечити псевдомногозадачность, щоб різні події відбувалися свого часу, зі своїми інтервалами і не блокували один-одного.
  • Було зручно цим користуватися.
  • Можна було оформити як бібліотеку і легко включати в інші проекти без копіпаст.
Підглянувши, що більшість ардуінскіх бібліотек зроблені із застосуванням ООП, я теж вирішив не виробляти і написав клас SmartDelay, який можна отримати з гітхаба як zip для додавання в Arduino IDE або зробити git clone в ~ / Arduino / libraries /

В результаті вийшло ось таке.

  #include   SmartDelay foo (1000000UL); // в мікросекундах void loop () (if (foo.Now ()) (// Код тут виконується кожен інтервал в мікросекундах, вказаний в конструкторі вище.) // Інший код)
  Метод Now () повертає true, якщо інтервал пройшов. В цьому випадку відлік починається знову на той же інтервал. Тобто, Now () кожен раз «перезаряджається» автоматично.

Класичне миготіння світлодіодом можна відразу ускладнити до миготіння двома. Наприклад, лампочки підключені до ніжок 12 і 11, повинні мигати з інтервалом в 1с і 777мс відповідно.

  #include   SmartDelay led12 (1000000UL); SmartDelay led11 (777000UL); setup () (pinMode (12, OUTPUT); pinMode (11, OUTPUT);) byte led12state \u003d 0; byte led11state \u003d 0; void loop () (if (led12.Now ()) (digitalWrite (12, led12state); led12state \u003d! led12state;) if (led11.Now ()) (digitalWrite (11, led11state); led11state \u003d! led11state;))
  У циклі можна виконувати ще щось, миготіння світлодіодів не блокуватиме виконання цього коду.

Зрозуміло, що це не повна заміна delay (), який зупиняє потік на заданий час, треба писати програму завжди як МКА (механізм кінцевих автоматів). Тобто, зберігати стан і в залежності від нього переходити до потрібного місця коду.

Старий варіант:

Action1 (); delay (1000); action2 (); delay (500); action3 (); ...
  Новий варіант:

Byte state \u003d 0; SmartDelay d (); ... switch (state) (case 0: action1 (); d.Set (1000000UL); state \u003d 1; break; case 1: if (d.Now ()) (action2 (); d.Set (500000UL) ; state \u003d 2;) break; case 2: if (d.Now ()) (action3 (); d.Stop (); state \u003d 0;) break;) ...
  Метод Set (інтервал) встановлює новий інтервал і повертає старий. Просто подивитися на інтервал можна методом Get ();

Stop () зупиняє обробку і Now () завжди повертає false.

Start () відновлює роботу і Now () починає працювати як зазвичай.

Якщо треба пригальмувати підрахунок часу, але не зупиняти зовсім, тобто метод Wait (). Наприклад, якщо блимає світлодіод 12, а при натисканні кнопки не блимає, досить додати ось такий код в loop () в прикладі з двома діодами вище:

If (digitalRead (9)) led12.Wait (); ...
  Так, при високому рівні сигналу на 9 нозі діод на 12 блимати не буде і продовжить, коли там з'явиться 0.

Коли за таким «таймером» промальовується екран, наприклад, і паралельно обробляються кнопки, то буває потрібно перемалювати екран або частина відразу після натискання на кнопку, а не чекати закінчення інтервалу. Для цього служить метод Reset (), після якого наступний виклик Now () поверне true. наприклад:

SmartDelay display (1000000UL); void loop () (if (btClick ()) display.Reset (); // тицьнув у кнопку, треба отрисовать екранчик. if (display.Now ()) screenRedraw (); // вивід екранчика.)
  З багів я бачу тільки, що не враховується переповнення лічильника мікросекунд, а в іншому так, треба почистити код. Мені не подобається, як зроблений Reset (), поки думаю.

Затримки в Ардуіно грають дуже велику роль. Без них не зможе працювати навіть найпростіший приклад Blink, який моргає світлодіод через заданий проміжок часу. Але більшість початківців програмістів мало знають про тимчасові затримки і використовують тільки Arduino delay, не знаючи побічних ефектів цієї команди. У цій статті я детально розповім про тимчасові функції і особливості їх використання в середовищі розробки Arduino IDE.

В Arduino cуществует кілька різних команд, які відповідають за роботу з часом і паузи:

  • delay ()
  • delayMicroseconds ()
  • millis ()
  • micros ()

Вони відрізняються за точністю і мають свої особливості, які варто враховувати при написанні коду.

Використання функції arduino delay

синтаксис

Ардуіно delay є найпростішою командою і її найчастіше використовують новачки. По суті вона є затримкою, яка призупиняє роботу програми, на вказане в дужках число мілісекунд. (В одній секунді 1000 мілісекунд.) Максимальне значення може бути 4294967295 мс, що приблизно дорівнює 50 діб. Давайте розглянемо простий приклад, що наочно показує роботу цієї команди.

Void setup () (pinMode (13, OUTPUT);) void loop () (digitalWrite (13, HIGH); // подаємо високий сигнал на 13 пін delay (10000); // пауза 10000мс або 10 секунд digitalWrite13, LOW); // подаємо низький сигнал на 13 пін delay (10000); // пауза 10000мс або 10 секунд)

У методі setup  прописуємо, що пін 13 буде використовуватися, як вихід. В основній частині програми спочатку на пін подається високий сигнал, потім робимо затримку в 10 секунд. На цей час програма як би припиняється. Далі подається низький сигнал і знову затримка і все починається спочатку. У підсумку ми отримуємо, що на пін по черзі подається, то 5 В, то 0.

Потрібно чітко розуміти, що на час паузи за допомогою delay робота програми припиняється, програма не буде отримувати ніяких даних з датчиків. Це є найбільшим недоліком використання функції delay в Arduino. Обійти це обмеження можна за допомогою переривань, але про це ми поговоримо в готельної статті.

Приклад delay з миготінням світлодіодом

  Приклад схеми для ілюстрації роботи функції delay.
  Можна побудувати схему з світлодіодом і резистором. Тоді у нас вийде стандартний приклад - миготіння світлодіодом. Для цього на пін, який ми позначили як вихідний, необхідно підключити світлодіод плюсовим контактом. Вільну ногу світлодіода через резистор приблизно на 220 Ом (можна трохи більше) підключаємо на землю. Визначити полярність можна, якщо подивитися на його нутрощі. Велика чашка всередині з'єднана з мінусом, а маленька ніжка з плюсом. Якщо ваш світлодіод новий, то визначити полярність можна по довжині висновків: довга ніжка - плюс, коротка - мінус.

функція delayMicroseconds

Ця функція є повним аналогом delay за винятком того, що одиниці вимірювання у неї не мілісекунди, а мікросекунди (в 1 секунді - 1000000 мікросекунд). Максимальне значення буде 16383, що дорівнює 16 мілісекунд. Дозвіл дорівнює 4, тобто число буде завжди кратно чотирьом. Шматочок прикладу буде виглядати наступним чином:

DigitalWrite (2, HIGH); // подаємо високий сигнал на 2 пін delayMicroseconds (16383); // пауза 16383мкс digitalWrite (2, LOW); // подаємо низький сигнал на 2 пін delayMicroseconds (16383); // пауза 16383мкс

Проблема з delayMicroseconds точно така ж, як у delay - ці функції повністю «вішають» програму і вона на деякий час буквально завмирає. В цей час неможлива робота з портами, зчитування інформації з датчиків і твір математичних операцій. Для мигалок даний варіант підходить, але досвідчені користувачі не використовують її для великих проектів, так як там не потрібні такі збої. Тому, набагато краще використовувати функції, описані нижче.

Функція millis замість delay

Функція millis () дозволить виконати затримку без delay на Ардуіно, тим самим обійти недоліки попередніх способів. Максимальне значення параметра millis таке ж, як і у функції delay (4294967295мс або 50 діб).

За допомогою millis ми не зупиняємо виконання всього скетчу, а просто вказуємо, скільки часу Ардуіно повинна просто "обходити" саме той блок коду, який ми хочемо припинити. На відміну від delay millis сама по собі нічого не зупиняє. Дана команда просто повертає нам від вбудованого таймера мікроконтролера кількість мілісекунд, що пройшли з моменту запуску. При кожному виклику loop Ми самі вимірюємо час, що минув з останнього дзвінка нашого коду і якщо різниця часу менше бажаної паузи, то ігноруємо код. Як тільки різниця стане більше потрібної паузи, ми виконуємо код, отримуємо поточний час за допомогою тієї ж millis і запам'ятовуємо його - це час буде новою точкою відліку. У наступному циклі відлік вже буде від нової точки і ми знову будемо ігнорувати код, поки нова різниця millis і нашого збереженого перш значення не досягне знову бажаної паузи.

Затримка без delay за допомогою millis вимагає більшого коду, але з її допомогою можна моргати світлодіодом і ставити на паузу скетч, не зупиняючи при цьому систему.

Ось приклад, що наочно ілюструє роботу команди:

Unsigned long timing; // Змінна для зберігання точки відліку void setup () (Serial.begin (9600);) void loop () (/ * У цьому місці починається виконання аналога delay () Обчислюємо різницю між поточним моментом і раніше збереженої точкою відліку. Якщо різниця більше потрібного значення, то виконуємо код. Якщо немає - нічого не робимо * / if (millis () - timing\u003e 10000) (// Замість 10000 підставте потрібне вам значення паузи timing \u003d millis (); Serial.println ( "10 seconds") ;))

Спочатку ми вводимо змінну timing, в ній буде зберігатися кількість мілісекунд. За замовчуванням значення змінної дорівнює 0. В основній частині програми перевіряємо умову: якщо кількість мілісекунд з запуску мікроконтролера мінус число, записане в змінну timing більше, ніж 10000, то виконується дія з виведення повідомлення в монітор порту і в змінну записується поточне значення часу. В результаті роботи програми кожні 10 секунд в монітор порту буде виводитися напис 10 seconds. Даний спосіб дозволяє моргати светодиодом без delay.

Функція micros замість delay

Ця функція так само може виконати затримку, не використовуючи команду delay. Вона працює точно так само, як і millis, але рахує не мілісекунди, а мікросекунди з дозволом в 4мкс. Її максимальне значення 4294967295 мікросекунд або 70 хвилин. При переповненні значення просто скидається в 0, не забувайте про це.

резюме

Платформа Arduino надає нам кілька способів виконання затримки в своєму проекті. За допомогою delay ви можете швидко поставити на паузу виконання скетчу, але при цьому заблокуєте роботу мікроконтролера. Використання команди millis дозволяє обійтися в Ардуіно без delay, але для цього буде потрібно трохи більше програмувати. Вибирайте кращий спосіб залежно від складності вашого проекту. Як правило, в простих скетчах і при затримці менше 10 секунд використовують delay. Якщо логіка роботи складніше і потрібна велика затримка, то замість delay краще використовувати millis.

Поділитися