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



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


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


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


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

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


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


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

Перше, з чим стикається новачок, що освоює 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=0; byte led11state=0; void loop () ( if (led12.Now()) ( digitalWrite(12,led12state); led12state=!led12state; ) if (led11.Now()) ( digitalWrite(11,led11state); led11state=!led11state; ))
У циклі можна виконувати ще щось, блимання світлодіодів не блокуватиме виконання цього коду.

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

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

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

Byte state = 0; SmartDelay d(); ... switch (state) ( case 0: action1(); d.Set(1000000UL); state=1; break; case 1: if (d.Now()) ( action2(); d.Set(500000UL)) state=2; ) break; case 2: if (d.Now()) ( action3(); d.Stop(); state=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(), поки думаю.

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

Unsigned long time; void setup()( Serial.begin(9600); ) void loop()( Serial.print(«Час включення: «); time = 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 = micros(); Serial.print(time); Serial.println(» мкс) "); delay (1000); )

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

Функція delay()

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

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

Час вказується у мілісекундах (1 сек = 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); //почекати 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%.

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

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

  • 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 > 10000)( // Замість 10000 підставте потрібне вам значення паузи timing = 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.

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

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

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

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

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

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

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

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

int MotorRightBack = 7; // Правий (В) двигун НАЗАД - IN4

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

unsigned int impulseTimeL=0;

unsigned int impulseTimeC=0;

unsigned int impulseTimeR=0;

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

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

long distR=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 = pulseIn (echoPinL, HIGH); // зчитування відстані з УЗ датчика

distL=impulseTimeL/58; // Перераховуємо до сантиметрів

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

digitalWrite (trigPinC, HIGH);

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

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

distC=impulseTimeC/58; // Перераховуємо до сантиметрів

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

digitalWrite (trigPinR, HIGH);

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

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

distR=impulseTimeR/58; // Перераховуємо до сантиметрів

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

// ********************** Режим проходження по лінії ********************** ***

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

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

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

unsigned long currentMillis = millis ();

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

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

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

ledState = HIGH;

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

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

Serial.println (distL);

Serial.println (distC);

Serial.println (distR);

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

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

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

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

// Робот на смузі - їдемо прямо

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

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

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

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

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

else if (SL == HIGH & SR == LOW) // БІЛИЙ - ЧОРНИЙ - поворот ВПРАВО

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

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

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

stopp (50); // СТОП

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