Connessioni XBee con device .NET Gadgeteer (Italiano)

By Mike Dodaro, translated by Marco Minerva from the original English version

Le schede XBee hanno un costo estramamente contenuto e possono essere integrate in qualsiasi tipo di device. Il loro raggio di funzionamento supera quello delle connessioni Bluetooth. L’articolo Zigbee Networking with XBee Series 2 and Seeed’s Products fornisce una rapida introduzione alle funzionalità di XBee. Il libro di Robert Faludi intitolato Building Wireless Sensor Networks è un’eccellente tutorial sull’uso di XBee nei device Arduino. Questo articolo mostra uno scenario di uso di XBee con device .NET Gadgeteer.

L’esempio di questo post dimostra l’uso di XBee nel cosiddetto AT communication mode, un protocollo di controllo human readableXBee può utilizzare anche l’API protocol.  Entrambi i metodi richiedono l’apprendimento dei dettagli dei comandi e delle impostazioni di configurazione. Allo scopo, è possibile fare riferimento a X-CTU tool sviluppato da Digi in accoppiata ad un Explorer dongle.

Questo esempio implementa due device .NET Gadgeteer con connessione XBee. Il primo invia notifiche all’altro, che funziona da gestore per un Relay. Quest’ultimo è esposto su Internet attraverso un modulo GHI Electronics WiFi RS21 ed è dotato di un circuito attuatore che viene chiuso alla ricezione delle notifiche. Più precisamente, quando un sensore invia una notifica, il relay attiva l’interruttore, che chiude un circuito che può alimentare qualsiasi periferica che richiede una potenza supportata dal modulo Seeed Studio Relay per .NET Gadgeteer, fino a DC 10 Amps/ 250 Volts, oppure AC 15 Amps/ 120 Volts.

Le due radio XBee usate in questo esempio sono state configurate usando l’utility X-CTU e il dongle XBee Explorer di SparkFun Electronics, come mostrato nella seguente immagine (fare clic per ingrandire).

XBee Explorer Dongle

XBee Explorer Dongle

Inseriamo la scheda XBee con il pin 1 allineato all’angolo in alto a sinistra del dongle, i cui socket 1 e 20 sono etichettati in corrispondenza con le etichette sul circuito XBee.

Con XBee nel suo socket, possiamo iniziare a lavorare con X-CTU.  Purtroppo esso non funziona sempre come ci potremo aspettare, quindi è necessario adottare qualche workaround.

Configurazione della scheda XBee con X-CTU

Inseriamo il dongle in una porta USB del PC ed avviamo X-CTU. Selezioniamo la porta USB a cui abbiamo collegato il dongle.

X-CTU with Dongle on COM9

X-CTU con il Dongle collegato alla porta COM9

Facciamo clic sul pulsante Test/Query. Se appare una finestra con il messaggio “Unable to communicate with modem”, è necessario chiuderla e selezionare Enable API.  Per effettuare le letture, X-CTU deve essere nella stessa modalità della scheda XBee (in questo esempio useremo la modalità AT, ma alcune schede potrebbero essere venduti con la modalità API attiva).

A questo punto, premiamo nuovamente il pulsante Test/Query. Se vediamo una schermata simile alla seguente, possiamo procedere ed effettuare il flashing della scheda XBee.

X-CTU Read Modem

X-CTU Read Modem

Passiamo al tab Modem Configuration di X-CTU.

X-CTU Modem Configuration

X-CTU Modem Configuration

Facciamo clic sul pulsante Read e, se tutto va a buon fine, i risultati saranno mostrati nel seguente screenshot.

X-CTU Normal Read Modem Configuration

X-CTU Normal Read Modem Configuration

Oea possiamo impostare i parametri di configurazione in X-CTU e scriverli nella flash del modulo XBee. Dobbiamo selezionare XBee modemFunction Set, e impostare PAN IDDestination Address HighDestination Address Low del modulo.  I byte high e low del modulo XBee sono stampati sul modulo stesso. Il byte high, come mostrato nella seguente immagine, è 0013A200.  Esso è apparentamente lo stesso per tutti i moduli X-Bee. Il byte low dei miei moduli, mostrato qui sotto, is 40790728 (fare clic per ingrandire).

