venerdì 1 maggio 2015

Comunicazione Wireless con XD-FST e XD-RF-5V e Arduino

Volevo fare un piccolo tutorial sul trasmettitore wireless XD-FST e il suo ricevitore XD-RF-5V. Ho iniziato con questi due componenti in quanto sono tra i più economici, si possono comprare in coppia su amazon ad un prezzo non superiore alle 4€ con spese di spedizione incluse, UN VERO AFFARE!

Il trasmettitore ha una modulazione a Radio Frequenza di 433Mhz ed è adatto a tutte quelle applicazioni che necessitano di un comando a distanza a ristretto raggio come l'apertura di un box, il comando per le finestre, accensione e spegnimento di luci, o come nel mio caso, il semplice invio di messaggi testuali wireless.

Il moduli si presentano cosi:


Se si fa una veloce ricerca su google si intuisce subito l'utilizzo è un gioco da ragazzi (inesperti) anche se io, per grandissima sfortuna (una sfortuna che si aggira ad 1 probabilità su 13), ho avuto un po di grattacapi, che in seguito espliciterò.

Innanzi tutto la prima cosa da fare, se non si vuole gestire manualmente tutta la comunicazione, è scaricare la libereria VirtualWire reperibile gratuitamente qui:

http://www.airspayce.com/mikem/arduino/VirtualWire/

Come scritto nelle prime righe è una libreria ormai non più mantenuta e sostituita da RadioHead, non ho ancora avuto modo di utilizzarla, ma sembra sicuramente più completa rispetto alla sua antecedente, anche se più complessa soprattutto per chi come me ha poca conoscenza dei diversi standard wireless.
Quindi continuando sulla nostra strada possiamo scaricare la versione 1.27 di VirtualWired direttamente dal link segnato sotto nella pagina dello sviluppatore, oppure più comodamente da questo link VirtualWired v1.27

Una volta scaricato e spacchettato verrà creara la cartela WirtualWire che avrà al suo interno i seguenti file:



-rw-r--r-- 1      39 gen 14  2013 CHANGES
drwxr-xr-x 2    4096 apr 29  2014 doc/
drwxrwxr-x 6    4096 apr 20 21:22 examples/
-rw-r--r-- 1      22 apr 17  2008 keywords.txt
-rw-r--r-- 1     841 apr 20  2008 LICENSE
-rw-r--r-- 1     677 apr 29  2014 Makefile
-rw-r--r-- 1     426 apr 29  2014 MANIFEST
-rw-r--r-- 1     248 apr 20  2008 README
-rw-r--r-- 1    4627 feb 24  2014 VirtualWire_Config.h
-rw-r--r-- 1   24086 apr 29  2014 VirtualWire.cpp
-rw-r--r-- 1   20522 apr 29  2014 VirtualWire.h
drwxrwxr-x 2    4096 apr 20 21:22 VWutil/


copiate quindi tutta la cartella nelle librerie utente di Arduino (nei sistemi Linux nella propria home, mentre nei sistemi Windows nella cartella Documents)

nel mio caso (con Ubuntu) la directory è la seguente:



/home/GnaGna/Arduino/libraries



Dopo aver copiato la cartella, apriamo Arduino IDE e iniziamo a sviluppare

Il cirtuito

Come si può notare il circuito è molto semplice, tutto quello che entrami i circuiti hanno bisogno è di 5V, GND e un segnale DATI.

Il trasmettitore



#include <VirtualWire.h>
void setup()
{
    vw_set_ptt_inverted(true);  // Required by the RF module
    vw_setup(2000);            // bps connection speed
    vw_set_tx_pin(3);         // Arduino pin to connect the transmit data pin
}
 
void loop()
{
   //Message to send:
   const char *msg = "Hello World";
   vw_send((uint8_t *)msg, strlen(msg));

   vw_wait_tx();        // We wait to finish sending the message       
   digitalWrite(13,HIGH);
   delay(200);         
   digitalWrite(13,LOW);   
}


Il setup non è complesso, ha solo 3 istruzioni, vw_set_ptt_inverted indica se il pin Push-To-Talk (apertura del canale durante la trasmissione) deve essere basso (zero) o alto (5v), nel caso del trasmettitore wireless XD-FST apre al comunicazione quando il pin è basso (quindi invertito rispetto al default).
La seconda istruzione indica la velocità di comunicazione, ho visto che nei vari tutorial è settata a 2000, quindi da brava pecorella l'ho riportata senza nessuna modifica, non ho provato a modificare il valore per vedere il risultato, ma sicuramente è una cosa da provare. Se si varia questo valore bisogna solo avere la cortezza di modificare il valore anche nel ricevitore. Infine, vw_set_tx_pin setta il pin utilizzato per inviare il messaggio (nel mio caso il pin 3).
Il loop non è assolutamente più complesso, la prima riga setta il messaggio da inviare (il classico Hello World), la seconda riga invia il messaggio, mentre la terza attende il completamento dell'invio, questo è tutto, per avere un riscontro di invio messaggio potete accendere il led standard 13 su arduino con le istruzioni successive.

Il Ricevitore




// include the library code:
#include <VirtualWire.h>

void setup() {
  Serial.begin(9600); 
  vw_set_ptt_inverted(true);  // Required by the RF module
  vw_setup(2000);            // bps connection speed
  vw_set_rx_pin(7);         // Arduino pin to connect the receiver data pin
  vw_rx_start();           // Start the receiver
}

void loop() { 
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if (vw_get_message(buf, &buflen)){      // We check if we have received data
  
    buf[buflen]='\0'; // Metto il terminatore di stringa
    String msg = (char *)buf;
    
    Serial.println(msg);
    Serial.println();
  }
}


la funzione di setup è autoesplicativa, la pirma riga setta la porta seriale (per avere un riscontro nel monitor dell'IDE di Arduino. Come nel caso del trasmettitore, la seconda e la terza riga settano rispettivamente la modalità del segnale di Push-To-Talk e la velocità di comunicazione (ricordarsi di utilizzare la stessa settata nel trasmettitore). Le riga successiva vw_set_rx_pin setta il pin di ricezione (nel mio caso il pin 7), mentre l'ultima riga vw_rx_start abilita il ricevitore.
La funzione di loop è un po' più complessa, la prima riga setta l'array dove verrà messo il contenuto del messaggio (VW_MAX_MESSAGE_LEN è una "costante" definita nella libreria VirtualWire, ha un valore di 30, questo significa che il singolo messaggio trasmesso avrà una lunghezza massima di 30byte), la seconda riga setta il valore della costante nella variabile buflen. Il controllo if successivo è utilizzato per controllare se è stato ricevuto un messaggio, se la funzione vw_get_message() ritorna true, mette nella variabile buf il messaggio e nella variabile buflen la lunghezza del messaggio ricevuto.
Prima nel controllo if è possibile aggiungere la funzione vw_wait_rx(); che rimane in attesa fino alla ricezione del messaggio, attenzione, questo metodo è bloccante, di conseguenza se avete esigenza di eseguire altre istruzioni durante l'attesa non è consigliato utilizzarlo, diversamente, se tutta la logica si basa sulla ricezione ("quando ricevo, allora faccio qualcosa") questo metodo potrebbe essere utile per non "sovracaricare" il controllore.
Una volta ricevuto il messaggio e la funzione vw_get_message ritorna il valore true, aggiungo inizialmente il carattere terminatore (in modo da poter utilizzare il messaggio come String), creo una variabile String con il messaggio, e stampo sul monitor di Arduino il messaggio ricevuto dal Trasmettitore

ATTENZIONE!

la libreria VirtualWire setta impropriamente dei pin di default per l'Rx, Tx, e PTT rispettivamente i pin 11, 12 e 10, di seguito le righe di codice incrimitate



// The digital IO pin number of the press to talk, enables the transmitter hardware
static uint8_t vw_ptt_pin = 10;
static uint8_t vw_ptt_inverted = 0;

// The digital IO pin number of the receiver data
static uint8_t vw_rx_pin = 11;

// The digital IO pin number of the transmitter data
static uint8_t vw_tx_pin = 12;


di conseguenza se create un circuito che utilizza VirtualWire utilizzando i pin sopra indicati per altri scopi (e non volete perdere ORE ed ORE come nel mio caso cercando di capire il perche il circuito da voi progettato non fa quello che si attende) ricordate di modificare nella funzione setup i pin Rx,Tx e PTT di VirtualWire, è sufficiente chiamare le seguenti funzioni di set.



void vw_set_rx_pin(uint8_t pin)
void vw_set_tx_pin(uint8_t pin)
void vw_set_ptt_pin(uint8_t pin)