This is an old revision of the document!


Sistem de Monitorizare si Protectie Industriala

Introducere

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.

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 e o abordare standard in sistemele industriale serioase.

Descriere generala

Sistemul este construit pe doua microcontrollere cu roluri foarte diferite:

  • 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.
  • 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.

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.

Fluxul de date implementat:

  1. Arduino citeste senzorii rapizi (PIR, sunet, apa, buton) la fiecare 10 ms
  2. Senzorul ultrasonic ruleaza asincron: declanseaza un puls la fiecare 60 ms, iar ecoul e cronometrat printr-o intrerupere pin-change (fara blocare cu pulseIn)
  3. State machine-ul evalueaza prioritatile cu histereza si seteaza starea
  4. La fiecare 50 ms Arduino trimite un cadru UART de 27 bytes catre ESP32 (20 Hz): 2 bytes header + 1 byte LEN + 23 bytes payload + 1 byte XOR checksum
  5. ESP32 valideaza checksum-ul, trimite ACK/NACK si imediat retransmite cadrul catre server prin WebSocket
  6. La fiecare ~2 secunde ESP32 trimite spre Arduino temperatura si umiditatea citite de la DHT11
  7. LCD-ul se reimprospateaza la fiecare 500 ms, cu paginile rotite la 3 secunde
  8. Dashboard-ul web primeste actualizari instant prin WebSocket si se redeseneaza la fiecare cadru

Logica de siguranta e organizata ca o cascada cu prioritati. Starile cu prioritate mai mare le suprascriu pe cele inferioare:

EMERGENCY      - buton apasat (latched, eliberat doar prin triple-press)
SOUND_SHUTDOWN - 5 secunde de pauza dupa un spike de zgomot
MAINTENANCE    - 10 secunde dupa detectie PIR (cu refresh la fiecare detectie noua)
PROXIMITY      - obiect mai apropiat de 40 cm (live, cu histereza la 50 cm)
WATER_HIGH    - senzor de apa peste 512/1023 (live, cu histereza la 450)
TEMP_HIGH      - temperatura peste 35 °C (live, cu histereza la 33 °C)
NORMAL         - functionare nominala

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.

Hardware Design

Lista de piese

# Componenta Cant. Link
1 Arduino MEGA 2560 R3 (clona, ATmega2560 + CH340) 1 Optimus Digital
2 Placa de dezvoltare ESP32 cu WiFi si Bluetooth (ESP-WROOM-32) 1 Optimus Digital
3 Modul senzor PIR HC-SR501 1 Optimus Digital
4 Senzor ultrasonic HC-SR04 1 Optimus Digital
5 Modul senzor de sunet (iesire A0 + D0) 1 Optimus Digital
6 Senzor de nivel al apei (analogic) 1 Optimus Digital
7 Modul senzor DHT11 (temperatura + umiditate) 1 Optimus Digital
8 Set motor pas cu pas 28BYJ-48 + driver ULN2003 1 Optimus Digital
9 LCD 1602 HD44780 cu backlight verde, 5 V (paralel, 16 pini) 1 Optimus Digital
10 Buzzer activ 5 V 1 Optimus Digital
11 Buton tactil 6x6x6 mm (emergency stop) 1 Optimus Digital
12 Mini potentiometru 10k (contrast LCD) 1 Optimus Digital
13 Set rezistoare 0.25 W (220 ohm pt. backlight + 1k si 2k pt. divizorul UART) 1 Optimus Digital
14 Breadboard HQ 830 puncte 2 Optimus Digital
15 Set fire tata-tata 40p / 20 cm 1 Optimus Digital
16 Set fire mama-tata 40p / 10 cm 1 Optimus Digital
17 Alimentator 9 V / 1 A cu mufa DC 1 Optimus Digital

Aproape toate componentele provin din acest kit AliExpress. Singura exceptie este placa ESP32 WROOM-32, achizitionata separat. Link-urile Optimus Digital de mai sus sunt echivalente individuale, pentru referinta.

Organizarea fizica

Componentele sunt distribuite pe doua breadboard-uri pentru a separa logic responsabilitatile sistemului si pentru a facilita mentenanta.

Breadboard principal (Arduino):

  • Arduino MEGA pozitionat central
  • Senzorii de intrare in partea stanga (PIR, ultrasonic, sound, water)
  • Actuatorii in partea dreapta (driver stepper, buzzer)
  • Distributia de alimentare (5V/GND) pe rail-urile superioare

Breadboard secundar (ESP32):

  • ESP32 pozitionat central
  • LCD1602 conectat prin 6 fire de control
  • DHT11 pentru monitorizarea ambientala
  • Conexiunile UART catre Arduino prin fire dedicate

Alimentarea pleaca de la adaptorul de 9V care intra in jack-ul DC al Arduino-ului. Regulatorul intern al placii furnizeaza 5V stabil, care alimenteaza toti senzorii si ESP32-ul (prin pinul Vin). ESP32-ul are propriul regulator intern care coboara tensiunea la 3.3V pentru functionarea interna. Toate componentele impart o masa comuna distribuita prin rail-urile negative ale celor doua breadboard-uri.

