Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2026:florin.stancu:andrei.bleortu [2026/05/24 23:42]
andrei.bleortu
pm:prj2026:florin.stancu:andrei.bleortu [2026/05/25 14:04] (current)
andrei.bleortu
Line 4: Line 4:
 Proiectul implementeaza un sistem de monitorizare si protectie pentru o linie de productie industriala simulata. In centrul sistemului se afla un motor stepper 28BYJ-48 care reprezinta echipamentul principal de productie - de exemplu o masa rotativa de asamblare sau un conveyor. In jurul lui sunt dispusi mai multi senzori care detecteaza situatiile periculoase:​ prezenta personalului in zona de operare, apropierea unor obiecte, infiltratii de apa, zgomote anormale si conditii de mediu nepotrivite. Proiectul implementeaza un sistem de monitorizare si protectie pentru o linie de productie industriala simulata. In centrul sistemului se afla un motor stepper 28BYJ-48 care reprezinta echipamentul principal de productie - de exemplu o masa rotativa de asamblare sau un conveyor. In jurul lui sunt dispusi mai multi senzori care detecteaza situatiile periculoase:​ prezenta personalului in zona de operare, apropierea unor obiecte, infiltratii de apa, zgomote anormale si conditii de mediu nepotrivite.
  
-Punctul de plecare a fost o intrebare ​destul de concreta: cum opresti ​in siguranta un echipament industrial cand apare o anomalie? In aplicatiile reale, timpul de raspuns trebuie sa fie de ordinul milisecundelor,​ iar sistemul trebuie sa functioneze fiabil chiar si atunci cand o parte din componente cedeaza. Aceste cerinte motiveaza arhitectura aleasa, cu doua microcontrollere avand roluri distincte.+Punctul de plecare a fost o intrebare concreta: cum se opreste ​in siguranta un echipament industrial cand apare o anomalie? In aplicatiile reale, timpul de raspuns trebuie sa fie de ordinul milisecundelor,​ iar sistemul trebuie sa functioneze fiabil chiar si atunci cand o parte din componente cedeaza. Aceste cerinte motiveaza arhitectura aleasa, cu doua microcontrollere avand roluri distincte.
  
-Proiectul acopera ​bine conceptele de curs - senzori analogici si digitali, comunicatie seriala, WiFi, interfata cu utilizatorul - dar principalul motiv de interes este arhitectural:​ separarea hard real-time (siguranta, control motor) de procesare si conectivitate pe microcontrollere distincte ​o abordare standard in sistemele industriale ​serioase.+Proiectul acopera conceptele de curs - senzori analogici si digitali, comunicatie seriala, WiFi, interfata cu utilizatorul - iar elementul principal ​de interes este arhitectural:​ separarea hard real-time (siguranta, control motor) de procesare si conectivitate pe microcontrollere distincte ​este o abordare standard in sistemele industriale.
  
 ===== Descriere generala ===== ===== Descriere generala =====
  
-Sistemul este construit pe doua microcontrollere cu roluri ​foarte diferite:+Sistemul este construit pe doua microcontrollere cu roluri ​distincte:
  
-  * **Arduino MEGA 2560** ​este "​creierul" ​hard real-time. Citeste toti senzorii la fiecare 10 ms, ruleaza state machine-ul de siguranta, controleaza direct motorul si buzzer-ul si calculeaza scorul de sanatate. Bucla principala este complet ​non-blocking si bounded ca durata. +  * **Arduino MEGA 2560** ​indeplineste functia de controler ​hard real-time. Citeste toti senzorii la fiecare 10 ms, ruleaza state machine-ul de siguranta, controleaza direct motorul si buzzer-ul si calculeaza scorul de sanatate. Bucla principala este non-blocking si bounded ca durata. 
-  * **ESP32 WROOM-32D** functioneaza ca punte intre Arduino si restul lumii. Singura sa "intrare" ​este citirea senzorului DHT11 (conectat fizic la el), pe care o trimite ​Arduino-ului inapoi ​printr-un cadru UART de retur. In rest, primeste cadrele ​bogate ​de la Arduino, le afiseaza pe LCD si le retransmite catre server prin WebSocket. Nu calculeaza nimic local.+  * **ESP32 WROOM-32D** functioneaza ca punte intre Arduino si infrastructura externa. Singura sa intrare ​proprie ​este citirea senzorului DHT11 (conectat fizic la el), retransmisa catre Arduino printr-un cadru UART de retur. In rest, primeste cadrele de la Arduino, le afiseaza pe LCD si le retransmite catre server prin WebSocket. Nu efectueaza procesare locala.
  