XBee Serial Number High and Low Bytes

I Byte Low e High del serial XBee

Il seguente screenshot mostra le impostazioni del Modem XB24-ZB. Il mio modulo XBee è etichettato XB24-Z7WIT, ma il libro di Bob Faludi dice che esso può essere configurato come un XB24-ZB, e in effetti la cosa funziona. La lista Function Set contiene una serie di opzioni, ma le uniche di cui abbiamo bisogno sono ZIGBEE COORDINATOR AT e ZIGBEE ROUTER AT.

Possiamo utilizzare anche ZIGBEE END DEVICE AT per una delle schede. Ogni rete XBee deve avere un solo Coordinator.  In ogni rete XBee possono essere più Router e End Devices, ma deve essere presente un solo Coordinator. End Devices possono inviare e ricevere messaggi, ma non possono inoltrare messaggi da un modulo XBee ad un altro.

X-CTU XBee Function Set

X-CTU XBee Function Set

Il tool dovrebbe leggere i byte high e low del numero di serie, così non dobbiamo inserirli manualmente. La seguente figura mostra la casella di testo Destination Address Low in modalità di editing.

X-CTU Set Destination Address Low

X-CTU Set Destination Address Low

Il valore Destination Address High è 0013A200 per tutti i moduli X-Bee, ma dobbiamo impostare Destination Address Low sul valore del low byte del Serial Number del modulo XBee a cui questo modulo invierà messaggi.  Dobbiamo anche impostare il PAN ID di entrambe le schede sullo stesso numero. Questo identificativo di rete può essere un numero qualsiasi; nel nostro esempio vale 1234.

Dopo che abbiamo correttamente specificato i valori di PAN ID,  Function Set, Destination Address High, e Destination Address Low in X-CTU, siamo pronti a scrivere la configurazione nella flash del modulo XBee inserito nel dongle. Facciamo clic sul pulsante Write.  Il processo inizierà mostrando una finestra simile alla seguente:

X-CTU Flash XBee Write New Flashing

X-CTU Flash XBee Write New Flashing

Ma potrebbe terminare mostrando qualcosa del genere:

X-CTU Flash XBee Write New Flash Error setting AT parameters

Errore durante l’impostazione dei parametri AT

In questo caso, il problema è che abbiamo iniziato con le impostazioni dei parametri API e quindi abbiamo provato il flashing dei parametri AT. Seguendo le istruzioni riportate nel messaggio di errore, facciamo clic sul pulsante Show Defaults nella sezione Parameters di X-CTU. Questo rimuoverà i valori che abbiamo inserito nei passaggi precedenti, quindi dovremo inserirli nuovamente e riprovare. Purtroppo, questi dettagli di configurazione richiedono più tempo della programmazione dei moduli in un’applicazione .NET Gadgeteer. Sono dovuto tornare nel tab PC Settings di X-CTU e deselezionare l’opzione API.

Potremmo trovarci nella situazione in cui X-CTU non riesce a comunicare con il modem e il flashing del modulo non funziona.  In questo caso, c’è un workaround che sembra funzionare: bisogna scollegare il cavo USB con il dongle; avviare X-CTU; (la porta COM selezionata in precedenza non sarà più mostrata nella lista); fare clic sul tab User COM Ports nella parte bassa della finestra di X-CTU; nella finestra Add User COM Port, aggiungere una COM porta (potrebbe essere necessario chiudere X-CTU e collegare il dongle per sapere quale porta sta usando); infine, aggiungere la porta COM come mostrato nel seguente screenshot.

X-CTU Repair Flash XBee

X-CTU Repair Flash XBee

Dopo aver aggiunto la porta COM, sarà possibile selezionarla nella lista COM Port Setup.

X-CTU Repair Flash XBee 2

X-CTU Repair Flash XBee 2

Selezioniamo o deselezioniamo l’opzione API in base alle impostazioni che abbiamo scritto nella flash. Ora facciamo clic sul pulsante Test/Query. Se il test ha successo, dovremmo essere in grado di effettuare il flash del modulo dal tab Modem Configuration di X-CTU.

