Podcast
Questions and Answers
Care este principalul avantaj al utilizării structurii struct MenuItem
într-un proiect ESP32 cu meniu navigabil?
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?
Î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?
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?
Ce rol are funcția callback
asociată unui element de meniu?
Care este metoda recomandată pentru parcurgerea unui meniu cu un encoder rotativ?
Care este metoda recomandată pentru parcurgerea unui meniu cu un encoder rotativ?
Ce funcție este utilizată pentru a reveni la meniul părinte într-o structură de meniu ierarhică?
Ce funcție este utilizată pentru a reveni la meniul părinte într-o structură de meniu ierarhică?
Într-o structură de meniu, ce legături sunt folosite pentru a permite navigarea laterală între itemi (stânga/dreapta)?
Într-o structură de meniu, ce legături sunt folosite pentru a permite navigarea laterală între itemi (stânga/dreapta)?
Ce tip de pointer este uzual folosit pentru a defini structura elementelor unui meniu?
Ce tip de pointer este uzual folosit pentru a defini structura elementelor unui meniu?
Cum se poate asigura stabilitatea afișajului când un utilizator rotește un encoder rapid?
Cum se poate asigura stabilitatea afișajului când un utilizator rotește un encoder rapid?
Cum previi citirea în afara limitelor meniului atunci când se rotește encoderul?
Cum previi citirea în afara limitelor meniului atunci când se rotește encoderul?
Care este scopul variabilei currentMenu
într-un sistem de meniu?
Care este scopul variabilei currentMenu
într-un sistem de meniu?
Care dintre următoarele reprezintă o bună practică în definirea meniurilor statice?
Care dintre următoarele reprezintă o bună practică în definirea meniurilor statice?
Cum afișezi un meniu cu mai mult de două opțiuni pe un ecran LCD 16x2?
Cum afișezi un meniu cu mai mult de două opțiuni pe un ecran LCD 16x2?
Ce tehnică este utilă pentru a implementa un meniu "circular"?
Ce tehnică este utilă pentru a implementa un meniu "circular"?
Ce avantaj oferă folosirea unui pointer constant (const MenuItem*
) pentru meniurile statice?
Ce avantaj oferă folosirea unui pointer constant (const MenuItem*
) pentru meniurile statice?
De ce este preferată funcția millis()
în locul funcției delay()
într-un proiect cu meniu și encoder?
De ce este preferată funcția millis()
în locul funcției delay()
într-un proiect cu meniu și encoder?
Care este modalitatea de a gestiona un refresh periodic al ecranului fără a bloca execuția principală?
Care este modalitatea de a gestiona un refresh periodic al ecranului fără a bloca execuția principală?
Ce problemă poate apărea dacă nu se resetează timestamp-ul după un trigger millis()
?
Ce problemă poate apărea dacă nu se resetează timestamp-ul după un trigger millis()
?
Care dintre următoarele reprezintă o abordare corectă pentru multitasking software cu flag-uri?
Care dintre următoarele reprezintă o abordare corectă pentru multitasking software cu flag-uri?
Cum se pot evita conflictele între două procese care folosesc același timer (millis()
)?
Cum se pot evita conflictele între două procese care folosesc același timer (millis()
)?
Ce valoare returnează millis()
după aproximativ 50 de zile de funcționare continuă (uptime)?
Ce valoare returnează millis()
după aproximativ 50 de zile de funcționare continuă (uptime)?
Care este metoda recomandată pentru actualizarea non-blocantă a unei variabile de afișaj?
Care este metoda recomandată pentru actualizarea non-blocantă a unei variabile de afișaj?
Cum afectează folosirea funcției while(true)
în loop()
procesele din fundal?
Cum afectează folosirea funcției while(true)
în loop()
procesele din fundal?
Ce bibliotecă se poate folosi pentru a implementa multitasking simplu pe ESP32?
Ce bibliotecă se poate folosi pentru a implementa multitasking simplu pe ESP32?
Ce tip de variabile trebuie protejate în procese paralele (utilizând FreeRTOS)?
Ce tip de variabile trebuie protejate în procese paralele (utilizând FreeRTOS)?
Flashcards
Scopul structurii struct Menultem
Scopul structurii struct Menultem
Permite gestionarea facilă a stărilor și a legăturilor dintre itemii unui meniu navigabil pe ESP32.
Rolul membrului child
Rolul membrului child
Indică submeniul asociat unui item în structura de tip Menultem.
Afișarea unui item pe LCD 16x2
Afișarea unui item pe LCD 16x2
Se realizează curățând ecranul și apoi afișând textul.
Rolul funcției callback
Rolul funcției callback
Signup and view all the flashcards
Parcurgere meniu cu encoder rotativ
Parcurgere meniu cu encoder rotativ
Signup and view all the flashcards
Revenirea la meniul părinte
Revenirea la meniul părinte
Signup and view all the flashcards
Navigare laterală în meniu
Navigare laterală în meniu
Signup and view all the flashcards
Tipul de pointer pentru structura itemilor
Tipul de pointer pentru structura itemilor
Signup and view all the flashcards
Stabilitatea afișajului la rotirea encoderului
Stabilitatea afișajului la rotirea encoderului
Signup and view all the flashcards
Prevenirea trecerii în afara limitelor meniului
Prevenirea trecerii în afara limitelor meniului
Signup and view all the flashcards
Scopul variabilei currentMenu
Scopul variabilei currentMenu
Signup and view all the flashcards
Definirea meniurilor statice
Definirea meniurilor statice
Signup and view all the flashcards
Afișarea unui meniu cu mai multe opțiuni pe LCD 16x2
Afișarea unui meniu cu mai multe opțiuni pe LCD 16x2
Signup and view all the flashcards
Implementarea unui meniu circular
Implementarea unui meniu circular
Signup and view all the flashcards
Avantajul pointerilor constanți
Avantajul pointerilor constanți
Signup and view all the flashcards
De ce millis() în loc de delay()?
De ce millis() în loc de delay()?
Signup and view all the flashcards
Refresh periodic fără blocare
Refresh periodic fără blocare
Signup and view all the flashcards
Problema neresetării timestamp-ului
Problema neresetării timestamp-ului
Signup and view all the flashcards
Multitasking soft cu flag-uri
Multitasking soft cu flag-uri
Signup and view all the flashcards
Evitarea conflictelor între procese
Evitarea conflictelor între procese
Signup and view all the flashcards
Ce valoare returnează millis() după mult timp?
Ce valoare returnează millis() după mult timp?
Signup and view all the flashcards
Actualizare non-blocantă a unei variabile de afișaj
Actualizare non-blocantă a unei variabile de afișaj
Signup and view all the flashcards
Impactul while(true) în loop()
Impactul while(true) în loop()
Signup and view all the flashcards
Bibliotecă pentru multitasking simplu
Bibliotecă pentru multitasking simplu
Signup and view all the flashcards
Variabilele care trebuie protejate în procese paralele
Variabilele care trebuie protejate în procese paralele
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
șinext
. - 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
esteNULL
. - 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 luidelay()
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)
înloop()
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
sauxQueue
. - 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();
șilcd.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 bibliotecaEncoder.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 apelezeEEPROM.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.