Serwisy partnerskie:
Close icon
Serwisy partnerskie

Używanie nadajnika i odbiornika RF 433MHz z Arduino

Podczas budowania projektów opartych na mikrokontrolerach zdarzają się sytuacje, w których wymagana jest komunikacja pomiędzy dwoma urządzeniami, albo w trybie duplex/transceiver (gdzie oba urządzenia mogą nadawać i odbierać w tym samym czasie), albo w trybie simplex, gdzie komunikacja jest jednokierunkowa (urządzenie odbierające nie może nadawać, a urządzenie nadające nie może odbierać).
Article Image

Istnieje kilka opcji dla wdrożenia któregokolwiek z dwóch wyżej wymienionych trybów komunikacji, a wybór konkretnej opcji zależy zwykle od specyfikacji projektu, zwłaszcza odległości między urządzeniami i kosztów. W przypadku komunikacji o niewielkim zasięgu i niskim budżecie pomiędzy dwoma mikrokontrolerami, jednym z najbardziej preferowanych mediów jest komunikacja za pomocą fal radiowych (RF) z wykorzystaniem modułów nadajnika i odbiornika 433MHz RF. W tym projekcie przyjrzymy się, jak wykorzystać te moduły do nawiązania komunikacji pomiędzy dwoma płytkami Arduino.

Moduły nadajnika i odbiornika 433 MHz

Moduły te są bardzo popularne wśród konstruktorów ze względu na ich niski koszt i łatwość użycia. Są one wykorzystywane we wszystkich formach komunikacji simplexowej krótkiego zasięgu między dwoma mikrokontrolerami,  gdy jeden z mikrokontrolerów służy jako nadajnik, a drugi służy jako odbiornik.Są to moduły ASK (Amplitude Shift Keying) lub OOK (Of Hook Keying) , co oznacza, że zazwyczaj nie czerpią żadnej mocy podczas transmisji logicznego "zero" i jako takie zużywają mało energii. Ten niski pobór mocy czyni je bardzo użytecznymi w implementacjach opartych na bateriach.

Niektóre specyfikacje modułów nadajnika i odbiornika są wymienione poniżej.

Specyfikacja nadajnika

Nadajnik RF 433 MHz
  • Napięcie robocze: 3…12 V
  • Prąd roboczy: maks. mniej niż 40 mA, min. 9 mA
  • Tryb rezonansu: (SAW)
  • Tryb modulacji: ASK
  • Częstotliwość robocza: 433,92 MHz
  • Moc nadawania: 25 mW
  • Błąd częstotliwości: +150 kHz (max)
  • Szybkość: mniej niż 10 Kbps
  • Zasięg transmisji: 90 m (w otwartej przestrzeni)

Specyfikacja odbiornika

Moduł odbiornika 433MHz
  • Napięcie robocze: 5 VDC +0,5 V
  • Prąd roboczy: ≤5,5 mA max
  • Tryb modulacji: OOK/ASK
  • Częstotliwość robocza: 433,92 MHz
  • Szerokość pasma: 2 MHz
  • Czułość: przekracza -100 dBm (50 Ω)

Aby zademonstrować łatwość, z jaką można dodać funkcje bezprzewodowe do projektów wykorzystujących te moduły, zbudujemy stację pogodową z możliwością zdalnego wyświetlania danych. Stacja pogodowa będzie składała się głównie z czujnika temperatury i wilgotności oraz modułu nadajnika 433 RF. Będzie mierzyć temperaturę i wilgotność otoczenia i wysyłać je przez nadajnik RF do jednostki wyświetlającej (odbierane przez moduł odbiornika RF) na kolorowym wyświetlaczu ST7735 1.8″ TFT LCD.

Schematy

Istnieją dwa schematy dla tego projektu. Pierwszy z nich jest dla nadajnika, który pobiera temperaturę i wilgotność z otoczenia i wysyła je do drugiej części projektu, odbiornika, który wyświetla dane na wyświetlaczu.

Schemat nadajnika

