Structuri de Meniu și Navigare

Choose a study mode

Play Quiz
Study Flashcards
Spaced Repetition
Chat to Lesson

Podcast

Listen to an AI-generated conversation about this lesson
Download our mobile app to listen on the go
Get App

Questions and Answers

Care este principalul avantaj al utilizării structurii struct MenuItem într-un proiect ESP32 cu meniu navigabil?

  • Accelerează comunicarea SPI.
  • Oferă acces direct la toți pinii GPIO.
  • Reduce dimensiunea programului (sketch-ului).
  • Permite gestionarea simplificată a stărilor și a relațiilor dintre elementele meniului. (correct)

În cadrul unei structuri de tip MenuItem, care membru indică submeniul asociat unui anumit element?

  • child (correct)
  • label
  • parent
  • callback

Care este metoda corectă de a afișa un item de meniu selectat pe un ecran LCD 16x2?

  • `Serial.println(item->label);`
  • `lcd.clear(); lcd.print(item->label);` (correct)
  • `lcd.print(item->label);`
  • `oled.display(item.label);`

Ce rol are funcția callback asociată unui element de meniu?

<p>Execută acțiunea specifică acelui element. (C)</p>
Signup and view all the answers

Care este metoda recomandată pentru parcurgerea unui meniu cu un encoder rotativ?

<p>Incrementarea/decrementarea indexului curent. (B)</p>
Signup and view all the answers

Ce funcție este utilizată pentru a reveni la meniul părinte într-o structură de meniu ierarhică?

<p><code>goToParent()</code> (C)</p>
Signup and view all the answers

Într-o structură de meniu, ce legături sunt folosite pentru a permite navigarea laterală între itemi (stânga/dreapta)?

<p><code>previous</code> și <code>next</code> (C)</p>
Signup and view all the answers

Ce tip de pointer este uzual folosit pentru a defini structura elementelor unui meniu?

<p><code>MenuItem*</code> (C)</p>
Signup and view all the answers

Cum se poate asigura stabilitatea afișajului când un utilizator rotește un encoder rapid?

<p>Se actualizează afișajul doar dacă poziția encoderului s-a schimbat. (A)</p>
Signup and view all the answers

Cum previi citirea în afara limitelor meniului atunci când se rotește encoderul?

<p>Se verifică dacă pointerul <code>next</code> este <code>NULL</code>. (A)</p>
Signup and view all the answers

Care este scopul variabilei currentMenu într-un sistem de meniu?

<p>Reprezintă pointerul la itemul curent din meniu. (C)</p>
Signup and view all the answers

Care dintre următoarele reprezintă o bună practică în definirea meniurilor statice?

<p>Inițializarea tuturor legăturilor în <code>setup()</code>. (D)</p>
Signup and view all the answers

Cum afișezi un meniu cu mai mult de două opțiuni pe un ecran LCD 16x2?

<p>Schimbi pagina afișată la fiecare două itemi. (B)</p>
Signup and view all the answers

Ce tehnică este utilă pentru a implementa un meniu "circular"?

<p><code>if(next == NULL) next = firstItem;</code> (A)</p>
Signup and view all the answers

Ce avantaj oferă folosirea unui pointer constant (const MenuItem*) pentru meniurile statice?

<p>Reduce memoria RAM utilizată. (A)</p>
Signup and view all the answers

De ce este preferată funcția millis() în locul funcției delay() într-un proiect cu meniu și encoder?

<p><code>millis()</code> permite execuția non-blocantă. (B)</p>
Signup and view all the answers

Care este modalitatea de a gestiona un refresh periodic al ecranului fără a bloca execuția principală?

<p>Se compară <code>millis()</code> cu un timestamp anterior. (D)</p>
Signup and view all the answers

Ce problemă poate apărea dacă nu se resetează timestamp-ul după un trigger millis()?

<p>Evenimentul se repetă constant fără pauză. (A)</p>
Signup and view all the answers

Care dintre următoarele reprezintă o abordare corectă pentru multitasking software cu flag-uri?

