Sunteți pe pagina 1din 12

Universitatea Tehnică a Moldovei

Facultatea Calculatoare Informatică și Microelectronică

Raport
la Internet of Things
Lucrarea de laborator Nr. 2
Tema: Sisteme de operare secvențiale și în timp real

A efectuat: st.gr. TI-205 Munteanu Iulian


A verificat: asist.univ. Litra Dinu

Chișinău 2023
Definirea problemei 1
Realizarea unei aplicații pentru MCU care va rula minim 3 task-uri – Secvential.
Aplicația va rula minim 3 task-uri printre care
1. Button Led - Schimbare stare LED la detecția unei apăsări pe buton.
2. un al doilea Led Intermitent în faza în care LED-ul de la primul Task e stins
3. Incrementare/decrementare valoare a unei variabile la apăsarea a doua butoane care va reprezenta
numărul de recurențe/timp în care ledul de la al doilea task se va afla într-o stare
4. Task-ul de Idle se va utiliza pentru afișarea stărilor din program, cum ar fi, afișare stare LED, și
afișare mesaj la detecția apăsării butoanelor, o implementare fiind ca la apăsarea butonului sa se
seteze o variabila, iar la afișare mesaj - resetare, implementând mecanismul provider/consumer.

Obiective
 configurarea aplucației pentru lucrul cu librăria STDIO;
 crearea schemei și codului conform sarcinii propuse;
 înțelegerea sistemului creat și procesele ce se întâmplă.

Introducere
Sistemele de operare secvențiale sunt proiectate pentru a rula un singur proces la un moment dat.
Acestea funcționează într-un mod liniar, procesul actual este executat în întregime înainte ca altul să
înceapă. Acest lucru înseamnă că procesele trebuie să aștepte să se termine procesul anterior pentru a
începe. În contextul Arduino, unde resursele sunt limitate, aceasta poate fi o alegere eficientă, deoarece
evită conflictul pentru resursele limitate ale microcontrolerului.
Cu toate acestea, aceste sisteme au dezavantaje evidente. Ele nu sunt potrivite pentru aplicații care
necesită răspunsuri rapide la evenimente externe. În plus, un crash al procesului curent ar putea bloca
întregul sistem, deoarece nu există mecanisme pentru a continua cu alte procese în timpul unui astfel de
eveniment.
Metode și materiale

Materiale Necesare:
Arduino Board (de exemplu, Arduino Uno);
breadboard și fire de conexiune;
3 butoane;
2 LED-uri;
2 rezistențe pentru LED-uri;
sursă de alimentare pentru Arduino;
editor Arduino IDE instalat pe un calculator.
Metoda de Implementare:
conexiuni hardware:
 conectare butoanele la pinii digitali ai Arduino;
 conectare LED-urile la pinii digitali ai Arduino, folosind rezistențe pentru a limita
curentul.
scrierea codului în Arduino IDE:
 definire variabilele și pinii corespunzători pentru butoane și LED-uri;
 implementare funcții pentru detectarea stării butoanelor și controlul stării LED-urilor;
 folosire structuri de control (if-else) pentru a gestiona logica sarcinilor secvențiale;
 implementare un task Idle care afișează stările LED-urilor și mesajele relevante.
testarea și debugging:
 încărcare cod pe Arduino folosind Arduino IDE;
 monitorizare comportament butoanelor și LED-urilor în timp real;
 identificare și rezolvare eventualelor erori în cod.

Rezultate
 loop(): Apelează patru funcții, task1(), task2(), task3() și taskIdle() în buclă infinită.
 Task 1 (task1()): Detectează apăsarea butonului 1 și schimbă starea LED-ului 1 (Button Led) între
aprins și stins.
 Task 2 (task2()): Interpretează starea LED-ului 1. Dacă LED-ul 1 este stins, intermitența LED-ului
2 (LED-ul intermitent) este controlată la fiecare recurrence * 10 milisecunde.
 Task 3 (task3()): Detectează apăsarea butoanelor 2 și 3 și ajustează valoarea variabilei recurrence
pentru a mări sau micșora frecvența de blink a LED-ului 2.
 Task Idle (taskIdle()): Afișează valoarea variabilei recurrence în Serial Monitor pentru a indica
frecvența actuală de blink a LED-ului 2.

