Arduino multitasking - část první

Větší a lepší designy

Jakmile zvládnete základní blikající LED diody , jednoduché senzory a serva , jste připraveni začít s většími a lepšími projekty. Obvykle to zahrnuje spojování částí jednodušších skic a pokus o jejich spolupráci. První věc, kterou zjistíte, je, že některé z těchto skic, které fungují perfektně samy o sobě, se neshodují s ostatními.

Arduino je velmi jednoduchý modul bez operačního systému, který dokáže spustit pouze jeden program. Na rozdíl od vašeho osobního počítače nebo Raspberry Pi nemá Arduino schopnost načítat a spouštět více programů.

To neznamená, že v Arduinu nemůžeme dělat mnoho úkolů. Musíme použít jinou metodu. Nemáme operační systém, který by nám pomáhal, takže ho musíme vzít do vlastních rukou.

Arduino multitasking

Zbavte se delay ()

První věcí, kterou jste se při hraní s Arduinem naučili, je pravděpodobně použití výše uvedené funkce delay. Funkce delay () není komplikovaná, ale při přidávání dalších funkcí se stává problematickou. Potíž je v tom, že touto funkcí je „ rušné čekání “, které dominuje CPU.

Při volání této funkce nemůžete reagovat na vstupy, nemůžete zpracovávat žádná data a nemůžete měnit žádné výstupy. Blokuje celý procesor. Pokud tedy některá část vašeho kódu používá tuto funkci, je na tu dobu vše ostatní zastaveno.

Pamatuješ si Blink?

 / *
Blikat
Rozsvítí opakovaně LED na jednu sekundu a poté na jednu sekundu zhasne.

Tento ukázkový kód je ve veřejné doméně.
* /

// Pin 13 má LED připojenou na většině desek Arduino.
// pojmenujte jej:
int led = 13;

// instalační rutina se spustí jednou, když stisknete reset:
void setup () {
// inicializuje digitální pin jako výstup.
pinMode (led, OUTPUT);
}

// rutina smyčky běží znovu a znovu navždy:
void loop () {
digitalWrite (led, HIGH); // rozsvítí LED (HIGH je úroveň napětí)
zpoždění (1000); // počkejte chvíli
digitalWrite (led, LOW); // zhasněte LED tím, že nastavíte NÍZKÉ napětí
zpoždění (1000); // počkejte chvíli
}

Jednoduchý Blink náčrt je téměř pořád ve funkci delay (). Během této doby tedy CPU nemůže dělat nic jiného.

Zapomněli jste na svou akci ?

Sweep používá funkci delay () k řízení své rychlosti. Pokud se pokusíte zkombinovat základní blikající náčrt s příkladem tažného serva, všimnete si, že kontrolka LED střídavě bliká a servo se pohybuje. Neděje se to však současně.

 #include 

// Pin 13 má LED připojenou na většině desek Arduino.
// pojmenujte jej:
int led = 13;

Servo myservo; // vytvoření serva objektu pro ovládání serva
// na většině desek lze vytvořit dvanáct servoobjektů

int pos = 0; // proměnná pro uložení polohy serva

neplatné nastavení ()
{
// inicializuje digitální pin jako výstup.
pinMode (led, OUTPUT);
myservo.attach (9); // připojí servo na kolíku 9 k objektu serva
}