<p><code>if (shouldUpdate)</code> (D)</p>
Signup and view all the answers

Cum se pot evita conflictele între două procese care folosesc același timer (millis())?

<p>Declarând două variabile timestamp separate. (D)</p>
Signup and view all the answers

Ce valoare returnează millis() după aproximativ 50 de zile de funcționare continuă (uptime)?

<p>Revine la 0. (C)</p>
Signup and view all the answers

Care este metoda recomandată pentru actualizarea non-blocantă a unei variabile de afișaj?

<p><code>if (millis() - lastRefresh &gt; 100)</code> (D)</p>
Signup and view all the answers

Cum afectează folosirea funcției while(true) în loop() procesele din fundal?

<p>Le oprește complet. (D)</p>
Signup and view all the answers

Ce bibliotecă se poate folosi pentru a implementa multitasking simplu pe ESP32?

<p><code>TaskScheduler.h</code> (C)</p>
Signup and view all the answers

Ce tip de variabile trebuie protejate în procese paralele (utilizând FreeRTOS)?

<p>Variabile globale modificate de mai multe task-uri (B)</p>
Signup and view all the answers

Flashcards

Scopul structurii struct Menultem

Permite gestionarea facilă a stărilor și a legăturilor dintre itemii unui meniu navigabil pe ESP32.

Rolul membrului child

Indică submeniul asociat unui item în structura de tip Menultem.

Afișarea unui item pe LCD 16x2

Se realizează curățând ecranul și apoi afișând textul.

Rolul funcției callback

Funcția callback execută acțiunea specifică itemului selectat.

Signup and view all the flashcards

Parcurgere meniu cu encoder rotativ

Incrementarea/decrementarea indexului curent este metoda recomandată.

Signup and view all the flashcards

Revenirea la meniul părinte

Funcția goToParent() navighează în sus în structura meniului.

Signup and view all the flashcards

Navigare laterală în meniu

Legăturile previous și next asigură navigarea laterală între itemi.

Signup and view all the flashcards

Tipul de pointer pentru structura itemilor

Se folosește un pointer la structura de tip Menultem.

Signup and view all the flashcards

Stabilitatea afișajului la rotirea encoderului

Se actualizează afișajul doar dacă poziția s-a schimbat; asigură stabilitatea.

Signup and view all the flashcards

Prevenirea trecerii în afara limitelor meniului

Se verifică dacă pointerul next este NULL; previne depășirea limitelor.

Signup and view all the flashcards

Scopul variabilei currentMenu

Reprezintă pointerul la itemul curent din meniu.

Signup and view all the flashcards

Definirea meniurilor statice

Inițializarea tuturor legăturilor în setup() este o bună practică.

Signup and view all the flashcards

Afișarea unui meniu cu mai multe opțiuni pe LCD 16x2

Se schimbă pagina afișată la fiecare două itemi.

Signup and view all the flashcards

Implementarea unui meniu circular

if(next == NULL) next = firstItem implementează un meniu circular.

Signup and view all the flashcards

Avantajul pointerilor constanți

Itemii constanți pot fi stocați în flash, eliberând RAM.

Signup and view all the flashcards

De ce millis() în loc de delay()?

millis() permite execuția non-blocantă, esențială pentru meniuri și encodere.

Signup and view all the flashcards

Refresh periodic fără blocare

Se compară millis() cu un timestamp anterior.

Signup and view all the flashcards

Problema neresetării timestamp-ului

Evenimentul se repetă constant, fără pauză.

Signup and view all the flashcards

Multitasking soft cu flag-uri

Utilizarea flag-urilor (shouldUpdate, trigger) permite controlul execuției.

Signup and view all the flashcards

Evitarea conflictelor între procese

Declară două variabile timestamp separate pentru a evita interferențe.

Signup and view all the flashcards

Ce valoare returnează millis() după mult timp?

Revine la 0 după aproximativ 50 de zile.

Signup and view all the flashcards

Actualizare non-blocantă a unei variabile de afișaj

Verifică dacă a trecut timpul necesar.

Signup and view all the flashcards

