Langaton Tiedonsiirto¶
Osaamistavoitteet: Langattoman tiedonsiirron periaatteet ja toteutus SensorTag-laitteessa.
Materiaalia korjattu 09.11.2022: Important message about usage of network task.
Kurssilla käytämme 6LoWPAN-teknologiaa (IEEE 802.15.4.) langattomaan tiedonsiirron toteuttamisessa SensorTag-laitteiden välille. Tästä teknologiasta meidän ei tarvitse tietää yksityiskohtia, ainoastaan että se on tunnettu Esineiden Internetiä varten optimoitu protokollapino. 6LoWPAN-ratkaisut toimivat mm. samalla taajusaalueella kuin Wi-Fi, eli 2.4 GHz. Näinollen kantama ja yhteyksien toimivuus on siis samaa luokkaa.
Kirjasto¶
Tiedonsiirtoa varten on kurssin henkilökunta toteuttanut oman kirjaston, joka löytyy laboratorioharjoituksen projekti-aihion koodeista hakemistosta
wireless
. Otsikkotiedosto on comm_lib.h
ja itse kooditiedostoon comm_lib.c
ei ole tarpeen koskea. Nyt meitä kiinnostavat seuraavat funktiot:
- void Init6LoWPAN(void): Tämä on tiedonsiirron alustusfunktio, jota kutsumme ohjelman main-funktiossa.
- int8_t StartReceive6LoWPAN(void): Tämä funktio asettaa radion kuuntelutilaan. Jotta voisimme vastaanottaa viestejä, radion täytyy olla vastaanottotilassa. Myös jokaisen lähetetyn viestin jälkeen radio tulee asettaa vastaanottotilaan joskun haluamme vastaanottaa lisää viestejä.
- void Send6LoWPAN(uint16_t DestAddr, uint8_t *ptr_Payload, uint8_t u8_length): Tällä funktiolla lähetät viestin halutulle vastaanottajalle.
- DestAddr on vastaanottajan osoite. Se voi olla kolmentyyppinen.
- Määrittele tiedostoon
address.h
vakio IEEE80154_SERVER_ADDR joka on gatewayn/serverin nettiosoite0x1234
, jolle lähetämme mm. laboratorioharjoituksessa viestin. - Yleislähetysviesti (engl. broadcast), osoite 0xFFFF, jonka kaikki kuuluvuusalueella olevat laitteet näkevät
- Osoite voi olla myös mikä tahansa 16-bittinen luku, vaikkapa kaverin laitteen osoite (joka selviää kysymällä kaverilta).
- *ptr_Payload on osoitin viestimerkkijonoon. Merkkijonon luot itse esim.
sprintf
-funktiolla. - length on lähetettävän viestin pituus. Käytännössä ei kannata lähettää monen kymmenen merkin mittaisia viestejä kerralla. Sovitaan tässä ja nyt, että maksimipituus yksittäiselle viestille on 16 merkkiä (jotta annetaan tilaa muidenkin viesteille...)
- uint8_t GetRXFlag(void): Tällä funktiolla kysytään radiolta, onko viestejä odottamassa puskurissa
- Palautusarvo true, jos puskurissa on viesti
- Palautusarvo -1 jos jotain meni tiedonsiirrossa pieleen
- int8_t Receive6LoWPAN(uint16_t *senderAddr, char *payload, uint8_t maxLen): Lue viesti puskurista
- *senderAddr tämä osoitin kertoo meille lähettävän laitteen osoitteen
- *payload tähän merkkijono-osoittimeen tallentuu vastaanotettu viesti. Merkkijono täytyy tietenkin ensin itse esitellä omassa koodissa
- maxLen Maksimiarvo viestin pituudelle, ts. viestin merkkijonon pituus
- int8_t GetRSSI(void): Tällä funktiolla voi kysyä vastaanotetun signaalin voimakkuutta, RSSI. Tätä arvoa voi (teoriassa) käyttää mm. etäisyyden arviointiin. Tosin täällä reaalimaailmassa langattomien signaalien kulkutiet ovat varsin arvaamattomat..
Esimerkki¶
Tässä esimerkissä laite lähettää viestin serverille, kun käyttäjä painaa nappia, ja vastaanottaa viestejä jos niitä on.
#include <comm_lib.h>
// Lähetetään viesti napin painalluksesta
void buttonFxn(PIN_Handle handle, PIN_Id pinId) {
...
char payload[16] = "Hello world!";
Send6LoWPAN(IEEE80154_SERVER_ADDR, payload, strlen(payload));
...
// Hox! Radio aina takaisin vastaanottotilaan ao. funktiokutssulla
// Hox2! Tässä ei enää tarkisteta paluuarvoa.. tarkistus vain alustuksessa.
StartReceive6LoWPAN();
}
// Tiedonsiirtotaski
Void commTask(UArg arg0, UArg arg1) {
char payload[16]; // viestipuskuri
uint16_t senderAddr;
// Radio alustetaan vastaanottotilaan
int32_t result = StartReceive6LoWPAN();
if(result != true) {
System_abort("Wireless receive start failed");
}
// Vastaanotetaan viestejä loopissa
while (true) {
// HUOM! VIESTEJÄ EI SAA LÄHETTÄÄ TÄSSÄ SILMUKASSA
// Viestejä lähtee niin usein, että se tukkii laitteen radion ja
// kanavan kaikilta muilta samassa harjoituksissa olevilta!!
// jos true, viesti odottaa
if (GetRXFlag()) {
// Tyhjennetään puskuri (ettei sinne jäänyt edellisen viestin jämiä)
memset(payload,0,16);
// Luetaan viesti puskuriin payload
Receive6LoWPAN(&senderAddr, payload, 16);
// Tulostetaan vastaanotettu viesti konsoli-ikkunaan
System_printf(payload);
System_flush();
}
}//HUOM NO TASK_SLEEP
}
Int main(void) {
...
// Tiedonsiirto alustetaan
// Ilman tätä funktiota viestintä ei toimi ohjelmasta
Init6LoWPAN();
/* Communication Task */
Task_Params_init(&commTaskParams);
commTaskParams.stackSize = COMMSTACKSIZE;
commTaskParams.stack = &commTaskStack;
commTaskParams.priority = 1; // Important to set the priority to 1
commTask = Task_create(commTaskFxn, &commTaskParams, NULL);
if (commTask == NULL) {
System_abort("Task create failed!");
}
...
}
Tiedonsiirto alustetaan funktiolla
Init6LoWPAN
. Laite alustetaan viestien vastaanottotilaan funktiolla
StartReceive6LoWPAN
. Tämä vaaditaan, jotta laite ylipäänsä vastaanottaisi mitään viestejä! Jokaisen viestilähetyksen jälkeen laite on taas asetettava vastaanottotilaan. Viestit lähetetään funktiolla
Send6LoWPAN
, joka ottaa parametrikseen vastaanottajan osoitteen. Tässä osoite on 0xFFFF
, joka tarkoittaa ns. broadcast-viestiä, joka on kaikki kuuluvuusalueella olevien luettavissa. Laboratorioharjoituksessa tulemme asettamaan omalle laitteelle sen oman osoitteen (muotoa 0xnnnn), johon muut voivat olla yhteydessä (sovitusti!). Toinen funktion parametri on viesti merkkijonona ja kolmas parametri sen pituus. Viestejä vastaanotetaan
commTask
:ssa jos viestejä on, eli funktiokutsu GetRXFlag
palauttaa true. Funktio Receive6LoWPAN
ottaa parametrikseen kokonaislukumuuttujan, johon se palauttaa viestin lähettäjän osoitteen senderAddr
, sitten merkkijono-osoittimen vastaanottopuskuriksi payload
, jonne se kirjoittaa saadun viesti ja viestin maksimipituuden. Käytetään kurssilla maksimipituutta 80
merkkiä (ts. merkkijonotaulukon pituus). Funktio palauttaa arvon -1
, jos vastaanotossa meni jotain pieleen. Huomatkaa
string.h
-kirjaston funktion memset-käyttö. Tämä funktio asettaa annetun muuttujan (tässä merkkijono) kaikki arvot arvoon keskimmäinen parametrii joka tässä on 0
. Tässä nyt siis funktiolla tyhjennetään merkkijono. HOX! Viestejä ei saa lähettää toistorakenteessa. Tämä siksi että laite kykenee hyvinkin lähettämään kymmeniä viestejä sekunnissa jotka tukkivat harjoituksen käytössä olevan tiedonsiirtokanavan. Usein tämän jälkeen muiden opiskelijoiden SensorTagit joudutaan jopa resetoimaan. Kiusallista. Eli, tarkistakaa aina koodimuutosten jälkeen, ettei viestinlähetys lipsahtanut silmukan sisään. Tästä syystä viestien lähetyksen testaukset aina painonapin toiminnallisuutena.
HOX!
- It is very important that:
- You do not use
Task_sleep
in the task that controls the network (where you call first time StartReceive6LowPan and you callgetRXFlag()
. - You give a lower priority to the network task: Rest of the tasks should have priority 2 and network task priority 1.
Lopuksi¶
Tervetuloa langattoman viestinnän maailmaan Esineiden Internetin -ympäristössä!
Laboratorioharjoituksen jälkeen osaat jo käyttää SensorTagia reaalimaailman sovelluksissa: kerätä sensoridataa omasta toiminnasta ja ympäristöstä ja viestitellä muiden laitteiden ja taustajärjestelmien kanssa. Pienen koon ja vähäisen virrankulutuksen vuoksi SensorTagia patterilla varustettuna voi esimerkiksi kuljettaa rintataskussa mukanaan.
Anna palautetta
Kommentteja materiaalista?