- Brisanje zadatka u FreeRTOS Arduinu
- Što je red u FreeRTOS-u?
- Stvaranje reda u FreeRTOS-u
- Kružni dijagram
- Implementacija reda FreeRTOS u Arduino IDE
U prethodnom uputstvu uveli smo FreeRTOS u Arduino Uno i stvorili zadatak za trepćuću LED diodu. Sada ćemo u ovom vodiču više zaroniti u napredne koncepte RTOS API-ja i naučiti o komunikaciji između različitih zadataka. Ovdje također učimo o redu čekanja za prijenos podataka s jednog zadatka na drugi i demonstriramo rad API-ja reda čekanja povezivanjem 16x2 LCD-a i LDR-a s Arduino Uno.
Prije rasprave o Redovima čekova, pogledajmo još jedan FreeRTOS API koji je koristan pri brisanju zadataka kada završi s dodijeljenim poslom. Ponekad zadatak treba izbrisati da biste oslobodili dodijeljenu memoriju. U nastavku prethodnog vodiča, koristit ćemo funkciju vTaskDelete () API u istom kodu za brisanje jednog od zadataka. Zadatak može koristiti funkciju vTaskDelete () API da bi se izbrisao ili bilo koji drugi zadatak.
Da biste koristili ovaj API, morate konfigurirati datoteku FreeRTOSConfig.h . Ova se datoteka koristi za prilagodbu FreeRTOS-a prema aplikaciji. Koristi se za promjenu algoritama rasporeda i mnogih drugih parametara. Datoteka se može naći u Arduino direktoriju koji je općenito dostupan u mapi Dokumenti na vašem računalu. U mom slučaju dostupan je u \ Documents \ Arduino \ libraries \ FreeRTOS \ src kao što je prikazano dolje.

Sada, otvoriti ove datoteke pomoću programa za uređivanje teksta i tražiti od #define INCLUDE_vTaskDelete i provjerite da je njegova vrijednost „1” (1 znači omogućiti i 0 znači onemogućiti). Po defaultu je 1, ali provjerava.

Ovu ćemo konfiguracijsku datoteku često koristiti u sljedećim vodičima za postavljanje parametara.
Sada, da vidimo kako izbrisati zadatak.
Brisanje zadatka u FreeRTOS Arduinu
Da bismo izbrisali zadatak, moramo koristiti funkciju vTaskDelete () API. Potreban je samo jedan argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Obriši se ručica zadatka. To je isto kao i šesti argument xTaskCreate () API-ja. U prethodnom je vodiču ovaj argument postavljen na NULL, ali adresu sadržaja zadatka možete proslijediti bilo kojim imenom. Recimo ako želite postaviti ručicu zadatka za Task2 koja je deklarirana kao
TaskHandle_t bilo koje_ime; Primjer: TaskHandle_t xTask2Handle;
Sada, u vTaskCreate () API set 6 -og argument
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1 i & xTask2Handle);
Sadržaju ovog zadatka sada se može pristupiti pomoću ručice koju ste dali.
Također, zadatak se može izbrisati prosljeđivanjem NULL umjesto valjane ručke zadatka.
Ako želimo izbrisati zadatak 3 iz samog zadatka 3, trebate napisati vTaskDelete (NULL); unutar funkcije Task3, ali ako želite izbrisati zadatak 3 iz zadatka 2, tada napišite vTaskDelete (xTask3Handle); unutar funkcije task2.
U prethodnom tutorial kodu, da biste izbrisali Task2 iz samog task2, samo dodajte vTaskDelete (NULL); u void funkciji TaskBlink2 (void * pvParameters) . Tada će gornja funkcija izgledati ovako
void TaskBlink2 (void * pvParameters) { Serial.println („Task2 je pokrenut i sprema se izbrisati“); vTaskDelete (NULL); pinMode (7, IZLAZ); while (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, PO) vTaskDelay (300 / portTICK_PERIOD_MS); } }
Sada prenesite kôd i promatrajte LED i serijski monitor. Vidjet ćete da druga LED lampica sada ne trepće i zadatak2 se briše nakon što naiđe na API za brisanje.

