Arduino, ZigBee e le infinite possibilità (5)

Dopo un po’ di tempo di attesa ecco la nuova puntata della, ehm, ‘fortunata’ serie su ZigBee & Arduino, dove finalmente applicheremo tutto quello che abbiamo visto negli articoli precedenti ad un esempio concreto (utile o meno, giudicate voi). L’obiettivo è realizzare un sensore di temperatura wireless che invii i rilevamenti ad Arduino utilizzando i trasmettitori XBee che ormai conosciamo perfettamente.

I pezzi del sistema

Per fare i nostri test dovremo configurare due moduli XBee in modo che uno rilevi la temperatura di un ambiente e la passi all’altro, il quale sarà collegato ad Arduino che si occuperà di inviare i dati ad un PC attraverso un collegamento USB. Molto semplice.

Pezzo numero 1: il termometro!

Vogliamo approfondire l”esplorazione’ delle capacità intrinseche di XBee come piattaforma per la sensoristica remota, quindi utilizzeremo per il nostro termometro wireless il solo modulo. L’elemento sensibile sarà costituito da un termistore opportunamente collegato, come fonte di alimentazione per i nostri esperimenti utilizzeremo il pin a +3,3 V del solito Arduino, che in questo caso non avrà altro ruolo.

Ma quale sarà effettivamente il dato che misureremo ed invieremo alla stazione ricevente?

Alcuni dei pin di XBee (i pin fisici 17, 18, 19 e 20) possono essere configurati come ‘Analog Input’, ovvero come campionatori di segnali analogici, analogamente (e scusate il gioco di parole) a quanto accade per Arduino: attraverso di essi è possibile leggere e comunicare la differenza di potenziale tra il singolo pin e ground, con le limitazioni che vedremo di seguito.

Attenzione! Tanto per complicare le cose, la numerazione dei pin fisici (indicati in figura) è diversa dal ‘nome’ del pin, ovvero dal numero che lo identifica all’interno di un comando AT!

A bordo del modulo viene effettuata una conversione analogico – digitale che assegna un valore tra 0 e 1023 (1024 livelli) alla differenza di potenziale (in altre parole, il segnale viene campionato su 10 bit), dove il valore massimo, 1023, corrisponde a +1,2V. Valori di tensione superiore al massimo saranno convertiti sempre come massimo (1023).

Detto questo, il circuito in cui si inserirà il termistore, nel nostro caso un semplice partitore di tensione, dovrà essere costruito in modo che i valori attesi siano all’interno del range misurabile. Nel mio caso ho utilizzato un termistore 4K7 (4,7 kΩ a 25°C) e ho calcolato i valori della resistenza (10 kΩ) sulla base delle informazioni reperibili sul datasheet: le prove fatte sembrerebbero indicare delle letture abbastanza accurate (ma forse è solo fortuna!). Ovviamente cambiando il modello di termistore va modificato opportunamente il circuito (e, in generale, la taratura, ma questo esula un po’ dallo scopo di questo articoletto). La figura seguente illustra circuito e componenti che ho utilizzato, il pin destinato al rilevamento del segnale è il pin fisico 20 (D0).

La parte più complessa (si fa per dire) è relativa alla configurazione del modulo. In questo caso, trattandosi di un dispositivo remoto potremo scegliere se definirlo come router o come end device: dal punto di vista delle funzionalità del singolo modulo (capacità di gestione dei sensori, frequenza di campionamento, ecc) non ci sono differenze, ciò che cambia sono invece le possibilità di interazione all’interno di una rete ZigBee. Gli end device, infatti, devono essere associati ad un ‘parent’ e non hanno capacità di forwarding di messaggi provenienti da altri moduli.

Nel nostro esperimento lo configureremo come un router, in particolare come router AT (non in API mode): ricordate la differenza?

I moduli API comunicano verso il device o l’applicazione che li utilizza attraverso frame specifici (leggete la puntata precedente per aver più dettagli), nei quali ‘organizzano’ i dati ricevuti, i moduli AT invece da questo punto di vista sono traparenti e adottano il protocollo RS232, comunicando all’applicazione i bit ricevuti senza alcun intervento. Come già detto precedentemente la comunicazione RF tra i moduli non varia nei due casi, ed è così possibile far convivere all’interno della stessa rete ZigBee moduli dei due tipi senza alcun problema. Scegliamo di configurare il router remoto come AT per facilitarne la gestione iniziale (scelta dei parametri, configurazione iniziale).

Utilizzando l’ormai noto X-CTU carichiamo quindi l’opportuno firmware sull’XBee (i dettagli su come collegare XBee ad Arduino per effettuare l’operazione li trovate qui). Ora, tramite comandi AT (leggete qui per informazioni su come inviare i comandi al modulo), istruiamo il modulo affinchè legga il dato che ci interessa e lo invii. La tabella seguente contiene l’elenco dei parametri da impostare insieme ai relativi comandi AT: alcuni sono ‘noti’, altri sono specifici per la gestione dei sensori.

E con questo è tutto, il nostro termometro ci invierà una lettura ogni decimo di secondo (fin troppo!).

Pezzo numero 2: la stazione ricevente

La stazione ricevente nel nostro caso è anche il coordinatore della rete ZigBee. Dal punto di vista hardware non c’è nulla di complesso: sarà costituito da un modulo XBeee opportunamente collegato ad un Arduino che, in questo caso, non solo fungerà da alimentatore ma si occuperà anche di elaborare il segnale ricevuto e di comunicarlo al PC via USB.

Configuriamo quindi il modulo come coordinatore API (qui trovate i dettagli), in modo che all’Arduino la lettura del sensore arrivi come un frame di dati strutturati:

Prima di programmare Arduino per trattare il frame ricevuto da XBee possiamo utilizzare X-CTU (o un altro terminale) per verificare che i moduli stiano trasmettendo (e ricevendo) i dati correttamente, ricordandoci di connettere XBee ad Arduino come nel caso descritto qui (e caricando su Arduino uno sketch vuoto). Di seguito ecco cosa vediamo con CoolTerm:

Sarà corretto? Torniamo un momento alla puntata precedente: tra i vari frame presentati c’è anche quello relativo al campionamento I/O (frame type 0x92). Proviamo a capire se quello che stiamo ricevendo è coerente con quel tipo di frame analizzando i byte ricevuti  uno per uno. La prima cosa da individuare è dove inizia e dove finisce ciascun frame, dal momento che CoolTerm mostra in sequenza tutti quelli che riceve. Il delimitatore del frame è il byte con valore 0x7E: partiamo da quello, il frame finirà quando incontreremo il delimitatore successivo.

Quindi, partendo dall’inizio, il primo frame ricevuto è costituito dall sequenza di byte:

0x7E 0x00 0x12 0x92 0x00 0x13 0xA2 0x00 0x40 0x8A 0x87 0xBD 0x6D 0x6A 0x01 0x01 0x00 0x00 0x01 0x03 0x02f 0x9E

Tenendo presente che il frame che desideriamo ricevere è il type 92, vediamo cosa c’è dentro:

Le due bit mask corrispondenti alla coppia di bye 16-17 ed al byte 18 meritano qualche ulteriore spiegazione. Funzionano così: ogni canale (pin) di input digitale o analogico viene mappato su un bit specifico appartenente ai byte che formano la bit mask: il bit assumerà valore 1 se il canale è abilitato, 0 in caso contrario. Il mapping è il seguente:

  • Input digitale:

  • Input analogico:

Nel nostro caso i due byte che compongono la bit mask degli input digitali, entrambi pari a 0x00, segnalano (correttamente) che nessuno di essi è attivo, il byte che invece contiene la bit mask dei canali analogici ha valore 0x01, che, tradotto in bit signifiica 00000001: esiste un solo canale di input analogico abilitato sul pin A0 (D0), corrispondente al pin fisico 20.

Una volta verificato che il frame è stato trasmesso correttamente possiamo iniziare a lavorare sulla seconda parte (Arduino) programmando il microcontrollore per passare al PC un valore in una forma più gestibile. La logica di elaborazione, in realtà, poteva stare ovunque, ma installarla sull’Arduino ci permette di avere una stazione autoconsistente, che fornisce in output un dato (in questo caso di temperatura) direttamente utilizzabile. In fondo all’articolo vedremo una bozza di applicazione per la visualizzazione.

Attenzione: ricordatevi che per caricare uno sketch sull’Arduino è necessario disconnettere il modulo Xbee (pin 0 e 1 di Arduino)!

Lo sketch che ho caricato sull’Arduino ha più o meno questo aspetto:

const int debugLedPin =  13; /* pin a cui collegare il led
                             di avvenuta ricezione */
const float vin =  3.18;
float analogValue =0;
float recVout = 0;
float recTemp = 0;
int minValue = 0;
int maxValue =255;
const float vmax=1.2;
const float vout[13]={2.66, 2.52, 2.35, 2.17, 1.98, 1.77,
                      1.57, 1.37, 1.18, 1.01, 0.86, 0.73, 0.61};
const float tout[13] = {-20, -15, -10,  -5, 0, 5, 10,
                       15, 20, 25, 30, 35, 40};

void setup() {
  pinMode(debugLedPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()>=16){
    if (Serial.read() == 0x7e){
      blinkLed(); /* Pacchetto ricevuto, il led lampeggia */
      for (int i=0;i<18;i++){
        Serial.read();
      }
      int analogHigh=Serial.read();
      int analogLow=Serial.read();
      analogValue = analogHigh * 0xFF + analogLow;
      recVout = (analogValue/1023)*vmax;
      float vBase, vTop, tBase, tTop;
      if (recVout > vout[0]) recTemp=-20;
      else if(recVout < vout[12]) recTemp=40;
      else {
        for(int i=0; i<13;i++){
          if (recVout < vout[i] & recVout >= vout[i+1]){
            vBase=vout[i];
            vTop = vout[i+1];
            tBase=tout[i];
            tTop = tout[i+1];
            recTemp = tBase+(tTop-tBase)*(recVout-vBase)/(vTop-vBase);
            break;
          }
        }
      }
      Serial.print("T");
      Serial.print(recTemp,4);
    }
  }

}

void blinkLed(){
  digitalWrite(debugLedPin,HIGH);
  delay(10);
  digitalWrite(debugLedPin, LOW);
}

Arduino, sostanzialmente:

  • salterà tutti i byte del frame fino ad arrivare a quelli di interesse (la lettura del sensore), che iniziano dal byte 18:
for (int i=0;i<18;i++){
        Serial.read();
      }
  • leggerà i due byte contenenti il dato e li convertirà  in formato decimale:
analogValue = analogHigh * 0xFF + analogLow;
  • risalirà al valore di tensione campionato:
recVout = (analogValue/1023)*vmax;
  • convertirà il segnale di tensione in una temperatura  con un’interpolazione lineare a partire da un insieme di coppie di punti tensione – temperatura di riferimento (calcolati in base ai dati sul datasheet ed ai valori di tensione effettivi misurati con un tester):
 if (recVout > vout[0]) recTemp=-20;
      else if(recVout < vout[12]) recTemp=40;
      else {
        for(int i=0; i<13;i++){
          if (recVout < vout[i] & recVout >= vout[i+1]){
            vBase=vout[i];
            vTop = vout[i+1];
            tBase=tout[i];
            tTop = tout[i+1];
            recTemp = tBase+(tTop-tBase)*(recVout-vBase)/
(vTop-vBase);
            break;
          }
        }
      }
  • invierà in output il valore calcolato, inserendo un delimitatore tra due invii:
 Serial.print("T");
 Serial.print(recTemp,4);

Lo sketch può essere certamente ottimizzato e modificato a piacimento, ma per ora è quanto basta ai nostri scopi.

Una volta caricato lo sketch, il modulo XBee dovrà essere collegato come in figura, in modo che i pin 2 e 3 del modulo siano collegati rispettivamente ai pin 0 e 1 di Arduino:

Il led connesso al pin 13 è quello che ci segnalerà l’avvenuta ricezione di un frame di dati. Ora possiamo ricorrere al solito CoolTerm per vedere cosa arriva al PC:

Ora il dato è quello che ci ha restituito Arduino, il quale ci dice che il sensore legge una temperatura intorno ai 28° C (T 28,7155 è il primo frame letto)……leggermente più alta del previsto, un po’ a causa della deriva termica del sensore (che il circuito ed il software molto basilare non sono in  grado di correggere), un po’ perchè, facendo una prova con un tester, scopriamo che l’alimentazione del ‘termometro’ non è esattamente a 3,3 V ma un po’ meno, e quaesto chiaramente introduce un errore di calcolo (andrebbe nuovamente tarato il circuito).

Per ora è tutto, nella prossima puntata proveremo a ‘mettere a nanna’ il sensore per ridurre i consumi. Ringrazio chiunque avrà avuto la pazienza di leggere tutti gli articoli pubblicati fin qui e spero che  possano essere stati utili!

Le puntate precedenti: parte prima, parte seconda, parte terza, parte quarta.

Comando AT Descrizione
ATID1973 Imposta l’ID della PAN (vedi articoli precedenti)
ATDH13A200 Imposta il LSB del modulo di destinazione, nel nostro caso il coordinatore della rete (vedi articoli precedenti)
ATDL408A8669 Imposta il MSB del modulo di destinazione, nel nostro caso il coordinatore della rete (vedi articoli precedenti)
ATJV1 Imposta il modulo in modo che allo startup cerchi di riassociarsi al coordinatore (riduce il tempo necessario alla ricerca di una rete, dal momento che per prima cosa cerca l’ultima rete a cui era associato)
ATD02 Imposta il pin D0 (pin fisico 20) come input analogico. Il comando è formato da due parti (oltre al prefisso AT): – D0 : indica il pin da impostare; – 2 :indica che il pin deve essere impostato come input analogico. Altri valori possono essere: 0: elimina impostazioni precedenti; 1: imposta come bottone di commissioning; 3: imposta come input digitale 4: imposta come output digitale (LOW) 5: imposta come output digitale (HIGH)
ATIR64 Imposta la frequenza di campionamento. Il comando è composta dal prefisso AT, dal comando IR (IO sample rate) e da un numero esadecimale che indica la frequenza in millisecondi. Nel nostro caso 0x64 = 100 millisecondi.
ATWR Scrive la configurazione sul modulo.
Print Friendly
This entry was posted in Arduino, DIY, Hardware, XBee and tagged , , , , , , . Bookmark the permalink.

19 Responses to Arduino, ZigBee e le infinite possibilità (5)

  1. Andrea says:

    Ciao complimenti per gli articoli, sono veramente utili per chi si avvicina(come me) per la prima volta a questo mondo. Mi potresti consigliare una guida in cui si spiega passo passo come scrivere uno sketch nel caso di un network?
    Della serie mi piacerebbe costruire una rete formata da tanti sensori di temperatura per monitorare una stanza. Come far parlare un termometro e il coordinatore l’ho capito grazie ai tuoi fantastici articoli e ora mi piacerebbe andare avanti
    grazie

    • michele says:

      Ciao, non so se esista qualche guida o tutorial specifica che tratti la programmazione di Arduino per gestire un network di sensori, ma sinceramente non ho fatto un’indagine approfondita.

      In ogni caso non dovrebbe essere particolarmente difficile, il frame di campionamento I/O (type 92) ricevuto dal coordinatore contiene l’indirizzo del mittente (byte da 4 a 13), quindi non è un problema identificare la provenienza del dato. Lo stesso per gestire gli eventuali sensori remoti: dal momento che il coordinatore lavora in API mode, potrà inviare comandi specifici a ciascun singolo modulo remoto in modo indipendente utilizzando il frame type 0x17.

      In ogni caso, la ‘bibbia’ per i moduli xbee è manuale utente (in inglese): http://ftp1.digi.com/support/documentation/90000976_L.pdf

  2. Sharktear says:

    Ciao, mi sono imbattuto su questo interessantissimo blog cercando informazioni sullo sleep mode dei moduli xbee… visto che sei molto ferrato in materia provo a chiederti aiuto sul mio problema.
    Ho un modulo xbee remoto configurato come end device in modalità api ed è alimentato a batteria… ahimè la batteria al momento è solo una comune 9v “transistor” (immagino mAh inferiore a 500), per cui ho deciso di configurare il modulo in maniera che consumi il meno possibile… per l’applicazione a cui è preposto (apertura serratura portone di casa) diciamo che uno sleep di 5 secondi e risveglio per 500ms è abbastanza accettabile (nella peggiore delle ipotesi mi toccherà attendere 5 secondi prima che la serratura venga aperta). Sono riuscito ad ottenere quanto voluto programmando opportunamente il modulo xbee ricevente (ed anche il coordinatore, avendo scoperto che andava configurato anch’esso in modo che conservasse l’eventuale messaggio durante i 5 secondi che il ricevente “dorme”).
    Il problema è che vorrei poter configurare il modulo in maniera remota tramite comandi in modalità API, inviandoli dal modulo coordinatore che è collegato al microcontrollore (Netduino – la controparte di Arduino programmabile in linguaggio C#). Perchè tutto ciò? Perchè vorrei che i parametri dello sleep mode fossero dinamici, cioè settati in base al momento della giornata (questo sempre per poter risparmiare il massimo dell’energia della batteria). Ad esempio vorrei che dalle 8 del mattino e fino all’una di notte ci fossero i tempi di sleep menzionati sopra, mentre la notte vorrei che il modulo dormisse tutto il tempo senza svegliarsi (e senza somministrargli sonniferi). Ho visto che settare un tempo molto lungo di sleep non è un problema (basta settare correttamente il parametro dei cicli di sleep), ma non sono riuscito a far funzionare il programma che dovrebbe settare opportunamente i comandi AT remoti da inviare al modulo ricevente… Per fare ciò mi sono appoggiato ad una libreria per Netduino che si occupa di preparare il frame da inviare al modulo remoto, ma quando invio in sequenza i 3 comandi, questi non vengono “applicati”… cioè vedo che il modulo ricevente riceve qualcosa, ma la modalità di sleep non viene impostata, come anche confermato andando poi a leggere il valore dei parametri tramite XCTU. I comandi che invio sono SM=4, SP=1F4 e ST=1F4 (cioè 5 sec di sleep e 500ms di “awake” prima di tornare a nanna)… ho provato anche a mettere una pausa di 30ms tra un comando e l’altro ma non è cambiato nulla… ho quasi il sospetto che il frame non venga creato in maniera corretta dalla libreria C# a cui mi appoggio! Quello che ti chiedo è: dal punto di vista pratico è possibile impostare remotamente la modalita di sleep e variarla a piacimento? C’è qualche altro accorgimento di cui devo tenere conto?
    Grazie 1000 e complimenti per il blog!

    • michele says:

      Dovrei fare qualche test, ma così ‘a sensazione’ ti direi di controllare se nel frame di richiesta comando AT (frame type 0x17) è impostato correttamente il byte di ‘apply changes’ che dovrebbe essere il sedicesimo byte del frame: deve essere impostato a 0x02, altrimenti i nuovi parametri vengono ricevuti ma non applicati…probabilmente di default sarà impostato a 0x00, visto che lo stesso byte può essere utilizzato anche per altro (richiesta di encryption o timeout di trasmissione esteso).

      Se non riesci a visualizzare il contenuto del frame o ad impostare manualmente il bye in questione, una volta conclusa la trasmissione dei parametri, invia (sempre utilizzando il solito frame) il comando ‘AC’ (senza parametri), che forza il modulo ad applicare i nuovi valori ricevuti.

      Fammi sapere!

      • Sharktear says:

        Grazie per la velocissima risposta! Al momento non ho modo di provare, ma ricordo che il byte che suggerisci viene già inserito nel frame. A questo punto non mi rimane che debuggare i frame ricevuti, ammesso che con xctu sia possibile “sniffarli”. Una domanda stupida… se nel frame devo inviare un valore che eccede il singolo byte come ad esemio 1F4 (500 in decimale) è corretto dividerlo in un byte array {0x1, 0xF4} ?? Ti chiedo questo perchè il metodo della libreria per inviare comandi AT remoti prevedeva come parametro un singolo byte… io l’ho modificato in modo che accetti un byte array e nel corpo del metodo incremento il byte che indica la dimensione del frame in maniera opportuna. Altra domanda: non riesco più a comunicare con il modulo xbee precedentemente settato tramite XCTU in modalità sleep per 5 secondi e risveglio per 500ms, perchè il periodo di risveglio è troppo corto e suppongo xctu non riesca a fare la read dei parametri per tempo… anche mandando il comando +++ da terminale non riesco a prenderne il controllo… c’è qualche modo per riprendere il controllo del modulo da xctu (andando a disattivare lo sleep mode) senza dover riflashare il firmware?
        Grazie ancora

  3. Sharktear says:

    Forse nel manuale ufficiale della Digi ho trovato come risvegliare il bello addormentato nel bosco… il pin 20 dovrebbe essere abilitato di default per la connessione con un pulsante… e la pressione singola dovrebbe svegliare il modulo per 30 secondi… questa sera provo a cortocircuitare il pin 20 a massa con un ponticello (per un istante) sperando di non fare danni 🙂

    • michele says:

      Dovrebbe funzionare…

      Per quanto riguarda la lunghezza del frame: il campo che contiene il parametro è di lunghezza variabile, quindi può contenere indifferentemente un singolo byte od un byte array (oppure mancare del tutto nel caso di inquiries).
      Probabilmetne dico banalità, ma il dubbio che ho è che la libreria C# che usi sia in grado di gestire la variabilità: oltre ad inserire un byte array devi anche assicurarti di ricalcolare correttamente la lunghezza del frame (bytes 1-2) e, ovviamente, il checksum (ultimo byte). Se c’è un errore da qualche parte il frame generato non è valido e non so bene come sia gestito, credo che venga scartato senza avvertimenti (non viene trasmesso). In un paio di occasioni mi è successo, non so se dipenda da qualche configurazione specifica del modulo o meno.
      In ogni caso, a fronte di un comando AT inviato, dovresti ricevere in risposta uno o più frames (dipende dal comando) con frame type 0x88 contenente lo status nel byte 7 (OK, Error, Invalid command, invalid parameter, tx failure).

      • Sharktear says:

        Rieccomi qui con un altro quesito… ma il fatto che dopo aver correttamente impostato i valori di sleep time ciclico tramite comando at remoto in modalità api (e funziona), se spengo il modulo e lo riaccendo questo effettua nuovamente il pairing ma ritorna ai valori di sleep time di default (quindi lo sleep mode non è più attivo)… mi aspettavo che i parametri venissero memorizzati così come accade quando li si imposta tramite xctu. Sulla documentazione ufficiale non ho trovato nulla in merito.

        • michele says:

          Credo che il problema sia dovuto al fatto che la configurazione, per poter ‘sopravvivere’ ad un ciclo di reset, deve essere scritta sulla flash memory del chip del modulo con il comando AT  WR (altro frame 0x17 da inviare!).

          Attenzione che secondo la documentazione il numero di scritture che è possibile effettuare è limitato : il datasheet del chip dice che è garantito per mille cicli, dopo non so cosa possa succedere…

          • Sharktear says:

            6 un pozzo di sapere! Se è il comportamento corretto per me va pure meglio, volevo solo capire se sbagliavo qualcosa. Se va via la corrente e perde la configuarazione, succede che anche il microcontrollore si spegne e quindi al suo riavvio mi basta inserire la reinizializzazione degli sleep time dei moduli.

  4. Sharktear says:

    Finalmente e grazie al link trovato su questo blog (http://ftp1.digi.com/support/utilities/digi_apiframes2.htm) sono riuscito a trovare dove era il problema… ho controllato ad uno ad uno i byte del frame che invio per settare lo sleep period e… mi accorgo che a causa di un errore di chi ha creato la libreria il comando SP veniva tradotto con 0x534c e non 0x5350… l’ho corretto ed ora funziona a meraviglia. Confermo anche che per risvegliare il bell’addormentato in caso di bisogno è sufficiente cortocircuitare per un istante il pin 20 a massa.

  5. Sharktear says:

    Come si suol dire… l’appetito vien mangiando…
    adesso che sono riuscito a far funzionare la modalità sleep ciclica, ho questo nuovo problema:
    devo inviare un impulso su una uscita GPIO del modulo xbee, quindi un frame dove setto lo stato “alto” e dopo circa 300ms uno stato “basso”, questo mi permette di chiudere un relè per un breve istante… il problema è che quando invio i due comandi in sequenza (sempre in modalità api dal microcontrollore) se il modulo è in fase sleep, il suo coordinatore terrà per lui in caldo soltanto l’ultimo comando ricevuto e non tutto lo “stack” di comandi arrivati in sua assenza. Questo per me si traduce in un nulla di fatto perchè arrivando solo il secondo comando che setta lo stato del pin a “low”, non ottengo il risultato sperato. La mia domanda è: come aggirare l’ostacolo? Esiste la possibilità di aumentare il numero di comandi che il coordinatore conserva per il bell’addormentato?
    In caso contrario dovrò inviare il primo comando ed attendere dal modulo la risposta di avvenuta consegna (cosa che potrebbe arrivare solo a seguito del suo risveglio) e poi solo a quel punto e senza dargli il tempo di tornare a nanna dargli anche il secondo messaggio. Altre soluzioni??

    • michele says:

      Effettivamente il coordinatore (o più in generale il parent device), in caso di trasmissioni broadcast, conserva solo il messaggio più recente, scartando messaggi vecchi non ancora trasmessi. Il comportamento non può essere riconfigurato, in quanto il buffer del dispositivo è limitato e immagino che sia stata data priorità al numero di end device che un parent può gestire piuttosto che al numero di messaggi per end device.
      Non so se invece, nel caso di trasmissione unicast (ovvero diretta ad un solo end device il cui indirizzo è scritto all’interno del frame) il parent sia in grado di gestire più messaggi. Non ho fatto esperimenti in proposito, e la documentazione è un po’ ‘fumosa’. C’è in ogni caso un timeout (impostabile) oltre il quale il messaggio è definitivamente eliminato.

      Detto questo, mi sorge un dubbio di fondo sull’architettura del tuo sistema, in quanto io, a occhio, l’avrei disegnato ‘al contrario’: il modulo che deve gestire il relè (collegato in qualche modo alla rete elettrica) come parent insieme ad un Arduino per l’elaborazione dei segnali ricevuti (sequenza hi-low per attivare il relè), l’altro come end device, in quanto mi aspetterei che il device vicino al relè sia quello più facilmente alimentabile in continuo (senza quindi usare batterie di sorta, al limite con un circuito di regolazione del voltaggio). Il modulo che invece rappresenta il ‘telecomando’ può essere un end device a batterie che ‘dorme’ in Pin mode, ovvero finchè non premo un bottone che innesca la sequenza risveglio – spedizione di un IO sample (banale lettura di input digitale HIGH su un pin o simile) – ritorno in sleep fino al prossimo giro (confesso che dovrei ragionare un po’ sulla configurazione di dettaglio dell’ipotetico end device, ma in generale penso che sia un’approccio più coerente).

      • Sharktear says:

        L’architettuta l’ho impostata in questo modo per esigenza… il mio end-device si trova all’interno del videocitofono ed è alimentato a batteria… non avevo altro modo per alimentarlo. Metterlo a nanna nasce dal fatto che essendo a batteria deve consumare il meno possibile. Se dorme per 5 secondi e si sveglia per 500ms il tutto si traduce in enorme risparmio della batteria. Certo invertendo coordinatore ed end-device avrei potuto usare il pin sleep o addirittura non usare lo sleep avendo una alimentazione da rete elettrica.
        L’approccio dell’attendere dall’end-device una conferma di ricezione del primo messaggio e poi inviargli il secondo può funzionare?

  6. Pingback: Arduino, Zigbee e le infinite possibilità (6) | The Monday Morning Tech Newsletter

  7. franco chiereghin says:

    ho letto il tuo articolo ma è difficile per me .
    Mi puoi aiutare??
    ho due arduini in contatto fra di loro tramite xbee
    con i digitali funziona tutto,ma io devo trasmettere un analogico e allora non funziona niente.non capisco hai un codice semplice da darmi???
    devo trasmettere il valore di un potenziometro
    grazie in anticipo

  8. Christian says:

    Ciao complimenti per il tuo ottimo tutorial su xbee e per come spieghi chiaramente le cose sono riuscito a far comunicare i due xbee per leggere una temperatura .
    Ora vorrei provare a far leggere un altro tipo di sensore un flussometro per acqua di questo tipo FE-7300-WFSENSOR . preso a robot domestici , posso chiederti se posso collegarlo direttamente ad xbee la sua alimentazione e di 5 V , e se molto gentilmente puoi darmi dei consigli su come procedere per lo sketch , io in attesa che arrivi il sensore sto scrivendolo per vedere se riesco a farcela con le mie forze ma un aiuto è sempre gradito .
    Grazie ancora per la tua corese attenzione
    Christian

    • admin says:

      Ho dato un’occhiata al sensore, ma temo che non sia possibile collegarlo direttamente ad xbee, non solo per un problema di alimentazione (i moduli sono alimentati a 3,3 V, ed anche se tollerano voltaggi più alti non arrivano a 5v). Il vero problema è il tipo di segnale che viene generato dal sensore: in linea di massima devi fare in modo di contare gli impulsi in un certo intervallo di tempo e di trasmettere questo valore, che poi potrà essere elaborato altrove. La ‘conta’ non puoi gestirla sull’xbee, devi per forza utilizzare un qualche altro sistema, per esempio con un Arduino. Qui c’è un articolo che ti può essere d’aiuto: http://www.seeedstudio.com/forum/viewtopic.php?f=4&t=989&start=0 .
      Scusa se sono stato un po’ sintetico ma sotto Natale gli impegni si moltiplicano, ma il tempo no! 🙂

Rispondi a michele Annulla risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *