Милис часовник на Arduino от началото. Многозадачност на Arduino с функцията millis. Използване на функцията за забавяне на arduino

Здравей Андрей. Много интересен е вашият подход за предаване на багажа от знания и опит, които сте натрупали. Помага много за започване. Е, аз, започвайки да овладявам ардуино, имам желание да напредвам. Освен това с външна помощ мога да го направя по-бързо. И така: първоначално моята задача беше да направя робот, който да се движи по линията. Направи го - всичко е наред. Но освен това, предоставяйки му допълнителни възможности, той не разбираше защо спря да отговаря правилно на линията. Попаднах на тази статия и разбрах защо.

Сега имам въпрос към вас: в скицата по-долу и готово, предвид проблемите със забавянето, трябва ли да превключвам на millis, където има тази функция? Ако е така, разбирам, че почти цялата скица ще трябва да бъде преработена? И не е съвсем ясно как да използвам милисекунди при измерване на разстояние? Благодаря ти.

//Робот с функция за следване на бяла линия

// ********************* Задайте кабели на двигателя ********************* *

int MotorLeftSpeed ​​​​= 5; // Ляв (A) СКОРОСТ НА ДВИГАТЕЛЯ - ENA

int MotorLeftForward = 4; // Ляв (A) мотор НАПРЕД - IN1

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

int MotorRightForward = 8; // Десен (B) Мотор НАПРЕД - IN3

int MotorRightBack = 7; // Десен (B) мотор НАЗАД - IN4

int MotorRightSpeed ​​​​= 9; // Десен (B) мотор SPEED - ENB

// ********************* Инсталирайте изходите на ултразвукови сензори ********************* **** *

inttrigPinL = 14; // настройка на изходния номер на ултразвуковия сензор на левия тригон

int echoPinL = 15; // настройка на изходния номер на левия ехо ултразвуков сензор

inttrigPinC = 10; // задаване на номера на изхода на централния триг ултразвуков сензор

int echoPinC = 11; // настройка на изходния номер на централния ехо ултразвуков сензор

inttrigPinR = 12; // настройка на изходния номер на ултразвуковия сензор на десния тригон

int echoPinR = 13; // настройка на изходния номер на десния ехо ултразвуков сензор

// ********************* Настройка на изходите на линейните сензори *******************

const int LineSensorLeft = 19; // ляв вход на сензора

const int LineSensorRight = 18; // вход на десния сензор

intSL; // състояние на левия сензор

intSR; // състояние на десния сензор

// ********************* Настройка на изхода на светлинни и звукови аларми ****************

int Light = 2; // настройка на изходния номер на светлинния сигнал

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

int ledState = LOW; // задаваме състоянието на светодиода на тази променлива

дълъг предишен милис = 0; // съхранява времето на последното превключване на светодиода

дълъг интервал = 300; // интервал между включване / изключване на светодиода (0,3 секунди)

// ******************** Измерване на променливо разстояние чрез сензори****************

unsigned int impulseTimeL=0;

unsigned int impulseTimeC=0;

unsigned int impulseTimeR=0;

long distL=0; // разстояние, измерено от левия ултразвуков сензор

дълго разстояние C=0; // разстояние, измерено от централния ултразвуков сензор

дълго разст.R=0; // разстояние, измерено от десния Uz сензор

// ******************************* НАСТРОЙКА *********** ***** ***************

Serial.begin(9600); // стартиране на сериен порт (скорост 9600)

//**************** Задайте контакти на двигателя********************

pinMode(MotorRightBack, OUTPUT); // Десен (B) мотор НАЗАД

pinMode(MotorRightForward, OUTPUT); // Десен (B) Мотор НАПРЕД

pinMode(MotorLeftBack, OUTPUT); // Ляв (A) мотор НАЗАД

pinMode(MotorLeftForward, OUTPUT); // Ляв (A) мотор НАПРЕД

забавяне (продължителност);

//**************** Настройте контактите на сензора на лентата********************

pinMode(LineSensorLeft, INPUT); // определяне на щифта на левия сензор

pinMode(LineSensorRight, INPUT); // определяне на щифта на десния сензор

// *************** Настройка на изходните режими на ултразвукови сензори****************************

