Jste zde

IQRF Prakticky III

Dostáváte se ke třetímu dílu seriálu o modulech IQRF. Do této chvíle jsme komunikovali pouze mezi dvěma body ? prakticky byly také příklady použitelné pro jeden vysílač a více přijímačů. V praxi se ale vyskytuje mnoho komplikovanějších systémů. Jak se s nimi vypořádat, o tom je dnešní díl.

Úvod do jednoduchých bezdrátových sítí s obvody IQRF

Z hlediska topologie sítí rozlišujeme několik variant:

  • Point to Point – to je varianta, kterou jsme si již vyzkoušeli v předchozích dvou dílech. V této variantě komunikují dva uzly (nody) mezi sebou bez nutnosti řízení komunikace a využití tzv. koordinátora, který by síť řídil.
  • Point to Multipoint – obdobná varinta k předchozí jen s tím rozdílem, že komunikujících prvků je více, prvky jsou si rovny, mají stejná práva ke komunikaci, ale také stejné povinnosti, co se týče režie sítě. Ani v tomto případě není v síti obsažen koordinátor, který by síť řídil.
  • Hvězdicová síť (star) – v síti je už obsažen centrální subjekt – koordinátor, jednotlivé uzly sítě mohou komunikovat pouze s centrálním prvkem nebo s ostatními uzly prostřednictvím koordinátora. Síť lze dále rozšiřovat o další prvky, tzv. routery, které umožňují propojení vzdálenějších uzlů (nodů) s centrálním prvkem. (extended star)
  • MESH sítě – jedná se o druh sítě s jedním koordinátorem a mnoha uzly (nody), kdy nejsou předem nijak stanoveny vazby mezi jednotlivými uzly. V této síti je možná komunikace i mezi uzly, které na sebe přímo „nevidí“, a to prostřednictvím mezilehlých uzlů schopných tzv. routingu. Routingu je schopný každý uzel, a tak je možné, aby zpráva z jednoho konce sítě „přeskákala“ na druhý. Tím lze podstatně zvětšit vzdálenost, na kterou jsme schopni komunikovat. Každý uzel má navíc možnost stát se koordinátorem další vlastní sítě. To nám dává možnost celou síť strukturovat do logických celků. Tento princip je často používán v armádní komunikaci například na bojišti, kde zajišťuje situace, kde může dojít k výpadku (zničení) některého z uzlů.

mesh.jpg

Samozřejmě existuje mnoho dalších variant sítí. V tomto článku se však budeme zabývat právě MESH sítěmi a to konkrétně IQMESH, která má svá specifika oproti obecné formulaci MESH sítí. V IQMESH se podsítě nazývají clustery. Za splnění určitých podmínek můžeme sestavit síť s téměř neomezeným počtem clusterů a tím také téměř neomezeným dosahem. To je možné díky řetězení clusterů, které nám obvody IQRF dovolují.

Každá síť IQMESH vyžaduje jednoho koordinátora. Bez něj není možné MESH síť realizovat. Spolu s koordinátorem je možné do sítě zařadit dalších 239 uzlů (nodů). A to stále v jenom clusteru. Přidáním dalšího clusteru nám přibude dalších 239 uzlů (které již však musí komunikovat prostřednictvím svého koordinátora).

Jak už bylo výše uvedeno, každý uzel i koordinátor může sloužit jako router. To znamená, že v jednom clusteru může být až 240 routerů. Omezen je však počet přeskoků, které může routovaný paket vykonat. Těch je maximálně osm při současném maximálním dosahu jednoho modulu.

Podpora IQMESH operačním systéme IQRF

Operační systém obvodů IQRF obsahuje sadu funkcí a speciálních registrů podporujících právě systém IQMESH. Jedná se v první řadě o funkce pro přijetí uzlu do sítě (na straně koordinátora i potencionálního uzlu), a také funkce pro zrušení „členství“ v síti. Funkce pro odesílání a příjem paketů zůstávají stejné jako pro komunikaci P2P. Přibývají nám pouze informace o odesílateli a příjemci. Vzhledem k tomu, jak rychle a živelně se systém rozvíjí, doporučuji pravidelně sledovat stránky věnované obvodům IQRF.