neplatná smyčka ()
{
digitalWrite (led, HIGH); // rozsvítí LED (HIGH je úroveň napětí)
zpoždění (1000); // počkejte chvíli
digitalWrite (led, LOW); // zhasněte LED tím, že nastavíte NÍZKÉ napětí
zpoždění (1000); // počkejte chvíli

pro (pos = 0; pos <= 180; pos + = 1) // přechází z 0 stupňů na 180 stupňů
{// v krocích po 1 stupni
myservo.write (pos); // řekni servu, aby šlo do polohy v proměnné 'pos'
zpoždění (15); // čeká 15 ms, než se servo dostane do polohy
}
for (pos = 180; pos> = 0; pos - = 1) // přechází ze 180 stupňů na 0 stupňů
{
myservo.write (pos); // řekni servu, aby šlo do polohy v proměnné 'pos'
zpoždění (15); // čeká 15ms na servo

Jak tedy zkontrolujeme zpoždění bez použití funkce zpoždění ?

Použijte funkci millis () ve zpoždění

Jednoduchou technikou implementace zpoždění je vytvoření plánu a sledování hodinek. Místo toho, abyste se soustředili na funkci zpoždění , pouze systematicky kontrolujete čas, abyste věděli, kdy jednat. Mezitím mohou CPU využívat i jiné úkoly. Velmi jednoduchým příkladem je náčrt BlinkyWithoutDelay s vývojovým prostředím.

Schéma připojení pro výše uvedený kód je uvedeno níže:

Arduino multitasking - schéma připojení

Bliká bez prodlení

Zde je ukázkový kód BlinkWithoutDelay:

 / * Bliká bez prodlevy

Zapíná a vypíná světelnou diodu (LED) připojenou k digitálnímu
pin, bez použití funkce delay (). To znamená, že jiný kód
může běžet současně bez přerušení LED kódem.

Obvod:
* LED připojená od kolíku 13 k zemi.
* Poznámka: na většině Arduinos je na desce již LED
který je připojen ke kolíku 13, takže pro tento příklad není nutný žádný hardware.


vytvořeno 2005
David A. Mellis
upraveno 8. února 2010
Paul Stoffregen

Tento ukázkový kód je ve veřejné doméně.


http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
* /

// konstanty se nezmění. Zde se používá k
// nastavit čísla pinů:
const int ledPin = 13; // číslo kolíku LED

// Proměnné se změní:
int ledState = LOW; // ledState slouží k nastavení LED
long previousMillis = 0; // uloží poslední aktualizaci LED

// následující proměnné jsou dlouhé, protože čas měřený v milisekundách,
// rychle se stane větším číslem, než kolik lze uložit do int.
dlouhý interval = 1000; // interval, ve kterém bliká (milisekundy)

void setup () {
// nastavit digitální pin jako výstup:
pinMode (ledPin, OUTPUT);
}

neplatná smyčka ()
{
// zde je místo, kam byste vložili kód, který musí být spuštěn po celou dobu.

// zkontrolujte, zda je čas blikat LED; to znamená, pokud
// rozdíl mezi aktuálním časem a posledním bliknutím
// LED je větší než interval, ve kterém chcete
// bliká LED.
nepodepsaný dlouhý proud Millis = millis ();

if (currentMillis - previousMillis> interval) {
// uložení posledního bliknutí LED
previousMillis = currentMillis;

// pokud LED nesvítí, rozsvítí se a naopak:
if (ledState == LOW)
ledState = HIGH;
jiný
ledState = LOW;

// nastavit LED s ledState proměnné:
digitalWrite (ledPin, ledState);
}
}

Dává to nějaký smysl?

Na první pohled se BlinkWithoutDelay nezdá příliš zajímavý. Vypadá to jako komplikovanější způsob rozsvícení LED diod . BlinkWithoutDelay však představuje velmi důležitý koncept známý jako konečný automat (s angličtinou. State Machine).

Při vytváření blikajícího LED programu se již nemusíte spoléhat na funkci delay (). BlinkWithoutDelay si pamatuje aktuální stav LED a poslední změnu. Po každé smyčce zkontroluje hodiny millis (), zda má znovu změnit stav LED.

Vítejte u stroje

Pojďme se podívat na trochu zajímavější variantu mrknutí , která má různé časy zapnutí a vypnutí. Říkali jsme tomu „FlashWithoutDelay“

// Tyto proměnné ukládají vzor flash
// a aktuální stav LED

int ledPin = 13; // číslo kolíku LED
int ledState = LOW; // ledState slouží k nastavení LED
bez znaménka long previousMillis = 0; // uloží poslední aktualizaci LED
dlouhý čas zapnutí = 250; // milisekundy doby zapnutí
dlouhý čas vypnutí = 750; // milisekundy mimo provoz

neplatné nastavení ()
{
// nastavit digitální pin jako výstup:
pinMode (ledPin, OUTPUT);
}

neplatná smyčka ()
{
// zkontrolujte, zda je čas změnit stav LED
nepodepsaný dlouhý proud Millis = millis ();

if ((ledState == HIGH) && (currentMillis - previousMillis> = OnTime))
{
ledState = LOW; // Vypněte to
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis> = OffTime))
{
ledState = HIGH; // zapnout
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
}

Status + Mashine = State Machine

Všimněte si, že máme proměnné, které sledují, zda LED svítí nebo nesvítí. Existují také ti, kteří sledují poslední změnu, která nastala. Je součástí stroje zvaného Status.

Máme také kód, který hlídá stav a rozhoduje, kdy a jak je třeba jej změnit. Toto je část zvaná Stroj . Po každé smyčce „spustíme stroj“ a aktualizuje stav.

Dále zkontrolujeme, jak připojujete stroje jejich současnou aktivací.

Cíl - dva najednou

Je čas na multitasking! Nejprve připojte další LED, jak je znázorněno na obrázku níže:

Arduino multitasking - schéma připojení LED

Dále vytvoříme další automat pro druhou LED, který bliká úplně jinými rychlostmi. Použití dvou samostatných strojů způsobí, že tyto dvě kontrolky LED budou blikat, aniž by byly na sobě navzájem závislé.

 // Tyto proměnné ukládají vzor flash
// a aktuální stav LED

int ledPin1 = 12; // číslo kolíku LED
int ledState1 = LOW; // ledState slouží k nastavení LED
bez znaménka long previousMillis1 = 0; // uloží poslední aktualizaci LED
long OnTime1 = 250; // milisekundy doby zapnutí
dlouhý čas vypnutí1 = 750; // milisekundy mimo provoz

int ledPin2 = 13; // číslo kolíku LED
int ledState2 = LOW; // ledState slouží k nastavení LED
bez znaménka long previousMillis2 = 0; // uloží poslední aktualizaci LED
long OnTime2 = 330; // milisekundy doby zapnutí
dlouhý čas vypnutí2 = 400; // milisekundy mimo provoz

neplatné nastavení ()
{
// nastavit digitální pin jako výstup:
pinMode (ledPin1, VÝSTUP);
pinMode (ledPin2, VÝSTUP);
}

neplatná smyčka ()
{
// zkontrolujte, zda je čas změnit stav LED
nepodepsaný dlouhý proud Millis = millis ();

if ((ledState1 == HIGH) && (currentMillis - previousMillis1> = OnTime1))
{
ledState1 = LOW; // Vypněte to
previousMillis1 = currentMillis; // Pamatovat čas
digitalWrite (ledPin1, ledState1); // Aktualizace aktuální LED
}
else if ((ledState1 == LOW) && (currentMillis - previousMillis1> = OffTime1))
{
ledState1 = HIGH; // zapnout
previousMillis1 = currentMillis; // Pamatovat čas
digitalWrite (ledPin1, ledState1); // Aktualizace aktuální LED
}

if ((ledState2 == HIGH) && (currentMillis - previousMillis2> = OnTime2))
{
ledState2 = LOW; // Vypněte to
previousMillis2 = currentMillis; // Pamatovat čas
digitalWrite (ledPin2, ledState2); // Aktualizace aktuální LED
}
else if ((ledState2 == LOW) && (currentMillis - previousMillis2> = OffTime2))
{
ledState2 = HIGH; // zapnout
previousMillis2 = currentMillis; // Pamatovat čas
digitalWrite (ledPin2, ledState2); // Aktualizace aktuální LED
}
}

Děkuji mnohokrát! Mohu získat další?

Můžete přidat další automaty, pokud máte dostatek paměti nebo GPIO pinů. Každý slot má svou vlastní frekvenci blikání. Úkolem je upravit výše uvedený kód, aby bylo možné přidat třetí automat.

  • Nejprve zkopírujte všechny stavové proměnné a kód jednoho z automatů.
  • Poté každou proměnnou přejmenujte, aby nedošlo k rozporu s prvním strojem.

Není to tak těžké udělat. Opakované přepisování kódu se ale zdá být poměrně časově náročné. Musí existovat nějaký jiný způsob, jak to udělat!

Existují lepší způsoby řešení. Existují programovací techniky, které jsou jednodušší a efektivnější.

Třída

Pojďme se znovu podívat na náš poslední náčrt. Jak vidíte, je to velmi monotónní. Stejný kód je kopírován téměř slovo za slovem pro každou blikající LED. Jediná věc, která se (mírně) mění, je název proměnných.

Tento kód je nejlepším kandidátem na objektově orientované programování (OOP)

OOP ve smyčce

Jazyk Arduino je variace jazyka C ++, která podporuje objektově orientované programování. Pomocí jazyka OOP můžeme shromažďovat všechny stavové proměnné a funkce blikající LED ve třídě C ++.

Není to tak těžké udělat, protože už máme napsaný celý kód. Musíme to přebalit jako třídu.

Určení třídy:

Začneme deklarováním třídy „Flasher“:

Poté přidáme všechny proměnné z FlashWithoutDelay. Jsou součástí třídy, takže je známe jako členské proměnné .

 třída Flasher
{
// Proměnné členů třídy
// Jsou inicializovány při spuštění
int ledPin; // číslo kolíku LED
dlouhý OnTime; // milisekundy doby zapnutí
dlouhý čas OffTime; // milisekundy mimo provoz

// Udržují aktuální stav
int ledState; // ledState slouží k nastavení LED
nepodepsaný dlouhý předchozí Millis; // uloží poslední aktualizaci LED
};

Pak přidáme konstruktor . Má stejný název jako třída a má za úkol inicializovat všechny proměnné.

 třída Flasher
{
// Proměnné členů třídy
// Jsou inicializovány při spuštění
int ledPin; // číslo kolíku LED
dlouhý OnTime; // milisekundy doby zapnutí
dlouhý čas OffTime; // milisekundy mimo provoz

// Udržují aktuální stav
int ledState; // ledState slouží k nastavení LED
nepodepsaný dlouhý předchozí Millis; // uloží poslední aktualizaci LED

// Konstruktor - vytvoří Flasher
// a inicializuje členské proměnné a stav
veřejnost:
Blikač (int pin, long on, long off)
{
ledPin = špendlík;
pinMode (ledPin, OUTPUT);

OnTime = zapnuto;
OffTime = vypnuto;

ledState = LOW;
previousMillis = 0;
}
};

Nakonec ze smyčky uděláme členskou funkci nazvanou „Update ()“.

 třída Flasher
{
// Proměnné členů třídy
// Jsou inicializovány při spuštění
int ledPin; // číslo kolíku LED
dlouhý OnTime; // milisekundy doby zapnutí
dlouhý čas OffTime; // milisekundy mimo provoz

// Udržují aktuální stav
int ledState; // ledState slouží k nastavení LED
nepodepsaný dlouhý předchozí Millis; // uloží poslední aktualizaci LED

// Konstruktor - vytvoří Flasher
// a inicializuje členské proměnné a stav
veřejnost:
Blikač (int pin, long on, long off)
{
ledPin = špendlík;
pinMode (ledPin, OUTPUT);

OnTime = zapnuto;
OffTime = vypnuto;

ledState = LOW;
previousMillis = 0;
}

void Update ()
{
// zkontrolujte, zda je čas změnit stav LED
nepodepsaný dlouhý proud Millis = millis ();

if ((ledState == HIGH) && (currentMillis - previousMillis> = OnTime))
{
ledState = LOW; // Vypněte to
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis> = OffTime))
{
ledState = HIGH; // zapnout
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
}
};

Tím, že jsme náš kód změnili na třídu Flasher, jsme zúžili všechny proměnné ( stav ) a funkce ( stroj ) blikající LED.

Nyní použijeme toto:

Pro každou LED, kterou chceme rozsvítit, vytvořte příklad třídy Flasher voláním konstruktoru. Pokaždé, když procházíme smyčkou, musíme zavolat Update () pro každý příklad Flasher.

Již není nutné opakovat celý strojový kód. Jediné, co nám zbývá, je požádat o další příklady třídy Flasher!

 třída Flasher
{
// Proměnné členů třídy
// Jsou inicializovány při spuštění
int ledPin; // číslo kolíku LED
dlouhý OnTime; // milisekundy doby zapnutí
dlouhý čas OffTime; // milisekundy mimo provoz

// Udržují aktuální stav
int ledState; // ledState slouží k nastavení LED
nepodepsaný dlouhý předchozí Millis; // uloží poslední aktualizaci LED

// Konstruktor - vytvoří Flasher
// a inicializuje členské proměnné a stav
veřejnost:
Blikač (int pin, long on, long off)
{
ledPin = špendlík;
pinMode (ledPin, OUTPUT);

OnTime = zapnuto;
OffTime = vypnuto;

ledState = LOW;
previousMillis = 0;
}

void Update ()
{
// zkontrolujte, zda je čas změnit stav LED
nepodepsaný dlouhý proud Millis = millis ();

if ((ledState == HIGH) && (currentMillis - previousMillis> = OnTime))
{
ledState = LOW; // Vypněte to
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis> = OffTime))
{
ledState = HIGH; // zapnout

previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
}
};


Blikač LED1 (12 100 400);
LED2 blikač (13, 350, 350);

neplatné nastavení ()
{
}

neplatná smyčka ()
{
led1.Update ();
led2.Update ();
}

Méně je více!

Nakonec - každá další LED vyžaduje pouze dva řádky kódu!

Kód je kratší a čitelnější. A protože neexistuje žádný duplicitní kód, je toho méně kompilace! To vše šetří paměť pro další projekty!

Co jiného můžeme dělat?

Pojďme aplikovat stejné principy na servo kódy a můžeme začít.

Nejprve spojte dvě serva dohromady na prkénku, jak je znázorněno na obrázku níže. Poté připojte také třetí LED .

Arduino multitasking - schéma připojení pro serva a LED

Zde je standardní kód zametání serva. Všimněte si, že vyvolá funkci delay (), kterou nechceme. Vezmeme části tohoto kódu k sestavení automatu „Sweeper“.

 // Zametat
// autor BARRAGAN
// Tento ukázkový kód je ve veřejné doméně.


#include

Servo myservo; // vytvoření serva objektu pro ovládání serva
// lze vytvořit maximálně osm servo objektů

int pos = 0; // proměnná pro uložení polohy serva

neplatné nastavení ()
{
myservo.attach (9); // připojí servo na kolíku 9 k objektu serva
}


neplatná smyčka ()
{
for (pos = 0; pos <180; pos + = 1) // přechází z 0 stupňů na 180 stupňů
{// v krocích po 1 stupni
myservo.write (pos); // řekni servu, aby šlo do polohy v proměnné 'pos'
zpoždění (15); // čeká 15 ms, než se servo dostane do polohy
}
for (pos = 180; pos> = 1; pos- = 1) // přechází ze 180 stupňů na 0 stupňů
{
myservo.write (pos); // řekni servu, aby šlo do polohy v proměnné 'pos'
zpoždění (15); // čeká 15 ms, než se servo dostane do polohy
}
}

Následující třída Sweeper shrnuje akci tažení , ale k nastavení zpoždění používá funkci millis ().

Musíme také přidat funkce Attach () a Detach (), aby se servo vázalo na konkrétní pin:

 třídní zametač
{
Servo servo; // servo
int pos; // aktuální poloha serva
přírůstek int; // přírůstek pro pohyb pro každý interval
int updateInterval; // interval mezi aktualizacemi
nepodepsaný dlouhý lastUpdate; // poslední aktualizace polohy

veřejnost:
Zametač (int interval)
{
updateInterval = interval;
přírůstek = 1;
}

void Attach (int pin)
{
servo.attach (pin);
}

void Detach ()
{
servo.detach ();
}

void Update ()
{
if ((millis () - lastUpdate)> updateInterval) // čas aktualizace
{
lastUpdate = millis ();
pos + = přírůstek;
servo.write (pos);
Serial.println (pos);
if ((pos> = 180) || (pos <= 0)) // konec tažení
{
// opačný směr
přírůstek = -přírůstek;
}
}
}
};

Jak moc?

Nyní můžeme vytvořit tolik blesků a zametačů, kolik chceme.

Každý příklad Flasher vyžaduje 2 řádky kódu:

  • jeden pro deklaraci příkladu
  • druhý pro spuštění aktualizační smyčky

Každý příklad Sweeper vyžaduje pouze 3 řádky kódu:

  • jeden pro deklaraci příkladu
  • druhý k připojení serva k čepu
  • a třetí pro spuštění aktualizační smyčky

 #include 

třída Flasher
{
// Proměnné členů třídy
// Jsou inicializovány při spuštění
int ledPin; // číslo kolíku LED
dlouhý OnTime; // milisekundy doby zapnutí
dlouhý čas OffTime; // milisekundy mimo provoz

// Udržují aktuální stav
int ledState; // ledState slouží k nastavení LED
nepodepsaný dlouhý předchozí Millis; // uloží poslední aktualizaci LED

// Konstruktor - vytvoří Flasher
// a inicializuje členské proměnné a stav
veřejnost:
Blikač (int pin, long on, long off)
{
ledPin = špendlík;
pinMode (ledPin, OUTPUT);

OnTime = zapnuto;
OffTime = vypnuto;

ledState = LOW;
previousMillis = 0;
}

void Update ()
{
// zkontrolujte, zda je čas změnit stav LED
nepodepsaný dlouhý proud Millis = millis ();

if ((ledState == HIGH) && (currentMillis - previousMillis> = OnTime))
{
ledState = LOW; // Vypněte to
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis> = OffTime))
{
ledState = HIGH; // zapnout
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
}
};

třídní zametač
{
Servo servo; // servo
int pos; // aktuální poloha serva
přírůstek int; // přírůstek pro pohyb pro každý interval
int updateInterval; // interval mezi aktualizacemi
nepodepsaný dlouhý lastUpdate; // poslední aktualizace polohy

veřejnost:
Zametač (int interval)
{
updateInterval = interval;
přírůstek = 1;
}

void Attach (int pin)
{
servo.attach (pin);
}

void Detach ()
{
servo.detach ();
}

void Update ()
{
if ((millis () - lastUpdate)> updateInterval) // čas aktualizace
{
lastUpdate = millis ();
pos + = přírůstek;
servo.write (pos);
Serial.println (pos);
if ((pos> = 180) || (pos <= 0)) // konec tažení
{
// opačný směr
přírůstek = -přírůstek;
}
}
}
};


LED1 blikač (11, 123, 400);
LED2 blikač (12, 350, 350);
LED3 blikač (13 200 222);

Zametací zametací stroj1 (15);
Zametací zametací stroj2 (25);

neplatné nastavení ()
{
Serial.begin (9600);
zametač 1. připevněte (9);
2. zametač (10);
}


neplatná smyčka ()
{
sweeper1.Update ();
sweeper2.Update ();

led1.Update ();
led2.Update ();
led3.Update ();
}

V tuto chvíli máme 5 nezávislých úkolů spuštěných nepřetržitě bez přerušení. A naše funkce loop () má pouze 5 řádků kódu!

Všichni společně!

Chceme také váš příspěvek

Dalším problémem s časováním založeným na delay () je, že vstup uživatele, jako je stisknutí tlačítka , je často ignorován. Je to proto, že procesor nemůže zkontrolovat stav tlačítka, když je ve funkci delay (). Se zpožděním založeným na funkci millis () může procesor pravidelně kontrolovat stav tlačítek a dalších vstupů. To nám umožňuje vytvářet složité programy, které dokážou dělat mnoho věcí najednou a stále reagovat.

Ukážeme to přidáním tlačítka do našeho obvodu, jak je znázorněno na obrázku:

Arduino multitasking - schéma připojení pomocí tlačítka

Následující kód zkontroluje stav tlačítka při každém průchodu smyčkou. Led1 a sweeper2 se po stisknutí tlačítka neaktualizují.

 #include 


třída Flasher
{
// Proměnné členů třídy
// Jsou inicializovány při spuštění
int ledPin; // číslo kolíku LED
dlouhý OnTime; // milisekundy doby zapnutí
dlouhý čas OffTime; // milisekundy mimo provoz

// Udržují aktuální stav
int ledState; // ledState slouží k nastavení LED
nepodepsaný dlouhý předchozí Millis; // uloží poslední aktualizaci LED

// Konstruktor - vytvoří Flasher
// a inicializuje členské proměnné a stav
veřejnost:
Blikač (int pin, long on, long off)
{
ledPin = špendlík;
pinMode (ledPin, OUTPUT);

OnTime = zapnuto;
OffTime = vypnuto;

ledState = LOW;
previousMillis = 0;
}

void Update ()
{
// zkontrolujte, zda je čas změnit stav LED
nepodepsaný dlouhý proud Millis = millis ();

if ((ledState == HIGH) && (currentMillis - previousMillis> = OnTime))
{
ledState = LOW; // Vypněte to
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis> = OffTime))
{
ledState = HIGH; // zapnout
previousMillis = currentMillis; // Pamatovat čas
digitalWrite (ledPin, ledState); // Aktualizace aktuální LED
}
}
};

třídní zametač
{
Servo servo; // servo
int pos; // aktuální poloha serva
přírůstek int; // přírůstek pro pohyb pro každý interval
int updateInterval; // interval mezi aktualizacemi
nepodepsaný dlouhý lastUpdate; // poslední aktualizace polohy

veřejnost:
Zametač (int interval)
{
updateInterval = interval;
přírůstek = 1;
}

void Attach (int pin)
{
servo.attach (pin);
}

void Detach ()
{
servo.detach ();
}

void Update ()
{
if ((millis () - lastUpdate)> updateInterval) // čas aktualizace
{
lastUpdate = millis ();
pos + = přírůstek;
servo.write (pos);
Serial.println (pos);
if ((pos> = 180) || (pos <= 0)) // konec tažení
{
// opačný směr
přírůstek = -přírůstek;
}
}
}
};


LED1 blikač (11, 123, 400);
LED2 blikač (12, 350, 350);
LED3 blikač (13 200 222);

Zametací zametací stroj1 (15);
Zametací zametací stroj2 (25);

neplatné nastavení ()
{
Serial.begin (9600);
zametač 1. připevněte (9);
2. zametač (10);
}


neplatná smyčka ()
{
sweeper1.Update ();

if (digitalRead (2) == HIGH)
{
sweeper2.Update ();
led1.Update ();
}

led2.Update ();
led3.Update ();
}

3 LED diody budou blikat svým vlastním tempem. 2 zametací stroje budou také běžet svou vlastní rychlostí. Ale po stisknutí tlačítka, sweeper2 a LED1 se zastaví, dokud uvolnění tlačítka.

Arduino multitasking - provoz

Nyní máme 5 úloh zadávání uživatelů spuštěných nezávisle. Neexistují žádná zpoždění, která zablokují procesor. A náš efektivní objektově orientovaný programovací kód ponechává dostatek prostoru pro rozšíření!

Závěry:

V této příručce jsme vám ukázali, že Arduino může provádět mnoho různých úkolů a stále reagovat na externí události.

  • Naučili jsme se, jak měřit čas pomocí millis () místo delay (), což procesoru umožňovalo dělat jiné věci.
  • Naučili jsme se, jak definovat úkoly jako automaty, které mohou běžet současně s jinými automaty, ale nezávisle na nich.
  • Zjistili jsme, jak zahrnout tyto automaty do tříd C ++, aby byl kód jednoduchý a výstižný.

Tyto techniky nezmění vaše Arduino na superpočítač. Pomohou vám však dostat z tohoto malého, ale neuvěřitelně výkonného modulu to nejlepší.

Ve druhé části budeme stavět pomocí těchto technik. Objevíme také další způsoby, jak zajistit, aby Arduino reagovalo na externí události a současně udržovalo běh více úkolů.

část druhá ->

Zdroj: https://learn.adafruit.com/multi-tasking-the-arduino-part-1

zveme vás ke spolupráci!