Dopo aver impostato Modem e Function Set, assicuriamo di cliccare su Show Defaults prima di impostare il valore di PAN ID e gli indirizzi di destinazione. Quindi, proviamo ancora a scrivere la configurazione. Ho impiegato diverse ore con queste procedure, quindi non stupitevi se dovrete ripetere questa procedura più di una volta. In ogni caso, dovrete ripetere questi passaggi anche per l’altro modulo.

Costruire il sensore con l’adattatore XBee per .NET Gadgeteer

La rete di device .NET Gadgeteer che costruiremo comprende sensori e un relay che riceve notifiche. Il relay attiva circuiti elettrici o invia dati su Internet. Lo scenario è molto versatile: possiamo utilizzare un numero qualsiasi di sensori; il relay può attivare numerosi tipi di circuiti elettrici ed inviare notifiche ad un Web service. Il relay può anche ricevere dati da utenti Internet, dati che sono poi inviati via radio ai sensori per impostarne lo stato. Il numero di device nella rete limita la portata di comunicazione dei sensori, ma il fatto che siano accessibile via Internet li rende usabili senza virtualmente alcun limite.

Il sensore che useremo in questo esempio è l’accelerometro di Seeed Studio. Esso può essere utilizzare per determinare l’orientamento, l’accelerazione, la vibrazione, il movimento e la caduta. Tale sensore può essere montato su un recinto o un cancello per identificare i movimenti ed inviare notifiche. Ricordiamo comunque che si possono usare molti altri tipi di sensori, come Passive Infrared SensorLight Sense Module, oppure Moisture Sensor, tutti prodotti da GHI Electronics.

La seguente immagine del .NET Gadgeteer Designer mostra i moduli Seeed Accelerometer e GHI XBee Adapter per la connessione XBee e l’invio di notifiche.  Il modulo Seeed Oled Display non è strettamente necessario, ma può essere utile a scopo di test (fare clic per ingrandire).

Sensor Device Modules in .NET Gadgeteer Designer

Sensor Device Modules in .NET Gadgeteer Designer

Il codice è abbastanza lungo, ma abbastanza semplice, poiché stiamo usando la modalità AT per lo scambio di messaggi tra XBee e il realy. Il cuore dell’applicazione è l’assembly Gadgeteer.Interfaces.Serial.  Istanziamo la Serial Interface dell’oggetto xBee come mostrato di seguito:

    xBee.Configure(9600, GT.Interfaces.Serial.SerialParity.None,
        GT.Interfaces.Serial.SerialStopBits.One, 8);

    serial = xBee.SerialLine;
    serial.Open();
    serial.LineReceived +=
        new GT.Interfaces.Serial.LineReceivedEventHandler(serial_LineReceived);
    serial.AutoReadLineEnabled = true;

Quindi impostiamo un timer e richiediamo la misura dell’accelerometro nell’evento Tick.

    void timer_Tick(GT.Timer timer)
    {
        accelerometer.RequestMeasurement();
    }

Nel gestore dell’evento Accelerometer.MeasurementComplete, controlliamo l’accelerazione sull’asse x. we check for acceleration on the x axis. Una forza specifica maggiore di .05, positiva o negativa, indica che c’è qualche disturbo nella misura del sensore.

void accelerometer_MeasurementComplete(Accelerometer sender,
                                Accelerometer.Acceleration acceleration)
{
    if(acceleration.X > .05 || acceleration.X < -.05)
        serial.WriteLine("XBee3 - Acc X: " + acceleration.X.ToString() +
            "    Y: " + acceleration.Y.ToString() +
            "    Z: " + acceleration.Z.ToString());
}

Il prototipo del device è mostrato nella seguente figura (fare clic per ingrandire).

Accelerometer Sensor Device

Accelerometer Sensor Device

Il file Program.cs completo è mostrato di seguito.

using Microsoft.SPOT;

using GT = Gadgeteer;
using Gadgeteer.Modules.GHIElectronics;
using Gadgeteer.Modules.Seeed;