Impactul while(true) în loop()

Oprește complet procesele de fundal.

Signup and view all the flashcards

Bibliotecă pentru multitasking simplu

TaskScheduler permite crearea și gestionarea task-urilor soft.

Signup and view all the flashcards

Variabilele care trebuie protejate în procese paralele

Accesul concurent la variabilele globale poate crea condiții de cursă.

Signup and view all the flashcards

Study Notes

Crearea Structurilor de Meniu

  • Structurile Menultem permit organizarea logică a elementelor meniului și păstrarea relațiilor între ele (următorul, anterior, părinte, copil).
  • Membrul "child" al unei structuri Menultem indică submeniul asociat acelui element.
  • Afișarea unui element selectat pe un ecran LCD 16x2 se face cu Icd.clear(); Icd.print(item->label);.
  • Funcția callback execută o acțiune specifică atunci când un element al meniului este selectat.
  • Parcurgerea meniului cu un encoder rotativ se face prin incrementarea/decrementarea indexului curent.
  • Funcția goToParent() este folosită pentru a reveni la meniul părinte.
  • Navigarea laterală (stânga/dreapta) într-o structură de meniu este asigurată de legăturile previous și next.
  • Pointerul uzual pentru definirea structurii elementelor într-un meniu este de tip Menultem*.
  • Stabilitatea afișajului la rotirea rapidă a encoderului se asigură prin actualizarea afișajului doar când poziția s-a schimbat.
  • Pentru a preveni trecerea în afara limitelor meniului la rotirea encoderului, se verifică dacă pointerul next este NULL.
  • Variabila currentMenu reprezintă pointerul la elementul curent din meniu.
  • O bună practică în definirea meniurilor statice este inițializarea tuturor legăturilor în setup().
  • Un meniu cu mai mult de două opțiuni pe un LCD 16x2 se afișează prin schimbarea paginii afișate la fiecare două elemente.
  • Tehnica utilă pentru a implementa un meniu circular este if(next == NULL) next = firstItem;.
  • Un meniu circular revine la primul element după ultimul, folosind legături bidirecționale.
  • Folosirea unui pointer constant (const Menultem*) pentru meniurile statice reduce memoria RAM utilizată deoarece itemii constanți pot fi stocați în flash.

