Arduino 433MHz Radio

Arduino 433MHz Radio

The 433MHz transmitters and receivers that are available everywhere trade cost for complexity. They cost very little, but require complex interfaces. It isn't as simple as hooking up a USART and talking. There is a lot going on in something like an XBee module, and it isn't happening in these little radios. More expensive radios use Frequency Shift Keying (FSK), where the input signal moves the frequency back and forth. Digital FSK receivers see either a one or a zero based on the frequency they receive. These little 433MHz modules use Amplitude Shift Keying (ASK), sometimes called On-Off Keying (OOK). ASK/OOK transmitters operate on a single frequency, and are either on or off for a one or zero.

Why is that a problem? The problem is in the receiver. If the carrier is on, it is a one. If it is off, is it a zero, or is the signal gone? The receiver can't tell, so it cranks up the gain looking for the signal, until it hits the noise floor, and random ones and zeros are produced. It is impossible to use it without two techniques. First, the receiver needs to be told when to start looking for real ones and zeros. To do that, the transmitter sends a string of interleaved ones and zeros. This both drops the gain on the receiver, eliminating the noise problem, and signals the start of transmission. Second, the signal can't contain a lot of zeroes in a row, since it would cause the receiver to adjust the gain back into the noise.

The Virtual Wire library solves both problems. It handles the protocol that establishes the communication and it creates little packets that don't cause the receiver to change the gain in the middle of the stream. It works similar to a serial library. The following is a full-duplex radio application using the 433MHz radios and the Virtual Wire library. It assumes the other end is the master, giving commands and expecting replies.

#include <VirtualWire.h>

#define transmitPin 2
#define receivePin 3

uint8_t buf[VW_MAX_MESSAGE_LEN];	// 30 bytes total, but only 27 you can use.
uint8_t buflen = VW_MAX_MESSAGE_LEN;

void setup()
	vw_set_tx_pin(transmitPin);	// Which pin for transmit.
	vw_set_rx_pin(receivePin);	// Which pin for receive.
	vw_set_ptt_pin(ptt_pin);	// Even though it is not used on our modules.
	vw_set_ptt_inverted(true);	// Invert the push to talk. Not needed on these modules.
	vw_setup(2000);			// 2000 BPS data rate.
	vw_rx_start();			// Start the PLL.

/* Main program */
void loop()
	if (vw_wait_rx_max(1000))
		if (vw_get_message(buf, &buflen))
			// Dump command?
			if (buf[0] == 'D')
				strcpy(buf,"here's some data");
				vw_send((buf, strlen(buf));
Arduino 433 MHz transmitter and receiver on a prototype board.

The cost compared to XBee is very low. This setup with XBee would cost around $90.00, and I put around $13.00 in the prototype boards and the 433MHz modules. What is the difference? The data rate is much lower, the range is a bit less than half the XBee range, and these are more challenging from a code standpoint. Note: testing shows very low performance for this module in practice.

Another way to use the ASK/OOK type modules is to use them with encoding like the old FM floppy disk encoding, where every other bit time is a clock pulse. Some number of microseconds after the clock ends, one should find either a one or a zero for the data bit. There would never be more than one clock time with a zero.

Arduino Board Logo


Arduino-Board is the go-to source for information on many available Arduino and Arduino-like boards, tutorials and projects.

Help and Support


Stay updated

Sign up if you would like to receive our once monthly newsletter.