How to use 433MHz RF Transmitter and Receiver Modules with Arduino.

433MHz RF Transmitter and Receiver

There are a number of ways of adding wireless capabilities to your electronics projects including Bluetooth, WiFi and using Radio Frequency transmitter and receiver modules. I have tutorials on how to use Bluetooth, Wifi and the nRF24L01 modules.

I will now discuss wireless communication using 433MHz RF modules which are cheap wireless modules providing one-way communication capabilities using Amplitude Shift Keying technique.

You need to be cautious when experimenting with devices that transmit radio waves and should be aware of the laws and regulations regarding unlicensed radio transmitters in your country of residence. However in most countries these 433MHz modules are legal for use as long as they are operated at low power, don’t transmit continuously and do not transmit voice signals.

433MHz RF modules hardware overview.

The modules consist of a Transmitter and Receiver as shown below

Transmitter

This is a Surface Acoustic Wave resonator tuned to operate at 433MHz. When the DATA input is high, the oscillator generates a constant RF output carrier wave at 433MHz, and when the DATA input is low, the oscillator ceases operation; resulting in an amplitude modulated wave. This technique is known as Amplitude Shift Keying.

The transmitter pinout is as follows:

  • DATA – for inputting digital data to be transmitter
  • VCC – power supply to the transmitter between 3.5 to 12V. The RF output is proportional to the supply voltage, so the higher the voltage, the greater the range.
  • GND – is ground pin
  • Antenna – for connecting an external antenna.

Receiver

Consists of an RF tuned circuit and a couple of operational amplifiers that amplify the received carrier wave. The amplified signal is then fed into a PLL (Phase Lock Loop), which allows the decoder to “lock” onto a stream of digital bits, resulting in improved decoded output and noise immunity.

The receiver pinout is as follows:

  • VCC – power supply for the receiver. The receiver uses 5V
  • DATA – there are two data pins that are internally linked so you can use either one for data out.
  • GND – ground pin
  • Antenna – for connecting an external antenna

Antenna for 433MHz RF modules

You need to attach antennas to both the transmitter and receiver in order to increase the range of transmission. A simple piece of 22 or 24 gauge solid wire can make an excellent antenna for both the transmitter and receiver.

The length of the most effective antenna is equal to the wavelength of the transmission frequency.

Equation for wave length of transmission frequency

The speed of transmission in air is equal to the speed of light, which is 299,792,458 m/s so for a 433MHz band the wavelength is:

wave length of transmission frequency

69.24cm will be quite a long antenna therefore it is more practical to use a half or quarter wave antenna.   A quarter wave will be 17.3cm.

It is common to coil the antenna wire to reduce the size and this sometimes increases the efficiency though it reduces the range of transmission.

ASK – Amplitude Shift Keying

433MHz RF modules use Amplitude Shift Keying technique to transmit digital data over the radio. In amplitude shift keying, the amplitude of the carrier wave is changed corresponding to an incoming data signal. It is sometimes referred to as Binary Amplitude Shift Keying because it only has two levels;

  • Digital 1 – the carrier wave is at full strength
  • Digital 0 – the carrier wave is off
Amplitude Shift Keying wave forms

The advantage of Amplitude Shift keying is that it is very simple to implement. The decoder circuitry is quite simple to design. Furthermore, ASK requires less bandwidth than other modulation techniques.

The disadvantage of ASK is that it is susceptible to interference from other radio devices and background noise. However, as long as you transmit data at a relatively slow rate, it can work reliably in most environments.

RadioHead Library

Before proceeding to look at how to connect and use 433MHz RF modules with Arduino, you need to first download install the RadioHead library into your Arduino IDE. This library was written by Mike McCauley for Airspayce and is used to drive many radio communication devices using a number of microcontrollers including Arduino.

You can download the RadioHead library form airspayce.com

To install the library, launch the Arduino IDE, navigate to Sketch > Include Library > Add.ZIP Library, and then choose the RadioHead file you just downloaded.

Connecting and testing the 433MHz RF modules using Arduino.

Connecting the Transmitter