-Arhitectura cu Arduino ca singura ​sursa de adevar aduce doua avantaje ​practice: redundanta (daca pica WiFi sau ESP32, Arduino continua sa opreasca motorul corect) si zero variabilitate ​de timing ​datorata retelei. Temperatura ambianta nu se schimba ​in milisecunde, ​deci e suficient ca ESP32 sa trimita ​valoarea DHT11 inapoi la Arduino ​o data la ~2 secunde.+Arhitectura cu Arduino ca unica sursa de adevar aduce doua avantaje: redundanta (la caderea ​WiFi sau ESP32, Arduino continua sa opreasca motorul corect) si eliminarea variabilitatii ​de timing ​introduse de retea. Temperatura ambianta nu se modifica ​in milisecunde, ​asadar este suficient ca ESP32 sa transmita ​valoarea DHT11 catre Arduino la interval de aproximativ ​2 secunde.
  
 {{:​pm:​prj2026:​florin.stancu:​safety_sensor_integration-2026-05-06-073804.png?​800|}} {{:​pm:​prj2026:​florin.stancu:​safety_sensor_integration-2026-05-06-073804.png?​800|}}
Line 41: Line 41:
 </​code>​ </​code>​
  
-Doar in NORMAL ​motorul se invarte. WARNING exista in enum (valoarea 1) dar nu este produsa de nicio conditie - orice anomalie declanseaza o stare de oprire, conform cerintei unui controler de siguranta industriala.+Motorul functioneaza exclusiv ​in starea ​NORMAL. WARNING exista in enum (valoarea 1) dar nu este produsa de nicio conditie - orice anomalie declanseaza o stare de oprire, conform cerintei unui controler de siguranta industriala.
  
 ===== Hardware Design ===== ===== Hardware Design =====
Line 70: Line 70:
 ==== Organizarea fizica ==== ==== Organizarea fizica ====
  
-Componentele sunt distribuite pe doua breadboard-uri pentru a separa ​logic responsabilitatile sistemului si pentru a facilita mentenanta.+Componentele sunt distribuite pe doua breadboard-uri pentru a separa responsabilitatile sistemului si pentru a facilita mentenanta.
  
 **Breadboard principal (Arduino):​** **Breadboard principal (Arduino):​**
Line 111: Line 111:
 ==== Compatibilitatea electrica ==== ==== Compatibilitatea electrica ====
  
-Principalul aspect ​electric ​care trebuie luat in considerare ​este interfatarea intre Arduino (logica 5V) si ESP32 (logica 3.3V). Conform datasheet-ului,​ pinii GPIO ai ESP32 sunt 5V tolerant pe input, ceea ce permite conectarea directa a liniei TX a Arduino-ului la RX-ul ESP32-ului fara level shifter. Pentru directia inversa (ESP32 TX 3.3V -> Arduino RX 5V), tensiunea de 3.3V interpretata ca HIGH, intrucat pragul de detectie al Arduino-ului este in jur de 3V.+Aspectul ​electric ​principal ​este interfatarea intre Arduino (logica 5V) si ESP32 (logica 3.3V). Conform datasheet-ului,​ pinii GPIO ai ESP32 sunt 5V tolerant pe input, ceea ce permite conectarea directa a liniei TX a Arduino-ului la RX-ul ESP32-ului fara level shifter. Pentru directia inversa (ESP32 TX 3.3V -> Arduino RX 5V), tensiunea de 3.3V este interpretata ca HIGH, intrucat pragul de detectie al Arduino-ului este in jur de 3V.
  
-Divizorul 1k/2k pe linia Arduino TX -> ESP32 RX functioneaza fara probleme ​la 115200 baud. La 250 000 baud parser-ul ESP32 pierdea ​sincronizarea frecvent - probabil prea putin margin ​de integritate prin divizor si fire de breadboard. La 115200 link-ul ​stabil ​si bandwidth-ul ramane ​mult peste necesar (cadrul de 27 bytes la 20 Hz ocupa sub 5% din capacitate).+Divizorul 1k/2k pe linia Arduino TX -> ESP32 RX functioneaza fara erori la 115200 baud. La 250 000 baud parser-ul ESP32 pierde ​sincronizarea frecvent - cauza probabila este marginea redusa ​de integritate ​a semnalului ​prin divizor si fire de breadboard. La 115200 link-ul ​este stabil ​iar bandwidth-ul ramane peste necesar (cadrul de 27 bytes la 20 Hz ocupa sub 5% din capacitate).
  
-LCD-ul este alimentat la 5V dar accepta semnale de control de 3.3V, deoarece ​pragul sau de HIGH este in jurul valorii de 2.5V.+LCD-ul este alimentat la 5V dar accepta semnale de control de 3.3V, intrucat ​pragul sau de HIGH este in jurul valorii de 2.5V.
  
 ==== Estimare consum energetic ==== ==== Estimare consum energetic ====
