Using short range RF transmissions between two Arduino devices.

“But how could they be jamming us if they don’t know… that we’re coming?” – Lando Calrissian.

That’s probably the only Star Wars quote that came to mind in regards to wireless/radio communications.

As part of one of the Arduino projects I had created, which was an ultrasonic range finder to ensure the cars were parked in the optimal position in the garage, I came upon a requirement to wirelessly transmit and receive data between two Arduino devices. I could have just connected both devices to the network and then had them communicate that way, but I wanted to avoid network links for one of the devices – it just wasn’t convenient to run a network cable there. I thought about using an Arduino Wi-Fi shield, but couldn’t justify the dollars for such a simple use case.

So I needed to find an alternate way of getting two Arduino devices to communicate without physically connecting them with cables. This is where I decided to look into the RF communications angle.

Let’s look at some of the parts that I purchased (once again, mostly from element14).

  • 1 x QAM-TX1 AM Transmitter Module
  • 1 x QAM-RX2 AM Receiver Module
  • 1 x HT-12E Encoder IC
  • 1 x HT-12D Decoder IC

The basic premise is that the AM Transmitter and Receiver modules use 433 MHz RF AM transmissions. That’s all well and good, but I wanted to be able to send multiple signals between these two devices. For example, I wanted to communicate the garage door state to the receiving unit, which meant that I needed to be able to send a radio signal for garage door closed, and a radio signal for garage door open.

After a bit more research I found the Encoder/Decoder IC chips. What these allow me to do is configure each device with a matching 8 bit address – so that the decoder only listens for signals that match its configured address – and send 16 different message types between them. Perfect.

Radio Overview

Those are the basic components. Two Arduino devices, each with an encoder or decoder and a transmitter or receiver respectively.

With any electronic component that you use, you will generally need to download the online data sheet that gives you instructions on the expected/max voltages/currents, the pinouts and expected behaviours of the components.

I created the transmit circuit as shown below:

 Transmit Circuit

The A0 – A7 pins are for configuring the address. I’ve put a sample address together as shown – Pins A0, A1, A2, A5, A7 are HIGH, where as pins A3, A4 and A6 have been pulled down to LOW. As long as that combination matches on my decoder chip, they will communicate.

The DOUT (Data Out) pin from the Encoder sends its output to the Transmitter module’s DATA pin.

As per the instructions on the transmitter, I needed to create a 17cm antenna – I just used a 17cm solid core single wire from an old Ethernet cable. Well actually a new Ethernet cable that I bought for parts.

With this particular encoder, as per the data sheet I needed to apply a 1.1M ohm resistor (or rather a 1M and a 100K ohm resistor in series) to the OSC1 and OSC2 pins.

This just leaves the TE and AD11 pins. The TE pin needs to be set to LOW when I wish to transmit. To facilitate that, I’ve used an NPN transistor (type 2N2222A). When I use digitalWrite(3, HIGH) on the Arduino and output +5V on pin D3, a current will hit the base pin on the transistor, turning on the current flow from the collector to the emitter (have a quick search on the internet for the basics of a transistor). So, when pin D3 has +5V, the transistor turns on, and the TE pin is set to LOW resulting in the encoder sending data out its DOUT pin. The 4.7K resistor was to drop the current down from the Arduino before it hit the base of the transistor.

What data does it send? Well, pins AD8 – AD11 represent the 4 data bits that are transmitted. Given each bit supports two combinations (HIGH and LOW), that gives me 2^4 (16) combinations to choose from. As I only needed to send two different messages, I only connected pin AD11. Therefore any message I sent had data pins AD8 – AD10 set to HIGH, and then AD11 would be HIGH or LOW depending on the output of pin D4 on the Arduino.

Let’s have a quick look at the basic transmit code.

#define PIN_TRANSMIT 3
#define PIN_DATA 4

/***************************************************************/
/* Function: setup()                                           */
/***************************************************************/
void setup()
{
	Serial.begin(9600);
	Serial.println("setup()");

	pinMode(PIN_TRANSMIT, OUTPUT);
	pinMode(PIN_DATA, OUTPUT);
}

/***************************************************************/
/* Function: loop()                                            */
/***************************************************************/
void loop()
{
	Serial.println("loop()");

	Serial.println("Transmitting Message 1");

	digitalWrite(PIN_DATA, HIGH); // Message 1
	digitalWrite(PIN_TRANSMIT, HIGH);

	delay(100);

	digitalWrite(PIN_TRANSMIT, LOW);

	// Wait 10 seconds between messages
	delay(10000);

	Serial.println("Transmitting Message 2");

	digitalWrite(PIN_DATA, LOW); // Message 2
	digitalWrite(PIN_TRANSMIT, HIGH);

	delay(100);

	digitalWrite(PIN_TRANSMIT, LOW);

	// Wait 10 seconds between messages
	delay(10000);
}

With that complete and a basic breadboard circuit wired up, I had my transmitter. On to the receiver.

Receive Circuit

In this circuit, you can see I’ve set pins A3, A4, A6 to ground resulting in the decoder IC having the same address bits as the encoder IC. If these bits match when a message is received, the decoder IC will set pin VT to HIGH – VT = Valid Transmission. This is how we know that the decoder is happy with what has been received.

It’s fairly straight forward after that – pins D10 and D11 on the Arduino have been pulled down to ground with a 10K resistor (as recommended by Arduino on their digital pins reference page). When VT or D11 are set to HIGH by the decoder, I can then read those HIGH signals from pins D10 and D11.

#define PIN_RECEIVE 10
#define PIN_DATA 11

/***************************************************************/
/* Function: setup()                                           */
/***************************************************************/
void setup()
{
	Serial.begin(9600);
	Serial.println("setup()");

	pinMode(PIN_RECEIVE, INPUT);
	pinMode(PIN_DATA, INPUT);
}

/***************************************************************/
/* Function: loop()                                            */
/***************************************************************/
void loop()
{
	Serial.println("loop()");

	if (digitalRead(PIN_RECEIVE) == HIGH)
	{
		Serial.println("Receiving Message");

		if (digitalRead(PIN_DATA) == HIGH)
			Serial.println("- Message 2");
		else
			Serial.println("- Message 1");
	}

	delay(100);
}

The receive code is a little simpler. We check if the VT pin has been set to HIGH to indicate a valid transmission. If so, we then check the Data pin. If you’re wondering why I seem to have the messages inverted on the receiving circuit, its due to the way the transmit circuit was designed. If we think back to the transmit circuit, the Data pins AD8 – AD11 start in the HIGH position. If I want to change a Data pin, I need to connect the Data pin to ground to achieve the LOW state. How did I do that? I set the Arduino’s data pin to HIGH, which set the transistor to ON, resulting in the AD11 Data pin being set to LOW. So when I set the Arduino pin to HIGH, I’m actually transmitting a data bit of LOW. This is why I need to infer a LOW reading on the data pin as Message 1 in the receive circuit. I could have redesigned the transmit circuit to invert the signals from the Arduino so that an Arduino output of LOW equalled a Data bit of LOW, but I was happy with the solution.

Really cool stuff, this allowed me to have two Arduino devices communicate with each other without putting them both on a network, or running data cables between them.

~ Mike

3 thoughts on “Using short range RF transmissions between two Arduino devices.

  1. You did a transmitter with QAM modulation, so do you think it’s possible to make something different and find a FSK, ASK and QSK transmitter with Arduino ? Because I want to be free to use the modulation that I choose for send data to other device. And I seek a transmitter with only the CNA and transmission part. Is it possible ?

Leave a comment