Arduino Mills pulkstenis no sākuma. Arduino vairākuzdevumu veikšana ar Millis funkciju. Izmantojot arduino aizkaves funkciju

Sveiks Andrej. Jūsu pieeja uzkrāto zināšanu un pieredzes bagāžas nodošanai ir ļoti interesanta. Tas ļoti palīdz uzsākt darbu. Nu, man, sākot apgūt arduino, ir vēlme progresēt. Turklāt ar ārēju palīdzību es to varu izdarīt ātrāk. Tātad: sākumā mans uzdevums bija izveidot robotu, kas kustas pa līniju. Izdarīja - viss kārtībā. Bet tālāk, sniedzot viņam papildu iespējas, viņš nesaprata, kāpēc viņš pārtrauca pareizi reaģēt uz līniju. Es uzgāju šo rakstu un sapratu, kāpēc.

Tagad man jums ir jautājums: zemāk esošajā skicē un gatavs, ņemot vērā problēmas ar kavēšanos, vai man ir jāpārslēdzas uz mili visur, kur šī funkcija ir pieejama? Ja tā, tad es saprotu, ka gandrīz visa skice būs jāpārtaisa? Un nav līdz galam skaidrs, kā attāluma mērīšanā izmantot mili? Paldies.

//Robots ar baltu līniju sekojošu funkciju

// ********************* Iestatiet motora vadus ************************* *

int Motor LeftSpeed ​​= 5; // Kreisais (A) Motors SPEED - ENA

int MotorLeftForward = 4; // Kreisais (A) motors FORWARD - IN1

int MotorLeftBack = 3; // Kreisais (A) Motors BACK - IN2

int MotorRightForward = 8; // Pa labi (B) Motors FORWARD - IN3

int MotorRightBack = 7; // Pa labi (B) Motors BACK - IN4

int MotorRightSpeed ​​= 9; // Labā (B) motora ĀTRUMS - ENB

// *********************Instalējiet ultraskaņas sensoru izejas************************ ****

intrigPinL = 14; // kreisā sprūda ultraskaņas sensora izejas numura iestatīšana

int echoPinL = 15; // kreisā atbalss ultraskaņas sensora izejas numura iestatīšana

intrigPinC = 10; // centrālā trigera ultraskaņas sensora izejas numura iestatīšana

int echoPinC = 11; // centrālā eho ultraskaņas sensora izejas numura iestatīšana

intrigPinR = 12; // labās sprūda ultraskaņas sensora izejas numura iestatīšana

int echoPinR = 13; // labā atbalss ultraskaņas sensora izejas numura iestatīšana

// ********************* Līnijas sensoru izeju iestatīšana *******************

const int LineSensorLeft = 19; // kreisās līnijas sensora ieeja

const int LineSensorRight = 18; // labās līnijas sensora ievade

intSL; // kreisā sensora statuss

intSR; // labā sensora statuss

// ********************* Gaismas un skaņas signālu izejas iestatīšana ****************

int Gaisma = 2; // gaismas signāla izejas numura iestatīšana

int Zumm = 6; // iestatīt skaņas signāla izvades numuru

int ledState = LOW; // iestatiet gaismas diodes stāvokli uz šo mainīgo

garš iepriekšējaisMillis = 0; // saglabā LED diodes pēdējās ieslēgšanas laiku

garš intervāls = 300; // intervāls starp LED ieslēgšanu/izslēgšanu (0,3 sekundes)

// ********************* Mainīga attāluma mērīšana ar sensoriem***************

unsigned int impulseTimeL=0;

neparakstīts int impulseTimeC=0;

neparakstīts int impulseTimeR=0;

garais distL=0; // attālums, ko mēra kreisais ultraskaņas sensors

garš distC=0; // attālums, ko mēra centrālais ultraskaņas sensors

garais dist.R=0; // attālums, ko mēra labais Uz sensors

// ****************************** IESTATĪŠANA *********** ***** **************

Serial.begin(9600); // sākt seriālo portu (ātrums 9600)

//*************** Iestatiet motora kontaktus********************

pinMode (MotorRightBack, OUTPUT); // Pa labi (B) Motors ATPAKAĻ

pinMode(MotorRightForward, OUTPUT); // Pa labi (B) Motors UZ PRIEKŠU