Line 133: Line 133:
 | Buzzer activ        | 30 mA            | 150 mW   | | Buzzer activ        | 30 mA            | 150 mW   |
  
-Consumul total maxim estimat este de aproximativ 840 mA (3.9 W), iar consumul tipic - cu stepper-ul in functiune intermitenta si buzzer-ul activat ocazional - ar trebui sa fie in jur de 550 mA (2.8 W). In practica ESP32-ul ruleaza cu ''​WiFi.setSleep(false)''​ (pentru latenta retelei), ​deci consuma constant ~240 mA si valoarea reala e mai aproape ​de plafon.+Consumul total maxim estimat este de aproximativ 840 mA (3.9 W), iar consumul tipic - cu stepper-ul in functiune intermitenta si buzzer-ul activat ocazional - se situeaza ​in jur de 550 mA (2.8 W). In practica ESP32-ul ruleaza cu ''​WiFi.setSleep(false)''​ (pentru latenta retelei), consuma constant ~240 mA, iar valoarea reala este apropiata ​de plafon.
  
-Pentru o eventuala alimentare cu acumulatori NiMH de 1.2V / 2500 mAh, ar fi necesari 8 acumulatori in serie pentru a obtine 9.6V (compatibil cu intrarea Vin a Arduino-ului). Autonomia estimata ​ar fi de aproximativ 4 ore.+Pentru o eventuala alimentare cu acumulatori NiMH de 1.2V / 2500 mAh, sunt necesari 8 acumulatori in serie pentru a obtine 9.6V (compatibil cu intrarea Vin a Arduino-ului). Autonomia estimata ​este de aproximativ 4 ore.
  
 ===== Software Design ===== ===== Software Design =====
Line 183: Line 183:
 </​code>​ </​code>​
  
-La fiecare iteratie a buclei principale (la 10 ms), conditiile sunt evaluate de la prioritatea cea mai mare catre cea mai mica. Prima conditie indeplinita determina starea curenta. Motorul ​se invarte doar in NORMAL.+La fiecare iteratie a buclei principale (10 ms), conditiile sunt evaluate de la prioritatea cea mai mare catre cea mai mica. Prima conditie indeplinita determina starea curenta. Motorul ​functioneaza exclusiv ​in NORMAL.
  
-Histerezele sunt importante ​pentru starile "​live"​ (PROXIMITY, WATER_HIGH, TEMP_HIGH) ​- fara ele, sistemul ar oscila intre stop si start atunci ​cand un senzor se afla exact la prag.+Histerezele sunt necesare ​pentru starile "​live"​ (PROXIMITY, WATER_HIGH, TEMP_HIGH); in absenta lor, sistemul ar oscila intre stop si start cand un senzor se afla in jurul pragului.
  
 **E-stop cu latching si reset prin triple-press** **E-stop cu latching si reset prin triple-press**
  
-Prima apasare latcheaza EMERGENCY indefinit. ​Pentru a iesi, utilizatorul trebuie sa apese inca 3 ori in maxim 2 secunde - asta forteaza ​o actiune deliberata si previne ​resetari ​accidentale. Debouncing 50 ms in software. La reset se sterg si timerele PIR / sunet, ​deci linia reporneste imediat.+Prima apasare latcheaza EMERGENCY indefinit. ​Iesirea necesita ​inca 3 apasari ​in maxim 2 secunde - secventa impune ​o actiune deliberata si previne ​resetarile ​accidentale. Debouncing 50 ms in software. La reset se sterg si timerele PIR / sunet, ​asadar ​linia reporneste imediat.
  
 **Driver stepper non-blocking cu rampa de acceleratie** **Driver stepper non-blocking cu rampa de acceleratie**
  
-28BYJ-48 are frecventa maxima de pull-in in jur de 600 Hz - sub viteza ​dorita ​pentru demo (~20 RPM). Solutiarampa liniarapornire la 4000 µs/pas (~7 RPM, sub pull-in) si reducerea delay-ului cu 2 µs/pas pana la 1500 µs/pas (~20 RPM). Rampa se completeaza in ~1250 pasi (~3.4 secunde). ​resetata la fiecare tranzitie OFF -> ON, deci motorul reporneste lin dupa fiecare iesire din MAINT / PROXIMITY (in loc sa incerce ​direct viteza de croaziera, ceea ce duce la vibratie fara rotatie).+28BYJ-48 are frecventa maxima de pull-in in jur de 600 Hz - sub viteza ​tinta pentru demo (~20 RPM). Solutia ​adoptata este o rampa liniarapornire la 4000 µs/pas (~7 RPM, sub pull-in) si reducerea delay-ului cu 2 µs/pas pana la 1500 µs/pas (~20 RPM). Rampa se completeaza in ~1250 pasi (~3.4 secunde). ​Este resetata la fiecare tranzitie OFF -> ON, astfel incat motorul reporneste lin dupa fiecare iesire din MAINT / PROXIMITY (incercarea de a porni direct ​la viteza de croaziera ​produce ​vibratie fara rotatie).
  
