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.