pinMode (MotorLeftBack, OUTPUT); // Kreisais (A) Motors ATPAKAĻ

pinMode(MotorLeftForward, OUTPUT); // Kreisais (A) Motors UZ PRIEKŠU

kavēšanās (ilgums);

//*************** Iestatiet sloksnes sensora kontaktus******************

pinMode (LineSensor Left, INPUT); // definējot kreisās līnijas sensora tapu

pinMode (LineSensorRight, INPUT); // definējot labās līnijas sensora tapu

// ***************Ultraskaņas sensoru izvades režīmu iestatīšana****************************

pinMode(trigPinL, OUTPUT); // kreisās trigas ultraskaņas sensora izejas darbības režīma iestatīšana

pinMode(echoPinL, INPUT); // kreisā atbalss ultraskaņas sensora izejas darbības režīma iestatīšana

pinMode(trigPinC, OUTPUT); // centrālā trigera ultraskaņas sensora izejas darbības režīma iestatīšana

pinMode(echoPinC, INPUT); // centrālā eho ultraskaņas sensora izejas darbības režīma iestatīšana

pinMode(trigPinR,OUTPUT); // labās sprūda ultraskaņas sensora izejas darbības režīma iestatīšana

pinMode(echoPinR, INPUT); // labā atbalss ultraskaņas sensora izejas režīma iestatīšana

// ************** Iestatīt kontaktus gaismas un skaņas signāliem**************************** **** *****

pinMode (Zumm, OUTPUT); // skaņas signāla izejas darbības režīma iestatīšana

pinMode (gaisma, OUTPUT); // gaismas signalizācijas izejas darbības režīma iestatīšana

// ******************** Pamata kustību komandas ******************

void forward (int a, int sa) // FORWARD

analogWrite(MotorRightSpeed, sa);

analogWrite(MotorLeftSpeed, sa);

tukšums pa labi (int b, int sb) // ROTATE RIGHT (viena puse)

digitalWrite(MotorRightBack, LOW);

digitalWrite (MotorLeftBack, LOW);

digitalWrite(MotorLeftForward, HIGH);

analogWrite(MotorLeftSpeed, sb);

tukšums pa kreisi (int k, int sk) // KREISĀS GRIEZES (viena puse)

digitalWrite(MotorRightBack, LOW);

digitalWrite (MotorRightForward, HIGH);

analogWrite(MotorRightSpeed, sk);

digitalWrite (MotorLeftBack, LOW);

void stopp(int f) // STOP

digitalWrite(MotorRightBack, LOW);

digitalWrite (MotorRightForward, LOW);

digitalWrite (MotorLeftBack, LOW);

digitalWrite(MotorLeftForward, LOW);

// ************************** Attāluma mērīšana******************** *

void izmdistL () // attāluma mērīšana ar kreiso ultraskaņas sensoru

digitalWrite(trigPinL, HIGH);

digitalWrite(trigPinL, LOW); // 10 mS impulss līdz ultraskaņas sensora izvadei attāluma mērīšanai

impulssTimeL = impulssIn(echoPinL, HIGH); // nolasīt attālumu no ultraskaņas sensora

distL=impulseTimeL/58; // Konvertēt uz centimetriem

void izmdistC () // attāluma mērīšana ar centrālo ultraskaņas sensoru

digitalWrite(trigPinC, HIGH);

digitalWrite(trigPinC, LOW); // 10 mS impulss līdz ultraskaņas sensora izvadei attāluma mērīšanai

impulssTimeC = impulssIn(echoPinC, HIGH); // nolasīt attālumu no ultraskaņas sensora

distC=impulseTimeC/58; // Konvertēt uz centimetriem

void izmdistR () // attāluma mērīšana ar centrālo ultraskaņas sensoru

digitalWrite(trigPinR, HIGH);

digitalWrite(trigPinR, LOW); // 10 mS impulss līdz ultraskaņas sensora izvadei attāluma mērīšanai

impulssTimeR = impulssIn(echoPinR, HIGH); // nolasīt attālumu no ultraskaņas sensora

distR=impulseTimeR/58; // Konvertēt uz centimetriem

// ********************************** CILPA *********** ***** **************

// ********************* LĪNIJAS sekošanas režīms ********************* ***

// *********************gaismas un skaņas signāli*******************