-Secventa de comutare ​full-step "​two-phases-on"​. Pe placa fizica IN3 si IN4 sunt inversate fata de ordinea alfabetica - mapping-ul real este //A=IN1, B=IN2, C=IN4, D=IN3//, verificat cu un sketch de diagnostic care energizeaza fiecare coil pe rand. Secventa din software reflecta acest mapping; fara corectie, motorul vibreaza fara sa se invarta.+Secventa de comutare ​este full-step "​two-phases-on"​. Pe placa fizica IN3 si IN4 sunt inversate fata de ordinea alfabetica - mapping-ul real este //A=IN1, B=IN2, C=IN4, D=IN3//, verificat cu un sketch de diagnostic care energizeaza fiecare coil pe rand. Secventa din software reflecta acest mapping; fara corectie, motorul vibreaza fara sa se roteasca.
  
 **Senzor ultrasonic non-blocking** **Senzor ultrasonic non-blocking**
  
-''​pulseIn'' ​blocking pana la ~25 ms - jitter inacceptabil pentru bucla. In loc, ecoul masurat printr-o intrerupere pin-change pe D10 (PCINT4): ISR citeste micros() la fiecare tranzitie si calculeaza latimea pulsului. Bucla doar declanseaza trigger-ul la 60 ms si citeste rezultatul cand e gata. Jitter ~3-5 µs, sub precizia proprie a HC-SR04.+''​pulseIn'' ​este blocking pana la ~25 ms - jitter inacceptabil pentru bucla. In locul sau, ecoul este masurat printr-o intrerupere pin-change pe D10 (PCINT4): ISR citeste micros() la fiecare tranzitie si calculeaza latimea pulsului. Bucla declanseaza trigger-ul la 60 ms si citeste rezultatul cand este disponibil. Jitter ​rezultat ​~3-5 µs, sub precizia proprie a HC-SR04.
  
 **Protocolul UART** **Protocolul UART**
Line 211: Line 211:
 </​code>​ </​code>​
  
-Payload-ul forward contine starea, toti senzorii, uptime, temp/​umiditate (echo-ate inapoi ​de la ESP32), scorul de sanatate, unghiul motorului si timpul ramas pana la repornire. Reverse contine ​doar temp_x10 si hum_x10 - DHT11 oricum ​nu se actualizeaza mai rapid de 1 Hz. Checksum-ul XOR prinde ​coruptiile cauzate de EMI-ul stepper-ului. NACK-urile sunt contorizate dar **nu** declanseaza retransmisie - asta ar introduce variabilitate de timingurmatorul cadru vine in 50 ms oricum.+Payload-ul forward contine starea, toti senzorii, uptime, temp/​umiditate (retransmise ​de la ESP32), scorul de sanatate, unghiul motorului si timpul ramas pana la repornire. Reverse contine temp_x10 si hum_x10 - DHT11 nu se actualizeaza mai rapid de 1 Hz. Checksum-ul XOR detecteaza ​coruptiile cauzate de EMI-ul stepper-ului. NACK-urile sunt contorizate dar **nu** declanseaza retransmisie - retransmisia ​ar introduce variabilitate de timing, iar urmatorul cadru ajunge ​in 50 ms.
  
 **Detectia status-ului link-ului** **Detectia status-ului link-ului**
  
-Arduino monitorizeaza contorul ACK. Daca nu creste ​1.5 s, declara link pierdut si afiseaza ''>>>​ LINK LOST/​UP''​ pe USB Serial la tranzitii. ESP32 face acelasi lucru in invers, cu timeout 3 s (mai indulgent fiindca ​propria bucla se poate bloca temporar in operatii WiFi/WS).+Arduino monitorizeaza contorul ACK. La absenta incrementarii timp de 1.5 s, declara link pierdut si afiseaza ''>>>​ LINK LOST/​UP''​ pe USB Serial la tranzitii. ESP32 aplica simetric aceeasi logica, cu timeout 3 s (mai permisiv intrucat ​propria bucla se poate bloca temporar in operatii WiFi/WS).
  
 **Calculul scorului de sanatate (Arduino)** **Calculul scorului de sanatate (Arduino)**
Line 236: Line 236:
 **Watchdog timer** **Watchdog timer**
  