Układ nadajnika składa się z Arduino, czujnika temperatury i wilgotności DHT22 oraz modułu nadajnika RF 433 MHz. Można dodać akumulator, aby zapewnić zasilanie Arduino, gdy jest odłączone od komputera. Podłącz elementy tak, jak pokazano poniżej.

Schemat nadajnika

Dla przejrzystości, połączenia pinów pomiędzy Arduino i innymi komponentami są pokazane poniżej.

Arduino - moduł nadawczy 433 MHz
VCC
5V
GND
GND
DATA
D12
Arduino - DHT22
VCC
5V
GND
GND
Sygnał
D4

Schemat układu odbiornika

Odbiornik składa się z modułu odbiornika RF 433 MHz, kolorowego wyświetlacza TFT ST7735 1,8″ oraz Arduino Uno. Podłącz elementy jak pokazano poniżej.

Schemat podłączenia odbiornika i wyświetlacza

Ze względu na różnice w układzie pinów wyświetlacza w zależności od producenta i dla przejrzystości, połączenia pinów pomiędzy Arduino i innymi komponentami tworzącymi odbiornik są podane poniżej:

Arduino - Moduł Rx 433 MHz
VCC
5V
GND
GND
Dane
D4
1.8″ TFT – Arduino
VCC
5V
GND
GND
DATA
D12
LED
3,3V
SCK
D13
SDA
D11
DC
D9
CS
D10
Reset
D8

Po wykonaniu wszystkich połączeń, możemy  przystąpić do pisania kodu dla tego projektu.

Kod

Tak jak musieliśmy zbudować dwa urządzenia, tak samo napiszemy dwa różne kody do tego projektu. Jeden z nich będzie służył do sterowania nadajnikiem, a drugi do sterowania odbiornikiem.

Aby łatwo napisać kod do tego projektu, użyjemy bibliotek, które ułatwiają sterowanie każdą częścią projektu. Dla modułów RF użyjemy biblioteki virtual wire do wysyłania i odbierania danych, natomiast do wyświetlania odebranych danych użyjemy bibliotek Adafruit GFX i Adafruit ST7735, aby łatwo aktualizować wyświetlacz LCD ST7735. Aby łatwo uzyskać dane o temperaturze i wilgotności z czujnika DHT22. Użyjemy biblioteki Adafruit DHT sensor.

Algorytm działania kodu jest prosty. Dla nadajnika, uzyskujemy wartości temperatury i wilgotności z DHT22 i wysyłamy przez nadajnik RF do odbiornika. Dla odbiornika, uzyskanie wartości temperatury i wilgotności wysłanej przez nadajnik za pomocą modułu RF Receiver i wyświetlenie jej na wyświetlaczu LCD.

Pokrótce wyjaśnię  kod dla dwóch połówek projektu, zaczynając od kodu nadajnika.

Kod nadajnika

Zaczynamy od dołączenia bibliotek, które będą używane w kodzie.

//Written by Nick Koumaris
//info@educ8s.tv

#include <VirtualWire.h>
#include "DHT.h"

Po tym deklarujemy pin Arduino, do którego podłączony jest nasz DHT, a także określamy typ używanego DHT.

#define DHTPIN 4  

#define DHTTYPE DHT22

Następnie wskazujemy pin Arduino, który będzie użyty jako pin do transmisji danych (który jest połączony z pinem danych modułu nadajnika RF) oraz tworzymy pakiet struct, który będzie użyty do wysyłania danych.

const int led_pin = 13;
const int transmit_pin = 12;

struct package
{
  float temperature ;
  float humidity ;
};

Następnie definiujemy typ dla pakietu i tworzymy instancję klasy DHT, aby zaadresować czujnik DHT.

typedef struct package Package;
Package data;

DHT dht(DHTPIN, DHTTYPE);

Po wykonaniu tych czynności przechodzimy do funkcji void setup(), w której ustawiamy pin TX oraz inne parametry inicjalizujące moduł RF.

void setup()
{
    // Initialise the IO and ISR
    vw_set_tx_pin(transmit_pin);
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(500);       // Bits per sec
    pinMode(led_pin, OUTPUT);
}

