Arduino – Trasmissione senza fili a 433 Mhz : Radiocomando a 3 canali

Dopo il sensore di temperatura wireless visto in un altro articolo, vediamo questa volta come realizzare un semplice radiocomando a tre canali con la coppia di moduli XD-FST XD-RF-5V gia visti in precedenza. Con questo dispositivo si possono realizzare una gran quantità di apparecchi comandati a distanza, come ad esempio prese o luci radio comandate, serrande elettriche, controllo a distanza di motori, ecc. In pratica, partendo dallo schema base e modificandolo in base alle proprie necessità possiamo realizzare molto facilmente qualsiasi dispositivo azionato a distanza.

 

Schema elettrico

Lo schema di base nel suo complesso è molto semplice, infatti sul trasmettitore vediamo tre soli pulsanti posti in serie alla propria resistenza da 10k e collegati alle entrate A0,A1 e A2, mentre il pin 12 è collegato all’ingresso DATA del modulo trasmettitore. Premendo uno dei tre pulsanti metteremo l’ingresso corrispondente a livello logico zero e così facendo invieremo un comando in grado di attivare o disattivare  una delle uscite poste sul ricevitore.

 

 

 

 

I tre led sono collegati ai pin 7, 8 e 9 mentre il pin 11 è collegato al terminale DATA del modulo ricevente. Il buzzer collegato al pin 5 emette ogni cinque secondi tanti beep quante sono le uscite che si trovano a livello logico 1, quindi se rimarrà accesso un solo led verrà emesso un solo beep, se i led accesi sono due allora verranno emessi due beep e così via. Questa segnalazione acustica può essere disattivata agendo sull’interruttore posto in serie su uno dei suoi terminali.

I led collegati sulle uscite possono essere sostituiti da relè per comandare carichi di una certa potenza e per far questo possiamo fare riferimento alla figura sottostante. Esso rappresenta il classico esempio per pilotare correttamente un relè attraverso un comune transistor NPN tipo BC547. Il diodo 1N4007 collegato in serie al collettore serve per proteggere il transistor dalle extra tensioni generate durante l’apertura e la chiusura dei contatti, mentre il diodo led ne indica lo stato di attivazione.

 

 

Se vogliamo trasformare lo schema visto sopra in maniera definitiva, e renderlo quindi più pratico da utilizzare, possiamo realizzare sia per il trasmettitore che per il ricevitore un sistema stand alone come mostrato nelle figure sottostanti.

 

Schema del trasmettitore stand alone con ATmega 328P

 

 

 

Schema del ricevitore stand alone

 

In questo caso dovremo procurarci due micro controllori ATmega 328 PU ( lo stesso chip presente sulle schede Arduino UNO ), preferibilmente con il boot loader precaricato, e pochi altri componenti come i quarzi da 16 Mhz, i condensatori da 22 pF e da 10 uF e gli stabilizzatori di tensione a 5 volt tipo 7805. Per i transistor possiamo usare indifferentemente i modelli BC 547 oppure i 2n2222 mentre per i relè i modelli da scegliere sono quelli con tensione di funzionamento a 5 V. Infine, anche per i diodi collegati in serie al collettore dei transistor possiamo scegliere il tipo  1N4007, 1N4004 o simili.  Per quanto riguarda invece la procedura di caricamento degli sketch sui controllori si rimanda ai numerosi tutorial sull’argomento presenti su Internet.

 

Gli sketch

Quello che segue è lo sketch relativo al trasmettitore nel quale ad ogni pressione di uno dei tre pulsanti, attraverso la funzione trasmetti(), si invia al ricevitore una stringa associata ad una determinata uscita.

 

/*
 * Programma radiocomando a 433 Mhz  : TRASMETTITORE
 */

#include <RH_ASK.h>
#include <SPI.h>
#define p1 A0
#define p2 A1
#define p3 A2



RH_ASK askTx;  // Crea un oggetto ASK che permette la trasmissione di dati via radio pin 12

void setup()
{
  pinMode(p1, INPUT);
  pinMode(p2, INPUT);
  pinMode(p3, INPUT);
  askTx.init();   // inizializza l'oggetto ASK

}

// Trasmette la stringa che dovrà essere riconosciuta dal ricevitore
//
void trasmetti(char *msg)
{
  askTx.send((uint8_t *)msg, strlen(msg));
  askTx.waitPacketSent();
  delay(200);
}


void loop()
{

  if (digitalRead(p1) == LOW ) {
    trasmetti("led1");
  }

  if (digitalRead(p2) == LOW ) {
    trasmetti("led2");
  }

  if (digitalRead(p3) == LOW ) {
    trasmetti("led3");
  }

}

 

 

Questa stringa captata dal modulo Rx verrà dapprima analizzata per poi andare ad attivare o disattivare una delle tre uscite. In pratica ogni pulsante sul trasmettitore inverte il livello logico presente sull’uscita corrispondente, quindi premendo una volta accenderemo il led ( o il relè ), premendolo nuovamente lo stesso led ( o relè ) verrà spento e viceversa in un ciclo continuo ON-OFF.

