Want wireless communication between two Arduinos without the complexity of WiFi or Bluetooth? Arduino RF 433MHz wireless modules are the simplest, cheapest, and most range-capable solution for one-way or two-way data transmission up to 100 metres. This tutorial covers the complete setup: hardware selection, wiring, the RadioHead library, encoding and decoding data, extending range with antennas, and building a practical wireless sensor node that transmits temperature data reliably.
Table of Contents
- Overview of 433MHz RF Modules
- Hardware You’ll Need
- Wiring Transmitter and Receiver
- RadioHead Library Setup
- Basic Transmit and Receive
- Sending Structured Data
- Antenna: Dramatically Improve Range
- Practical Project: Wireless Temperature Node
- FAQ
Overview of 433MHz RF Modules
The 433 MHz ISM (Industrial, Scientific, Medical) band is a license-free radio frequency used worldwide for short-range devices. The most common Arduino-compatible modules are the FS1000A transmitter and XY-MK-5V receiver pair — a matched pair that costs under ₹100 combined and can achieve 20-100 metre range depending on environment and antenna quality.
Key characteristics of 433 MHz RF:
- Range: 20-50 m (no antenna) to 100+ m (quarter-wave antenna in open air)
- Data rate: Up to 5 Kbps with ASK modulation; RadioHead library works well at 2 Kbps
- Power: Transmitter: 3-12V (higher voltage = longer range); Receiver: 5V
- Modulation: ASK (Amplitude Shift Keying) — simple on/off RF carrier
- Frequency: 433.92 MHz (check local regulations; some regions require 315 MHz instead)
- Interference: Susceptible to noise from motors, switching supplies, and other 433 MHz devices (garage door openers, weather stations, etc.)
Compared to alternatives: 433 MHz offers better range than Bluetooth, works without a router (unlike WiFi), and is far simpler than LoRa — but it has lower data rate and no encryption. It’s ideal for simple sensor-to-hub setups like garden monitoring, garage door triggers, and remote switch control.
Hardware You’ll Need
- 2x Arduino Uno (or Nano) boards — one for transmitting, one for receiving
- 1x FS1000A 433 MHz transmitter module
- 1x XY-MK-5V 433 MHz receiver module
- 2x 17 cm copper wire (for quarter-wave antennas — more on this later)
- Breadboards and jumper wires
- Optional: DHT11/DHT22 temperature sensor (for the practical project)
The transmitter module has 3 pins: DATA, VCC, GND. The receiver has 4 pins: VCC, DATA, DATA (redundant, same signal on both), GND. Some receiver modules have a 4th pin for an external antenna.
Wiring Transmitter and Receiver
Transmitter wiring:
- VCC → Arduino 5V (or up to 12V for extended range via external supply)
- GND → Arduino GND
- DATA → Arduino digital pin 12
Receiver wiring:
- VCC → Arduino 5V
- GND → Arduino GND
- DATA → Arduino digital pin 11
- ANT (if present) → 17 cm wire
Important notes:
- The transmitter and receiver are separate modules. Each connects to its own Arduino.
- Do NOT connect both to the same Arduino’s 5V if the transmitter is running at 5V — the RF interference can corrupt serial communication.
- Keep the transmitter away from the receiver during initial testing (at least 10 cm). Too close and the signal saturates the receiver.
RadioHead Library Setup
The RadioHead library by Mike McCauley is the standard library for RF modules on Arduino. It handles bit timing, preamble, message framing, and CRC error checking — you get reliable packet-based communication instead of raw bit banging.
Install it:
- Go to Sketch → Include Library → Manage Libraries
- Search for “RadioHead”
- Install “RadioHead” by Mike McCauley
The library supports multiple RF drivers. For 433 MHz ASK modules, use RH_ASK.
Basic Transmit and Receive
Transmitter sketch:
#include <RH_ASK.h>
#include <SPI.h> // Required by RadioHead even for ASK
// RH_ASK(speed, rxPin, txPin, pttPin, invertedPTT)
// Default: 2000 bps, rx=11, tx=12, ptt=10
RH_ASK driver;
void setup() {
Serial.begin(9600);
if (!driver.init()) {
Serial.println("RF init failed!");
} else {
Serial.println("RF transmitter ready");
}
}
void loop() {
const char *msg = "Hello from TX!";
driver.send((uint8_t *)msg, strlen(msg));
driver.waitPacketSent();
Serial.println("Message sent");
delay(1000);
}
Receiver sketch:
#include <RH_ASK.h>
#include <SPI.h>
RH_ASK driver;
void setup() {
Serial.begin(9600);
if (!driver.init()) {
Serial.println("RF init failed!");
} else {
Serial.println("RF receiver ready");
}
}
void loop() {
uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
uint8_t buflen = sizeof(buf);
if (driver.recv(buf, &buflen)) {
// Message received — null-terminate and print
buf[buflen] = '';
Serial.print("Received: ");
Serial.println((char*)buf);
Serial.print("RSSI: "); Serial.println(driver.lastRssi(), DEC);
}
}
Upload the transmitter sketch to one Arduino and the receiver to the other. Open both Serial Monitors. You should see “Message sent” on the TX side and “Received: Hello from TX!” on the RX side every second. If you don’t receive anything, check your antenna (even a plain wire makes a big difference) and ensure your pin numbers match the code.
Sending Structured Data
Sending plain text wastes bandwidth and is hard to parse. For multiple sensor values, use a struct and cast it to a byte array:
// Transmitter — sending a struct
#include <RH_ASK.h>
#include <SPI.h>
RH_ASK driver;
struct SensorData {
uint16_t nodeId; // Which sensor node (supports up to 65535 nodes)
int16_t temperature; // Celsius * 10 (e.g., 245 = 24.5°C)
uint8_t humidity; // 0-100%
uint16_t batteryMv; // Battery voltage in millivolts
};
void setup() {
Serial.begin(9600);
driver.init();
}
void loop() {
SensorData data;
data.nodeId = 1;
data.temperature = 245; // 24.5°C
data.humidity = 68;
data.batteryMv = 3820;
driver.send((uint8_t*)&data, sizeof(data));
driver.waitPacketSent();
Serial.println("Data sent");
delay(5000);
}
// Receiver — decoding the struct
// (separate Arduino)
void loop() {
uint8_t buf[sizeof(SensorData)];
uint8_t buflen = sizeof(buf);
if (driver.recv(buf, &buflen) && buflen == sizeof(SensorData)) {
SensorData *data = (SensorData*)buf;
Serial.print("Node ID: "); Serial.println(data->nodeId);
Serial.print("Temp: "); Serial.print(data->temperature / 10.0); Serial.println("°C");
Serial.print("Humidity: "); Serial.print(data->humidity); Serial.println("%");
Serial.print("Battery: "); Serial.print(data->batteryMv); Serial.println("mV");
}
}
This struct approach packs 7 bytes of data (much more efficient than a CSV string like “1,24.5,68,3820” = 14 bytes). The `sizeof()` check on the received length provides a basic sanity check against corrupted packets.
Antenna: Dramatically Improve Range
The single biggest improvement you can make to a 433 MHz link is adding a proper antenna. The default wire stub on most modules is random length — not optimised. A quarter-wave antenna tuned to 433.92 MHz is cut to a precise length:
Quarter-wave length = (speed of light / frequency) / 4
= (300,000,000 m/s / 433,920,000 Hz) / 4
= 0.691 m / 4
= 17.3 cm
Steps:
- Cut a solid copper wire to exactly 17.3 cm (stripped single-core wire works best).
- Solder it directly to the ANT pad on both the transmitter and receiver modules.
- Keep the antenna wire vertical and straight during operation for best results.
- A helical (coiled) antenna achieves the same electrical length in less physical space — wind 17.3 cm of wire into a tight coil around a 5 mm diameter form.
With quarter-wave antennas on both modules and 5V transmitter supply, expect 50-100 metres of reliable range in open air, or 15-30 metres through walls. Powering the transmitter at 9-12V with an external supply can push this to 200+ metres in open air.
Practical Project: Wireless Temperature Node
Here is a complete, production-ready wireless temperature sensor node that reads DHT11 data and transmits every 30 seconds with an error check:
// Wireless Temperature Transmitter Node
// Hardware: Arduino Nano + DHT11 on D4 + FS1000A TX on D12
#include <RH_ASK.h>
#include <SPI.h>
#include <DHT.h>
#define DHT_PIN 4
#define DHT_TYPE DHT11
#define NODE_ID 1
RH_ASK driver(2000, 11, 12, 10); // 2Kbps, rx=11, tx=12
DHT dht(DHT_PIN, DHT_TYPE);
struct SensorPacket {
uint8_t nodeId;
int16_t tempC10; // temp * 10
uint8_t humidity;
uint8_t checksum; // simple XOR checksum
};
uint8_t calcChecksum(SensorPacket* p) {
uint8_t cs = 0;
uint8_t* bytes = (uint8_t*)p;
for (int i = 0; i < sizeof(SensorPacket) - 1; i++) cs ^= bytes[i];
return cs;
}
void setup() {
Serial.begin(9600);
dht.begin();
driver.init();
Serial.println("Wireless temp node started");
}
void loop() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
if (isnan(temp) || isnan(hum)) {
Serial.println("DHT read error!");
} else {
SensorPacket pkt;
pkt.nodeId = NODE_ID;
pkt.tempC10 = (int16_t)(temp * 10);
pkt.humidity = (uint8_t)hum;
pkt.checksum = calcChecksum(&pkt);
driver.send((uint8_t*)&pkt, sizeof(pkt));
driver.waitPacketSent();
Serial.print("Sent: ");
Serial.print(temp); Serial.print("°C ");
Serial.print(hum); Serial.println("%");
}
delay(30000); // Transmit every 30 seconds
}
FAQ
Why does my 433 MHz receiver pick up noise even when no transmitter is active?
433 MHz is a busy frequency band shared by garage door openers, weather stations, alarm sensors, and many other devices. The XY-MK-5V receiver is a super-regenerative design that is extremely sensitive but also picks up any RF energy in the band. The RadioHead library’s CRC check filters out most garbage packets. For better noise immunity, consider using the RFM69 or LoRa modules that use more sophisticated FSK modulation.
What is the maximum reliable data rate with 433 MHz ASK modules?
The RadioHead RH_ASK driver defaults to 2000 bps (2 Kbps). You can set it higher (up to 9600 bps) but reliability drops significantly at higher speeds, especially over longer ranges. For sensor data (a few bytes every few seconds), 2 Kbps is more than adequate and gives the best range and reliability.
Can I have multiple transmitters sending to one receiver?
Yes, with careful design. Include a node ID in your packet (as shown in the struct example) and transmit from each node at different time intervals to avoid collisions. The RadioHead library doesn’t implement CSMA/CA collision avoidance — if two nodes transmit simultaneously, both packets are lost. Use fixed time slots or random backoff delays between transmissions to minimise collisions.
Is 433 MHz legal to use in India?
Yes, the 433.05-434.79 MHz band is designated as an ISM band in India and is legal for use without a license for short-range devices with transmit power below 10 mW (10 dBm). The FS1000A at 5V is well within this limit. Check the WPC (Wireless Planning and Coordination Wing) rules for the latest regulations if deploying commercially.
How can I make two-way communication with 433 MHz modules?
The FS1000A/XY-MK-5V pair is one-way (TX only and RX only modules). For two-way communication, put one TX and one RX at each end, use different data pins for each, and implement half-duplex logic (only one side transmits at a time). Alternatively, use a transceiver module like the nRF24L01+ or RFM69HW that can both transmit and receive on the same antenna.
Start building your wireless sensor network today. The 433 MHz RF link is the easiest entry point into wireless Arduino communication — no WiFi credentials, no pairing process, and it works through walls that stop Bluetooth. Explore our full range of Arduino boards and wireless modules at Zbotic and get your remote sensor project transmitting today.
Add comment