Descriere Detaliată:
 Când butonul 1 este apăsat, LED-ul 1 se schimbă între starea aprins și stins.
 Dacă LED-ul 1 este stins, LED-ul 2 se aprinde și stinge la fiecare recurrence * 10 milisecunde.
 Butonul 2 scade recurrence cu 100 la fiecare apăsare, controlând astfel viteza intermitenței LED-
ului 2.
 Butonul 3 crește recurrence cu 100 la fiecare apăsare, controlând astfel viteza intermitenței LED-
ului 2.
 Dacă recurrence ajunge la 0, un mesaj este afișat în Serial Monitor.
Codul implementează aceste funcționalități folosind o buclă infinită și patru funcții separate pentru
a simula sarcinile secvențiale ale unui sistem de operare simplu pe o placă Arduino.

Figura 1 – Asamblarea circuitului pentru 2 LED-uri cu aprindere controlată de butoane

Definirea problemei 2
Realizarea unei aplicații pentru MCU care va rula minim 3 task-uri cu FreeRTOS.
Aplicația va rula minim 3 task-uri printre care
 Button Led - Schimbare stare LED la detecția unei apăsări pe buton;
 un al doilea Led Intermitent în faza în care LED-ul de la primul Task e stins;
 Incrementare/decrementare valoare a unei variabile la apăsarea a doua butoane care va reprezenta
numărul de recurențe/timp în care ledul de la al doilea task se va afla într-o stare;
 Task-ul de Idle se va utiliza pentru afișarea stărilor din program, cum ar fi, afișare stare LED, și
afișare mesaj la detecția apăsării butoanelor, o implementare fiind ca la apăsarea butonului sa se
seteze o variabila, iar la afișare mesaj - resetare, implementând mecanismul provider/consumer.

Obiective
 configurarea aplucației pentru lucrul cu librăria FreeRTOS;
 crearea schemei și codului conform sarcinii propuse;
 înțelegerea sistemului creat și procesele ce se întâmplă.

Introducere
Sistemele de operare în timp real (RTOS) sunt concepute pentru a răspunde la evenimente în timp
real într-un mod predictibil și eficient. Ele gestionează procesele concurente și oferă funcționalități
precum planificarea, gestionarea memoriei și comunicarea interproces. Un exemplu notabil de RTOS
open-source este FreeRTOS, care este potrivit pentru aplicații pe platforma Arduino.
În cazul utilizării FreeRTOS pe platforma Arduino, beneficiile sunt evidente:
 Planificare Avansată: RTOS poate gestiona multiple sarcini concurente, fiecare cu propriul său
context și prioritate. Aceasta înseamnă că sarcinile pot fi planificate eficient în funcție de cerințele
lor, ceea ce este crucial în aplicațiile în timp real;
 Comunicare și Sincronizare: RTOS facilitează comunicarea între sarcini și sincronizarea acțiunilor
acestora. Acest lucru este important în aplicațiile IoT unde diverse componente trebuie să
coopereze pentru a îndeplini o funcție;
 Gestionarea Resurselor: RTOS asigură că resursele hardware, cum ar fi timpul de procesare și
memoria, sunt utilizate eficient. Astfel, resursele limitate ale unui dispozitiv Arduino sunt
gestionate optim;
 Reactivitate la Evenimente: RTOS permite programatorilor să creeze sarcini care pot reacționa la
evenimente în timp real, precum intrările de la senzori sau alte evenimente externe. Acest lucru
este esențial în aplicațiile IoT, unde reacția rapidă la mediu este crucială.
Metode și materiale

Materiale Necesare:
Arduino Board (de exemplu, Arduino Uno) cu suport FreeRTOS;
breadboard și fire de conexiune;
3 butoane;
2 LED-uri;
2 rezistențe pentru LED-uri;
sursă de alimentare pentru Arduino;
editor Arduino IDE instalat pe un calculator cu suport pentru FreeRTOS.

Metoda de Implementare:
 configurarea Proiectului cu FreeRTOS:
 descărcare și instalare biblioteca FreeRTOS în Arduino IDE;
 configurare proiect pentru a utiliza FreeRTOS.
 definirea Task-urilor:
 definire task-urile pentru fiecare funcționalitate: Button Led, LED Intermitent,