Procese în Fundal

  • millis() este preferat lui delay() pentru că permite execuția non-blocantă în proiectele cu meniu și encoder.
  • Refresh-ul periodic al ecranului fără blocarea execuției se gestionează prin compararea millis() cu un timestamp anterior.
  • Dacă timestamp-ul nu este resetat după un trigger millis(), evenimentul se repetă constant fără pauză.
  • O abordare corectă pentru multitasking soft cu flag-uri este if (shouldUpdate).
  • Conflictele între procese care folosesc același timer millis() se evită prin declararea a două variabile timestamp separate.
  • millis() revine la 0 după aproximativ 50 de zile de uptime (overflow).
  • Actualizarea non-blocantă a unei variabile de afișaj se face cu if (millis() - lastRefresh > 100).
  • Folosirea while(true) în loop() oprește complet procesele de fundal.
  • TaskScheduler.h este o bibliotecă utilizată pentru multitasking simplu pe ESP32.
  • Variabilele globale modificate de mai multe task-uri trebuie protejate în procese paralele (cu FreeRTOS).
  • Funcția vTaskDelay() poate fi folosită pentru a amâna execuția unui task în FreeRTOS pe ESP32 fără a bloca restul sistemului.
  • Unitatea implicită de timp pentru vTaskDelay(1000) în FreeRTOS este ticks (1 tick ≠ 1 ms, depinde de frecvența sistemului).
  • Dacă un task rulează fără vTaskDelay() într-un sistem FreeRTOS, acesta acaparează toată execuția CPU.
  • Sincronizarea între două task-uri în ESP32/FreeRTOS se realizează cu xSemaphore sau xQueue.
  • Un task separat pentru controlul LCD-ului permite delay-uri în paralel cu restul logicii.
  • Orice doi pini de pe ESP32 pot fi configurați ca SDA și SCL la inițializare pentru a conecta un LCD cu I2C.
  • Comanda corectă pentru inițializarea unui LCD I2C 16x2 este Icd.init(); Icd.backlight();.
  • Biblioteca I2C necesită apelul init() și activarea backlight-ului explicit.
  • Atenuarea flicker-ului afișajului LCD se face folosind comanda Icd.setCursor(0,0); lcd.print(" ");
  • Poziția cursorului pe LCD se controlează cu Icd.setCursor(col, row);.
  • Animația de scroll pe un ecran 16x2 se creează prin utilizarea functiei Icd.scrollDisplayLeft();.
  • Comanda Icd.noBacklight(); oprește iluminarea de fundal a LCD-ului.
  • Suprascrierea unui text mai scurt peste unul mai lung pe LCD se evită adăugând spații la finalul textului.
  • Dacă se încearcă scrierea pe rândul 2 (index 1) înainte de Icd.begin(), nu apare nimic pe ecran.
  • LCD-urile 16x2 permit definirea a până la 8 caractere speciale, folosind funcția Icd.createChar(nr, pattern[]);.
  • Limita standard de caractere customizabile pentru un LCD clasic HD44780 este de 8.
  • Afișarea rapidă fără întârziere între caractere se asigură prin scrierea într-un buffer și afișarea completă.
  • Biblioteca necesară pentru a folosi LCD-ul cu I2C în Arduino IDE este LiquidCrystal_I2C.h.
  • Dacă se scriu mai mult de 16 caractere pe un rând, textul continuă în afara ecranului, dar este invizibil.
  • Simbolul ° (grad) pe LCD 16x2 se afișează cu lcd.print((char)223);.
  • Consumul energetic al LCD-ului se reduce oprind iluminarea și afișajul cu comenzile lcd.noBacklight(); și lcd.noDisplay();.

Butoane și Encodere

  • Un buton se conectează între pin și GND, cu activare INPUT_PULLUP pentru a obține nivel LOW la apăsare.
  • Efectul de "bounce" la un buton reprezintă apăsări false cauzate de oscilații rapide.
  • Debounce-ul se evită cu debounce logic cu millis().
  • Citirea non-blocantă a unui buton evită blocarea loop-ului prin implementarea de tip millis() non-blocking.
  • Encoderul rotativ generează două semnale digitale în cuadratură la rotire.
  • Direcția de rotație a unui encoder este determinată prin compararea semnalelor A și B.
  • Tehnica de reacție imediată la o schimbare a stării unui buton este attachInterrupt() pe pin.
  • O limitare a folosirii întreruperilor cu encodere rotative este pierderea semnalului dacă se rotește rapid.
  • Un encoder cu 3 pini folosește două cuadraturi și un pin LOW/HI pentru buton.
  • Biblioteca Arduino frecvent utilizată pentru encodere este Encoder.h.
  • Se obțin 40 de stări distincte per clic pentru un encoder standard (20 pulsuri) dacă se citește și faza.
  • Zgomotul la nivel hardware este filtrat folosind condensatori pe semnale.
  • Pentru a citi corect encoderul, în loop(), fără întreruperi , se verifică fiecare pin individual și se deduce rotația.
  • Pentru o abordare eficientă pentru debounce, softwar-ul encoderului compară starea anterioară și temporizează tranzițiile.
  • Funcția read() asigură citirea non-blocking a encoderului în biblioteca Encoder.h.