pinMode(trigPinL, ИЗХОД); // настройка на режима на работа на изхода на левия тригонален ултразвуков сензор

pinMode(echoPinL, INPUT); // настройка на режима на работа на изхода на левия ехо ултразвуков сензор

pinMode(trigPinC, ИЗХОД); // настройка на режима на работа на изхода на централния триг ултразвуков сензор

pinMode(echoPinC, INPUT); // настройка на режима на работа на изхода на централния ехо ултразвуков сензор

pinMode(trigPinR,ИЗХОД); // настройка на режима на работа на изхода на десния тригонален ултразвуков сензор

pinMode(echoPinR, INPUT); // настройка на изходния режим на изхода на десния ехо ултразвуков сензор

// *************** Задайте контакти за светлинни и звукови аларми**************************** **** *****

pinMode(Zumm,ИЗХОД); // настройка на режима на работа на изхода на зумера

pinMode(Светлина,ИЗХОД); // настройка на режима на работа на изхода за светлинна сигнализация

// ******************** Основни команди за движение *******************

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

analogWrite(MotorRightSpeed, sa);

analogWrite(MotorLeftSpeed, sa);

void дясно (int b, int sb) // ЗАВЪРТЕНЕ НАДЯСНО (една страна)

digitalWrite(MotorRightBack, LOW);

digitalWrite(MotorLeftBack, LOW);

digitalWrite(MotorLeftForward, HIGH);

analogWrite(MotorLeftSpeed, sb);

void ляво (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); // 10mS импулс към тригонометричния изход на ултразвуковия сензор за измерване на разстояние

impulseTimeL = pulseIn(echoPinL, HIGH); // чете разстояние от ултразвуков сензор

distL=impulseTimeL/58; // Преобразуване в сантиметри

void izmdistC () // измерване на разстояние от централния ултразвуков сензор

digitalWrite(trigPinC, HIGH);

digitalWrite(trigPinC, LOW); // 10mS импулс към тригонометричния изход на ултразвуковия сензор за измерване на разстояние

impulseTimeC = pulseIn(echoPinC, HIGH); // чете разстояние от ултразвуков сензор

distC=импулсно времеC/58; // Преобразуване в сантиметри

void izmdistR () // измерване на разстояние от централния ултразвуков сензор

digitalWrite(trigPinR, HIGH);

digitalWrite(trigPinR, LOW); // 10mS импулс към тригонометричния изход на ултразвуковия сензор за измерване на разстояние

impulseTimeR = pulseIn(echoPinR, HIGH); // чете разстояние от ултразвуков сензор

distR=impulseTimeR/58; // Преобразуване в сантиметри

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

// ********************* LINE Follow Mode ********************* ***

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

тон (Zumm,900); // включете звука на 900 Hz

тон (Zumm,900); // включете звука на 800 Hz

unsigned long currentMillis = millis();

if (currentMillis - previousMillis > interval) // проверка дали необходимият интервал е изтекъл, ако е изтекъл тогава

предишни мили = текущи мили; // съхранява времето за последно превключване

if (ledState == LOW) // ако светодиодът е изключен, тогава го светваме и обратно

ledState = ВИСОКО;

digitalWrite(Светлина, 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) // БЯЛО - БЯЛО - отидете НАПРАВО

напред(10, 100);// НАПРЕД(време, скорост)

// РОБОТ започва да се пренасочва от лентата - рулираме

иначе ако (SL == LOW & SR == HIGH) // ЧЕРНО - БЯЛО - завийте НАЛЯВО

наляво (10, 100);// завийте НАЛЯВО (време, скорост)

иначе ако (SL == HIGH & SR == LOW) // БЯЛО - ЧЕРНО - завийте НАДЯСНО

надясно (10, 100); // завийте НАДЯСНО (време, скорост)

// ЗАВЪРШВАНЕ - РОБОТът вижда лента и с двата сензора

иначе ако (SL == HIGH & SR == HIGH) // ЧЕРНО - ЧЕРНО - СТОП

stopp(50); // СПРИ

иначе // ако измереното разстояние е по-малко или равно на минимума, спрете

