MODULI: Esempio Ricevitore/Trasmettitore RF
Per costruire il seguente circuito occorre avere un Trasmettitore RF wireless e il suo modulo ricevente.
Attenzione! I progetti seguenti richiedono la presenza dell'antenna
Per costruire i programmi presentati in questa sezione č necessario utilizzare la libreria VirtualWire scaricabile al seguente link. Per installarla basta scompattare il file e copiare la cartella prodotta (VirtualWire) all'interno della cartella contenente le librerie di Arduino (solitamente C:\Program Files\Arduino\libraries). Terminare il setup aggiungendo la cartella appena copiata, mediante il menu "Add Library", all'interno dell'IDE di Arduino
Con questa operazione i files della libreria vengono poi ricopiati nella cartella
C:\Users\<User>\Documents\Arduino\libraries.
Qualora ci fossero problemi nell'installazione occorre cancellare la cartella della libreria
dalle due directory sopra citate e ripetere l'operazione.
Ecco alcune delle funzioni messe a disposizione dalla libreria.
Funzioni di configurazione
vw_set_tx_pin(transmit_pin)
Imposta
il pin di trasmissione. Il pin di default impostato nella libreria č il 12.
vw_set_rx_pin(receive_pin)
Imposta il pin per la ricezione. Il pin di default
impostato nella libreria č il 11.
vw_setup(baudrate)
Inizializza la libreria. Prima di
mandare in esecuzione tale comando tutti i pin devono essere giā stati
impostati. L'argomento č la velocitā di trasferimento (numero di bit al
secondo).
Funzioni di trasmissione
vw_send(message, length)
Trasmette il messaggio.
"message" č un array di byte mentre length
č il numero di byte da spedire. Questa funzione ritorna il controllo al
programma chiamante immediatamente ed esegue l'invio mediante un processo in
background basato su interrupt. Restituisce true se
il messaggio č stato accettato per la trasmissione false
se il messaggio č troppo lungo (maggiore di
VW_MAX_MESSAGE_LEN - 3).
vw_tx_active()
Ritorna true se il
messaggio č in spedizione altrimenti false. E'
utilizzato per testare se, dopo il comando di spedizione, il messaggio č stato
completamente trasmesso.
vw_wait_tx()
Aspetta che il messaggio sia completamente spedito. Solitamente č
utilizzato dopo il comando vw_send().
Funzioni di Ricezione
vw_rx_start()
Attiva il processo di
ricezione. E' necessario effettuare una chiamata a tale funzione prima di
procedere con qualsiasi ricezione. Attiva un processo in background basato su
interrupt che controlla se ci sono dati in arrivo.
vw_have_message()
Ritorna true se il messaggio č stato ricevuto. E'
analogo ai comandi "available" presenti in molte
librerie.
vw_wait_rx()
Attende l'arrivo di un messaggio.
Tale funzione termina solo quando arriva il messaggio altrimenti resta in attesa
per sempre.
vw_wait_rx_max(timeout_ms)
Aspetta l'arrivo di un messaggio per un tempo definito in "timeout_ms".
Restituisce true se arriva un messaggio
nell'intervallo stabilito, false altrimenti.
vw_get_message(buf, &buflen))
Legge l'ultimo messaggio ricevuto.
Tale funzione dovrebbe essere chiamata solo quando si č verificato l'arrivo di
un messaggio mediante una delle 3 precedenti funzioni. "buf"
č un array dove verrā depositato il messaggio in arrivo. "buflen"
contiene inizialmente la dimensione dell'array e successivamente il numero di
byte letti. La funzione restituisce true se il
messaggio ricevuto č corretto altrimenti false se il
messaggio appare corrotto (non ).
vw_rx_stop()
Disabilita il processo di ricezione.
Codice Sorgente A
Obiettivo progetto: Accendere un LED su un circuito remoto quando schiaccio un pulsante sul circuito dotato di trasmettitore RF
soluzione:
Per costruire il circuito del trasmettitore servono:
Costruiamo il seguente circuito trasmettitore (si osservi la presenza dell'antenna ottenuta mediante un semplice cavo di collegamento):
e quello del ricevitore
Ecco il codice del trasmettitore
#include <VirtualWire.h> #define TX_pin 12 #define LED_pin 13 #define PB_pin 3 int prec_Stato=-1; const char *msg_ON = "LED_ON"; const char *msg_OFF = "LED_OFF"; void setup() { Serial.begin(9600); pinMode(LED_pin,OUTPUT); pinMode(PB_pin,INPUT); digitalWrite(LED_pin, LOW); vw_set_tx_pin(TX_pin); // Imposto il pin per la trasmissione vw_setup(3000); // Bits per sec } void loop() { int buttonState = digitalRead(PB_pin); if (buttonState!=prec_Stato) { if (buttonState==HIGH) vw_send((uint8_t *)msg_ON, strlen(msg_ON)); else vw_send((uint8_t *)msg_OFF, strlen(msg_OFF)); vw_wait_tx(); // Aspetta che il processo in background di spedizione sia completo Serial.println("Stato: "+String(buttonState) + " - Prec. Stato: "+String(prec_Stato)); digitalWrite(LED_pin, buttonState); prec_Stato=buttonState; } }
e quello del ricevente
/* ---------------------------------------------------------- Riceve un comando per accendere il led sul pin 13 ----------------------------------------------------------- */ #include#define LED_pin 13 #define RX_pin 11 void setup() { pinMode(LED_pin, OUTPUT); digitalWrite(LED_pin, LOW); vw_set_rx_pin(RX_pin); //Non servirebbe: il default č 11 vw_setup(3000); // Bits per sec vw_rx_start(); // Inizio il processo di ricezione Serial.begin(9600); // Solo per debug Serial.println("Ricevitore attivo: "); } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if (vw_get_message(buf, &buflen)) // Non-blocking { buf[buflen]='\0'; // Metto il terminatore di stringa if (strncmp((char *)buf,"LED_ON",buflen)==0) digitalWrite(LED_pin, HIGH); // Accendo il LED else if (strncmp((char *)buf,"LED_OFF",buflen)==0) digitalWrite(LED_pin,LOW); // Spengo il LED Serial.print("Comando Ricevuto (" +String(buflen)+" car.): "); Serial.println((char *)buf+String("//")); } }
Con questo codice quando premo il pushbutton sul Serial Monitor (del trasmettitore) appare il seguente messaggio:
Mentre sul Serial Monitor del ricevitore appare la seguente risposta:
Inoltre quando al ricevitore arriva il comando LED_ON il led si accende mentre si spegne quando riceve il comando LED_OFF.
Codice Sorgente B
Obiettivo progetto: costruire un circuito ricevente e uno trasmissivo che consenta di replicare sul Serial Monitor del ricevente quello che viene digitato sul Serial Monitor del trasmettitore. Il limite di caratteri č pari a 26 (VM_MAX_MESSAGE_LEN-4)
soluzione:
Possiamo riutilizzare gli stessi circuiti costruiti nell'esempio precedente. Ecco il codice del trasmettitore
/* ------------------------------------------------------ Invia il testo scritto sul Serial Monitor del trasmettitore al Serial Monitor del ricevente --------------------------------------------------------- */ #include <VirtualWire.h> int i=0; char buffer[VW_MAX_MESSAGE_LEN-3]; // posso spedire 26 char al massimo #define RX_pin 12 void setup() { Serial.begin(9600); Serial.println("Trasmettitore:"); vw_set_tx_pin(RX_pin); vw_setup(3000); } void loop() { if ( (Serial.available() > 0) && (i <(VW_MAX_MESSAGE_LEN-4) ) ) { buffer[i++] = Serial.read(); delay(10); // piccolo ritardo per evitare che spezzi l'invio della frase } else if (i>0) { buffer[i]='\0'; vw_send((uint8_t *)&buffer, i+1); // spedisce al massimo VW_MAX_MESSAGE_LEN-3 {26} caratteri vw_wait_tx(); // Aspetta che il processo in background di spedizione sia completo Serial.print(buffer+String(" -->> send (")+String(i)+String(" char)\n")); i=0; } }
e quello del ricevente
/* ------------------------------------------------------ Riceve il testo scritto sul Serial Monitor del trasmettitore e lo mostra sul suo Serial Monitor (ricevente). --------------------------------------------------------- */ #include <VirtualWire.h> #define RX_pin 11 void setup() { Serial.begin(9600); Serial.println("Ricevitore:"); vw_set_rx_pin(RX_pin); vw_setup(3000); vw_rx_start(); } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if (vw_get_message(buf, &buflen)) { buf[buflen]='\0'; // Metto il terminatore di stringa Serial.println(String("Receive (") +String(buflen-1)+String(" char) --> {") +(char *)buf+"}"); } }
Sul Serial Monitor del ricevente appare la sequenza di messaggi
digitata su quello del trasmittente:
Codice Sorgente B1
Obiettivo progetto: obiettivo identico al precedente ma con la possibilitā di trasmettere un numero arbitrario di caratteri.
soluzione:
Ecco il codice del trasmettitore
/* ------------------------------------------------------ Invia il testo scritto sul Serial Monitor del trasmettitore al Serial Monitor del ricevente --------------------------------------------------------- */ #include <VirtualWire.h> #define RX_pin 12 #define N 10 int i=0; int r=0; char buffer[N][VW_MAX_PAYLOAD]; // posso spedire N x 27 char void setup() { Serial.begin(9600); Serial.println("Trasmettitore:"); vw_set_tx_pin(RX_pin); vw_setup(3000); } void loop() { int j; if ( (Serial.available() > 0) ) { // Questo Loop senza delay() permette di acquisire tutti i dati // nel buffer del Serial Monitor. while ((Serial.available() > 0)) { if ( i == (VW_MAX_PAYLOAD-1) ) { buffer[r][i]='\0'; r++; i=0; } buffer[r][i++] = Serial.read(); } buffer[r][i]='\0'; delay(10); // piccolo ritardo per evitare che dei pezzi di frase vengano persi } else if ( (i>0) || (r>0) ) { for (j=0 ; j <= r ; j++) { vw_send( (uint8_t *)&buffer[j], strlen(buffer[j]) ); // spedisco l'intera riga vw_wait_tx(); // Aspetta che il processo in background di spedizione sia completo } for (j=0 ; j <= r ; j++) Serial.print(buffer[j]+String(" {")+String(strlen(buffer[j]))+String(" char}\n")); Serial.print(String(" -->> send (")+String(r+1)+String("-> nr. righe // ")+String(r*(VW_MAX_PAYLOAD-1)+i)+String(" char)\n")); i=r=0; } }
Sul Serial monitor del trasmettitore appare questo risultato se digito la frase: "Questo č un esempio di trasmissione via radio tramite Arduino implementata da Marco Sechi"
Mentre il codice del ricevente č lo stesso del precedente esempio B.