-Pe Arduino ​am activat watchdog-ul cu timeout de 4 secunde. ​Daca bucla principala se blocheaza ​din orice motiv (deadlock, ciclu infinit), microcontroller-ul se reseteaza automat. Apelul ''​wdt_reset()''​ este facut la inceputul fiecarei iteratii a buclei.+Pe Arduino ​este activat watchdog-ul cu timeout de 4 secunde. ​La blocarea buclei principale ​din orice motiv (deadlock, ciclu infinit), microcontroller-ul se reseteaza automat. Apelul ''​wdt_reset()''​ este executat ​la inceputul fiecarei iteratii a buclei.
  
 ==== Optimizari pentru determinism si latenta ==== ==== Optimizari pentru determinism si latenta ====
  
-Decizii aplicate in fiecare strat pentru bucla Arduino predictibila si latenta end-to-end ​mica:+Decizii aplicate in fiecare strat pentru ​bucla Arduino predictibila si latenta end-to-end ​redusa:
  
-  * **Arduino**:​ ultrasonic prin PCINT (fara ''​pulseIn''​ blocking), link UART open-loop fara retransmisii la NACK, port I/O direct (PORTx/​PINx) pe pinii hot, prescaler ADC /32 (~27 µs/​citire),​ watchdog 4 s. +  * **Arduino**:​ ultrasonic prin PCINT (fara ''​pulseIn''​ blocking), link UART open-loop fara retransmisii la NACK, port I/O direct (PORTx/​PINx) pe pinii frecvent accesati, prescaler ADC /32 (~27 µs/​citire),​ watchdog 4 s. 
-  * **ESP32**: ''​WiFi.setSleep(false)''​ pentru a evita ~100 ms latenta per pachet de la modem sleep, buffer UART RX 2048 bytes ca blocajele temporare ale buclei sa nu desincronizeze parser-ul, WebSocket persistent catre server cu push la fiecare cadru primit (20 Hz). +  * **ESP32**: ''​WiFi.setSleep(false)''​ pentru a evita ~100 ms latenta per pachet ​introdusa ​de modem sleep, buffer UART RX 2048 bytes pentru ​ca blocajele temporare ale buclei sa nu desincronizeze parser-ul, WebSocket persistent catre server cu push la fiecare cadru primit (20 Hz). 
-  * **Server**: SQLite WAL cu ''​synchronous=NORMAL''​ (commit-uri sub-ms ​in loc de ~10 ms cu fsync), broadcast WS thread-safe peste un set de clienti. +  * **Server**: SQLite WAL cu ''​synchronous=NORMAL''​ (commit-uri sub-ms ​fata de ~10 ms cu fsync), broadcast WS thread-safe peste un set de clienti. 
-  * **Frontend**:​ WebSocket pentru update-uri live, bootstrap istoric prin REST la incarcare ​apoi append incremental,​ Chart.js cu ''​animation:​ false''​.+  * **Frontend**:​ WebSocket pentru update-uri live, bootstrap istoric prin REST la incarcare ​urmat de append incremental,​ Chart.js cu ''​animation:​ false''​.
  
 ==== Functii principale ==== ==== Functii principale ====
Line 278: Line 278:
 ==== Interfata utilizator (dashboard) ==== ==== Interfata utilizator (dashboard) ====
  
-Dashboard-ul are o ierarhie vizuala ​clara, de sus in jos:+Dashboard-ul are o ierarhie vizuala ​definita, de sus in jos:
  