namespace XBee3
{
    public partial class Program
    {
        GT.Interfaces.Serial serial;
        uint yIndex;
        GT.Timer timer;

        void ProgramStarted()
        {
            accelerometer.MeasurementComplete +=
                new Accelerometer.MeasurementCompleteEventHandler(accelerometer_MeasurementComplete);

            button.ButtonPressed +=
                new Button.ButtonEventHandler(button_ButtonPressed);

            xBee.Configure(9600, GT.Interfaces.Serial.SerialParity.None,
                GT.Interfaces.Serial.SerialStopBits.One, 8);

            serial = xBee.SerialLine;
            serial.Open();
            serial.LineReceived +=
                new GT.Interfaces.Serial.LineReceivedEventHandler(serial_LineReceived);
            serial.AutoReadLineEnabled = true;

            yIndex = 1;
            timer = new GT.Timer(500);
            timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);

            Debug.Print("Program Started");
        }

        void accelerometer_MeasurementComplete(Accelerometer sender,
                                        Accelerometer.Acceleration acceleration)
        {
            if(acceleration.X > .05 || acceleration.X < -.05)
                serial.WriteLine("XBee3 - Acc X: " + acceleration.X.ToString() +
                    "    Y: " + acceleration.Y.ToString() +
                    "    Z: " + acceleration.Z.ToString());
        }

        void timer_Tick(GT.Timer timer)
        {
            accelerometer.RequestMeasurement();
        }

        void serial_LineReceived(GT.Interfaces.Serial sender, string line)
        {
             // This event handler is mainly for setup and testing of the sensor device.
            if (line != null)
            {
                oledDisplay.SimpleGraphics.DisplayText(line,
                    Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 1, yIndex);

                yIndex += 10;
            }
        }

        void button_ButtonPressed(Button sender, Button.ButtonState state)
        {
            if (!button.IsLedOn)
            {
                accelerometer.Calibrate();

                button.TurnLEDOn();

                oledDisplay.SimpleGraphics.DisplayText("Ready to send or receive",
                    Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 1, yIndex);

                yIndex += 10;
                timer.Start();
            }

            else
            {
                timer.Stop();
                button.TurnLEDOff();
            }

        }
    }
}

Costruire il Relay

Il modulo XBee che riceve notifica dai sensori, utilizza anch’esso un oggetto di tipo GT.Interfaces.Serial.  Istanziamo l’interfaccia Serial come visto in precedenza, ma in questo caso il delegate GT.Interfaces.Serial.LineReceived non serve solo a scopo di test.

    serial = xBee.SerialLine;
    serial.Open();

    serial.LineReceived +=
           new GT.Interfaces.Serial.LineReceivedEventHandler(serial_LineReceived);

Quando un sensore riceva una notifica, l’unica parte essenziale del codice seguente è l’ultima linea, che chiude il circuito del releay. Quest’ultimo può attivare qualsiasi dispositivo DC o AC che richiede una potenza supportata dal modulo Seeed Studio Relay, fino a DC 10 Amps/ 250 Volts, oppure AC 15 Amps/ 120 Volts.

    void serial_LineReceived(GT.Interfaces.Serial sender, string line)
    {
        if (line != null)
        {
            if (225 < yIndex)
            {
                // Clear if text is near bottom of display.
                display.SimpleGraphics.Clear();

                yIndex = 1; // Reset output to top of display.
            }

            display.SimpleGraphics.DisplayText(line,
                Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 1, yIndex);

            yIndex += 10;
        }

        // Close the circuit on relay1 to start a motor or power any electrical device.
        relays.Relay1 = true;
    }

Il resto del codice configura il modulo GHI Electronics WiFi RS21 per inviare le notifiche ad un Web service e/o ricevere informazioni di stato da un utente Internet. Il seguente codice evidenzia solo la parte che effettua la richiesta Web. Essa avvia un processo asincrono che invia e riceve dati da/verso un servizio Web.  Il servizio può essere realizzato con il (WCF) REST service template per C# e la versione 4.0 di .NET Framework.