Następna jest funkcja void loop(), w której za pomocą funkcji read sensor otrzymujemy temperaturę i wilgotność. Po uzyskaniu danych, są one wysyłane za pomocą funkcji vw_send(). Czas opóźnienia 2000ms jest zaimplementowany, aby stworzyć odstęp pomiędzy danymi i zapewnić, że jedna z nich zostanie wysłana przed drugą.

void loop()
{
  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
  readSensor();
  vw_send((uint8_t *)&data, sizeof(data));
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(led_pin, LOW);
  delay(2000);
}

Kompletny kod jest napisany poniżej i dołączony do pliku zip w sekcji download.

#include <VirtualWire.h>
#include "DHT.h"

#define DHTPIN 4  

#define DHTTYPE DHT22 

const int led_pin = 13;
const int transmit_pin = 12;

struct package
{
  float temperature ;
  float humidity ;
};


typedef struct package Package;
Package data;

DHT dht(DHTPIN, DHTTYPE);

void setup()
{
    // Initialise the IO and ISR
    vw_set_tx_pin(transmit_pin);
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(500);       // Bits per sec
    pinMode(led_pin, OUTPUT);
}



void loop()
{
  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
  readSensor();
  vw_send((uint8_t *)&data, sizeof(data));
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(led_pin, LOW);
  delay(2000);
}

void readSensor()
{
 dht.begin();
 delay(1000);
 data.humidity = dht.readHumidity();
 data.temperature = dht.readTemperature();
}

Kod odbiornika

Jak zwykle zaczynamy od dołączenia bibliotek, które będą używane.

//Written by Nick Koumaris
//info@educ8s.tv

#include <VirtualWire.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>

Następnie deklarujemy piny Arduino, do których podłączone są piny wyświetlacza LCD.

#define TFT_CS     10
#define TFT_RST    8                      
#define TFT_DC     9
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!

Następnie deklarujemy pin(receive_pin) Arduino, do którego podłączony jest pin danych modułu odbiornika RF i tworzymy zmienne char, które będą przechowywały wartości temperatury i wilgotności.

const int receive_pin = 12;
char temperatureChar[10];
char humidityChar[10];

Następnie tworzymy pakiet struct podobny do tego, który znajduje się w kodzie nadajnika.

struct package
{
  float temperature = 0.0;
  float humidity = 0.0;
};

Po wykonaniu tych czynności przechodzimy do funkcji void setup(), w której inicjalizujemy wyświetlacz oraz moduł odbiornika RF ustawiając prędkość bitową oraz uruchamiając PLL odbiornika.

void setup()
{
    tft.initR(INITR_BLACKTAB);
    tft.fillScreen(ST7735_BLACK); 
    printUI();
    delay(1000);

    // Initialise the IO and ISR
    vw_set_rx_pin(receive_pin);
    vw_setup(500);   // Bits per sec
    vw_rx_start();       // Start the receiver PLL running
}

Następnie funkcja void loop(). Rozpoczynamy ją od sprawdzenia czy została odebrana wiadomość za pomocą funkcji vw_have_message(). Jeśli wiadomość została odebrana, wyciągamy z niej dane o temperaturze i wilgotności i wyświetlamy je na wyświetlaczu LCD.

void loop()
{
    uint8_t buf[sizeof(data)];
    uint8_t buflen = sizeof(data);

if (vw_have_message())  // Is there a packet for us? 
  {
    vw_get_message(buf, &buflen);
    memcpy(&data,&buf,buflen);

    Serial.print("\nPackage:");
    Serial.print(data.temperature);
    String temperatureString = String(data.temperature,1);
    temperatureString.toCharArray(temperatureChar,10);
    tft.fillRect(10,20,80,30,ST7735_BLACK);
    printText(temperatureChar, ST7735_WHITE,10,20,3);

    String humidityString = String(data.humidity,1);
    humidityString.toCharArray(humidityChar,10);
    tft.fillRect(10,95,80,100,ST7735_BLACK);
    printText(humidityChar, ST7735_WHITE,10,95,3);

    Serial.print("\n");
    Serial.println(data.humidity);
  }
}

