MODULI: Esempio Ricevitore/Trasmettitore RF

Per costruire il seguente circuito occorre avere un Trasmettitore RF wireless e il suo modulo ricevente.

 RF Ricevitore e Trasmettitore

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

Agiunta libreria

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):

Trasmettitore RF

e quello del ricevitore

Ricevitore RF

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:

Output Trasmettitore RF

Mentre sul Serial Monitor del ricevitore appare la seguente risposta:

Output Ricevitore RF

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

 Output Receiver 1

digitata su quello del trasmittente:

Output Transmitter

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"

Esempio B1

Mentre il codice del ricevente č lo stesso del precedente esempio B.