Differences

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

Link to this comparison view

pm:prj2021:avaduva:fire_alarm [2021/05/18 19:33]
cosmin.vancea Adăugate link-uri către componentele utilizate
pm:prj2021:avaduva:fire_alarm [2021/05/24 23:45] (current)
cosmin.vancea
Line 9: Line 9:
  
 ==== Descriere generală ==== ==== Descriere generală ====
 +
 {{:​pm:​prj2021:​avaduva:​fire-alarm-schema-logica.png?​700}} {{:​pm:​prj2021:​avaduva:​fire-alarm-schema-logica.png?​700}}
    
Line 20: Line 21:
  
 ==== Hardware Design ==== ==== Hardware Design ====
 +
 +=== Componente ===
 +
   - [[https://​www.optimusdigital.ro/​ro/​compatibile-cu-arduino-uno/​1678-placa-de-dezvoltare-compatibila-cu-arduino-uno-atmega328p-i-ch340.html|Arduino UNO]]   - [[https://​www.optimusdigital.ro/​ro/​compatibile-cu-arduino-uno/​1678-placa-de-dezvoltare-compatibila-cu-arduino-uno-atmega328p-i-ch340.html|Arduino UNO]]
   - [[https://​www.optimusdigital.ro/​ro/​senzori-de-gaze/​107-modul-senzor-gas-mq-2.html|Senzor de gaze MQ-2]]   - [[https://​www.optimusdigital.ro/​ro/​senzori-de-gaze/​107-modul-senzor-gas-mq-2.html|Senzor de gaze MQ-2]]
Line 33: Line 37:
   - [[https://​www.optimusdigital.ro/​ro/​fire-fire-mufate/​885-set-fire-tata-tata-10p-10-cm.html|Fire tată-tată (3 seturi)]]   - [[https://​www.optimusdigital.ro/​ro/​fire-fire-mufate/​885-set-fire-tata-tata-10p-10-cm.html|Fire tată-tată (3 seturi)]]
   - [[https://​www.optimusdigital.ro/​ro/​fire-fire-mufate/​650-fire-colorate-mama-tata-10p.html|Fire mamă-tată (1 set)]]   - [[https://​www.optimusdigital.ro/​ro/​fire-fire-mufate/​650-fire-colorate-mama-tata-10p.html|Fire mamă-tată (1 set)]]
 +
 +=== Schema electrică ===
 +
 +{{:​pm:​prj2021:​avaduva:​fire-alarm-schema-electrica.png?​700}}
  
 ==== Software Design ==== ==== Software Design ====
 +
 +=== Informații generale ===
 +
 +Proiectul este compus din două componente software:
 +
 +  - [[https://​github.com/​csvancea/​fire-alarm/​tree/​master/​fire-alarm|software-ul pentru Arduino]]: responsabil cu citirea senzorilor și transmiterea datelor către server
 +  - [[https://​github.com/​csvancea/​fire-alarm/​tree/​master/​howl|software-ul pentru server]]: responsabil cu prelucrarea și stocarea datelor primite, urmată de notificarea dispozitivelor clienților
 +
 +Codul Arduino a fost dezvoltat în [[https://​www.visualmicro.com/​|Visual Micro]].
 +
 +=== Biblioteci ===
 +
 +Pentru realizarea proiectului am utilizat următoarele biblioteci 3rd-party:
 +
 +  * [[https://​www.arduino.cc/​en/​reference/​SD|SDLib]]:​ permite accesarea cardului SD unde este stocat fișierul de configurare
 +  * [[https://​www.arduino.cc/​reference/​en/​libraries/​inifile/​|IniFile]]:​ permite citirea fișierului ''/​fire-alarm/​net-config.ini''​ de pe cardul SD
 +
 +În plus am dezvoltat următoarele două mini-biblioteci pentru a ușura interacțiunea cu dispozitivele conectate:
 +
 +  * [[https://​github.com/​csvancea/​fire-alarm/​blob/​master/​fire-alarm/​src/​ESP8266.cpp|ESP8266]]:​ abstractizează comenzile date plăcii Wi-Fi ESP-01. În mod normal, ESP-01 primește comenzi de forma ''​AT+<​cmd>​ <​parametri>''​ și returnează un răspuns pe interfața serială. Biblioteca are rolul de a ascunde aceste detalii în spatele unei interfețe high-level (clasă C++), astfel nu va trebui să lucrez direct cu interfața serială. În plus, biblioteca oferă suport minimalist pentru trimiterea de cereri HTTP.
 +  * [[https://​github.com/​csvancea/​fire-alarm/​blob/​master/​fire-alarm/​src/​AsyncADC.cpp|AsyncADC]]:​ permite inițializarea unei conversii ADC fără să se aștepte rezultatul. Se poate utiliza în cadrul întreruperilor deoarece timpul de execuție este foarte scurt (doar se face o scriere într-un registru de control). Biblioteca abstractizează lucrul cu regiștrii de control ai ADC-ului (''​ADCSRA''​ și ''​ADMUX''​).
 +
 +=== Funcții implementate ===
 +
 +Mai jos sunt detaliate cele mai importante funcții din fișierul sursă principal: [[https://​github.com/​csvancea/​fire-alarm/​blob/​master/​fire-alarm/​fire-alarm.ino|fire-alarm.ino]].
 +
 +Funcții de **''​setup()''​**:​
 +
 +  * ''​InitSDCard'':​ inițializează modulul pentru SD Card și citește datele de configurare din fișierul ''/​fire-alarm/​net-config.ini''​
 +  * ''​InitWiFi'':​ așteaptă inițializarea modulului Wi-Fi și se conectează la AP-ul (router wireless) specificat în fișierul de configurare de către utilizator
 +  * ''​BlinkForever'':​ în cazul în care se detectează o eroare la oricare pas de inițializare descris anterior, se apelează această funcție care blochează execuția codului și va seta LED-ul să emită o anumită culoare care semnalează eroarea întalnită.
 +  * ''​SetLEDColour'':​ setează culoarea LED-ului RGB. Acest LED este folosit pentru a semnala starea în care se află aparatul (ex: verde = inițializat + stare OK de funcționare)
 +
 +În plus, în faza de ''​setup''​ se activează întreruperile pe liniile ''​INT0''​ (senzor fum) și ''​INT1''​ (senzor flăcări) și se atașează câte un ISR care va fi executat la schimbarea valorilor.
 +
 +Funcții de **''​loop()''​**:​
 +
 +  * ''​PostDataToServer'':​ se reconectează la AP (în cazul în care s-a pierdut conexiunea) și se postează un mesaj HTTP la endpoint-ul specificat în fișierul de configurare. Dacă nu se poate trimite mesajul, atunci se va semnala eroarea prin LED și se va reîncerca transmiterea pachetului la fiecare 10 secunde până se reușește. Spre deosebire de o eroare de inițializare,​ aici execuția codului nu se mai oprește.
 +  * ''​SendNotification'':​ se generează body-ul cererii HTTP POST în funcție de datele citite de la senzori, apoi se apelează ''​PostDataToServer''​ pentru a trimite cererea.
 +
 +Pe langă semnalizarea prin LED, dispozitivul va scrie pe interfața serială mesaje de logging la fiecare pas important (în special: inițializare SD Card/Wi-Fi și trimiterea de mesaje HTTP). Acest lucru ajută la depanarea problemelor.
 +
 +Rutine pentru **întreruperi**:​
 +
 +  * ''​GasInterrupt'':​ apelată la schimbarea valorii de pe pinul digital asociat senzorului de fum. Dacă noua valoare este ''​LOW''​ înseamnă că senzorul a detectat fum și se va inițializa ''​AsyncADC''​-ul definit anterior pentru a porni citirea de pe pinul analog asociat. Se va seta o variabilă globală pentru a marca evenimentul.
 +  * ''​FlameInterrupt'':​ apelată la schimbarea valorii de pe pinul digital asociat senzorului de flăcări. Dacă noua valoare este ''​LOW''​ înseamnă că senzorul a detectat flăcări și se va marca faptul că s-au detectat flăcări într-o variabilă globală
 +    * //notă:// din păcate modulul pentru senzorul de flăcări folosit de mine nu are și un pin analog de pe care să pot citi intensitatea.
 +
 +De asemenea, la detectarea de fum sau flăcări se va activa alarma sonoră. Aceasta se oprește când ambii senzori nu mai detectează nimic suspect.
 +
 +După cum se observă, în rutinele de întreruperi nu se întamplă nimic excepțional,​ maxim se scrie în 1-2 variabile/​regiștri. Codul care se ocupă cu notificarea se află în ''​loop''​. Aici la fiecare //X// secunde se verifică dacă senzorii au detectat ceva (se interoghează variabilele globale scrise în ISR), iar în caz afirmativ, se va citi valoarea senzorului de fum prin ''​AsyncADC''​ și se vor trimite măsurătorile la server.
 +Motivul pentru care am optat să implementez și să folosesc ''​AsyncADC''​ în loc de un simplu ''​analogRead''​ în ''​loop''​ este că de la momentul în care este declanșată întreruperea până la momentul în care se face polling în ''​loop''​ pot trece multe secunde/​minute,​ iar astfel senzorul poate să îmi returneze valori normale în momentul când eu le citesc în ''​loop''​. Folosind ''​AsyncADC''​ mă asigur că în ''​loop''​ voi avea acces la datele care erau citite acum //Y// secunde când s-a declanșat întreruperea.
 +
 +=== Fișierul de configurare ===
 +
 +Utilizatorul dispozitivului poate specifica datele de configurare fără a fi nevoit sa recompileze software-ul -- doar trebuie să modifice un fișier de configurare de pe un SD Card! Fișierul trebuie plasat pe card la calea: ''/​fire-alarm/​net-config.ini''​. Exemplu:
 +
 +<file ini net-config.ini>​
 +[wifi]
 +ssid=HUAWEI-abcd ​                         ; nume rețea wireless
 +pass=my-extremely-hard-to-guess-password ​ ; parolă wireless
 +
 +[server]
 +host=fire-alarm.example.com ​              ; adresa serverului destinație
 +port=7331 ​                                ; portul serverului destinație
 +endpoint=/​api/​v1/​measurement/​add ​         ; calea către endpoint-ul unde se vor posta măsurătorile
 +guid=744A2B95-D130-40A1-94E3-D8719FEDCCCD ; identificator unic pentru fiecare dispozitiv "Fire Alarm"
 +</​file>​
 +
 +=== Optimizări de memorie ===
 +
 +Arduino UNO dispune de două spații de memorie diferite: 2K memorie SRAM și 32K memorie flash. Memoria SRAM mică limitează foarte mult dimensiunea datelor cu care pot lucra (inclusiv string-uri -> acestea sunt stocate în SRAM, deci în cel mai bun caz aș putea avea maxim ~2000 de caractere fără să mai iau în considerare stack-ul și restul datelor din program).
 +
 +Pentru a ocoli această limită, am ales să stochez datele constante (eg: string-uri) în memoria flash folosind keyword-ul [[https://​www.arduino.cc/​reference/​en/​language/​variables/​utilities/​progmem/​|PROGMEM]] oferit de AVR și să le aduc în SRAM doar când am nevoie să le prelucrez (eg: formatarea unei cereri HTTP/unui mesaj de eroare). Acest trick îmi permite să:
 +
 +  - am string-uri de dimensiune mare în program (eg: cereri HTTP neformatate)
 +  - am mesaje de eroare foarte explicite
 +  - reduc la minim utilizarea SRAM-ului
 +
 +În plus, majoritatea funcțiilor care acceptă string-uri constante implementate de mine au două forme: (vezi [[https://​github.com/​csvancea/​fire-alarm/​blob/​master/​fire-alarm/​src/​ESP8266.h|ESP8266.h]])
 +
 +  - una care accepta string-uri din SRAM
 +  - una care acceptă string-uri din FLASH
 +
 +=== Server ===
 +
 +Software-ul pentru server este realizat în [[https://​flask.palletsprojects.com/​en/​1.1.x/​|Flask]]. Practic este un web server care:
 +
 +  - expune un endpoint la care dispozitivul Arduino trimite măsurătorile împreuna cu GUID-ul său (fiecare dispozitiv Fire Alarm este identificat printr-un GUID specificat în fișierul de configurare)
 +  - oferă utilizatorului o interfață web prin care poate citi măsurătorile senzorilor săi (trebuie să cunoască GUID-ul)
 +
 +Notificarea pe telefon se face prin serviciul [[https://​pushbullet.com/​|PushBullet]]. În interfața web, proprietarul poate asocia un cont de PushBullet dispozitivelor sale. Fiecare măsurătoare care depășește valorile normale va fi trimisă ca notificare contului PushBullet asociat.
 +
 +Detaliile de implementare nu intră în materia cursului. :-)
  
 ==== Rezultate obținute ==== ==== Rezultate obținute ====
 +
 +=== Poze dispozitiv ===
 +
 +{{:​pm:​prj2021:​avaduva:​fire-alarm-photo.jpg?​350}}
 +{{:​pm:​prj2021:​avaduva:​fire-alarm-photo-2.jpg?​350}}
 +
 +=== Interfața cu utilizatorul ===
 +
 +{{:​pm:​prj2021:​avaduva:​fire-alarm-web-interface.png?​350}}
 +{{:​pm:​prj2021:​avaduva:​fire-alarm-phone-notification.png?​350}}
 +
 +=== Videoclip de prezentare ===
 +
 +<​html><​iframe width="​712"​ height="​400"​ src="​https://​www.youtube.com/​embed/​dchMreNvpHc"​ title="​YouTube video player"​ frameborder="​0"​ allow="​accelerometer;​ autoplay; clipboard-write;​ encrypted-media;​ gyroscope; picture-in-picture"​ allowfullscreen></​iframe></​html>​
  
 ==== Concluzii ==== ==== Concluzii ====
 +
 +A fost o experiență productivă deoarece proiectul ales de mine a trebuit să fie gândit din două perspective diferite care trebuie să se întâlnească într-un punct comun: un sistem local ce colectează date de la senzori și un sistem remote ce primește aceste date, le prelucrează și le distribuie mai departe. Pe lângă implementarea efectivă, a fost nevoie de multă documentare în prealabil, iar astfel m-am familiarizat cu căutarea de informații în documentația oficială.
  
 ==== Download ==== ==== Download ====
-<​html><​a class="​media mediafile ​mf_pdf" href="?​do=export_pdf">PDF</​a></​html>​+ 
 +  * <​html><​a class="​media mediafile ​mf_rar" href="https://​github.com/​csvancea/​fire-alarm/​archive/​refs/​heads/​master.zip">Cod sursă (arhivă)</​a></​html>​ 
 +  * [[https://​github.com/​csvancea/​fire-alarm/​|Cod sursă (GitHub)]]
  
 ==== Jurnal ==== ==== Jurnal ====
-  ​* 19 aprilie - sosire componente + 
-  * 23 aprilie - realizat ansambul hardware +  ​* 19 aprilie ​2021 - sosire componente 
-  * 24 aprilie - creată pagina proiectului+  * 23 aprilie ​2021 - realizat ansambul hardware 
 +  * 24 aprilie ​2021 - creată pagina proiectului 
 +  * 03 mai 2021 - implementat software-ul pentru Arduino 
 +  * 06 mai 2021 - implementat software-ul pentru Server 
 +  * 24 mai 2021 - completată pagina proiectului
  
 ==== Bibliografie/​Resurse ==== ==== Bibliografie/​Resurse ====
 +
 +  * [[https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|ATmega328P Datasheet (ADC & Timers)]]
 +  * [[https://​www.espressif.com/​sites/​default/​files/​documentation/​4a-esp8266_at_instruction_set_en.pdf|ESP8266 AT Instruction Set]]
 +  * [[https://​www.arduino.cc/​en/​Reference/​softwareSerial|Arduino SoftwareSerial]]
 +  * [[https://​www.arduino.cc/​en/​reference/​SD|Arduino SD Library]]
 +  * [[https://​www.arduino.cc/​en/​Reference/​SDCardNotes|Arduino SD Card Best Practices]]
 +  * [[https://​www.arduino.cc/​reference/​en/​language/​variables/​utilities/​progmem/​|Arduino PROGMEM]]
 +  * [[https://​flask.palletsprojects.com/​_/​downloads/​en/​1.1.x/​pdf/​|Flask Documentation]]
 +  * [[https://​docs.pushbullet.com/​|PushBullet API Documentation]]
 +
 +<​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
 +
pm/prj2021/avaduva/fire_alarm.1621355624.txt.gz · Last modified: 2021/05/18 19:33 by cosmin.vancea
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