W kodzie znajdują się również funkcje, które posłużyły do wyświetlenia wyników w sposób bardziej przyjazny dla użytkownika.

void printText(char *text, uint16_t color, int x, int y,int textSize)
{
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextSize(textSize);
  tft.setTextWrap(true);
  tft.print(text);
}

void printUI()
{
    printText("TEMPERATURE", ST7735_GREEN,30,5,1);  // Temperature Static Text
    printText("o", ST7735_WHITE,90,13,2);
    printText("C", ST7735_WHITE,105,20,3);

    printText("HUMIDITY", ST7735_BLUE,30,80,1);  // Temperature Static Text
    printText("%", ST7735_WHITE,90,95,3);
}

Kompletny kod odbiornika jest dostępny poniżej. Jest on również załączony w pliku zip w sekcji download tego projektu.

#include <VirtualWire.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>

#define TFT_CS     10
#define TFT_RST    8                      
#define TFT_DC     9
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!

const int receive_pin = 12;
char temperatureChar[10];
char humidityChar[10];


struct package
{
  float temperature = 0.0;
  float humidity = 0.0;
};


typedef struct package Package;
Package data;


void setup()
{
    tft.initR(INITR_BLACKTAB);
    tft.fillScreen(ST7735_BLACK); 
    printUI();
    delay(1000);

    // Initialise the IO and ISR
    vw_set_rx_pin(receive_pin);
    vw_setup(500);   // Bits per sec
    vw_rx_start();       // Start the receiver PLL running
}

void loop()
{
    uint8_t buf[sizeof(data)];
    uint8_t buflen = sizeof(data);

if (vw_have_message())  // Is there a packet for us? 
  {
    vw_get_message(buf, &buflen);
    memcpy(&data,&buf,buflen);

    Serial.print("\nPackage:");
    Serial.print(data.temperature);
    String temperatureString = String(data.temperature,1);
    temperatureString.toCharArray(temperatureChar,10);
    tft.fillRect(10,20,80,30,ST7735_BLACK);
    printText(temperatureChar, ST7735_WHITE,10,20,3);

    String humidityString = String(data.humidity,1);
    humidityString.toCharArray(humidityChar,10);
    tft.fillRect(10,95,80,100,ST7735_BLACK);
    printText(humidityChar, ST7735_WHITE,10,95,3);

    Serial.print("\n");
    Serial.println(data.humidity);
  }
}

void printText(char *text, uint16_t color, int x, int y,int textSize)
{
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextSize(textSize);
  tft.setTextWrap(true);
  tft.print(text);
}

void printUI()
{
    printText("TEMPERATURE", ST7735_GREEN,30,5,1);  // Temperature Static Text
    printText("o", ST7735_WHITE,90,13,2);
    printText("C", ST7735_WHITE,105,20,3);

    printText("HUMIDITY", ST7735_BLUE,30,80,1);  // Temperature Static Text
    printText("%", ST7735_WHITE,90,95,3);
}

Demo

Wgraj odpowiedni kod do każdego z Arduino. Obie płytki Arduino mogą być zasilane za pomocą baterii. Po kilku minutach od włączenia urządzeń, na wyświetlaczu LCD powinny pojawić się dane o temperaturze i wilgotności.

Zasięg pary modułów nadajnika i odbiornika 433 MHz jest generalnie niewielki, ale poprzez przylutowanie zewnętrznych anten można zwiększyć ich zasięg.

Wideo
Do pobrania
Download icon Kod do Arduino do nadajnika i odbiornika 433 MHz

Artykuł Using the 433MHz RF transmitter and receiver with Arduino opracowano w wersji polskiej na podstawie współpracy z portalem www.electronics-lab.com.

AUTOR
Źródło
www.electronics-lab.com
Udostępnij
UK Logo
Elektronika dla Wszystkich
Zapisując się na nasz newsletter możesz otrzymać GRATIS
najnowsze e-wydanie magazynu "Elektronika dla Wszystkich"