Функцията millis() ви позволява да преброите времето, изминало от стартирането на текущата програма. Функцията връща стойност във формат "unsigned long" и ви позволява да броите стойности до 50 дни от момента на стартиране на програмата. След това време обратното броене ще започне отново. Следва пример за използване на функцията millis():

неподписан дълго време; void setup()( Serial.begin(9600); ) void loop()( Serial.print("Време за включване: "); time = millis(); // стойност на времето за съхранение Serial.println(time); // изпращане на информация чрез забавяне на сериен порт (1000); )

В горния пример всяка секунда информация за времето, изминало от стартирането на програмата, ще бъде изпратена до монитора на порта. Тъй като времето се измерва в милисекунди, всяка следваща стойност ще се различава с 1000. Точността на отчитане зависи от стабилността на кварцовия резонатор Arduino.

функция micros().

Функцията micros() е подобна на функцията millis(), като разликата е в точността на измерването. С помощта на функцията micros() получаваме времето, изминало от началото на текущата програма в микросекунди. Броячът на отброените микросекунди ще бъде нулиран след 70 минути. Следва пример за използване на функцията micros():

неподписан дълго време; void setup()( Serial.begin(9600); ) void loop()( Serial.print("Време от началото: "); време = micros(); Serial.print(време); Serial.println(" ms " ); забавяне (1000); )

Точно както в примера с функцията millis(), тук всяка секунда информация за измереното време ще се изпраща на монитора на порта, единствената разлика е, че в този случай времето се измерва в микросекунди.

функция delay().

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

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

Времето е посочено в милисекунди (1 сек = 1000 ms). Този параметър може да бъде от тип "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 ,НИСКО); // изключване на LED забавяне (1000); // изчакване 1000 ms (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); // pin 8 high delayMicroseconds(50); // пауза 50 микросекунди digitalWrite(outPin, LOW); // пин 8 ниско забавяне Microseconds(50); // пауза 50 микросекунди)

Този пример генерира квадратна вълна с период от 100 микросекунди и 50% запълване.

Латентността в Arduino играе много важна роля. Без тях дори най-простият пример на Blink, който мига светодиод след определен период от време, не може да работи. Но повечето начинаещи програмисти знаят малко за закъсненията във времето и използват само забавяне на Arduino, без да знаят страничните ефекти на тази команда. В тази статия ще говоря подробно за временните функции и характеристиките на тяхното използване в средата за разработка на Arduino IDE.

Arduino има няколко различни команди, които отговарят за работата с времето и паузите:

  • забавяне ()
  • delayMicroseconds()
  • милис()
  • микро ()

Те се различават по точност и имат свои собствени характеристики, които трябва да се вземат предвид при писане на код.

Използване на функцията за забавяне на arduino

Синтаксис

Arduino delay е най-простата команда и най-често използвана от начинаещи. Всъщност това е забавяне, което спира програмата за броя милисекунди, посочени в скоби. (В една секунда има 1000 милисекунди.) Максималната стойност може да бъде 4294967295 ms, което е приблизително равно на 50 дни. Нека да разгледаме един прост пример, който илюстрира как работи тази команда.

Void setup() ( pinMode(13, OUTPUT); ) void loop() ( digitalWrite(13, HIGH); // сигнален пин 13 високо забавяне (10000); // пауза 10000ms или 10 секунди digitalWrite13, LOW); // изпраща нисък сигнал към пин 13 delay(10000); // пауза 10000ms или 10 секунди)

В метод настройвамние предписваме, че щифт 13 ще се използва като изход. В основната част на програмата първо се подава висок сигнал към щифта, след което правим забавяне от 10 секунди. В момента програмата изглежда е спряна. След това се дава слаб сигнал и пак забавяне и всичко започва отначало. В резултат на това получаваме, че щифтът се захранва алтернативно, след това 5 V, след това 0.

Трябва ясно да разберете, че по време на паузата, използвайки забавяне, програмата е спряна, приложението няма да получава никакви данни от сензорите. Това е най-големият недостатък на използването на функцията за забавяне на Arduino. Можете да заобиколите това ограничение с помощта на прекъсвания, но ще говорим за това в отделна статия.

Пример за забавяне с мигащ светодиод

Примерна диаграма, която илюстрира как работи функцията за забавяне.
Можете да изградите верига със светодиод и резистор. Тогава получаваме стандартен пример - мигащ светодиод. За да направите това, на щифта, който обозначихме като изход, трябва да свържете светодиода с положителен контакт. Свързваме свободния крак на светодиода през резистор от приблизително 220 ома (може малко повече) към земята. Можете да определите полярността, ако погледнете вътрешността му. Голямата чаша отвътре е свързана с минуса, а малкият крак е свързан с плюса. Ако вашият светодиод е нов, тогава можете да определите полярността по дължината на проводниците: дългият крак е плюс, късият крак е минус.

функция delayMicroseconds

Тази функция е пълен аналог на закъснението, с изключение на това, че мерните й единици не са милисекунди, а микросекунди (1000000 микросекунди за 1 секунда). Максималната стойност ще бъде 16383, което е равно на 16 милисекунди. Разделителната способност е 4, което означава, че числото винаги ще бъде кратно на четири. Примерен фрагмент ще изглежда така:

DigitalWrite(2, ВИСОКО); // изпращане на пин 2 с голямо забавяне Микросекунди(16383); // пауза 16383µs digitalWrite(2, LOW); // изпраща слаб сигнал към пин 2 delayMicroseconds(16383); // пауза 16383µs

Проблемът с delayMicroseconds е абсолютно същият като със забавянето - тези функции напълно "закачат" програмата и тя буквално замръзва за известно време. Понастоящем е невъзможно да се работи с портове, да се чете информация от сензори и да се извършват математически операции. За мигачи тази опция е добра, но опитни потребители не я използват за големи проекти, тъй като там не са необходими такива повреди. Затова е много по-добре да използвате описаните по-долу функции.

милис функция вместо забавяне

Функцията millis() ще ви позволи да извършите забавяне без забавяне на arduino, като по този начин заобикаляте недостатъците на предишните методи. Максималната стойност на параметъра в милисекири е същата като за функцията за забавяне (4294967295ms или 50 дни).

Използвайки millis, ние не спираме изпълнението на цялата скица, а просто посочваме колко дълго arduino трябва просто да „прескочи“ точно блока от код, който искаме да поставим на пауза. За разлика от delay millis сам по себе си не спира нищо. Тази команда просто ни връща от вградения таймер на микроконтролера броя милисекунди, изминали от началото. С всяко извикване на цикъл Ние самите измерваме времето, изминало от последното извикване на нашия код, и ако времевата разлика е по-малка от желаната пауза, тогава игнорираме кода. Веднага щом разликата стане по-голяма от желаната пауза, ние изпълняваме кода, получаваме текущото време, използвайки същия милис и го запомняме - това време ще бъде новата референтна точка. В следващия цикъл обратното броене вече ще бъде от новата точка и ние отново ще игнорираме кода, докато новата разлика между милиси и нашата предварително съхранена стойност отново достигне желаната пауза.

Забавянето без забавяне с милиси изисква повече код, но може да мига светодиода и да постави на пауза скицата, без да спира системата.

Ето един пример, който ясно илюстрира работата на командата:

неподписано дълго време; // Променлива за съхраняване на референтната точка void setup() ( Serial.begin(9600); ) void loop() ( /* Това е мястото, където започва изпълнението на delay() analog. Изчислете разликата между текущия момент и предишния запазена референтна точка. Ако разликата е по-голяма от Ако не, не правете нищо */ if (millis() - време > 10000)( // Вместо 10000, заменете стойността на пауза, от която се нуждаете timing = millis(); Serial. println ( "10 секунди") ;) )

Първо въвеждаме времева променлива, която ще съхранява броя милисекунди. По подразбиране стойността на променливата е 0. В основната част на програмата проверяваме условието: ако броят милисекунди от стартирането на микроконтролера минус числото, записано в променливата за време, е по-голямо от 10 000, тогава се извършва действие за извеждане на съобщение към монитора на порта и текущата времева стойност се записва в променливата. В резултат на работата на програмата съобщението 10 секунди ще се показва на монитора на порта на всеки 10 секунди. Този метод ви позволява да мигате светодиода без забавяне.

micros функция вместо забавяне

Тази функция може също да забави, без да използва командата за забавяне. Работи по абсолютно същия начин като милисекунди, но отчита не милисекунди, а микросекунди с разделителна способност 4 µs. Максималната му стойност е 4294967295 микросекунди или 70 минути. При препълване стойността просто се нулира на 0, не забравяйте това.

Резюме

Платформата Arduino ни предоставя няколко начина за прилагане на забавяне в нашия проект. Със закъснение можете бързо да поставите на пауза изпълнението на скицата, но в същото време да блокирате работата на микроконтролера. Използването на командата millis ви позволява да се отървете от забавянето в Arduino, но това изисква малко повече програмиране. Изберете най-добрия метод в зависимост от сложността на вашия проект. Като правило, в прости скици и със закъснение по-малко от 10 секунди се използва закъснение. Ако логиката на работа е по-сложна и се изисква голямо забавяне, тогава е по-добре да използвате милиси вместо забавяне.

Ако искате да поставите на пауза микроконтролера, просто трябва да въведете инструкцията за забавяне на правилното място в програмата. Но това се превръща в истинско препятствие, когато се опитвате да правите други неща, като например проследяване на щракване на бутон. В този случай е необходимо да се приложи един вид многозадачност.



Да, ще добави няколко реда код към вашите програми, но това от своя страна ще ви направи по-опитен програмист и ще увеличи потенциала на вашия Arduino. За да направите това, просто трябва да научите как да използвате функцията millis.


Трябва да се разбере, че функцията за забавяне поставя на пауза изпълнението на вашата програма Arduino, което я прави неспособна да прави нищо друго през този период от време. Вместо да спираме цялата си програма за определено време, ще се научим как да броим колко време е минало преди завършването на действието. Това, разбира се, става с функцията millis() и няколко приятелски променливи за съхраняване на нашите данни. За да направим нещата лесни за разбиране, ще започнем с първата скица на урока, наречена „Мигане“, но в този случай ще мигаме светодиода без забавяне.


Началото на тази програма е същото като всяка друга стандартна програма на Arduino. Първо идва декларацията на всички необходими променливи и входно-изходни линии (например ред 13 за светодиода). Тук също се нуждаем от целочислена променлива за съхраняване на текущото състояние на светодиода. Той ще бъде настроен на LOW, тъй като първоначалното състояние на светодиода е изключено. След това декларираме променливата "previousMillis" от тип "unsigned long". За разлика от "int", дългите неподписани променливи са 32 бита, това е за променливи, чиято стойност може да стане много голяма - като потенциално време можем да изчакаме, докато се предприеме действие. Променливата previousMillis ще се използва за съхраняване на времето, когато светодиодът е мигал последно. Има и тип "const long", той също е 32 битов, но не променя стойността, тоест е за константи (в случая за интервална константа). Ще го зададем на 1000 и ще го използваме като време за пауза, измерено в милисекунди.


const int ledPin = 13; // дефиниране на изхода на светодиода // Променливите ще се променят: int ledState = LOW; // ledState се използва за определяне на състоянието на светодиода unsigned long previousMillis = 0; // съхранява времето, когато светодиодът е последно актуализиран // константите няма да се променят: const long interval = 1000; // мигащ интервал в милисекунди void setup() ( // настройка на изходния ред 13 pinMode(ledPin, OUTPUT); )

След това влизаме в безкраен цикъл. Не забравяйте, че вместо забавяне, ние искаме да преброим колко време е изминало от последното ни мигане, в нашия случай 1000ms. Ако определеното време е изтекло, е време да променим състоянието на нашия светодиод.


Първо, ще зададем дългия без знак "currentMillis" на "millis()", който указва текущото време в милисекунди. Това ще ни помогне да разберем дали разликата между текущото и предишното време е надхвърлила 1000ms. За да направим това, ние казваме: „Ако текущото време минус предишното време, когато нашият светодиод е мигал, е по-голямо или равно на зададената ни стойност от 1000ms, запазете времето на последното мигане като предишното.“ Това ще ни помогне да си спомним колко време е минало от последното мигане при следващата итерация на цикъла. След това, ако състоянието на светодиода е НИСКО, направете го ВИСОКО, в противен случай го направете НИСКО. След това използвайте командата digitalWrite, за да отпечатате текущото състояние на светодиода.


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

Първото нещо, с което се сблъсква начинаещ, който овладява Arduino, е неприятното свойство на функцията delay () - блокиране на изпълнението на програмата. Много примери в интернет използват тази функция, но практическото приложение по някакъв начин подсказва, че е по-добре да се направи без нея.

Както подобава на начинаещ, изобретих велосипед и направих своя собствена реализация на неблокиращо забавяне. Задачата беше следната:

  • Осигурете псевдо многозадачност, така че различните събития да се случват по свое време, на свои собствени интервали и да не се блокират едно друго.
  • Беше удобно да го използвам.
  • Може да се проектира като библиотека и лесно да се включва в други проекти без копиране и поставяне.
Виждайки, че повечето от библиотеките на Arduino са направени с помощта на ООП, аз също реших да не се изтъквам и написах класа SmartDelay, който може да бъде получен от github като zip за добавяне към Arduino IDE или да направя git клонинг в ~/Arduino/ библиотеки/

Резултатът е този.

#включи SmartDelay foo(1000000UL); // в микросекунди void loop () ( if (foo.Now()) ( // Кодът тук се изпълнява на всеки интервал в микросекунди, указан в конструктора по-горе. ) // Друг код )
Методът Now() връща true, ако интервалът е изтекъл. В този случай обратното броене започва отново със същия интервал. Тоест Now () всеки път се "презарежда" автоматично.

Класическото мигане на светодиода може веднага да бъде усложнено до две мигания. Например, светлините, свързани към щифтове 12 и 11, трябва да мигат съответно на интервали от 1s и 777ms.

#включи SmartDelay led12(1000000UL); SmartDelay led11(777000UL); настройка () ( pinMode(12,OUTPUT); pinMode(11,OUTPUT); ) byte led12state=0; байт led11state=0; void loop () ( if (led12.Now()) ( digitalWrite(12,led12state); led12state=!led12state; ) if (led11.Now()) ( digitalWrite(11,led11state); led11state=!led11state; ) )
Можете да направите нещо друго в цикъла, мигането на светодиодите няма да блокира изпълнението на този код.

Ясно е, че това не е пълна замяна на delay (), което спира нишката за дадено време, винаги трябва да пишете програмата като MFA (механизъм на краен автомат). Тоест съхранява състоянието и в зависимост от него отива на правилното място в кода.

Стара версия:

Действие1(); забавяне (1000); действие2(); забавяне (500); действие3(); ...
Нова опция:

Състояние на байта = 0; SmartDelayd(); ... switch (състояние) ( case 0: action1(); d.Set(1000000UL); state=1; break; case 1: if (d.Now()) ( action2(); d.Set(500000UL) ; състояние=2; ) прекъсване; случай 2: ако (d.Now()) ( действие3(); d.Stop(); състояние=0; ) прекъсване; ) ...
Методът Set(interval) задава нов интервал и връща стария. Можете просто да погледнете интервала с помощта на метода Get();

Stop() спира обработката и Now() винаги връща false.

Start() се възобновява и Now() започва да работи както обикновено.

Ако трябва да забавите отброяването на времето, но не и да го спрете напълно, тогава има метода Wait (). Например, ако светодиод 12 мига и когато бутонът е натиснат, той не мига, просто добавете следния код към loop() в примера с два диода по-горе:

If (digitalRead(9)) led12.Wait(); ...
И така, при високо ниво на сигнала на крак 9, диодът на 12 няма да мига и ще продължи, когато там се появи 0.

Когато екранът се изчертава от такъв „таймер“ например и бутоните се обработват паралелно, тогава може да се наложи екранът или частта да се преначертаят веднага след натискане на бутона, а не да се чака интервалът да приключи. За това се използва методът Reset(), след което следващото извикване на Now() ще върне true. Например:

SmartDelay дисплей (1000000UL); void loop() ( if (btClick()) display.Reset(); // щракнахме върху бутона, трябва да нарисуваме екрана. if (display.Now()) screenRedraw(); // начертаем екрана. )
От бъговете виждам само, че не се отчита препълването на брояча на микросекундите, но иначе да, трябва да изчистим кода. Не ми харесва начина, по който Reset() се прави, докато се мисли.