Schema electrica

Pinout

Arduino MEGA:

Componenta Pini Arduino
PIR HC-SR501 OUT → D12, VCC → 5V, GND → GND
HC-SR04 Trig → D11, Echo → D10 (PCINT4)
Sound Sensor A0 → A0, D0 → D9, + → 5V, G → GND
Water Sensor S → A1, + → 5V, - → GND
Emergency Button D18 cu INPUT_PULLUP, celalalt capat → GND
Stepper ULN2003 IN1→D8, IN2→D7, IN3→D6, IN4→D5
Buzzer + → D4, - → GND
UART catre ESP32 TX2 (D16) → divizor 1k/2k → RX2 ESP; RX2 (D17) ← TX2 ESP direct

ESP32:

Componenta Pini ESP32
DHT11 GPIO32
LCD1602 RS→GPIO5, EN→GPIO18, D4→GPIO19, D5→GPIO21, D6→GPIO22, D7→GPIO23
UART catre Arduino RX2 (GPIO16), TX2 (GPIO17)

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 e 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 e stabil si bandwidth-ul ramane mult 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.

Estimare consum energetic

Valorile de mai jos sunt estimate pe baza datasheet-urilor componentelor.

Componenta Curent (estimat) Putere
Arduino MEGA active 200 mA 1000 mW
ESP32 cu WiFi activ 240 mA 792 mW
PIR 50 mA 250 mW
HC-SR04 15 mA 75 mW
Sound sensor 4 mA 20 mW
Water sensor 5 mA 25 mW
DHT11 0.3 mA 1.5 mW
LCD1602 20 mA 100 mW
Stepper activ 300 mA 1500 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.

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.

Software Design

Mediu de dezvoltare

  • Arduino IDE pentru ambele microcontrollere, folosind board package-ul ESP32 oficial Espressif
  • Python 3 cu Flask + flask-sock pentru server-ul web
  • SQLite in modul WAL pentru persistenta datelor
  • HTML, CSS si JavaScript vanilla pentru dashboard, cu Chart.js incarcat din CDN

Biblioteci si surse 3rd-party

Pe Arduino:

  • avr/wdt.h si avr/interrupt.h pentru watchdog si ISR (built-in)
  • Driver propriu pentru motorul stepper (full-step, two-phases-on, cu rampa de acceleratie)
  • Parser propriu pentru cadrele UART (state machine, fara alocare dinamica)

Pe ESP32:

  • WiFi.h - conectarea la retea
  • WebSocketsClient (Markus Sattler / Links2004) - clientul WebSocket spre server
  • LiquidCrystal.h - controlul LCD-ului (interfata paralela)
  • DHT.h (Adafruit) - citirea senzorului DHT11
  • ArduinoJson.h (Benoit Blanchon) - serializarea cadrelor in JSON

Pe server:

  • Flask - framework web minimalist
  • flask-sock + simple-websocket - endpoint-urile WebSocket
  • sqlite3 (built-in) - persistenta datelor
  • Chart.js (CDN) - graficele de pe dashboard

Algoritmi si structuri

State machine pentru siguranta (Arduino)

Sistemul functioneaza pe baza unei masini cu 7 stari active si o stare rezervata. Prioritatile, de la cea mai mare la cea mai mica:

EMERGENCY      - buton apasat (latched, eliberat prin triple-press)
SOUND_SHUTDOWN - 5 secunde dupa un spike de zgomot
MAINTENANCE    - 10 secunde dupa detectie PIR
PROXIMITY      - obiect < 40 cm (live, histereza la 50 cm)
WATER_HIGH    - apa > 512 (live, histereza la 450)
TEMP_HIGH      - temperatura > 35 °C (live, histereza la 33 °C)
WARNING        - rezervata (anomalie minora care nu opreste motorul)
NORMAL         - functionare nominala

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.

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.

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.

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). Solutia: rampa liniara, pornire 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). E 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).

Secventa de comutare e 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.

Senzor ultrasonic non-blocking

pulseIn e blocking pana la ~25 ms - jitter inacceptabil pentru bucla. In loc, ecoul e 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.

Protocolul UART

Doua tipuri de cadre, ambele cu acelasi pattern (header + LEN + payload + XOR):

Forward  (Arduino -> ESP32): 0xAA 0x55 LEN(23) payload XOR    la fiecare 50 ms
Reverse  (ESP32 -> Arduino): 0xBB 0x66 LEN(4)  payload XOR    la fiecare ~2 s
ACK / NACK (single byte): 0x06 / 0x15, ESP32 -> Arduino       per cadru forward

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 timing; urmatorul cadru vine in 50 ms oricum.

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).

Calculul scorului de sanatate (Arduino)

Scorul (0-100) este calculat cu aritmetica intreaga la fiecare 50 ms, chiar inainte de trimiterea cadrului. Penalizari:

temperatura in afara 18-28 °C  : 3 puncte / grad
umiditate in afara 30-70 %     : 1 punct / procent
apa peste 500                  : -30 puncte
distanta sub 40 cm             : -10 puncte
stare WARNING                  : -20
stare MAINTENANCE              : -10
stare SOUND_SHUTDOWN           : -25
stare EMERGENCY                : -100 (forteaza 0)
link cu ESP32 pierdut          : -40
DHT nu a raportat inca         : -5

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.

Optimizari pentru determinism si latenta

Decizii aplicate in fiecare strat pentru bucla Arduino predictibila si latenta end-to-end mica:

  • 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.
  • 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).
  • 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.
  • Frontend: WebSocket pentru update-uri live, bootstrap istoric prin REST la incarcare apoi append incremental, Chart.js cu animation: false.

Functii principale

Pe Arduino:

  • readFastSensors() - citeste senzorii rapizi prin acces direct la PINx
  • ultrasonicTick() - state machine pentru declansarea pulsului si culegerea rezultatului
  • buttonTick() - detectia edge a butonului E-stop, latching, triple-press reset
  • evaluateSafetyState() - aplica logica state machine cu histereza
  • stepperTick() - driver non-blocking cu rampa de acceleratie
  • buzzerTick() - patternuri sonore diferite per stare
  • sendFrame() - impacheteaza cadrul forward si il scrie in TX-ul UART
  • pollEspStream() - parser pentru bytes-urile primite de la ESP32 (ACK/NACK si cadre reverse)
  • computeHealth() - calculul scorului de sanatate (aritmetica intreaga)
  • updateLinkStatus() - monitorizarea contorului de ACK-uri, mesaje »> pe Serial

Pe ESP32:

  • pollUart() - parser pentru cadrele forward de la Arduino, ACK/NACK
  • pushReadingOverWs() - serializare JSON + sendTXT pe WebSocket
  • sendReverseFrame() - trimite temperatura/umiditate spre Arduino
  • renderLcd() - actualizare LCD cu pagini rotite
  • ensureWifi() - reconectare automata WiFi
  • wsEvent() - callback pentru evenimente WebSocket (conectat / deconectat)

Pe server (Flask):

  • /ws/ingest (WS) - primeste datele de la ESP32, le salveaza in SQLite si le retransmite tuturor clientilor de dashboard
  • /ws/stream (WS) - clientii dashboard se aboneaza aici, primesc fiecare mesaj ingest in timp real
  • /api/data (POST) - acelasi ingest ca WS-ul, expus si pe HTTP pentru testare cu curl
  • /api/latest, /api/history, /api/stats (GET) - pentru bootstrap-ul dashboard-ului
  • / (GET) - serveste dashboard-ul HTML

Interfata utilizator (dashboard)

Dashboard-ul are o ierarhie vizuala clara, de sus in jos:

  1. Banner de stare - cel mai mare element din pagina, cu numele starii mare, o descriere scurta si (cand e cazul) un countdown urias pentru timpul ramas pana la repornire. Culorile se schimba per stare, EMERGENCY pulseaza.
  2. Cardurile “feature” - scorul de sanatate cu un gauge SVG si motorul cu un cadran care arata unghiul curent in timp real.
  3. 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.
  4. 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.

Rezultate Obtinute

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:

Etapa Latenta
Citire senzor + cadru Arduino pana la 50 ms (cadenta UART)
Transmisie UART (27 bytes @ 115200) ~2.3 ms
Parsare + push WebSocket ESP32 ~1 ms
WiFi → server ~2-5 ms
Insert SQLite WAL + broadcast ~1 ms
Server → browser ~2-5 ms
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.

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.

Link-ul UART e 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.

Dashboard-ul primeste 20 Hz fara lag - 4 grafice + KPI-uri + gauge sanatate + cadran motor redesenate la fiecare cadru.

Capcane 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.
  • Frecventa de pull-in: 28BYJ-48 nu poate porni direct la viteza de croaziera, rampa de acceleratie e mandatorie.
  • WiFi modem sleep: pornit by default, costa ~100 ms per pachet. WiFi.setSleep(false) are impact mai mare decat te-ai astepta.
  • 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.
  • 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.

Concluzii

Cateva decizii arhitecturale au avut impact mai mare decat restul:

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 retea, si 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.

WebSocket cu push la 20 Hz. Latenta end-to-end e 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.

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.

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.

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.

Imbunatatiri viitoare neimplementate din lipsa de timp / piese:

  • Senzor de vibratii (MPU6050) pentru detectia uzurii rulmentilor
  • Profil de acceleratie S-curve pentru pornire si mai lina
  • Tranzitii de stare salvate ca eveniment separat, nu doar metricile
  • Autentificare pe dashboard + HTTPS/WSS pentru un deployment “serios”
  • Trecere la un motor mai puternic - 28BYJ-48 la 20 RPM e prea blajin pentru aplicatii reale

Download

Jurnal

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 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 invarta. Am scris un sketch dedicat (firmware/stepper_test) care energizeaza fiecare coil pe rand - s-a vazut 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 14 (25-29 Mai) - PM Fair: prezentarea proiectului.

Bibliografie/Resurse

pm/prj2026/florin.stancu/andrei.bleortu.1779655321.txt.gz · Last modified: 2026/05/24 23:42 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