This shows you the differences between two versions of the page.
iothings:laboratoare:lab3 [2021/10/12 19:16] 127.0.0.1 external edit |
iothings:laboratoare:lab3 [2022/03/23 20:04] (current) cosmin.chenaru [Exerciții] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Implementarea unui protocol de acces la mediu în rețele de senzori wireless ====== | + | ===== Laborator 03. Publicarea datelor prin IFTTT ===== |
- | ===== Comunicatia intre noduri ===== | + | În laboratorul de astăzi vom studia următoarele subiecte: |
- | Compilati codul de mai jos si rulati pe doua noduri de adrese diferite: nodul cu adresa 1 este cel care trimite pachete iar al doilea (adresa diferita de 1) va receptiona pachetele trimise. Receptia va fi semnalata prin aprinderea led-ului de pe PB5 pe placa de extensie. | + | * Folosirea platformei online IFTTT.com și folosirea serviciului WebHooks |
- | + | * Conectarea (teoretică) a unui senzor la plăcuța ESP32 prin simulatorul online Wokwi.com | |
- | <code C> | + | |
- | #include <avr/io.h> | + | |
- | #include <avr/interrupt.h> | + | |
- | #define F_CPU 16000000UL | + | |
- | #include <util/delay.h> | + | |
- | #define TRX_FRAME_BUFFER(index) (*(volatile uint8_t *)(0x180 + (index))) | ||
- | volatile uint8_t rxPayload; | + | ==== IFTTT ==== |
- | uint8_t nod1_address __attribute__((section(".data"))) = 2; | + | Platforma online IFTTT.com permite utilizarea unor servicii online des întâlnite în domeniul IoT, precum interacțiunea cu un server Web. În acest laborator vom folosi serviciul WebHooks, care în momentul primirii unei cereri HTTP (POST) de la un echipament IoT, va iniția o acțiune în numele (contul) utilizatorului (ex. folosirea serviciului Google Assistant/Alexa/Siri). |
- | uint8_t node_address __attribute__((section(".data"))) = 2; | + | |
+ | Un foarte bun tutorial pentru crearea contului IFTTT este [[https://randomnerdtutorials.com/esp32-esp8266-publish-sensor-readings-to-google-sheets|acesta]], în care utilizatorul creează un WebHook pentru a scrie datele de la un device IoT într-un Google Spreadsheet. | ||
+ | ==== Wokwi ==== | ||
- | void initLeds() | + | Wokwi.com este un simulator de device-uri IoT, precum Arduino, ATtiny sau ESP32. Oferă o interfață grafică prin care putem scrie codul (similar cu Arduino IDE) si o fereastră in care putem conecta mai multe periferice (ex. senzori, LCD-uri) la plăcuța simulată. |
- | { | + | |
- | DDRB = 0xff; | + | |
- | PORTB = 0x00; | + | |
- | } | + | |
- | void setState(uint8_t state) | + | {{:iothings:laboratoare:lab3_wokwi.png?600|}} |
- | { | + | ==== Exerciții ==== |
- | TRX_STATE = CMD_FORCE_TRX_OFF; | + | |
- | TRX_STATE = state; | + | |
- | while (state != TRX_STATUS_struct.trx_status); | + | |
- | } | + | |
- | // send a short frame with a magic payload | + | === Ex. 1 === |
- | void sendFrame() | + | |
- | { | + | |
- | setState(CMD_PLL_ON); | + | |
- | TRX_FRAME_BUFFER(0) = 3; //length - minimum length is 3 | + | Urmăriți tutorialul [[https://randomnerdtutorials.com/esp32-esp8266-publish-sensor-readings-to-google-sheets/|acesta]] dar în loc de a scrie într-un Google spreadsheet, folosiți WebHook-ul care trimite un mail către utilizator. |
- | TRX_FRAME_BUFFER(1) = 0x00; //magic payload | + | |
- | + | ||
- | + | ||
- | // start transmission | + | |
- | TRX_STATE = CMD_TX_START; | + | |
- | } | + | |
- | + | ||
- | + | ||
- | // upon receipt make a simple verification of correctness | + | |
- | ISR(TRX24_RX_END_vect) | + | |
- | { | + | |
- | rxPayload = TRX_FRAME_BUFFER(0); | + | |
- | if (rxPayload == 0) | + | |
- | PORTB ^= (1<<PB5); | + | |
- | setState(CMD_RX_ON); | + | |
- | } | + | |
- | + | ||
- | void rfInit(void) | + | |
- | { | + | |
- | setState(CMD_TRX_OFF); | + | |
- | + | ||
- | IRQ_STATUS = 0xff; | + | |
- | IRQ_MASK_struct.rx_end_en = 1; | + | |
- | sei(); | + | |
- | + | ||
- | //PHY_CC_CCA_struct.channel = 0x0b; | + | |
- | TRX_CTRL_2_struct.rx_safe_mode = 1; | + | |
- | } | + | |
- | + | ||
- | int main() | + | |
- | { | + | |
- | rfInit(); | + | |
- | initLeds(); | + | |
- | + | ||
- | while(1) | + | |
- | { | + | |
- | if (node_address == 1) | + | |
- | { | + | |
- | sendFrame(); | + | |
- | PORTB ^= (1<<PB7); | + | |
- | _delay_ms(3000); | + | |
- | } | + | |
- | else | + | |
- | { | + | |
- | PORTB &= ~(_BV(PB5)); | + | |
- | setState(CMD_RX_ON); | + | |
- | while (rxPayload != 0) asm("nop"); | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | return 0; | + | |
- | } | + | |
+ | Înainte de a testa codul pe plăcuța ESP32, puteți testa request-ul HTTP din linie de comanda (pe Linux): | ||
+ | <code> | ||
+ | curl -X POST -H "Content-Type: application/json" -d '{"value1":"10","value2":"20","value3":"30"}' https://maker.ifttt.com/trigger/{event}/with/key/dY4pxl1Yiq49wynrqz | ||
</code> | </code> | ||
+ | Înlocuiți {event} cu numele WebHook-ului creat de voi. Un mesaj cu textul "Congratulations! You've fired the {event}" va trebui să apară. | ||
- | Nodurile vor urma un program comun de activitate wireless, vor transmite la început un broadcast pentru a obține informații de rutare apoi vor transmite un pachet de la un nod specificat către nodul desemnat base-station (nodul 0). | ||
- | |||
- | Ipoteză simplificatoare: Senzorii sunt sincronizați perfect. Senzorii vor trebui să alterneze între perioade active și perioade de conservare a energiei și vor putea face acest lucru simultan, fără alt ajutor din partea voastră. | ||
- | |||
- | === Cerințe === | ||
- | - Veți implementa alternanța între perioada de activitate și perioada de conservare de energie | ||
- | |||
- | - Implementarea se va face cu ajutorul timer-ului pe 32 de biți SymbolCounter. Urmăriți tutorialul de pe wiki | ||
- | |||
- | - În perioada inactivă atât microcontroller-ul cât și transceiver-ul wireless vor intra în starea Sleep. Urmăriți tutorialul | ||
- | |||
- | - Veți implementa transmiterea inițială a unui broadcast în toată rețeaua, ce va genera informații minime de rutare către nodul 0 | ||
- | |||
- | - Veți implementa metoda de transmitere a pachetelor normale către nodul 0, urmărind protocolul | ||
- | |||
- | - Veți trimite un pachet de test în frame-ul 10 de la nodul cu indexul 1. Încercați mai multe topologii (exemplu de topologii simple aveți aici) | ||
- | |||
- | === Descrierea protocolului === | ||
- | Protocolul presupune următorii pași: | ||
- | |||
- | - Broadcast inițial din partea Base-station-ului (nodul cu indicele 0). Toți senzorii rețin numărul de hop-uri până la base-station și next-hop până la base-station. Pentru a minimiza șansele ca mesajul de broadcast să fie pierdut, fiecare nod care primește un mesaj de broadcast (prima oară) va transmite în următoarele două frame-uri câte un broadcast. | ||
- | |||
- | - Orice pachet este direcționat înspre base-station (în cazul nostru simplificat). | ||
- | |||
- | * Pentru a transmite un pachet, un nod va trimite mai întâi un scurt pachet RTS (care conține destinația hop-ului curent). Trimiterea acestui pachet se face cu contention period, nodul va aștepta un interval random mărginit de un sfert din perioada activă (deci între 0 și ACTIVE_PERIOD/4) înainte de a trimite, și se abține dacă a fost transmis între timp alt pachet RTS. | ||
- | |||
- | * Nodul care este adresat ca next hop va răspunde cu un mesaj CTS | ||
- | |||
- | * Pachetul poate fi transmis în acea perioadă activă imediat după recepționarea CTS | ||
- | |||
- | === Schelet de cod === | ||
- | Scheletul de cod conține câteva definiții și funcții ce vă pot fi utile: | ||
- | |||
- | - Frame_t este structura ce definește un frame venit pe rețea | ||
- | |||
- | - node_address este indexul nodului | ||
- | |||
- | - initRF este o funcție de inițializare a transceiver-ului | ||
- | - setState este funcția ce setează o nouă stare | + | Folosiți scheletul de cod de {{:iothings:laboratoare:lab3_ex1.c.txt.txt|aici}} pentru a încerca un request către IFTTT direct de pe plăcuța ESP32. |
- | - initTimer inițializează timer-ul | + | === Ex. 2 === |
- | - ISR(SCNT_CMP1) și ISR(TRX24_RX_END) sunt cele două întreruperi pe care trebuie să le folosiți | + | Accesați exemplul cu senzorul DHT22 de umiditate/temperatură/presiune simulat in Wokwi prin exemplul de [[https://wokwi.com/projects/322410731508073042|aici]]. Detalii despre componenta DHT22 din simulator găsiți [[https://docs.wokwi.com/parts/wokwi-dht22|aici]] |
- | - se recomandă să folosiți cât mai puțin cod în întreruperi (urmărind modelul în care se amână diverse procesări pentru bucla din main, cum apare și în schelet) | + | Schimbați conexiunea firului de SDA al DHT22-ul de la PIN-ul de GPIO 15 la PIN-ul 21, ca în poza următoare, si ajustați codul la noua valoare a PIN-ului. |
- | === Testare === | + | {{:iothings:laboratoare:lab3_ex2.png?300|}} |
- | Pentru testare este necesar ca rețeaua să execute următorii pași | + | |
- | 1) Fiecare nod să aprindă led-ul roșu (PE4) în perioada activă și să-l stingă în celelalte momente. Implementarea folosește SymbolCounter. | + | === Ex. 3 === |
- | 2) Nodul 0 trebuie să trimită broadcast-ul, pentru ca fiecare nod să poată ști cum să ruteze pachete către el | + | Folosiți exemplul de conectare la reteaua WiFi din platforma Wokwi de [[https://docs.wokwi.com/guides/esp32-wifi|aici]]. Copiați apoi codul folosit la ex. 1 în aplicația de simulare a DHT22 pentru a citi temperatura și umiditatea și a le trimite prin Internet la platforma IFTTT. |
- | 3) Fiecare nod va retransmite de două ori mesajul de broadcast, în două perioade succesive (diametrul rețelei va fi limitat la 9 pentru ca mesajele de broadcast să înceteze înainte de transmiterea pachetelor efective) | + | ===== Resurse ===== |
- | 4) În timpul frame-ului 10, nodul cu indexul 1 va trimite un pachet conform protocolului către 0 | + | * https://randomnerdtutorials.com/esp32-esp8266-publish-sensor-readings-to-google-sheets/ |
+ | * https://docs.wokwi.com/guides/esp32 | ||
+ | * https://docs.wokwi.com/parts/wokwi-dht22 | ||
+ | * https://docs.wokwi.com/guides/esp32-wifi | ||
+ | * https://www.hackster.io/Hack-star-Arduino/how-to-use-wokwi-arduino-simulator-in-2022-what-is-wokwi-304e6b |