EEPROM

  • Memoria folosită pe ESP32 pentru stocarea datelor persistente este de tip Flash (emulare EEPROM).
  • Biblioteca EEPROM.h trebuie inclusă pentru a folosi EEPROM pe ESP32.
  • Funcția EEPROM.begin(size) trebuie apelată pentru a începe lucrul cu EEPROM.
  • Un int la adresa 0 în EEPROM pe ESP32 se scrie cu EEPROM.put(0, val);.
  • Funcția EEPROM.commit() este esențială după scrierea în EEPROM pentru salvarea datelor.
  • Dimensiunea maximă ce poate fi alocată prin EEPROM.begin() pe ESP32 este de 4096 bytes.
  • ESP32 permite alocarea de până la 4KB pentru zona de EEPROM simulată.
  • O structura de date din EEPROM se citeste cu EEPROM.get(adr, var);.
  • Un risc al scrierii frecvente în EEPROM este uzura memoriei flash.
  • Scrierile repetate inutile în EEPROM se evită verificând dacă valoarea s-a schimbat.
  • O structură personalizată este recomandată pentru salvarea mai multor parametri în EEPROM.
  • După salvarea datelor cu EEPROM.put(), este necesar sa se apeleze EEPROM.commit().
  • Datele salvate în EEPROM se şterg prin scrierea unei alte valori peste ele.
  • Dacă este necesar să salvați 2 structuri diferite în EEPROM, trebuie să alocați zone diferite de memorie.
  • Funcția EEPROM.get() returnează datele salvate ca referință în EEPROM.
  • Este sigur să accesezi EEPROM dintr-un task paralel (FreeRTOS) doar cu mutex și acces sincronizat.

PWM

  • Funcția utilizată pe ESP32 pentru a asocia un canal PWM cu un pin este ledcAttachPin(pin, channel).
  • ESP32 nu setează frecvență implicită pentru PWM, e necesară definirea cu ledcSetup().
  • Funcția ledcSetup(channel, freq, resolution) setează frecvența și rezoluția unui canal PWM.
  • Valoarea maximă a duty-cycle-ului pentru rezoluție de 8 biți este 255.
  • ESP32 permite 16 canale PWM independente (0-15).
  • Un semnal PWM de 10kHz și 10 biți pe canalul 2 se setează cu ledcSetup(2, 10000, 10);.
  • Nivelul de duty-cycle pe un canal PWM se setează cu ledcWrite(channel, duty);.
  • În timp real, frecvența unui canal PWM se modifică apelând din nou functia ledcSetup().
  • O frecvență mare + rezoluție mare consumă resurse ridicate și limita hardware.
  • Dacă două canale PWM diferite controlează același pin, ultimul ataşat va funcționa(il inlocuieste pe primul).
  • ESP32 poate controla independent 16 canale PWM – unul pentru fiecare dispozitiv.
  • Software-ul PWM nu este legat de timere hardware și funcționează pe orice pin.
  • Metoda recomandată pentru a controla luminozitatea unui LED cu PWM este ledcWrite().
  • Canalele PWM care folosesc același timer pot fi sincronizate precis.
  • PWM este o metodă de modulare a duratei impulsurilor.

ADC(Analog to digital conversion)

  • analogRead(pin) este funcția folosită pentru a citi o valoare analogică pe ESP32.
  • Rezoluția implicită a ADC-ului pe ESP32 este de 12 biți.
  • Valoarea returnată de analogRead() este între 0 și 4095 (rezoluție pe 12 biți).
  • ADC-ul ESP32 funcționează fără calibrare specială pe intervalul de tensiune 0-3.3V.
  • Intrările ADC pe ESP32 acceptă în mod normal între 0 și 3.3V.
  • analogSetBits(bits) este funcția care setează rezoluția ADC-ului pe ESP32.
  • La citirea semnalelor analogice brute pe ESP32, apare adesea zgomotul și fluctuațiile mari.
  • Zgomotul și fluctuațiile pot fi reduse prin media a mai multor citiri.
  • Pin-ii GPIO(General Purpose Input/Output) trebuie să nu fie folosiţi de SPI sau Flash.
  • Tensiunea (V) se convertesete prin tensiune = analogRead(pin) / 4095.0 * 3.3;
  • Cu analogSetAttenuation() se seteaza factorul de atenuare, deci se poate crește intervalul de Tensiune Măsurabil.
  • Dacă un senzor are o tensiune care iese peste 3.3V, se conectează cu un divizor de tensiune.

Studying That Suits You

Use AI to generate personalized quizzes and flashcards to suit your learning preferences.

Quiz Team

More Like This

Use Quizgecko on...
Browser
Browser