vineri, 15 aprilie 2016

mini DX Cluster cu ESP8266 ( partea 1 )

                De curind am descoperit pe internet un modul WiFi gestionat de un microcontroler Tensilica capabil de conexiuni TCP/IP, construit de o firma chineza Espressif. Acest modul se cheama ESP8266 si pina la momentul actual a fost construit in mai multe versiuni. Nu voi intra foarte mult in detalii legate de capabilitatile acestui modul deoarece ele sint descrise detaliat pe pagina producatorului cit si pe o multime de pagini din internet. Acest modul poate fi programat de utilizatori folosind diferite limbaje de programare, dintre cele mai utilizate fiind Lua, C++ si Arduino, dar si comenzile 'AT', atunci cind folositi un microcontroler extern. Din nefericire pentru mine niciunul dintre aceste limbaje nu imi este bine cunoscut, dar uitindu-ma peste sursele diferitelor aplicatii publicate pe internet, Lua se apropie cel mai bine de cunostintele mele in programare. Asa ca de voie, de nevoie, m-am apucat sa invat din mers... LUA. Pentru a scrie in Lua este nevoie ca in  modul sa fie incarcat un interpretor, respectiv firmware-ul NodeMCU. Va sfatuiesc sa intrati pe pagina oficiala NodeMCU si sa va uitati pe diferitele programe date ca exemplu, mai mult ca sigur o sa ramineti pe ginduri.
                Deoarece marea majoritate a modulelor sint construite minimal, pentru aplicatii simple unde este nevoie decit de alimentare si citeva conexiuni cu exteriorul, eu am optat pentru o placa de dezvoltare. Principalele motive sint: 
- usor de programat deoarece contine interfata USB - Serial
- alimentarea se face atit prin intermediul portului micro USB cit si prin pini dedicati. Deobicei o alimentez din USB-ul calculatorului, iar cind sint plecat folosesc incarcatorul telefonului mobil
- port serial prin pini dedicati pentru conexiuni cu exteriorul
- si nu in ultimul rind, o gramada de porturi GPIO
               Placa de dezvoltare pe care am cumparat-o este 'teoretic' construita de firma LoLin, am gasit-o pe un site de vinzari - cumparari din tara noastra.


Softul folosit de mine pentru incarcarea programului scris in Lua este ESP8266 LuaLoader.


                Programul in sine redirectioneaza toate spoturile transmise de un DX Cluster ( DXCL ) catre un client TCP, conectat de aceasta data la serverul ESP8266. Nu am incercat conectarea si retransmiterea in acelasi timp a spoturilor din doua sau mai multe clustere, dar o voi incerca pe viitor. Ceea ce este inedit la aceasta aplicatie, este faptul ca inafara de alimentare si citeva setari in routerul de internet, avem cel mai mic si mai simplu server si client TCP. Ca facilitati, doar folosind clientul TCP al DXCL, se pot implementa in acesta filtrarea spoturilor. De exemplu spoturile care anunta propagarea Es sporadic sau Aurora, pot fi filtrate si retransmise catre un client. Alta posibila aplicatie ar putea fi anuntarea clientului prin trimiterea unui SMS sau email, a unui spot anume. Si posibiltatile mai pot fi multe altele. 
               Simplitatea presupune si dezavantaje. Un dezavantaj observat de mine este faptul ca serverul nu poate gestiona mai mult de un client. In momentul conectarii celui de al doilea client, toate spoturile sint redirectionate catre acesta, primul client nemai receptionind nimic. Probabil functioneaza si aceasta, sau poate nu, ramine de studiat pe viitor.
                O problema pentru mine a fost extragerea spotului receptionat de catre clientul DXCL si retransmiterea lui catre server. Desii am incercat mai multe variante de a reimprospata datele din server cu cele din clientul DXCL, nu am avut niciun rezultat multumitor. Singura solutie, care marturisesc ca nu mi-a placut, a fost sa fac refresh cu ajutorul unui timer setat arbitrar de mine la 100 msec. Un dezavantaj ar fi ca daca in decursul a 100 msec vin doua spoturi, unul dintre ele se va pierde sigur. O alta solutie incercata de mine, cu sanse foarte mari de reusita era sa transmit datele pe iesirea portului serial si printr-o bucla, sa le reintroduc pe intrarea aceluiasi port. Functioneaza, chiar foarte bine, dar din cauza logo-ului din restartul modulului, NodeMCU 0.9.6 build 20150704  powered by Lua 5.1.4, acesta nu poate restarta corect programul, facind restart continuu. Problema se putea rezolva cu ajutorul unei porti exterioare comandata intirziat de un registru GPIO, dar atunci proiectul isi pierde din farmecul simplicitatii lui. Pe partea de client, spoturile transmise de serverul ESP8266, pot fi vizualizate cu ajutorul unui client TCP. Pe smartphone am folosit aplicatia TCP Client pe care o descarcati din Google Store, iar in Windows am folosit aplicatia Hercules Setup Utility.