Dakle, ovaj se API može koristiti za zaustavljanje izvršavanja određenog zadatka.
Sada, krenimo s Redom čekanja.
Što je red u FreeRTOS-u?
Red čekanja je struktura podataka koja može sadržavati konačan broj elemenata fiksne veličine i djeluje u FIFO shemi (First-in First-out). Redovi pružaju mehanizam komunikacije zadatak do zadatka, zadatak do prekida i prekid do zadatka.
Maksimalni broj elemenata koji se u redu može držati naziva se njegova "duljina". Dužina i veličina svakog elementa postavljaju se kada se stvori red.
Primjer kako se red koristi za prijenos podataka dobro je ilustriran u FreeRTOS dokumentaciji koju možete pronaći ovdje. Navedeni primjer možete lako razumjeti.

Nakon razumijevanja Redova, pokušajmo razumjeti postupak stvaranja reda i pokušati ga implementirati u naš FreeRTOS kod.
Stvaranje reda u FreeRTOS-u
Prvo opišite iskaz problema koji se treba implementirati uz pomoć reda FreeRTOS i Arduino Uno.
Vrijednost LDR senzora želimo ispisati na LCD 16 * 2. Dakle, sada postoje dva zadatka
- Zadatak 1 je dobivanje analognih vrijednosti LDR.
- Task2 ispisuje analognu vrijednost na LCD.
Dakle, ovdje red ima svoju ulogu jer za slanje podataka generiranih od task1 do task2. U zadatku 1 poslat ćemo analognu vrijednost u red, a u zadatku 2 primit ćemo je iz reda.
Postoje tri funkcije za rad s redovima
- Stvaranje reda čekanja
- Slanje podataka u red čekanja
- Primanje podataka iz reda čekanja
Za stvaranje reda koristite API funkcije xQueueCreate (). Potrebna su dva argumenta.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Maksimalan broj stavki koje red koji se kreira može istovremeno sadržavati.
uxItemSize: Veličina u bajtovima svake podatkovne stavke koja se može pohraniti u red čekanja.
Ako ova funkcija vrati NULL, red se ne stvara zbog nedostatka memorije, a ako vrati vrijednost koja nije NULL, red se uspješno kreira. Spremite ovu povratnu vrijednost u varijablu da biste je koristili kao hvataljku za pristup redu kao što je prikazano u nastavku.
QueueHandle_t red čekanja1; queue1 = xQueueCreate (4, sizeof (int));
To će stvoriti red od 4 elementa u hrpi memorije veličine int (2 bajta svakog bloka) i pohraniti povratnu vrijednost u varijablu ručice queue1 .
2. Slanje podataka u red čekanja u FreeRTOS-u
Da bi vrijednosti poslao u red, FreeRTOS u tu svrhu ima 2 varijante API-ja.
- xQueueSendToBack (): Koristi se za slanje podataka na stražnji dio (rep) reda.
- xQueueSendToFront (): Koristi se za slanje podataka na prednju stranu (glavu) reda.
Sada , xQueueSend () je ekvivalentna, a točno isto kao, xQueueSendToBack ().
Svi ovi API-ji uzimaju 3 argumenta.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Ručka reda u koji se podaci šalju (zapisuju). Ova je varijabla ista kao i za pohranu povratne vrijednosti API-ja xQueueCreate.
pvItemToQueue: pokazivač na podatke koji će se kopirati u red čekanja.
xTicksToWait: Maksimalno vrijeme zadatka treba ostati u blokiranom stanju da pričeka da prostor postane dostupan u redu čekanja.
Ako xTicksToWait postavite na portMAX_DELAY , zadatak će čekati neograničeno (bez vremenskog ograničenja), pod uvjetom da je INCLUDE_vTaskSuspend postavljeno na 1 u FreeRTOSConfig.h, a možete koristiti makronaredbu pdMS_TO_TICKS () za pretvaranje vremena određenog u milisekundama u vrijeme određeno u tikovima.
3. Primanje podataka iz reda u FreeRTOS
Za primanje (čitanje) stavke iz reda koristi se xQueueReceive (). Primljena stavka uklanja se iz reda čekanja.
Ovaj API također uzima tri argumenta.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Prvi i treći argument su isti kao i slanje API-ja. Samo je drugi argument drugačiji.
const pvBuffer: pokazivač na memoriju u koju će se kopirati primljeni podaci.
Nadam se da ste razumjeli tri API-ja. Sada ćemo implementirati ove API-je u Arduino IDE i pokušati riješiti problem koji smo gore opisali.
Kružni dijagram