tonis (Zumm,900); // ieslēdz skaņu 900 Hz

tonis (Zumm,900); // ieslēdz skaņu 800 Hz

neparakstīta garā strāvaMillis = millis();

if (currentMillis - previousMillis > intervāls) // pārbaudīt vai ir pagājis nepieciešamais intervāls, ja ir pagājis tad

previousMillis = pašreizējaisMillis; // saglabāt pēdējo pārslēgšanās laiku

if (ledState == LOW) // ja gaismas diode ir izslēgta, tad mēs to iedegam un otrādi

ledState = AUGSTS;

digitalWrite (gaisma, ledState); // iestatiet izvades stāvokļus, lai ieslēgtu vai izslēgtu LED

// ************************** Attāluma mērīšana******************** ******

Serial.println(distL);

Serial.println(distC);

Serial.println(distR);

if (distL>50 && distC>50 && distR>50) // ja izmērītais attālums ir lielāks par 50 centimetriem - aiziet

SL=digitalRead(LineSensorLeft); // nolasa signālu no kreisās joslas sensora

SR=digitalRead(LineSensorRight); // nolasa signālu no labās joslas sensora

// ************************* Sekojot melnajai līnijai ******************* ****

// ROBOTS uz joslas - ejam taisni

ja (SL == LOW & SR == LOW) // BALTS — BALTS — iet taisni

uz priekšu(10, 100);// UZ PRIEKŠU(laiks, ātrums)

// ROBOTS sāk pārslēgties no joslas - mēs taksējam

cits, ja (SL == LOW & SR == HIGH) // MELNS — BALTS — pagriezieties PA kreisi

pa kreisi (10, 100);// pagriezieties PA kreisi (laiks, ātrums)

cits, ja (SL == AUGSTS & SR == LOW) // BALTS — MELNS — pagriezieties PA labi

pa labi (10, 100); // pagriezieties PA labi (laiks, ātrums)

// FINISH - ROBOTS redz joslu ar abiem sensoriem

cits, ja (SL == AUGSTS & SR == AUGSTS) // MELNS — MELNS — STOP

stop(50); // STOP

else // ja izmērītais attālums ir mazāks vai vienāds ar minimālo, apstājieties

Funkcija millis() ļauj skaitīt laiku, kas pagājis kopš pašreizējās programmas palaišanas. Funkcija atgriež vērtību “neparakstīta garā” formātā un ļauj skaitīt vērtības līdz 50 dienām no programmas palaišanas brīža. Pēc šī laika atpakaļskaitīšana atsāksies. Šis ir funkcijas millis() izmantošanas piemērs:

neparakstīts ilgu laiku; void setup()( Serial.begin(9600); ) void loop()( Serial.print("Ieslēgšanas laiks: "); laiks = millis(); // saglabā laika vērtību Serial.println(time); // nosūtīt informāciju, izmantojot seriālā porta aizkavi (1000);)

Iepriekš minētajā piemērā katra otrā informācija par laiku, kas pagājis kopš programmas palaišanas, tiks nosūtīta porta monitoram. Tā kā laiks tiek mērīts milisekundēs, katra nākamā vērtība atšķirsies par 1000. Nolasīšanas precizitāte ir atkarīga no Arduino kvarca rezonatora stabilitātes.

micros() funkcija

Funkcija micros () ir līdzīga funkcijai millis (), atšķirība ir mērījuma precizitātē. Izmantojot funkciju micros(), mēs iegūstam laiku, kas pagājis kopš pašreizējās programmas sākuma mikrosekundēs. Skaitīto mikrosekunžu skaitītājs tiks atiestatīts pēc 70 minūtēm. Šis ir funkcijas micros() izmantošanas piemērs:

neparakstīts ilgu laiku; void setup()( Serial.begin(9600); ) void loop()( Serial.print("Laiks kopš sākuma: "); laiks = mikros(); Serial.print(time); Serial.println(" ms " ); kavēšanās (1000); )

Tāpat kā piemērā ar funkciju millis(), arī šeit katra otrā informācija par izmērīto laiku tiks nosūtīta uz porta monitoru, vienīgā atšķirība ir tāda, ka šajā gadījumā laiks tiek mērīts mikrosekundēs.

delay() funkcija

Funkcija delay() ļauj apturēt pašreizējās programmas izpildi uz parametrā norādīto laiku. Komandas sintakse ir šāda:

//komandu aizkave(500); //aizkavēšanās uz 0,5 s //aizkavēšanās(1000); //aizkavēšanās par 1 s

Laiks ir norādīts milisekundēs (1 s = 1000 ms). Šī parametra tips var būt "unsigned long", kas svārstās no 0 līdz 4294967295. Tālāk ir parādīts komandas delay() izmantošanas piemērs:

#define ledPin 13 void setup() ( pinMode(ledPin,13); ) void loop() ( digitalWrite(ledPin, HIGH); //ieslēdziet LED aizkavi (500); //gaidiet 500 ms (0,5 sek) digitalWrite( ledPin ,LOW); // izslēgt LED aizkavi (1000); // gaidīt 1000 ms (1 s))

Iepriekš minētajā piemērā gaismas diode iedegas uz 0,5 sekundēm, pēc tam nodziest uz 1 sekundi un tā tālāk, līdz Arduino tiek izslēgts.

delayMicroseconds() funkcija

Funkcija delayMicroseconds() ir funkcijas delay() variācija. Atšķirība ir laika noteikšanas skaitā un precizitātē. Funkcija delay() ļauj skaitīt laiku ar 1 milisekundes precizitāti, savukārt delayMicroseconds() ar 1 mikrosekundes precizitāti.

Vērtība, ko var norādīt parametrā, ir diapazonā no 0 līdz 16383. Lai iegūtu ilgākus laika intervālus, izmantojiet funkciju delay() vai vairākas reizes izmantojiet delayMicroseconds().

#define outPin 8 void setup() ( pinMode(outPin, OUTPUT); // kontakts 8 kā izeja ) void loop() ( digitalWrite(outPin, HIGH); // pin 8 high delayMicroseconds(50); // pauze 50 mikrosekundes digitalWrite(outPin, LOW); // pin 8 zema aizkaveMicroseconds(50); // pauze 50 mikrosekundes )

Šis piemērs ģenerē kvadrātveida vilni ar 100 mikrosekundes periodu un 50% polsterējumu.

Arduino latentumam ir ļoti svarīga loma. Bez tiem nevar darboties pat visvienkāršākais Blink piemērs, kas mirgo gaismas diode pēc noteikta laika. Bet lielākā daļa iesācēju programmētāju maz zina par laika aizkavi un izmanto tikai Arduino aizkavi, nezinot šīs komandas blakusparādības. Šajā rakstā es detalizēti runāšu par pagaidu funkcijām un to izmantošanas iespējām Arduino IDE izstrādes vidē.

Arduino ir vairākas dažādas komandas, kas ir atbildīgas par darbu ar laiku un pauzēm:

  • kavēšanās ()
  • kavēšanās mikrosekundes ()
  • millis()
  • mikros ()

Tie atšķiras pēc precizitātes, un tiem ir savas īpašības, kas jāņem vērā, rakstot kodu.

Izmantojot arduino aizkaves funkciju

Sintakse

Arduino aizkave ir vienkāršākā komanda, un to visbiežāk izmanto iesācēji. Faktiski tā ir aizkave, kas pārtrauc programmas darbību uz iekavās norādīto milisekundžu skaitu. (Vienā sekundē ir 1000 milisekundes.) Maksimālā vērtība var būt 4294967295 ms, kas ir aptuveni vienāda ar 50 dienām. Apskatīsim vienkāršu piemēru, kas ilustrē šīs komandas darbību.

Void setup() ( pinMode(13, OUTPUT); ) void loop() ( digitalWrite(13, HIGH); // signāla kontakts 13 liela aizkave (10000); // pauze 10000ms vai 10 sekundes digitalWrite13, LOW); // nosūtīt zemu signālu uz pin 13 delay(10000); // pauze 10000 ms vai 10 sekundes)

Metodē uzstādīt mēs paredzam, ka tapa 13 tiks izmantota kā izeja. Programmas galvenajā daļā vispirms uz tapu tiek pielietots augsts signāls, pēc tam mēs veicam 10 sekunžu aizkavi. Šobrīd šķiet, ka programma ir apturēta. Tad tiek dots zems signāls un atkal aizkave un viss sākas no jauna. Rezultātā mēs iegūstam, ka tapa tiek piegādāta pārmaiņus, tad 5 V, tad 0.

Jums ir skaidri jāsaprot, ka pauzes laikā, izmantojot aizkavi, programma tiek apturēta, lietojumprogramma nesaņems datus no sensoriem. Tas ir lielākais trūkums, izmantojot Arduino aizkaves funkciju. Šo ierobežojumu var apiet, izmantojot pārtraukumus, taču mēs par to runāsim atsevišķā rakstā.

Aizkaves piemērs ar mirgojošu LED

Diagrammas piemērs, lai ilustrētu, kā darbojas aizkaves funkcija.
Jūs varat izveidot ķēdi ar LED un rezistoru. Tad mēs iegūstam standarta piemēru - mirgojošu LED. Lai to izdarītu, uz tapas, kuru mēs norādījām kā izeju, jums ir jāpievieno gaismas diode ar pozitīvu kontaktu. Mēs savienojam gaismas diodes brīvo kāju caur aptuveni 220 omu rezistoru (var būt nedaudz vairāk) ar zemi. Jūs varat noteikt polaritāti, ja paskatās uz tā iekšpusi. Lielā kauss iekšpusē ir savienots ar mīnusu, un mazā kāja ir savienota ar plusu. Ja jūsu LED ir jauns, tad polaritāti varat noteikt pēc vadu garuma: gara kāja ir plus, īsa kāja ir mīnuss.

delayMicroseconds funkcija

Šī funkcija ir pilnīgs aizkaves analogs, izņemot to, ka tās mērvienības ir nevis milisekundes, bet mikrosekundes (1000000 mikrosekundes 1 sekundē). Maksimālā vērtība būs 16383, kas ir vienāda ar 16 milisekundēm. Izšķirtspēja ir 4, kas nozīmē, ka skaitlis vienmēr būs četrinieks. Fragmenta piemērs izskatītos šādi:

DigitalWrite(2, AUGSTS); // nosūtīt pin 2 liela kavēšanāsMicroseconds(16383); // pauze 16383µs digitalWrite(2, LOW); // nosūtīt zemu signālu uz pin 2 delayMicroseconds(16383); // pauze 16383µs

Problēma ar delayMicroseconds ir tieši tāda pati kā ar aizkavi - šīs funkcijas pilnībā "uzkarina" programmu un tā burtiski uz brīdi sastingst. Šobrīd nav iespējams strādāt ar portiem, nolasīt informāciju no sensoriem un veikt matemātiskas darbības. Mirgotājiem šī opcija ir piemērota, taču pieredzējuši lietotāji to neizmanto lieliem projektiem, jo ​​​​šādas kļūmes tur nav vajadzīgas. Tāpēc daudz labāk ir izmantot tālāk aprakstītās funkcijas.

miss funkcija aizkaves vietā

Funkcija millis () ļaus jums bez kavēšanās veikt arduino aizkavēšanos, tādējādi apejot iepriekšējo metožu trūkumus. Millis parametra maksimālā vērtība ir tāda pati kā aizkaves funkcijai (4294967295 ms vai 50 dienas).

Izmantojot millis, mēs neapturam visas skices izpildi, bet vienkārši norādām, cik ilgi arduino ir vienkārši “apiet” tieši tas koda bloks, kuru mēs vēlamies apturēt. Atšķirībā no kavēšanās, milis pats par sevi neaptur neko. Šī komanda vienkārši atgriež mums no mikrokontrollera iebūvētā taimera milisekundes, kas ir pagājušas kopš sākuma. Ar katru zvanu uz cilpu Mēs paši izmērām laiku, kas pagājis kopš pēdējā mūsu koda izsaukuma, un, ja laika starpība ir mazāka par vēlamo pauzi, mēs kodu ignorējam. Tiklīdz starpība kļūst lielāka par vēlamo pauzi, mēs izpildām kodu, iegūstam pašreizējo laiku, izmantojot tos pašus mili un atceramies to - šis laiks būs jaunais atskaites punkts. Nākamajā ciklā atpakaļskaitīšana jau būs no jaunā punkta, un mēs atkal ignorēsim kodu, līdz jaunā atšķirība starp mili un mūsu iepriekš saglabāto vērtību atkal sasniegs vēlamo pauzi.

Lai aizkavētu bez kavēšanās ar millis, ir nepieciešams vairāk koda, taču tas var mirgot LED un apturēt skici, neapturot sistēmu.

Šeit ir piemērs, kas skaidri ilustrē komandas darbību:

neparakstīts ilgs laiks; // Mainīgais atskaites punkta saglabāšanai void setup() ( Serial.begin(9600); ) void loop() ( /* Šeit sākas delay() analogā izpilde. Aprēķiniet starpību starp pašreizējo momentu un iepriekšējo saglabāts atskaites punkts. Ja atšķirība ir lielāka par Ja nē, neko nedariet */ if (millis() - laiks > 10000)( // 10000 vietā aizstājiet nepieciešamo pauzes vērtību timing = millis(); Serial. println ( "10 sekundes") ;)))

Pirmkārt, mēs ieviešam laika mainīgo, kas saglabās milisekundes. Pēc noklusējuma mainīgā vērtība ir 0. Programmas galvenajā daļā mēs pārbaudām nosacījumu: ja milisekundes kopš mikrokontrollera sākuma mīnus laika mainīgajam ierakstītais skaitlis ir lielāks par 10000, tad darbība tiek veikta, lai izvadītu ziņojumu porta monitoram, un mainīgajam tiek ierakstīta pašreizējā laika vērtība. Programmas darbības rezultātā ostas monitorā ik pēc 10 sekundēm tiks parādīts ziņojums 10 sekundes. Šī metode ļauj bez kavēšanās mirgot LED.

mikros funkcija aizkaves vietā

Šī funkcija var arī aizkavēt, neizmantojot aizkaves komandu. Tas darbojas tieši tāpat kā mili, bet tas neskaita milisekundes, bet gan mikrosekundes ar izšķirtspēju 4 µs. Tā maksimālā vērtība ir 4294967295 mikrosekundes jeb 70 minūtes. Pārpildes gadījumā vērtība tiek vienkārši atiestatīta uz 0, neaizmirstiet to.

Kopsavilkums

Arduino platforma sniedz mums vairākus veidus, kā īstenot aizkavēšanos mūsu projektā. Ar aizkavi jūs varat ātri apturēt skices izpildi, bet tajā pašā laikā bloķēt mikrokontrollera darbību. Komandas millis izmantošana ļauj atbrīvoties no Arduino aizkaves, taču tas prasa nedaudz vairāk programmēšanas. Izvēlieties labāko metodi atkarībā no jūsu projekta sarežģītības. Parasti vienkāršās skicēs un ar kavēšanos, kas mazāka par 10 sekundēm, tiek izmantota aizkave. Ja darbības loģika ir sarežģītāka un nepieciešama liela aizkave, tad aizkaves vietā labāk izmantot millis.

Ja vēlaties "pauzēt" mikrokontrolleri, jums vienkārši jāievada kavēšanās instrukcija pareizajā programmas vietā. Taču tas kļūst par īstu šķērsli, mēģinot veikt citas darbības, piemēram, izsekot pogas klikšķiem. Šajā gadījumā ir jāīsteno sava veida daudzuzdevumu veikšana.



Jā, tas jūsu programmām pievienos dažas koda rindiņas, taču tas savukārt padarīs jūs par pieredzējušāku programmētāju un palielinās jūsu Arduino potenciālu. Lai to izdarītu, jums vienkārši jāiemācās izmantot Millis funkciju.


Jāsaprot, ka aizkaves funkcija aptur jūsu Arduino programmas izpildi, neļaujot tai šajā laika periodā darīt neko citu. Tā vietā, lai uz noteiktu laiku apturētu visu programmu, mēs iemācīsimies saskaitīt, cik daudz laika ir pagājis pirms darbības pabeigšanas. Tas, protams, tiek darīts, izmantojot funkciju millis () un dažus drauga mainīgos, lai saglabātu mūsu datus. Lai lietas būtu viegli saprotamas, mēs sāksim ar pirmo apmācības skici ar nosaukumu "Mirkšķināšana", taču šajā gadījumā mēs mirgosim LED bez kavēšanās.


Šīs programmas sākums ir tāds pats kā jebkurai citai standarta Arduino programmai. Vispirms tiek deklarēti visi nepieciešamie mainīgie un I / O līnijas (piemēram, LED 13. rinda). Šeit mums ir nepieciešams arī vesels skaitlis, lai saglabātu LED pašreizējo stāvokli. Tas tiks iestatīts uz LOW, jo gaismas diodes sākotnējais stāvoklis ir izslēgts. Pēc tam mēs deklarējam mainīgo "previousMillis" tipa "unsigned long". Atšķirībā no "int", garie neparakstītie mainīgie ir 32 biti, tas ir paredzēts mainīgajiem, kuru vērtība var kļūt ļoti liela - kā potenciālo laiku mēs varam gaidīt, līdz tiek veikta darbība. Mainīgais previousMillis tiks izmantots, lai saglabātu laiku, kad LED pēdējo reizi mirgoja. Ir arī "const long" tips, tas ir arī 32 bitu, bet tas nemaina vērtību, tas ir, tas ir paredzēts konstantēm (šajā gadījumā intervāla konstantei). Mēs iestatīsim to uz 1000 un izmantosim kā pauzes laiku, mērot milisekundēs.


const int ledPin = 13; // definēt gaismas diodes izvadi // Mainīsies mainīgie: int ledState = LOW; // ledState izmanto, lai noteiktu LED stāvokli bez paraksta long previousMillis = 0; // saglabāt laiku, kad LED pēdējo reizi tika atjaunināts // konstantes nemainīsies: const long interval = 1000; // mirgojošs intervāls milisekundēs void setup() ( // izvades līnijas 13 pinMode(ledPin, OUTPUT) iestatīšana)

Tad mēs ieejam bezgalīgā cilpā. Atcerieties, ka kavēšanās vietā mēs vēlamies skaitīt, cik daudz laika ir pagājis kopš mūsu pēdējās mirkšķināšanas, mūsu gadījumā 1000 ms. Ja norādītais laiks ir pagājis, ir pienācis laiks mainīt mūsu LED stāvokli.


Pirmkārt, mēs iestatīsim neparakstīto garo "currentMillis" uz "millis()", kas norāda pašreizējo laiku milisekundēs. Tas mums palīdzēs noskaidrot, vai starpība starp pašreizējo un iepriekšējo laiku ir pārsniegusi 1000 ms. Lai to izdarītu, mēs sakām: "Ja pašreizējais laiks, atskaitot iepriekšējo mirgošanas reizi, kad mūsu LED mirgo, ir lielāks vai vienāds ar mums piešķirto vērtību 1000 ms, saglabājiet pēdējo mirgošanas laiku kā iepriekšējo." Tas mums palīdzēs atcerēties, cik daudz laika ir pagājis kopš pēdējās mirkšķināšanas nākamajā cilpas atkārtojumā. Pēc tam, ja LED stāvoklis ir LOW, padariet to HIGH, pretējā gadījumā padariet to LOW. Pēc tam izmantojiet komandu digitalWrite, lai izdrukātu pašreizējo stāvokli LED.


void loop() ( unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= intervāls) ( // saglabāt pēdējās LED stāvokļa maiņas laiku previousMillis = currentMillis; // ja gaismas diode ir izslēgta, ieslēdziet to, un otrādi if (ledState == LOW) ( ledState = HIGH; ) else ( ledState = LOW; ) // LED izeja digitalWrite(ledPin, ledState); ) )

Pirmā lieta, ar ko saskaras iesācējs, kurš apgūst Arduino, ir nepatīkamais kavēšanās () funkcijas īpašums - programmas izpildes bloķēšana. Daudzos interneta piemēros šī funkcija tiek izmantota, taču praktiskā pielietošana kaut kā liek domāt, ka labāk iztikt bez tās.

Kā jau iesācējam pienākas, izgudroju velosipēdu un pats izveidoju nebloķēšanas aizkaves ieviešanu. Uzdevums bija šāds:

  • Nodrošiniet pseido daudzuzdevumu veikšanu, lai dažādi notikumi notiktu savā laikā, ar saviem intervāliem un nebloķētu viens otru.
  • Bija ērti to lietot.
  • To varētu veidot kā bibliotēku un viegli iekļaut citos projektos bez copy-paste.
Redzot, ka lielākā daļa Arduino bibliotēku tiek veidotas, izmantojot OOP, es arī nolēmu neizrādīties un uzrakstīju SmartDelay klasi, ko var iegūt no github kā zip, lai pievienotu Arduino IDE vai veiktu git klonu ~/Arduino/. bibliotēkas/

Rezultāts ir šāds.

#iekļauts SmartDelay foo (1000000UL); // mikrosekundēs void loop () ( if (foo.Now()) ( // Šeit esošais kods tiek izpildīts katrā iepriekš konstruktorā norādītajā intervālā mikrosekundēs. ) //Cits kods )
Metode Now() atgriež patieso vērtību, ja intervāls ir pagājis. Šajā gadījumā atpakaļskaitīšana sākas no jauna ar tādu pašu intervālu. Tas ir, Tagad () katru reizi, kad "pārlādē" automātiski.

Klasiskā LED mirgošana var būt uzreiz sarežģīta līdz diviem mirgošanas gadījumiem. Piemēram, gaismām, kas savienotas ar tapām 12 un 11, vajadzētu mirgot attiecīgi ar 1 s un 777 ms intervālu.

#iekļauts SmartDelay led12 (1000000UL); SmartDelay led11 (777000UL); setup () ( pinMode(12,OUTPUT); pinMode(11,OUTPUT); ) baits led12state=0; baits led11state=0; void loop () ( if (led12.Now()) ( digitalWrite(12,led12state); led12state=!led12state; ) if (led11.Now()) ( digitalWrite(11,led11state); led11state=!led11state; ) )
Ciklā varat darīt ko citu, gaismas diožu mirgošana nebloķēs šī koda izpildi.

Ir skaidrs, ka tas nav pilnīgs aizkaves (), kas aptur pavedienu uz noteiktu laiku, aizstāšana, jums vienmēr ir jāraksta programma kā MFA (ierobežots automātikas mehānisms). Tas ir, saglabājiet stāvokli un, atkarībā no tā, dodieties uz pareizo vietu kodā.

Vecā versija:

Darbība1(); kavēšanās (1000); darbība2(); kavēšanās (500); darbība3(); ...
Jauna iespēja:

Baita stāvoklis=0; SmartDelayd(); ... slēdzis (stāvoklis) ( 0. gadījums: action1(); d.Set(1000000UL); stāvoklis=1; pārtraukums; 1. gadījums: if (d.Now()) ( action2(); d.Set(500000UL) ; stāvoklis=2; ) pārtraukums; 2. gadījums: if (d.Now()) (darbība3(); d.Stop(); stāvoklis=0; ) pārtraukums; ) ...
Metode Set(interval) iestata jaunu intervālu un atgriež veco. Jūs varat vienkārši apskatīt intervālu, izmantojot Get() metodi;

Stop() pārtrauc apstrādi, un Now() vienmēr atgriež false.

Start() atsāk un Now() sāk darboties kā parasti.

Ja jums ir nepieciešams palēnināt laika skaitīšanu, bet neapturēt to pilnībā, tad ir Gaidīšanas () metode. Piemēram, ja LED 12 mirgo un, nospiežot pogu, tā nemirgo, vienkārši pievienojiet tālāk norādīto kodu cilpai () piemērā ar divām diodēm iepriekš:

If (digitalRead(9)) led12.Wait(); ...
Tātad ar augstu signāla līmeni 9. posmā diode pie 12 nemirgos un turpinās, kad tur parādīsies 0.

Piemēram, ja ekrāns tiek zīmēts ar šādu “taimeri” un pogas tiek apstrādātas paralēli, iespējams, ka ekrāns vai daļa ir jāpārzīmē uzreiz pēc pogas nospiešanas, nevis jāgaida, līdz beigsies intervāls. Šim nolūkam tiek izmantota metode Reset(), pēc kuras nākamais Now() izsaukums atgriezīsies true. Piemēram:

SmartDelay displejs (1000000UL); void loop() ( ja (btClick()) display.Reset(); // noklikšķinājis uz pogas, mums jāzīmē ekrāns. if (display.Now()) screenRedraw(); // uzzīmējiet ekrānu. )
No kļūdām redzu tikai to, ka netiek ņemta vērā mikrosekunžu skaitītāja pārpilde, bet pretējā gadījumā, jā, mums ir jātīra kods. Man nepatīk, kā domāšanas laikā tiek darīts Reset().