Iata in continuare programul meu:

---------------------------------------------------------------
--                         v1.4                              --
---------------------------------------------------------------
 -- setez id wireless si parola
 ssid = "YO7FWS"
 pass = "********"

 -- configurez wifi in client mode
 wifi.setmode(wifi.STATION)

 -- numai pentru debug, afisez modul
 --print('set mode=STATION (mode='..wifi.getmode()..')\n')

 -- setez SSID si parola wifi
 wifi.sta.config(ssid,pass)

 -- ma conectez wifi
 wifi.sta.connect()

 -- creez o conexiunea client la un dx cluster
 client = net.createConnection(net.TCP, false)

 -- creez un server viitor dx cluster
 server = net.createServer(net.TCP)

 -- variabila care memoreaza portul din routerul meu
 -- unde poate fi accesat clusterul
 port = 9876

 -- variabile care preia spotul de la clientul dx cluster
 -- si il transmite viitorului server dx cluster
 spot = ''

 -- variabila care memoreaza ultimul spot retransmis
 mem = spot

 -- atunci cind clientul a receptionat un mesaj sau spot
 client:on("receive", function(sck, c) 
    -- daca cere sa ma loghez atunci transmit indicativul
    if c == 'login: ' then client:send("yo7fws\n") end  
    -- extrag spotul sau mesajul pentru a fi retransmis 
    spot = c
 end )

 -- atunci cind la server s-a conectat un client 
 server:listen(port, function(server)
    -- la fiecre conectare a unui client afisez un logo
    server:send("Bine ati venit pe clusterul lui YO7FWS\n\n")
    -- nu-mi place asta, dar n-am gasit nicio solutie
    -- execut odata la 100 msec
    tmr.alarm(0, 100, 1, function()
        -- daca spotul este diferit de ceea ce a fost 
        -- retransmis anterior, atunci
        if mem ~= spot then
            -- numai pentru debug, afisez spotul
            --print(spot) 
            -- transmit clientului spotul
            server:send(spot)
            -- memorez acest spot pentru 
            -- a nu-l retransmite dinou
            mem = spot
        end
    end )
 end)

 -- ma conectez ca client la dx clusterul lui N2YO
 client:connect(7300,"dxc.n2yo.net")
---------------------------------------------------------------
--                     YO7FWS - APR 2016                     --
---------------------------------------------------------------

                Proiectul descris aici nu este mare lucru. Este o solutie din alte multe altele. Un simplu smartphone face mult mai mult decit aici. Dar placerea este cu mult mai mare cind am gasit eu rezultatul la provocarea: ia sa vedem, eu pot ? Si am putut...
Pe curind !

Cind nu fac experimente, puteti accesa clusterul pe adresa: http://ywar2.go.ro:9876

Ca surse de inspiratie am folosit:

Si totul a plecat de aici: