Arduino, ZigBee e le infinite possibilità (3)

Come promesso nella scorsa puntata questa volta cercheremo di far lavorare un po’ di più il nostro Arduino: finora ci siamo limitati ad utilizzarlo come un alimentatore stabilizzato e come convertitore USB-Seriale, ma ora è giunto il momento che si dia da fare.

Da CoolTerm ad Arduino

Cominciamo col mettere mano ai circuiti. L’input ai moduli XBee non dovrà più arrivare dal PC attraverso un emulatore di terminale ma sarà gestito da  Arduino stesso: per far questo sarà sufficiente che il pin 0 di Arduino (RX) sia collegato con il pin 2 del modulo (Data OUT) e che il pin 1 di Arduino (TX) sia invece collegato con il pin 3 del modulo (Data IN):

Attenzione: tutte le volte che si dovrà caricare uno sketch su Arduino sarà necessario scollegare il modulo!

I moduli sono già stati configurati per parlarsi nella scorsa puntata, quindi, per ora, non sarà necessario alcun intervento.

Luce!

Il primo test consisterà nel comandare l’accensione di un LED da una scheda all’altra (simulando un classico interruttore), una sorta di ‘Hello World’ in termini elettronici. Aggiungeremo, per semplicità,  un LED sul pin 13 dell’Arduino collegato al router ed un bottone per comandarlo sul pin 2 dell’altra scheda (il coordinatore):

La scheda colegata al bottone leggerà l’input (HIGH o LOW) del pin 2 e, nel caso abbia cambiato stato, invierà un segnale sull’avvenuta transizione (da HIGH a LOW o viceversa) all’altro Arduino che, sua volta, varierà lo stato del LED. Come sempre, per qualsiasi dubbio su Arduino, consultate il sito di riferimento. Gli sketch da caricare sugli Arduino sono riportati di seguito. Il coordinatore avrà il compito di inviare un segnale al router quando viene premuto il bottone, il router dovrà ricevere il segnale e cambiare lo stato del LED, da acceso a spento o viceversa. Quindi, sul coordinatore:

const int buttonPin = 2;     // pin a cui è collegato il bottone

int ledState =LOW; //assumiamo che all'inizio il led sia spento     
int lastButtonState = LOW; 

void setup() {
 pinMode(buttonPin, INPUT);
 Serial.begin(9600);
}

void loop() {
 // legge lo stato del bottone
 int reading = digitalRead(buttonPin);
 if (reading == HIGH && reading != lastButtonState){
   // si agisce solo se lo stato del bottone è cambiato
   if (ledState == HIGH){
     Serial.print('L');
     ledState = LOW;
   }
   else {
    Serial.print('H');
    ledState =HIGH;
  }
 }
 lastButtonState = reading; // aggiorna lo stato del bottone
 delay(10); // pausa per non sovraccaricare la seriale
}

Sul router, invece:

byte incoming;

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

}

void loop() {
 if(Serial.available()>0) {
 incoming = Serial.read();
 if (incoming == 'L') digitalWrite(13,LOW);
 if (incoming == 'H') digitalWrite(13,HIGH);
 }
 delay(10);
}

Una volta caricati gli sketch sulle rispettive schede premendo il bottone collegato al coordinatore dovremmo essere in grado di accendere e spegnere il LED sul router. Se qualcosa non va:

  1. rivedete il cablaggio;
  2. controllate gli sketch caricati sui due Arduino (avete scollegato e ricollegato i moduli a caricamento avvenuto?);
  3. controllate la configurazione dei moduli con i comandi AT visti nella puntata precedente;
  4. controllate che effettivamente il coordinatore spedisca l’output corretto utilizzando il Serial Monitor dell’IDE di Arduino: ad ogni pressione del bottone deve essere inviata una lettera (‘L’ o ‘H’ in sequenza);
  5. di nuovo, dormiteci sopra! Vedrete che poi sarete in grado di sistemare le cose senza problemi…

Ma funziona davvero?

Supponiamo che, nonostante tutta la buona volontà, il LED rimanga spento: come posso capire se la trasmissione è stata ricevuta? I moduli XBee prevedono di poter utilizzare alcuni pin per avere informazioni su quanto sta accadendo, e basterà aggiungere qualche LED per vedere come davvero stanno le cose. Sfrutteremo, più in particolare:

  1. il pin 6: si accende quando il modulo XBee riceve una trasmissione. In teoria dovrebbe variare la luminosità in base alla potenza del segnale ricevuto (Received Signal Strenght Indicator, RSSI, è un output digitale PWM) ma in pratica non si nota granchè. In ogni caso alla ricezione di un messaggio si accende e resta acceso 10 secondi (a meno di non variarrne la configurazione).
  2. il pin 13: acceso se il modulo è alimentato e attivo (non in sleep mode)
  3. il pin 15: segnala l’associazione del modulo ad una rete. Rimane fisso nella fase di ricerca della rete, ad associazione avvenuta inizia a lampeggiare.

Nell’immagine sopra, il LED verde indica lo stato (acceso), quello rosso l’associazione (lampeggiante, colto in un momento in cui era spento) e quello giallo indica la potenza del segnale ricevuto.

Possiamo poi modificare un po’ gli sketch caricati sugli Arduino per avere un ulteriore feedback: basterà far sì che, una volta eseguita l’istruzione richiesta (accensione o spegnimanto del LED), l’Arduino collegato al router invii indietro un feedback al coordinatore. Sull’Arduino router quindi carichiamo:

byte incoming;

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

}

void loop() {
  if(Serial.available()>0) {
    incoming = Serial.read();
    if (incoming == 'L') digitalWrite(13,LOW);
    if (incoming == 'H') digitalWrite(13,HIGH);
    Serial.print('A'); //invio 'A' per indicare tutto ok
  }
  delay(10);

}

mentre  sul coordinatore:

const int buttonPin = 2;     // pin a cui è collegato il bottone
const int ackPin=13;

int ledState =LOW; //assumiamo che all'inizio il led sia spento    
int lastButtonState = LOW; 

void setup() {
 pinMode(buttonPin, INPUT);
 pinMode(ackPin, OUTPUT);
 Serial.begin(9600);
}

void loop() {
 // legge lo stato del bottone
 int reading = digitalRead(buttonPin);
 if (reading == HIGH && reading != lastButtonState){
   // si agisce solo se lo stato del bottone è cambiato
   if (ledState == HIGH){
     Serial.print('L');
     ledState = LOW;
   }
   else {
    Serial.print('H');
    ledState =HIGH;
  }
 }
 lastButtonState = reading; // aggiorna lo stato del bottone
 if (Serial.available()>0){ //legge il feedback dalla seriale
                            //(se riceve'A' tutto ok)
 int incoming = Serial.read();  
 if (incoming == 'A') {
     digitalWrite(ackPin,HIGH);
     delay(30);
     digitalWrite(ackPin,LOW);
    }   
  }
  else delay(10); // pausa per non sovraccaricare la seriale
}

In questo modo, anche se il router è ‘remoto’ e quindi non visibile, sono in grado di capire se il segnale è stato ricevuto (in realtà la cosa è vera solo se la trasmissione è simmetrica, ma per ora va bene così).

Un LED, due LED, tanti LED

Finora le comunicazioni sono state punto a punto: sui ciascun modulo XBee è stato impostato come indirizzo di destinazione quello dell’altro modulo. Il protocollo ZigBee prevede anche la possibilità di inviare trasmissioni ‘broadcast’, ovvero direte a tutti i moduli associati ad una stessa rete. Il routing all’interno di una rete ZigBee è un argomento piuttosto complesso, quindi atteniamoci al pratico.

Prima di tutto, chi è intitolato ad eseguire il broadcasting? Solamente router e coordinatori. Gli end devices non lo possono fare, in quando sono in grado di parlare esclusivamente con il proprio dispositivo ‘parent’ che deve essere, appunto, un router od un coordinatore.

E come fa un modulo a lanciare un messaggio broadcast? E’ semplice: va impostato come indirizzo di destinazione un indirizzo speciale: 0xFFFF. Tutti i messaggi spediti a questo indirizzo, di fatto, saranno gestiti come broadcast. Attenzione però che gli algoritmi di routing non sono banalissimi e comportano una serie abbastanza articolata di richieste e risposte: generare messaggi broadcast con eccessiva frequenza potrebbe comportare un ‘intasamento’ della rete.

Nel nostro caso, se avessimo più moduli tutti configurati nello stesso modo, l’inserire l’indirizzo di broadcasting sul coordinatore come destinazione ci permetterebbe di accendere tutti i LED sparsi in giro con un solo bottone.

Nella prossima puntata: API!

(prima parte, seconda parte)

ledState
Print Friendly, PDF & Email
This entry was posted in Arduino, DIY, Hardware, Senza categoria, XBee and tagged , , , , , , . Bookmark the permalink.

2 Responses to Arduino, ZigBee e le infinite possibilità (3)

  1. Pingback: Arduino, ZigBee e le infinite possibilità (5) | The Monday Morning Tech Newsletter

  2. Stemby says:

    Sto seguendo con interesse tutta questa serie di guide.

    Riguardo questa puntata, pur essendo abbastanza ignorante in fatto di elettronica, mi sembra di vedere due errori:
    * i LED dovrebbero essere messi in serie con una resistenza ciascuno
    * per il bottone bisognerebbe prevedere un sistema anti-rimbalzo (anche solo software)

    È corretto?

    Grazie!

Lascia un commento

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