====== Comunicația radio în Rețele de Senzori Wireless ====== ===== Sistemul de senzori de pe nodul Sparrow v3 ===== Nodul senzorial Sparrow este echipat cu trei tipuri de senzori: temperatură, umiditate și luminozitate ambientală. Senzorul de luminozitate este analogic și furnizează o tensiune direct proporțională cu nivelul iluminării ambientale. Această tensiune poate fi citită de către microcontrollerul ATMega128RFA1 de pe portul F, pinul 2 (PF2). Tot pe portul F, pinul PF0 puteți citi și tensiunea de alimentare a nodului senzorial. Valoarea tensiunii citite este divizată cu 2, așa că va trebui să o adjustați. Senzorul de umiditate și temperatură este de tipul [[http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_SHT21_Datasheet_V3.pdf | SHT21]] și este conectat la interfața I2C a microcontroller-ului. Descărcați scheletul de cod de {{:wiki:tema1.zip| aici}} și completați TODO-urile astfel încât să citiți date de la toate tipurile de senzori. ===== Stări de low power pentru Sparrow v3 ===== Dat fiind faptul că rezervele de energie din bateria proprie sunt limitate, nodul senzorial poate fi programat să ruleze într-o stare de consum redus sau sleep pentru a minimiza consumul de energie. Aceasta poate fi realizată prin dezactivarea tuturor senzorilor externi (bitul PE7 pe 0 logic) apoi trecerea microcontroller-ului însuși în sleep. Descărcați scheletul de cod de {{:wiki:tema2.zip| aici}} și completați TODO-urile astfel încât să citiți date de la toate tipurile de senzori la intervale regulate de timp, apoi să intrați în sleep. ===== Transceiver-ul de pe ATMega128RFA1 ===== Transceiver-ul de pe microcontroller-ul ATMega128RFA1 permite acestuia să transmită în diferite benzi din 2.4GHz. Permite viteze de transmisie de 250kbps, 1Mbps și 2 Mbps. Are două moduri de funcționare, Basic și Extended. Modul Extended include multe funcționalități prevăzute de obicei în nivelele de acces la mediu. În acest caz, funcționalitățile sunt cele necesare pentru implementarea IEEE 802.15.4 ==== Interfața cu microcontroller-ul ==== Interfața cu microcontroller-ul este necesară pentru a comanda transceiver-ul din program și pentru a obține/trimite date către acesta. În cazul RFA1, avantajul major de a avea transceiver-ul și microcontroller-ul pe același chip înseamnă că se pot face transferuri foarte rapide între acestea. RFA1 pune la dispoziție următoarea interfață: * Regiștrii de comandă: Sunt tratați ca orice alt registru I/O și sunt accesați la fel de rapid. Sunt folosiți pentru a trimite comenzi către transceiver sau a obține informații punctuale despre funcționarea acestuia. Exemple sunt: ''TRX_STATE'', ''TRX_STATUS'', ''PHY_RSSI''. Folosirea acestor regiștri este posibilă doar atunci când ceasul transceiver-ului nu este oprit * Frame buffer: Este o zonă de memorie de 128 bytes în care se recepționează/din care se transmit pachete. Este accesibilă din microcontroller tot ca o zonă de regiștri I/O de 128bytes, începutul este ''TRXFBST'' și sfârșitul este ''TRXFBEND''. Scrierea/Citirea în/din framebuffer va dura întotdeauna un ciclu de ceas, adică avem maxim 128Mbps! **Atenție!** Scrierea și citirea în/din buffer se face în mod diferit, conform tabelului de mai jos: ^ **Operații pe frame buffer** ||| ^Operație ^ Date ^ Lungime | | Scriere | TRXFBST+1 .. TRXFBEND | TRXFBST | | Citire | TRXFBST .. TRXFBEND-1| TST_RX_LENGTH | * Registrul ''TRXPR'': Moștenire din timpurile în care microcontroller-ul și transceiver-ul erau în chip-uri separate, ''TRXPR'' este registrul care deține două flag-uri (în trecut doi pini) care afectează transceiver-ul chiar dacă acesta este în sleep. * Bit-ul TRXRST Care poate reseta oricând transceiver-ul * Bit-ul SLPTR, care controlează atât starea de sleep a transceiver-ului cât și startul transmisiei unui pachet * Întreruperi: Transceiver-ul poate fi configurat să genereze mai multe întreruperi microcontroller-ului, dintre care amintim: * TRX24_RX_START: A început recepția unui pachet. Se poate începe imediat citirea frame buffer-ului * TRX24_TX_END: Semnalează sfârșitul transmisiei ==== Mașina de stări ==== Transceiver-ul de pe RFA1 folosește o mașină de stări pentru a reșine care este modul de operare curent (dacă transmite, recepționează, dacă este în standby, dacă se pregătește să transmită, etc.) Stările care apar sunt: * **SLEEP** Transceiver-ul este în stare de hibernare, nu consumă curent * **RESET** Transceiver-ul tocmai a fost restartat * **TRX_OFF** Starea de standby, în care nu se ascultă mediul pentru pachete * **RX_ON** Starea în care se ascultă mediul * **BUSY_RX** Se recepționează un pachet * **PLL_ON** Starea în care componenta de transmisie este activă și pregătită * **BUSY_TX** Se transmite un pachet Tranzițiile între stări sunt fie declanșate de evenimente exterioare, și atunci sunt subliniate cu verde, fie prin comandă de la microcontroller (și atunci sunt fie colorate cu albastru, fie cu roșu). {{ :wiki:rfa1_basic_states.png?nolink&900 |}} Regiștrii care se ocupă de controlul și observarea mașinii de stări sunt ''TRX_STATE'' și ''TRX_STATUS''. ''TRX_STATE'' conține biții ce comandă tranzițiile dintre stări (omitem stările ce nu le vom folosi în cadrul laboratorului, pentru o listă completă consultați datasheet-ul): ^ ''TRX_STATE'': | TRAC_STATUS2..0 | **TRX_CMD4..0** | ^ Biți ^ Valoare ^ Înțeles ^ Macro GCC ^ Detalii | | ''TRX_CMD'' | ''0x00'' | NOP | | | | ::: | ''0x02'' | TX_START | CMD_TX_START | Comandă ce pornește transmiterea pachetelor, similar cu SLPTR | | ::: | ''0x03'' | FORCE_TRX_OFF | CMD_FORCE_TRX_OFF | Transceiver-ul trece imediat în TRX_OFF (delay depinde de starea curentă) | | ::: | ''0x04'' | FORCE_PLL_ON | CMD_FORCE_PLL_ON | Similar, forțează trecerea în starea ''PLL_ON'' | | ::: | ''0x06'' | RX_ON | CMD_RX_ON | Trecerea în ''RX_ON'' | | ::: | ''0x08'' | TRX_OFF | CMD_TRX_OFF | Trecerea în ''TRX_OFF'', ce presupune și terminarea activităților curente | | ::: | ''0x09'' | PLL_ON | CMD_PLL_ON | Trecerea în starea din care se poate transmite | ^ ''TRX_STATUS'': | CCA_DONE | CCA_STATUS | TST_STATUS | **TRX_STATUS4..0** | ^ Biți ^ Valoare ^ Înțeles ^ Detalii | | ''TRX_STATUS'' | ''0x01'' | BUSY_RX | Transceiver-ul este ocupat cu primirea unui pachet | | ::: | ''0x02'' | BUSY_TX | Transceiver-ul trimite un pachet | | ::: | ''0x06'' | RX_ON | Starea curentă este ''RX_ON''| | ::: | ''0x08'' | TRX_OFF | Starea curentă este ''TRX_OFF''| | ::: | ''0x09'' | PLL_ON | Starea curentă este ''PLL_ON''| | ::: | ''0x0F'' | SLEEP | Transceiver-ul este în starea de ''SLEEP''| | ::: | ''0x1F'' | STATE_TRANSITION_IN_PROGRESS | Mașina de stări execută o tranziție | Accesul la acești biți se poate face la fel ca la orice registru I/O. TRX_STATE &= 0xe0; // masca corespunzătoare biților TRAC_STATUS2..0 TRX_STATE |= CMD_FORCE_TRX_OFF; Dat fiind că biții TRAC_STATUS2..0 sunt read-only, putem prescurta la: TRX_STATE = CMD_FORCE_TRX_OFF; Folosind structuri: TRX_STATE_struct.TRX_CMD = CMD_FORCE_TRX_OFF; ==== Procedura de tranziție între stări ==== - Se setează starea dorită în ''TRX_STATE'' - Se așteaptă până când ''TRX_STATUS'' nu mai contine TRANSITION_IN_PROGRESS in campul de biti **TRX_STATUS4..0** ==== Procedura de transmisie a unui pachet ==== - Se intră în starea ''PLL_ON''. Acest lucru garantează că nu se va începe recepția unui pachet peste frame buffer între momentul în care scriem în buffer și momentul în care pornim transmisia - Copiem datele în buffer * Primul octet reprezintă dimensiunea pachetului * Urmează pachetul, maxim 127 bytes - Pornim transmisia (prin bit-ul ''SLPTR'' sau prin comanda ''TX_START'') ==== Procedura de recepție a unui pachet ==== - Se intră în starea ''RX_ON'' - Se primește întreruperea ''RX_START'' sau ''RX_END'' - Se începe citirea frame-buffer-ului * Pachetul este în frame-buffer începând cu primul octet * Dimensiunea este în ''TST_RX_LENGTH'' ===== Particularități Avrora ===== Pentru a cunoaște identificatorului nodului din program, trebuie declarată variabila ''node_address'' în felul următor (datorită unui defect-?- de compilator prima variabilă declarată nu ajunge în .data chiar dacă se cere explicit): uint8_t nod1_address __attribute__((section(".data"))) = 0; uint8_t node_address __attribute__((section(".data"))) = 0; Nodurile își vor avea trecut identificatorul în ''node_address'' dacă se rulează avrora cu opțiunea ''update-node-id=true''. Această funcționalitate este asemănătoare cu citirea din EEPROM la un nod real. ===== Exerciții ===== Folosiți scheletul de laborator - {{:wiki:schelet_labwsn2.zip|}}. - Transmiteți un pachet de la nodul 1 la nodul 0 * Hint: Utilizați macro-ul TRX_FRAME_BUFFER * Hint2: Ultimii doi octeți dintr-o transmisie reprezintă un CRC adăugat/verificat automat de transceiver * verificarea se face cu flag-ul ''RX_CRC_VALID'' din registrul ''PHY_RSSI'' * dezactivarea CRC-ului automat se face din registrul ''TRX_CTRL_1'', flag-ul ''TX_AUTO_CRC_ON'' - În rețeaua cu 4 noduri cu topologia dată în fișierul .top, transmiteți un pachet de la nodul 1 la nodul 0 * Hint: Pentru a ajunge de la 1 la 0, un pachet trebuie să treacă prin nodurile intermediare 2 si 3