-  - **Banner de stare** - cel mai mare element din pagina, cu numele starii mare, o descriere scurta si (cand cazulun countdown ​urias pentru timpul ramas pana la repornire. Culorile se schimba per stare, EMERGENCY pulseaza. +  - **Banner de stare** - elementul ​cel mai proeminent al paginii, cu numele starii ​afisat ​mare, o descriere scurta sicand este cazulun countdown ​amplu pentru timpul ramas pana la repornire. Culorile se schimba per stare, ​iar EMERGENCY pulseaza. 
-  - **Cardurile "​feature"​** - scorul de sanatate cu un gauge SVG si motorul cu un cadran care arata unghiul curent in timp real.+  - **Cardurile "​feature"​** - scorul de sanatate cu un gauge SVG si motorul cu un cadran care indica ​unghiul curent in timp real.
   - **Senzori grupati** in 3 sectiuni: //Ambient// (temp, umiditate), //Proximity & Personnel// (distanta, PIR, E-stop), //Anomaly detectors// (sunet, apa). PIR si E-stop devin rosii cand sunt active.   - **Senzori grupati** in 3 sectiuni: //Ambient// (temp, umiditate), //Proximity & Personnel// (distanta, PIR, E-stop), //Anomaly detectors// (sunet, apa). PIR si E-stop devin rosii cand sunt active.
   - **Grafice istorice** Chart.js pentru temperatura/​umiditate,​ distanta/​apa,​ sunet si scor de sanatate.   - **Grafice istorice** Chart.js pentru temperatura/​umiditate,​ distanta/​apa,​ sunet si scor de sanatate.
  
-Countdown-ul motorului foloseste ​un mic trick: la fiecare cadru primit, dashboard-ul retine ''​hold_ms''​ si timestamp-ul local, apoi decrementeaza local la 100 ms intre cadre. Fiecare cadru nou resincronizeaza valoarea, ​deci curge fluid in loc sa sara in trepte de 50 ms.+Countdown-ul motorului foloseste ​interpolare locala: la fiecare cadru primit, dashboard-ul retine ''​hold_ms''​ si timestamp-ul local, apoi decrementeaza local la 100 ms intre cadre. Fiecare cadru nou resincronizeaza valoarea, ​rezultand o afisare fluida ​in loc de salturi ​in trepte de 50 ms.
  
 ===== Rezultate Obtinute ===== ===== Rezultate Obtinute =====
Line 291: Line 291:
 Sistemul functioneaza end-to-end conform specificatiilor. Sistemul functioneaza end-to-end conform specificatiilor.
  
-**Latenta end-to-end** (schimbare de senzor -> pixel pe dashboard): ~50-75 ms tipic, ~25 ms best-case. Componentele:​+**Latenta end-to-end** (schimbare de senzor -> pixel pe dashboard): ~50-75 ms tipic, ~25 ms in cazul cel mai favorabil. Componentele:​
  
 ^ Etapa ^ Latenta ^ ^ Etapa ^ Latenta ^
Line 302: Line 302:
 | Randare browser | ~16 ms (un frame la 60 fps) | | Randare browser | ~16 ms (un frame la 60 fps) |
  
-**Motorul** ​se invarte ​stabil la ~20 RPM dupa rampa de acceleratie,​ fara vibratii. Pornirile dupa MAINT / PROXIMITY sunt line, opririle pentru siguranta instantanee.+**Motorul** ​functioneaza ​stabil la ~20 RPM dupa rampa de acceleratie,​ fara vibratii. Pornirile dupa MAINT / PROXIMITY sunt line, iar opririle pentru siguranta ​sunt instantanee.
  
-**State machine-ul** raspunde corect la toate scenariile: trecere de mana = MAINT cu countdown, obiect sub 40 cm = PROXIMITY (live), ​bat din palme = SOUND_SHUTDOWN,​ apa peste prag = WATER_HIGH, buton = EMERGENCY latched, triple-press = reset.+**State machine-ul** raspunde corect la toate scenariile: trecere de mana = MAINT cu countdown, obiect sub 40 cm = PROXIMITY (live), ​bataie ​din palme = SOUND_SHUTDOWN,​ apa peste prag = WATER_HIGH, buton = EMERGENCY latched, triple-press = reset.
  
-**Link-ul UART** ​stabil la 115200 baud prin divizor - zero NACK-uri si zero "LINK LOST" in functionare normala. 250000 baud nu trece curat prin divizor ​fire de breadboard.+**Link-ul UART** ​este stabil la 115200 baud prin divizor - zero NACK-uri si zero "LINK LOST" in functionare normala. 250000 baud nu se transmite corect ​prin divizor ​combinat cu fire de breadboard.
  
-**Dashboard-ul** primeste 20 Hz fara lag - 4 grafice ​KPI-uri ​gauge sanatate ​cadran motor redesenate la fiecare cadru.+**Dashboard-ul** primeste 20 Hz fara lag - 4 graficeKPI-urigauge sanatate ​si cadran motor redesenate la fiecare cadru.
  
-**Capcane ​intalnite**:​+**Probleme ​intalnite**:​
   * **Coil mapping pe stepper**: pe placa fizica IN3 si IN4 sunt inversate fata de ordinea alfabetica. Verificat cu un sketch de diagnostic (''​firmware/​stepper_test''​) care energizeaza fiecare coil pe rand; secventa din firmware reflecta mapping-ul real.   * **Coil mapping pe stepper**: pe placa fizica IN3 si IN4 sunt inversate fata de ordinea alfabetica. Verificat cu un sketch de diagnostic (''​firmware/​stepper_test''​) care energizeaza fiecare coil pe rand; secventa din firmware reflecta mapping-ul real.
-  * **Frecventa de pull-in**: 28BYJ-48 nu poate porni direct la viteza de croaziera, rampa de acceleratie ​e mandatorie+  * **Frecventa de pull-in**: 28BYJ-48 nu poate porni direct la viteza de croaziera, rampa de acceleratie ​este obligatorie
-  * **WiFi modem sleep**: ​pornit by defaultcosta ~100 ms per pachet. ''​WiFi.setSleep(false)'' ​are impact mai mare decat te-ai astepta+  * **WiFi modem sleep**: ​activ implicitintroduce ​~100 ms per pachet. ''​WiFi.setSleep(false)'' ​produce o imbunatatire substantiala a latentei
-  * **Buffer UART RX ESP32**: 256 bytes default ​sunt insuficient ​cand bucla se blocheaza ocazional (reconectare WS); buffer de 2048 lasa headroom de ~4 secunde la cadenta 20 Hz. +  * **Buffer UART RX ESP32**: ​cei 256 bytes impliciti ​sunt insuficienti ​cand bucla se blocheaza ocazional (reconectare WS); un buffer de 2048 ofera headroom de ~4 secunde la cadenta ​de 20 Hz. 
-  * **Heartbeat de debug**: zeci de ''​Serial.print'' ​apeluri ​separate blocheaza bucla cu 19 ms (motorul desincronizeaza); un singur ''​snprintf''​ compact in TX-ul UART trece nedetectat.+  * **Heartbeat de debug**: zeci de apeluri ​''​Serial.print''​ separate blocheaza bucla timp de 19 ms (rezultand desincronizarea motorului); un singur ''​snprintf''​ compact in TX-ul UART are impact neglijabil.
  
 ===== Concluzii ===== ===== Concluzii =====
  
-Cateva decizii arhitecturale au avut impact ​mai mare decat restul:+Cateva decizii arhitecturale au avut impact ​disproportionat de mare:
  
-**Logica de siguranta pe Arduino, nu pe ESP32.** Calculul scorului de sanatate si state machine-ul ​traiesc ​pe Arduino, ​cu ESP32 ca punte simpla. Avantajele: o singura sursa de adevar, ​zero variabilitate ​de timing de la reteasi rezistenta la caderea WiFi (Arduino ​continua sa opreasca ​motorul corect independent de conectivitate). Orice modul WiFi cu acelasi protocol ​UART de 27 bytes poate inlocui ESP32-ul.+**Logica de siguranta pe Arduino, nu pe ESP32.** Calculul scorului de sanatate si state machine-ul ​ruleaza ​pe Arduino, ESP32 functionand ​ca punte. Avantajele: o singura sursa de adevar, ​eliminarea variabilitatii ​de timing ​introduse ​de retea si rezistenta la caderea WiFi (Arduino ​opreste ​motorul corect independent de conectivitate). Orice modul WiFi care implementeaza protocolul ​UART de 27 bytes poate inlocui ESP32-ul.
  
-**WebSocket cu push la 20 Hz.** Latenta end-to-end ​in jur de 75 ms, iar dashboard-ul ​se simte live in loc de refreshat ​periodic. Push-ul declansat de fiecare cadru parsat ​scoate complet din ecuatie orice timer separat pentru transmisia catre server.+**WebSocket cu push la 20 Hz.** Latenta end-to-end ​este in jur de 75 ms, iar dashboard-ul ​are comportament ​live in loc de refresh ​periodic. Push-ul declansat de fiecare cadru parsat ​elimina necesitatea unui timer separat pentru transmisia catre server.
  
-**Determinismul ​costa.** Cost-per-iteratie bounded ​cere multe alegeri individuale ​mici (PCINT, port I/O direct, ​fara retransmisii, ADC prescaler, heartbeat compact). Cumulate, ​dau o bucla cu cost predictibil in zona de microsecunde.+**Determinismul ​are cost.** Cost-per-iteratie bounded ​necesita numeroase ​alegeri individuale (PCINT, port I/O direct, ​absenta retransmisiilor, ADC prescaler, heartbeat compact). Cumulate, ​rezultatul este o bucla cu cost predictibil in zona de microsecunde.
  
-**Histereza ​nu e optionala.** Toate starile "​live"​ (PROXIMITY, WATER_HIGH, TEMP_HIGH) ​au nevoie de praguri separate enter / exit. Altfel, un senzor care variaza in jurul pragului ​face sistemul sa intre si sa iasa rapid - inutilizabil.+**Histereza ​este obligatorie.** Toate starile "​live"​ (PROXIMITY, WATER_HIGH, TEMP_HIGH) ​necesita ​praguri separate enter / exit. In caz contrar, un senzor care variaza in jurul pragului ​determina ​sistemul sa intre si sa iasa rapid din stare comportament ​inutilizabil.
  
-**Triple-press pentru reset.** ​Forteaza ​o actiune deliberata si previne ​resetari ​accidentale ale E-stop-ului. Un singur buton face atat latch cat si reset - secventa de 3 apasari in 2 secunde ​e suficient ​de grea incat sa nu se intample din greseala.+**Triple-press pentru reset.** ​Impune ​o actiune deliberata si previne ​resetarile ​accidentale ale E-stop-ului. Un singur buton indeplineste ​atat functia de latch cat si pe cea de reset - secventa de 3 apasari in 2 secunde ​are probabilitate redusa ​de declansare accidentala.
  
-**Imbunatatiri viitoare** neimplementate din lipsa de timp / piese:+**Imbunatatiri viitoare** neimplementate din lipsa de timp sau de componente:
   * Senzor de vibratii (MPU6050) pentru detectia uzurii rulmentilor   * Senzor de vibratii (MPU6050) pentru detectia uzurii rulmentilor
-  * Profil de acceleratie S-curve pentru pornire ​si mai lina+  * Profil de acceleratie S-curve pentru ​pornire mai lina
   * Tranzitii de stare salvate ca eveniment separat, nu doar metricile   * Tranzitii de stare salvate ca eveniment separat, nu doar metricile
-  * Autentificare pe dashboard ​HTTPS/WSS pentru un deployment ​"​serios"​ +  * Autentificare pe dashboard ​si HTTPS/WSS pentru un deployment ​in productie 
-  * Trecere la un motor mai puternic - 28BYJ-48 la 20 RPM e prea blajin ​pentru aplicatii reale+  * Trecere la un motor mai puternic - 28BYJ-48 la 20 RPM are cuplu limitat ​pentru aplicatii reale
  
 ===== Download ===== ===== Download =====
Line 346: Line 346:
 Etapele s-au aliniat pe milestone-urile cursului: Etapele s-au aliniat pe milestone-urile cursului:
  
-  * **Saptamana 11 (4-8 Mai) - Milestone documentatie**:​ alegerea componentelor,​ motivarea arhitecturii dual-MCU, schema electrica in KiCad, calculul de consum si scrierea ​acestei pagini in forma initiala. +  * **Saptamana 11 (4-8 Mai) - Milestone documentatie**:​ alegerea componentelor,​ motivarea arhitecturii dual-MCU, schema electrica in KiCad, calculul de consum si redactarea ​acestei pagini in forma initiala. 
-  * **Saptamana 12 (11-15 Mai) - Milestone hardware**: montaj fizic pe cele doua breadboard-uri,​ cablare divizor 1k/2k pentru linia Arduino TX -> ESP32 RX, testare individuala a fiecarui senzor. ​Aici am descoperit ​prima capcana: motorul stepper vibra fara sa se invartaAm scris un sketch dedicat (''​firmware/​stepper_test''​) care energizeaza fiecare coil pe rand - s-vazut ca pe placa concreta IN3 si IN4 sunt inversate fata de ordinea alfabetica. +  * **Saptamana 12 (11-15 Mai) - Milestone hardware**: montaj fizic pe cele doua breadboard-uri,​ cablare divizor 1k/2k pentru linia Arduino TX -> ESP32 RX, testare individuala a fiecarui senzor. ​In aceasta etapa a fost identificata ​prima problema: motorul stepper vibra fara sa se roteascaA fost dezvoltat ​un sketch dedicat (''​firmware/​stepper_test''​) care energizeaza fiecare coil pe rand, iar testul ​indicat ​ca pe placa concreta IN3 si IN4 sunt inversate fata de ordinea alfabetica. 
-  * **Saptamana 13 (18-22 Mai) - Milestone software**: prima versiune end-to-end functionala (Arduino + ESP32 cu HTTP POST + Flask + dashboard cu polling), urmata in aceeasi saptamana de refactor-ul mare: inversarea arhitecturii (tot real-time pe Arduino, ESP32 doar punte), migrarea la WebSocket persistent in ambele directii, rampa de acceleratie pentru motor, starile noi (PROXIMITY, TEMP_HIGH, WATER_HIGH) cu histereza, E-stop cu latching si triple-press reset, optimizari pentru determinism (PCINT, port I/O direct, ADC prescaler, WiFi.setSleep(false),​ SQLite WAL).+  * **Saptamana 13 (18-22 Mai) - Milestone software**: prima versiune end-to-end functionala (Arduino + ESP32 cu HTTP POST + Flask + dashboard cu polling), urmata in aceeasi saptamana de refactorul principal: inversarea arhitecturii (logica ​real-time pe Arduino, ESP32 doar ca punte), migrarea la WebSocket persistent in ambele directii, rampa de acceleratie pentru motor, starile noi (PROXIMITY, TEMP_HIGH, WATER_HIGH) cu histereza, E-stop cu latching si triple-press reset, optimizari pentru determinism (PCINT, port I/O direct, ADC prescaler, WiFi.setSleep(false),​ SQLite WAL).
   * **Saptamana 14 (25-29 Mai) - PM Fair**: prezentarea proiectului.   * **Saptamana 14 (25-29 Mai) - PM Fair**: prezentarea proiectului.
  
pm/prj2026/florin.stancu/andrei.bleortu.txt · Last modified: 2026/05/25 14:04 by andrei.bleortu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0