Un aspetto cui bisogna prestare attenzione è la lunghezza della stringa che intendiamo trasmettere e che sarà analizzata nel ricevitore. Ad esempio, premendo il pulsante p1 sul trasmettitore invieremo la stringa “led1” formata da 4 caratteri, nel ricevitore la lunghezza di questa stringa sarà usata anche per il riconoscimento del dato ricevuto perciò è necessario che anche la variabile lung_datoRicevuto sia impostata a 4.  Così pure quando andremo ad usare il metodo substring() della variabile “dato” ( convertita in stringa ) dovremo mettere come secondo parametro il numero 4.  Facendo un altro esempio, se dal trasmettitore attraverso la pressione di uno dei pulsanti decidiamo di inviare la stringa “led1ONOFF“, poichè essa è formata da 9 caratteri,  sappiamo quindi che nello sketch del ricevitore dovremo scrivere “byte lung_datoRicevuto = 9;” e  “if (String(dato).substring(0, 9) == “led1ONOFF”)”  per far si che l’uscita del led ( o relè ) in questione venga commutata. Anche se nel codice non è riportato, si potrebbe tranquillamente inserire la variabile lung_datoRicevuto nel metodo di estrazione della sotto stringa, scrivendo cioè “if (String(dato).substring(0, lung_datoRicevuto ) == “led1ONOFF”)“.

 

/*
   Programma radiocomando a 433 Mhz  : RICEVITORE
*/

#include <RH_ASK.h>
#include <SPI.h>

int led1 = 8; // led rosso
int led2 = 9; // led verde
int led3 = 7; // led blu

#define buzzer 5

unsigned long tempoTrascorso;
unsigned long t0 = 0;
byte nUscite;

RH_ASK ask; // Crea un oggetto ask per la ricezione dati

void setup()
{

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(buzzer, OUTPUT);
  ask.init();           // Inizializza l'oggetto ask sul pin 11


}


// Genera il beep riprodotto dal buzzer collegato all'uscita 5

void beep_Usc_att(int n) {

  for (int i = 1; i < n; i++)
  {
    analogWrite(buzzer, 30);  // valore compreso tra 1 e 254
    delay(40);
    analogWrite(buzzer, 0);
    delay(150);
  }
}




void loop()
{

  // Array in cui viene memorizzato il dato ricevuto

  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
  uint8_t buflen = sizeof(buf);
  byte lung_datoRicevuto = 4; // Lunghezza dell stringa che ci si aspetta di avere
  char dato[lung_datoRicevuto];

  if (ask.recv(buf, &buflen))
  {

    // Prendo i primi quattro caratteri della variabile buf e li memorizzo nella variabile 'dato'

    for (int j = 0; j < lung_datoRicevuto; j++)
    {
      dato[j] = buf[j];
    }



    // converto la variabile char 'dato' in stringa
    // e controllo se è idonea a comandare una delle tre uscite led

    if (String(dato).substring(0, 4) == "led1")
    {
      digitalWrite(led1, !digitalRead(led1)); // inverto lo stato del led 1

    }

    if (String(dato).substring(0, 4) == "led2")
    {
      digitalWrite(led2, !digitalRead(led2)); // inverto lo stato del led 2

    }

    if (String(dato).substring(0, 4) == "led3")
    {
      digitalWrite(led3, !digitalRead(led3)); // inverto lo stato del led 3

    }

  }


  // Stato delle uscite

  tempoTrascorso = millis();

  if (tempoTrascorso >= 10000)                // Dopo 10 secondi la variabile tempoTrascorso viene azzerata
  {
    tempoTrascorso = 0;
    tempoTrascorso = millis();
  }


  // Ogni lasso di tempo uguale a t0+millisec ( in questo caso 5 secondi )
  // vengono emessi un numero di beep corrispondenti al numero di uscite a livello logico 1 ( HIGH )
  //
  if (tempoTrascorso > t0 + 5000)
  {
    int n = 0;
    int uscite[] = {led1, led2, led3};

    for (int x = 0; x < sizeof(uscite);  x++)
    {
      if (digitalRead(uscite[x]) == HIGH)
      {
        n++;
      }
    }
    beep_Usc_att(n);

    t0 = millis();
  }


}

 

L’ultima parte del codice non fa altro che verificare ogni 5 secondi  quante uscite si trovano a livello logico 1 ( led accesi o relè attivati ) ed emettere il corrispondente numero di beep attraverso il richiamo della funzione beep_Usc_att( int n ).  Come già specificato nel precedente articolo, per assicurare una buona trasmissione su entrambi i moduli è necessario saldare sugli appositi reofori contrassegnati con la dicitura “ANT” uno spezzone di filo del diametro di 1-2 mm e lungo 17 cm.

 

Trasmettitore e ricevitore su breadbord

 

 

 

Pin Out dei moduli radio XD-FST ( TX ) e XD-RF-5V (RX)

 

 

 

 

Qui è possibile scaricare i file del progetto

Sketch TX RX radiocomando

Schemi

RadioHead-1.86