Incrementare/Decrementare;
 stabilire prioritățile pentru aceste task-uri.
 implementarea Task-urilor:
 implementare codul pentru fiecare task utilizând funcțiile și macro-urile FreeRTOS;
 utilizare semafoare sau cozi pentru a gestiona comunicația între task-uri;
 implementare un task Idle pentru afișarea stărilor și mesajelor.
 testarea și debugging:
 încărcare cod pe Arduino folosind Arduino IDE cu suport FreeRTOS;
 monitorizare comportament butoanelor și LED-urilor în timp real;
 utilizare instrumente de debugare FreeRTOS pentru a identifica și rezolva eventualele
probleme.

Rezultate
Acest cod implementează aceeași funcționalitate ca și codul anterior, dar folosind FreeRTOS pentru a
gestiona sarcinile într-un mod multitasking. Iată o analiză detaliată a codului:
 Include-uri și Variabile: Codul include biblioteca Arduino FreeRTOS și definește variabilele
pentru pinii LED-urilor și butoanelor, precum și variabila recurrence pentru controlul frecvenței
de blink a LED-ului 2.
 Funcții Task:
 task1(void *pvParameters): Acest task controlează starea LED-ului 1 în funcție de starea
butonului 1. Dacă butonul este apăsat, starea LED-ului 1 se inversează.
 task2(void *pvParameters): Acest task monitorizează starea LED-ului 1. Dacă LED-ul 1
este stins, task-ul afișează recurrence în Serial Monitor și face ca LED-ul 2 să pulseze cu
frecvența specificată de recurrence.
 task3(void *pvParameters): Acest task monitorizează butoanele 2 și 3. Dacă butonul 2 este
apăsat, recurrence este decrementat, iar dacă butonul 3 este apăsat, recurrence este
incrementat.
 taskIdle(void *pvParameters): Acest task afișează valoarea lui recurrence în Serial
Monitor.
 Configurarea Hardware și Crearea Sarcinilor:
 În funcția setup(), pinii și modul de funcționare sunt configurați.
 Cu funcția xTaskCreate(), sunt create patru sarcini: task1, task2, task3, și taskIdle.
 Bucla Infinită: Funcția loop() este lăsată goală, deoarece sarcinile gestionate de FreeRTOS rulează
în mod independent în fundal, fără a fi nevoie de o buclă principală.
 Funcțiile Task Rulează în Mod Infinit: Fiecare funcție de sarcină (task) conține o buclă infinită
(while(1)) și utilizează funcții FreeRTOS precum vTaskDelay() pentru a controla perioadele de
așteptare între iterații.

Concluzii
Prin implementarea sistemelor de operare secvențiale și a celor în timp real (folosind FreeRTOS), am
învățat să gestionăm multiple sarcini în mod eficient, să sincronizăm interacțiunile dintre ele și să
realizăm aplicații IoT care reacționează în timp real la evenimentele din mediul înconjurător.
Principalele puncte de învățare din laborator includ:
 Sarcinile Secvențiale: Am înțeles cum să organizăm sarcinile astfel încât fiecare să aștepte rândul
pentru a rula. Acest lucru este eficient pentru aplicații simple, dar poate duce la întârzieri în
răspunsul la evenimente externe.
 Sarcinile în Timp Real cu FreeRTOS: Am aplicat conceptele unui sistem de operare în timp real
pentru a crea aplicații care reacționează rapid la evenimente într-un mod predictibil. Am învățat să
gestionăm sincronizarea și planificarea sarcinilor folosind FreeRTOS.
 Utilizarea Resurselor Eficient: Am învățat să gestionăm eficient resursele limitate ale
dispozitivelor IoT, cum ar fi pinii digitali și memoria, pentru a evita blocajele și a asigura
funcționarea stabilă a sistemului.
 Comunicarea între Sarcini: Am implementat mecanisme de comunicare între sarcini, cum ar fi
semafoarele și cozile, pentru a permite schimbul de informații și controlul accesului la resurse
comune.

Prin acest laborator, am dobândit cunoștințe și experiență practică în implementarea și gestionarea


sistemelor de operare în contextul Internet of Things, ceea ce reprezintă o bază solidă pentru proiecte
viitoare și pentru a lucra în domeniul tehnologiilor conectate.