Funkce pro práci v síti:

  • setNetworkOne() – již výše bylo uvedeno, že moduly mohou pracovat ve dvou režimech. Jako koordinátor a jako uzel (node). Zavoláním funkce setNetworkOne() se přepne modul do práce v síti, kde je koordinátorem. Tuto funkci je vhodné volat před odesláním zprávy. Při příjmu je automaticky přepnut modul do té sítě, ze které je zpráva přijata.
  • setNetworkTwo() – funkce opačná k předchozí, přepne do té sítě, kde je uzlem (node)
  • setCoordinatorMode() – přepne do režimu, kdy se modul chová jako koordinátor
  • setNodeMode() – přepne do režimu, kdy se modul chová jako uzel (node)
  • setNetworkFilteringOn()- přijímá zprávy pouze z aktuálně přepnuté sítě (souvisí s funkcemi setNetworkOne() a setNetworkTwo().
  • setNetworkFilteringOff()- vypne filtrování zpráv z neaktivní sítě
  • getNetworkParams() – vrací informace o síti. Pro nás je důležitý parametr vracený v proměnné param2, v něm je totiž vracena adresa uzlu v síti.

Dále jsou zde funkce pro routing, setRoutingOn() a setRoutingOff(), ty však v dnešním díle nebudeme využívat a jejich popis si uvedeme později.

Funkce pro bondování se liší podle funkce modulu v síti, zda je koordinátorem nebo uzlem. Pokud se jedná o koordinátora, máme k dispozici několik funkcní. Nás dnes bude zajímat jediná:

  • bondNewNode() – tato funkce nejprve nastaví režim koordinátor (v tuto chvíli se nacházíme ve vlastním clusteru (NetworkOne), dále po dobu cca 8 sekund přijímá požadavky uzlů pro přibudování do clusteru. Funkce vrací log „1“ v případě přibudování nového uzlu, resp. Log „0“ v případě, že se žádný nový uzel nepodařilo přibudovat.

V případě uzlu využijeme více funkcí:

  • bondRequest() – i tato funkce automaticky přepne modul IQRF, ovšem do režimu uzlu (node). Dále žádá dostupné koordinátory o přijetí do clusteru. Je-li žádosti vyhověno, je uzlu zaslána jeho adresa v síti a některé další informace. Opět i zde vrací funkce log „0“ nebo „1“ podle úspěšnosti.
  • removeBond()- funkce vymaže informaci o spárování, ale ponechá si v paměti adresu, která mu byla při posledním párování přidělena. Při dalším párování se o ní pokusí zažádat. Chceme-li tuto adresu nastálo vymazat, použijeme následně funkci wipeBondNR()
  • amIBonded()- zjistí, zda je přibudován v nějakém clusteru. Pokud no, vrátí log „1“.

Se znalostí těchto funkcí se můžeme směle pustit do vytvoření našeho prvního příkladu využívajícího síťovou komunikaci. Začneme nejprve uzlem. Upozorňuji, že následující příklady jsou zjednodušením ukázkových příkladů uvedených na webu věnovaném systému IQRF.

První úkol, který před námi stojí, je zjištění, zda je náš modul již přibudován do některého z clusterů, v případě, že není, takové přibudování zajistit. To provede následující část kódu:

    setNetworkTwo();          // nastavi cluster, kde jsem uzel (node)
    while (!amIBonded())      // zjisti zda jsem pribondovan
    {
        pulsingLED();         // pokud ne, vesele si blikam
        bondRequest();        // a snazim se pribondovat
        clrwdt();             // nezapominam na WTD
        stopLED();            
        clrwdt();
        waitDelay(100);
    }

Je-li modul přibudován, neproběhne cyklus ani jednou, program se nám tedy o výraznou dobu nepozdrží. V opačném případě bude „potenciální uzel“ pravidelně blikat vysílat žádosti o přibudování. Objeví-li se v blízkosti koordinátor, který v tu samou chvíli přijímá požadavky, je modulu předána adresa v síti a množství dalších informací (kódování apod.) a uzel je zařazen do clusteru.

Dále již pokračuje hlavní smyčka programu obsahující dvě důležité podmínky:

¨    while (1)                 // pokud jsem pribondovan...
    {
      clrwdt();               // opet nezapominam na WDT           
      if (RFRXpacket())       // sem tam se podivam, zda mi neprisel paket
      {
         clrwdt();
         pulseLED();          // pokud ani, dat to na vedomi
      }       
      if (buttonPressed)      // muze se stat ze nechci byt pribondovan   
      {                       // a tak stisknu tlačítko
         setNetworkTwo();     // nasatavim se do clusteru kde jsem uzlem
         removeBond();        // vymazu informaci o sparovani
         wipeBondNR();        // a vymazu adresu - co kdyz budu chtit jinam
         reset();             // a oblibeny vseopravny SW reset
      }
    }

První podmínka řeší stav, kdy nám přišel paket. Neřeší co je to za typ paketu, ani co je jeho obsahem. Nezasílá žádnou odpověď s uživatelskými daty. To bude naším úkolem příště. Jeho přijetí indikuje bliknutím LED, což nám v tomto jednoduchém příkladě stačí. Druhá podmínka pak řeší ten případ, kdy chceme modul použít v jiném clusteru. Pomocí dvojice funkcí removeBond() a wipeBondNR() pak vymaže z eeprom informace o přibudování do clusteru. Následuje reset modulu, což nám umožní přibondovat modul do jiného clusteru (začátek aplikace). Celý kód je možné stáhnout na konci článku. Už tento jednoduchý příklad by bylo možné vyzkoušet s hotovým kódem pro koordinátora uvedeným na webu věnovaném IQRF.

My si však vytvoříme vlastní a částečně zjednodušený. Nebudeme zde oproti originální verzi řešit routování, ani zpracování odpovědi, kterou stejně na uzlu nevysíláme. Přidáme si však vymazání všech uzlů a tím si vyzkoušíme, jaký vliv tato funkce má. Protože jako „základnu“ pro koordinátora budeme používat programovací a ladící desku CK-USB-02, můžeme si dovolit použít pro ovládání rozhranní SPI. Na začátku aplikace tedy dáme odeslat po SPI do PC řetězec obsahující informaci o tom, jakou aplikaci máme spuštěnou, a spolu s tím vypíšeme také seznam dostupných příkazů:

    enableSPI();          // povolim si SPI
    appInfo();            // prekopiruji si aplikacni informace BufferINFO
    copyBufferINFO2COM(); // odtud si je presunu do bufferu SPI
    startSPI(32);         // odeslu do terminalu (seznam prikazu)

řetězec máme uložen v eeprom:

#pragma packedCdataStrings 0
#pragma cdata[__EEAPPINFO] =  "Prikaz: b mX r               "

Dále již pokračuje hlavní smyčka programu, ve které samozřejmě nesmíme zapomínat resetovat WDT. Při každém průchodu kontrolujeme stav SPI, zda nám nepřišla nějaká data. K tomu slouží funkce getStatusSPI() Příznak _SPIRX je touto funkcí nastaven vždy, pokud máme přijatá data. Zároveň je nastavován příznak _SPICRCok, který nám říká, zda byl správně kontrolní součet. Přes SPI totiž budeme našemu koordinátorovi předávat příkazy k přibondování nového uzlu, odeslání dat na konkrétní uzel nebo smazání všech uzlů v clusteru.

Máme-li data z SPI a je-li kontrolní součet v pořádku, můžeme začít zpracovávat příkazy. Celkem máme 3 a postačí nám tedy jednoduchý switch:

            switch (bufferCOM[0])    // zjistuji jaky ze to prisel prikaz
            {
               case 'm':             // prikaz "m" ? - odesilam požadavek
                                     // na modul
               case 'b':             // pozadavek na bondovani
               case 'r':             // pozadavek na vymazani vsech uzlu
            }

Pro odeslání zprávy určenému uzlu použijeme následující kód:

                    RX = bufferCOM[1] - '0';
                    // cilem (RX) je modul uvedeny po prikazu "m"...
                    DLEN = 0;
                    // delka dat je nulova - poslu prazdny paket
                    setNetworkOne();
                    // tento cluster mi patri - jsem koordinátorem
                    RFTXpacket();        
                    // odeslu sestaveny (prazdny) paket
                    pulseLED();
                    //a bliknu si, aby bylo videt, ze neco delam
                    clrwdt();
                    continue;

Pokud bychom chtěli odeslat v paketu data, stačilo by naplnit bufferRF nějakými smysluplnými daty a nastavit DLEN (délku paketu) na požadovanou velikost.

Pro bondování se příklad nijak neliší od uvedeného na webu IQRF:

                case 'b':                   // prijat prikaz na bondovani
                    pulsingLED();           // dam vedet, ze bonduji
                    if (bondNewNode())      // cca 8s se snazim bondovat
                    {
                        pomj = param2;      // uspesne – ulozim si adresu
                        bufferCOM[0] = 'O'; // hlaseni o uspesnosti
                        bufferCOM[1] = 'K'; // ze se to povedlo
                        bufferCOM[2] = ':';
                        bufferCOM[3] = ' ';
                        bufferCOM[4] = param2 + '0';
                    }
                    else                    // pokud je proces neuspesny
                    {                       // dam to opet vedet
                        bufferCOM[0] = 'E';
                        bufferCOM[1] = 'R';
                        bufferCOM[2] = 'R';
                        bufferCOM[3] = 'O';
                        bufferCOM[4] = 'R';
                    }
                    stopLED();              // vypnu indikaci bondovani
                    startSPI(5);            // odeslu zpravu o stavu
                    continue;

V našem příkladě však přibyl nový příkaz. Můžeme jím vymazat tabulku o připojených uzlech. Po jeho použití doporučuji modul resetovat:

                case 'r':
                    clearAllBonds();
                    bufferCOM[0] = 'E';
                    bufferCOM[1] = 'R';
                    bufferCOM[2] = 'A';
                    bufferCOM[3] = 'S';
                    bufferCOM[4] = 'E';
                    bufferCOM[5] = 'D';
                    startSPI(6);
                    continue;

Zajímavým je kus kódu restartující SPI. Pokud totiž příjdou do modulu data sběrnicí SPI, mohou nastat dva případy. Kontrolní součet je správně – v tom případě je masterovi odeslán kód 0x3F – buffer plný, CRC je OK. Pokud však příjde zpráva se špatným CRC, je nutné SPI restartovat a to zavoláním funkce startSPI(0);. Pokud by se tak nestalo, odesílal by modul masterovi stále status, že kontrolní součet je špatný (z e-mailu se zástupcem Microriscu). SPI bude podrobněji rozebráno v některém z příštích dílů. Jeho popis je ale možné shlédnout v nově vydaném manuálu SPI na webu věnovaném modulům IQRF.

DOWNLOAD & Odkazy

IQRF - Complete platform for RF connectivity and simple way to smarter wireless solutions
                      ... nejenom moduly, ale vse, co je treba k vytvoreni chytrejsich bezdratovych reseni

 
Hodnocení článku: 

Komentáře