Connect VCC to 5V of Arduino, GND to one of the Arduino ground terminals and the DATA to pin 12 of the Arduino. We use pin 12 since the RadioHead library we’ll be using in our sketch uses this pin for data output.

Connecting 433MHz RF Transmitter to Arduino

For better transmission, you can solder a 17.3 cm piece of solid hookup wire to the antenna terminal on the module.

Transmitter code

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

RH_ASK rf_driver;
 
void setup()
{
    // Initialize ASK Object
    rf_driver.init();
}
 
void loop()
{
    const char *msg = "Hello World!";
    rf_driver.send((uint8_t *)msg, strlen(msg));
    rf_driver.waitPacketSent();
    delay(1000);
}

We begin by loading the RadioHead ASK library and also include the Arduino SPI Library as the ASK library is dependant upon it.  Next we create an ASK object named “rf_driver”.

In the setup section we initialize the ASK object.

In the loop section, we begin by encoding a message which is a text string. This needs to be a char data type stored in a character pointer called “msg”. You can use any string but keep it fairly short, not be longer than 27 characters for optimal performance. Also be sure to count the number of characters in it since you will need that count for the receiver code. In my case my message has 12 characters.

The message is then sent using the send() function. This function takes two parameters: an array of data and the number of bytes to send.

The send() function is followed by the waitPacketSent() function, which waits until transmission is complete and then apply  delay of a second to give our receiver time to process everything. The delay can be longer depending on the length of the message sent.

After that the loop repeats and our message is sent over and over.

Connecting the Receiver

Although the receiver module has four pins the two center pins are tied together, so you can use either one for data out.

The connections are as follows:

Connect VCC to the 5V output from the Arduino, GND to any Arduino ground pin and DATA to digital pin 11 on the Arduino.

Connecting 433MHz Receiver to Arduino

Receiver code

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

RH_ASK rf_driver;
 
void setup()
{
    // Initialize ASK Object
    rf_driver.init();
 // Setup Serial Monitor
    Serial.begin(9600);
}
 
void loop()
{
   // Set buffer to size of expected message
    uint8_t buf[12];
    uint8_t buflen = sizeof(buf);
    // Check if received packet is correct size
    if (rf_driver.recv(buf, &buflen))
    {
      
      // Message received with valid checksum
      Serial.print("Message Received: ");
      Serial.println((char*)buf);         
    } 
}

The receive code is also very simple. It starts out exactly the same as the transmit code, loading both the RadioHead and SPI libraries and creating an ASK object.

In the setup routine we initialize the ASK object and we also set up the serial monitor as this is how we will view our received message.

In the loop section, we create a buffer to match the size of the transmitted message. Since my message is 12 characters I used a value of 12. You will need to adjust this to match your message length. Be sure to include any spaces and punctuation as they all count as characters.

Then we call the recv() function to activate the receiver. When a valid message is available, it copies it to its first parameter buffer and returns true. If the function returns true, the received message is printed on the serial monitor.

Then we go back to the start of the loop and do it all over again.

After loading the code open your serial monitor. If all is working you should see your message.

The above setup and code is useful for testing the working of 433MHz RF modules before using them in more practical applications. You can be able to adjust the length and orientation of the transmitting and receiving antennas in order to improve on the range of transmission.

Application of 433MHz RF Modules with Arduino to Send Sensor Data

After testing the working of our RF modules, we can now use them in a more practical application like sending sensor data. In this example, I am going to be sending temperature and humidity data from a DHT11 sensor attached to the transmitter and then displaying the readings on an I2C LCD on the receiver side.

Transmitter setup

Connecting the transmitter to Arduino is done as before but this time I’ll add a DHT11 temperature and humidity sensor. The DHT11 sensor has three pins; VCC connected to 5V of Arduino, GND connected to Arduino ground and Data Out pin connected to an Arduino digital I/O pin. In this case I used pin 8.

Transmitter code

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

#define outPin 8        // Defines pin number to which the sensor is connected 
// Define Variables 
float h;    // Stores humidity value in percent
float t;   // Stores temperature value in Celcius
 