Anexa 1 – Codul sursă sarcina 1


#include <stdio.h>
int led1 = 13;
int led2 = A0;
int button1 = 12;
int button2 = A1;
int button3 = A2;
int recurrence = 200;
bool buttonStateBool = false;
byte lastButtonState = LOW;
byte lastButtonState1 = LOW;
byte lastButtonState2 = LOW;

byte ledState1 = LOW;


byte ledState2 = LOW;

unsigned long previousMillis = 0;


const unsigned long interval = recurrence * 10;
void setup()
{
Serial.begin(9600);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP);
}

void loop()
{
task1();
task2();
task3();
taskIdle();
}

void task1(){
byte buttonState = digitalRead(button1);
if (buttonState != lastButtonState) {
lastButtonState = buttonState;
if (buttonState == LOW) {
ledState1 = (ledState1 == HIGH) ? LOW : HIGH;
digitalWrite(led1, ledState1);
}
}
}

void task2() {
static unsigned long previousBlinkTime = 0;
int ledState = digitalRead(led1);
if (ledState == 0) {
unsigned long currentMillis = millis();
if (currentMillis - previousBlinkTime >= recurrence){
previousBlinkTime = currentMillis;
if (digitalRead(led2) == 0){
digitalWrite(led2, HIGH);
}else{
digitalWrite(led2, LOW);
}
}
}else {
digitalWrite(led2, LOW);
}
}

void task3(){
int buttonState1 = digitalRead(button2);
if (buttonState1 != lastButtonState1){
lastButtonState1 = buttonState1;
if (buttonState1 == LOW && recurrence > 0){
recurrence = recurrence - 100;
}
if (recurrence == 0){
Serial.println("speed of blinking is exceeded !");
}
}

int buttonState2 = digitalRead(button3);


if (buttonState2 != lastButtonState2){
lastButtonState2 = buttonState2;
if (buttonState2 == LOW && recurrence > 0){
recurrence = recurrence + 100;
}
if (recurrence == 0){
Serial.println("speed of blinking is exceeded !");
}
}
}

void taskIdle(){
Serial.println(recurrence);
}

Anexa 2 – Codul sursă sarcina 2


#include <Arduino_FreeRTOS.h>
#include <stdio.h>
int led1 = 13;
int led2 = A0;
int button1 = 12;
int button2 = A1;
int button3 = A2;
int recurrence = 100;
bool buttonStateBool = false;

void task1( void *pvParameters );


void task2( void *pvParameters );
void task3( void *pvParameters );
void taskIdle( void *pvParameters );

void setup()
{
Serial.begin(9600);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP);
xTaskCreate(task1, "task1", 128, NULL, 1, NULL );
xTaskCreate(task2, "task2", 128, NULL, 1, NULL );
xTaskCreate(task3, "task3", 128, NULL, 1, NULL );
xTaskCreate(taskIdle, "taskIdle", 128, NULL, 0, NULL );
vTaskStartScheduler();
}

void loop()
{}
void task1(void *pvParameters){
while(1){
vTaskDelay( 200 / portTICK_PERIOD_MS ); //const - durata unui tick in milisecunde
int buttonState = digitalRead(button1);
if(buttonState == LOW){
buttonStateBool = !buttonStateBool;
if(buttonStateBool) {
digitalWrite(led1, HIGH);
}
else {
digitalWrite(led1, LOW);}}}}

void task2(void *pvParameters){


while(1){
vTaskDelay( 100 / portTICK_PERIOD_MS );
if(digitalRead(led1) == LOW){
Serial.println(recurrence);
digitalWrite(led2, HIGH);
vTaskDelay( (recurrence * 10) / portTICK_PERIOD_MS);
digitalWrite(led2, LOW);
vTaskDelay( (recurrence * 10) / portTICK_PERIOD_MS);}}}
void task3(void *pvParameters){
while(1){
int buttonState1 = digitalRead(button2);
if(buttonState1 == LOW){
if(recurrence > 0){
recurrence--;} }
int buttonState2 = digitalRead(button3);
if(buttonState2 == LOW){
recurrence++;}
}
}

void taskIdle(void *pvParameters){


while(1){
Serial.println(recurrence);
}
}

S-ar putea să vă placă și