Evo kako to izgleda na ploči:

Implementacija reda FreeRTOS u Arduino IDE
Počnimo pisati kod za našu aplikaciju.
1. Prvo otvorite Arduino IDE i uključite datoteku zaglavlja Arduino_FreeRTOS.h . Ako se koristi bilo koji objekt jezgre poput reda, uključite njegovu zaglavnu datoteku. Kako koristimo LCD 16 * 2, uključite i knjižnicu za njega.
#include #include
2. Inicijalizirajte ručicu reda za spremanje sadržaja reda. Također, inicijalizirajte LCD brojeve pinova.
QueueHandle_t red čekanja_1; LCD LiquidCrystal (7, 8, 9, 10, 11, 12);
3. U praznom postavljanju (), inicijalizirajte LCD i serijski monitor brzinom od 9600 baud-podataka. Stvorite red i dva zadatka pomoću odgovarajućih API-ja. Ovdje ćemo stvoriti red veličine 4 s cijelim brojem. Stvorite zadatak s jednakim prioritetima, a kasnije se pokušajte igrati s tim brojem. Napokon, pokrenite program za planiranje kao što je prikazano dolje.
void setup () { Serial.begin (9600); lcd.begin (16, 2); queue_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("Red se ne može stvoriti"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Sada napravite dvije funkcije TaskDisplay i TaskLDR . U funkciji TaskLDR pročitajte analogni pin A0 u varijabli jer imamo LDR spojen na A0 pin Arduino UNO. Sada pošaljite vrijednost pohranjenu u varijablu tako što ćete je proslijediti u xQueueSend API i poslati zadatak za blokiranje stanja nakon 1 sekunde pomoću vTaskDelay () API kao što je prikazano dolje.
void TaskLDR (void * pvParameters) { int current_intensity; while (1) { Serial.println ("Zadatak1"); trenutna_intenziteta = analogRead (A0); Serial.println (trenutna_intenziteta); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Slično tome, napravite funkciju za TaskDisplay i primite vrijednosti u varijabli koja se prosljeđuje funkciji xQueueReceive . Također, xQueueReceive () vraća pdPASS ako se podaci mogu uspješno primiti iz reda i vraća errQUEUE_EMPTY ako je red prazan.
Sada prikažite vrijednosti na LCD-u pomoću funkcije lcd.print () .
void TaskDisplay (void * pvParameters) { int intenzitet = 0; while (1) { Serial.println ("Zadatak2"); if (xQueueReceive (queue_1, & intenzitet, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intenzitet:"); lcd.setCursor (11, 0); lcd.print (intenzitet); } } }
To je to. Završili smo kodiranje dijela implementacije reda. Kompletni kôd s radnim videom možete pronaći na kraju.
Sada spojite LCD i LDR s Arduino UNO prema shemi prenosa koda. Otvorite serijski monitor i promatrajte zadatke. Vidjet ćete da se zadaci mijenjaju, a vrijednosti LDR-a mijenjaju u skladu s intenzitetom svjetlosti.


NAPOMENA: Većina knjižnica izrađenih za različite senzore ne podržava jezgro FreeRTOS zbog kašnjenja implementacije funkcije unutar knjižnica. Odgoda čini da se CPU potpuno zaustavi, stoga i jezgra FreeRTOS prestaje raditi, a kôd se neće izvršavati dalje i počinje se loše ponašati. Dakle, knjižnicama moramo omogućiti da bez odgađanja rade s FreeRTOS-om.