// Define output strings 
String str_humid;
String str_temp;
String str_out;

RH_ASK rf_driver; // Create Amplitude Shift Keying Object
dht DHT;   // Creates a DHT object
 
void setup()
{    
    rf_driver.init();  // Initialize ASK Object
}
 
void loop()
{
   delay(2000);  // Delay so DHT-11 sensor can stabalize
    int readData = DHT.read11(outPin);
    h = DHT.humidity();  // Get Humidity value
    t= DHT.temperature();  // Get Temperature value
    
    str_humid = String(h);  // Convert Humidity to string
    
    str_temp = String(t);  // Convert Temperature to string
   
    str_out = str_humid + "," + str_temp;   // Combine Humidity and Temperature
    
    static char *msg = str_out.c_str();   // Compose output character
    
    rf_driver.send((uint8_t *)msg, strlen(msg));
    rf_driver.waitPacketSent(); 
}

As before begin by including both the RadioHead library and the Arduino SPI library.  We also include the dht.h library for the DHT11 sensor.

After that we define some constants for the DHT sensor, specifically the pin we have it connected to and the sensor in my case it is pin 8.

Next we define some variables for the temperature and humidity data. We also define some strings, we’ll need to convert the temperature and humidity floats to strings and assemble them into a comma delimited string so we can send it.

We create ASK and DHT objects. We also initialize the DHT11 sensor.

In the setup routine we initialize the ASK object.

In the loop section, we read the temperature and humidity values from the sensor and assign them to their respective floats. We then convert both of those floats to strings, which we then use to construct our comma delimited string.

The string is converted into a char named “msg”, then we send the char and wait until it has been transmitted then start the loop again.

Receiver setup

On the receiver side, we add an I2C LCD by connecting the lcd Clock to A5, Data to A4 and the VCC and GND to Arduino 5V and ground respectively.

Receiver code

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

LiquidCrystal_I2C lcd(0x27, 16, 2);

String str_humid;
String str_temp;
String str_out;

RH_ASK rf_driver;
 
void setup()
{
    rf_driver.init();
    lcd.begin();
    lcd.backlight();
}
 
void loop()
{
   // Set buffer to size of expected message
    uint8_t buf[11];
    uint8_t buflen = sizeof(buf);
    // Check if received packet is correct size
    if (rf_driver.recv(buf, &buflen))
    {
      // Message received with valid checksum
      // Get values from string    
     
      str_out = String((char*)buf);  // Convert received data into string
      
      // Split string into two values
      for (int i = 0; i < str_out.length(); i++) {
	if (str_out.substring(i, i+1) == ",") {
	str_humid = str_out.substring(0, i);
	str_temp = str_out.substring(i+1);
	break;
         }
      }
      //display values on lcd
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("TEMP:");
      lcd.print(str_temp);
      lcd.print((char)223);	
      lcd.print("C");
      lcd.setCursor(0,1);
      lcd.print("HUMIDITY: ");
      lcd.print(str_humid);
      lcd.print("%");               
    } 
}

Include the RadioHead ASK and Arduino SPI libraries. Also include Wire and LiquidCrystal_I2C libraries for controlling the I2C LCD.  Then we define the same strings we used in the transmitter sketch for temperature and humidity and one for the comma delimited string that we will be receiving.

Then we create an ASK object named “rf_driver” and LCD object

In the setup, we initialize the ASK object and setup the LCD parameters.

The loop also starts off the same as the last receiver sketch, the only difference being that our packet size is 11 characters.

If a valid packet is received we convert the received data into a string. This will be our comma delimited text.

The Arduino has no command to extract elements from a delimited string like other higher level programming languages do. So we run a small routine to do that for us. It measures the string length and the position of the comma then uses that information to divide the string into two substrings. We assign each of these substrings to the string variables we created to hold humidity and temperature values.

Finally we format the output text and display it on the LCD.

If the transmitter and receiver are setup properly and the corresponding code uploaded, you will be able to see the temperature and humidity readings displayed on the LCD.