Per maggiori informazioni su come usare il WCF REST Template con .NET Gadgeteer, è possibile fare riferimento all’articolo Sending .NET Gadgeteer Sensor Data to a REST Web Service. Per un esempio di come impostare lo stato dei device .NET Gadgeteer da un servizio Web, vedere Remote Control of .NET Gadgeteer Device via REST Web Service and .NET Gadgeteer Relay Actuator via REST Web Service. Questi articoli, a loro volta, contengono link a risorse utili per approfondimenti.

Il codice completo è mostrato di seguito. Nei prossimi post aggiungerò altri sensori e relay (il modulo Seeed per .NET Gadgeteer dispone di quattro relay a cui si possono collegare luci, motori, allarmi, ecc.)

using Microsoft.SPOT;

using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;
using Gadgeteer.Networking;

namespace GadgeteerXbeeRelay
{
    public partial class Program
    {
        GT.Interfaces.Serial serial;
        uint yIndex;
        GT.Timer timer;

        void ProgramStarted()
        {
            wifi.UseDHCP();
            Gadgeteer.Modules.GHIElectronics.WiFi_RS21.WiFiNetworkInfo info =
                new WiFi_RS21.WiFiNetworkInfo();
            info.SSID = "WiFiSecurityID";
            info.SecMode = WiFi_RS21.SecurityMode.WEP;
            info.networkType = WiFi_RS21.NetworkType.AccessPoint;

            wifi.Join(info, "passphrase");
            wifi.NetworkUp +=
                new GTM.Module.NetworkModule.NetworkEventHandler(wifi_NetworkUp);
            wifi.NetworkDown +=
                new GTM.Module.NetworkModule.NetworkEventHandler(wifi_NetworkDown);

            button.ButtonPressed +=
                new Button.ButtonEventHandler(button_ButtonPressed);

            xBee.Configure(9600, GT.Interfaces.Serial.SerialParity.None,
                GT.Interfaces.Serial.SerialStopBits.One, 8);

            serial = xBee.SerialLine;
            serial.Open();

            serial.LineReceived += new GT.Interfaces.Serial.LineReceivedEventHandler(serial_LineReceived);

            yIndex = 1;

            // Start a timer to report to Web service at one minute interval.
            timer = new GT.Timer(60000, GT.Timer.BehaviorType.RunContinuously);
            timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
            timer.Start();

            Debug.Print("Program Started");
        }

        void serial_LineReceived(GT.Interfaces.Serial sender, string line)
        {
            if (line != null)
            {
                if (225 < yIndex)
                {
                    // Clear if text is near bottom of display.
                    display.SimpleGraphics.Clear();

                    yIndex = 1; // Reset output to top of display.
                }

                display.SimpleGraphics.DisplayText(line,
                    Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 1, yIndex);

                yIndex += 10;
            }

            // Close the circuit on relay1 to start a motor or power any electrical device.
            relays.Relay1 = true;
        }

        void button_ButtonPressed(Button sender, Button.ButtonState state)
        {
            if (!button.IsLedOn)
            {
                serial.AutoReadLineEnabled = true;
                serial.WriteLine("XBee Relay ready.");
                display.SimpleGraphics.Clear();
                yIndex = 0;

                display.SimpleGraphics.DisplayText("Ready to send or receive data.",
                    Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 1, 1);

                yIndex += 10;
                button.TurnLEDOn();
            }

            else
            {
                serial.AutoReadLineEnabled = false;
                button.TurnLEDOff();
                relays.Relay1 = false;
            }

        }

        void timer_Tick(GT.Timer timer)
        {
            // Send data and poll Web service.
            HttpRequest request = HttpHelper.CreateHttpGetRequest("");
            request.ResponseReceived +=
                  new HttpRequest.ResponseHandler(request_ResponseReceived);

            request.SendRequest();  // Sends a non blocking web request.
        }

        void request_ResponseReceived(HttpRequest sender, HttpResponse response)
        {
            //throw new System.NotImplementedException();
        }

        void wifi_NetworkDown(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
        {
            led.TurnRed();
        }

        void wifi_NetworkUp(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
        {
            led.TurnGreen();
        }
    }
}

, , , , , , , , , , , ,

  1. Leave a comment

Leave a comment