Skip to main content

Radio Communication: How to use RFM69HCW Radio Data Module

What is APC220RFM69HCW Radio Data Module?

The APC220 Radio Data ModuleRFM69HCW is a compact,high-performance, low-power,power wirelessradio transceiver module designed for seriallong-range wireless communication overusing longsub-GHz distancesfrequencies. usingUnlike simple UART-based modules like the 433APC220, MHzthe ISMRFM69HCW band.offers It’sSPI commonlycommunication, usedencryption, and packet-based transmission, making it highly suitable for Arduinomore projectscomplex and secure wireless sensor networks,networks.

especially where a simple UART interface and long-range communication are needed.

APC220.png

In this tutorial, we will usebe using two Arduino,Arduino UNO, one for sending (Leonardo) and one for receivingreceiving. (UNO).RFM69HCW Forcomes clarity,with different versions, we useare twousing differentthe models,433 butMHz youversion in this tutorial.

Differences from APC220

FeatureAPC220RFM69HCW
Communication InterfaceUART (Serial)SPI
Operating Frequency433 MHz433 / 868 / 915 MHz (depending on model)
Modulation TypeGFSKFSK, GFSK, OOK
Communication Range~1000 m (line of sight)500 m – 1500+ m (configurable)
Data Rate1200 – 19200 bpsUp to 300 kbps
Encryption❌ Not supported✅ 128-bit AES encryption
Power Supply3.3V – 5V1.8V – 3.6V
TopologyPoint-to-pointPoint-to-point or mesh
Library RequiredNo (uses standard Serial)Yes (RadioHead, RFM69, etc.)
Use Case SimplicityBeginner-friendlyRequires more setup/code

Wiring (same wiring for both)

3.3V Only
RFM69HCW runs on 3.3V — powering it from 5V can usepermanently thedamage same model or any other model.it.

Wiring

  1. Arduino Leonardo - Sending:
    • GND to GND
    • VCCVIN to 5V3.3V
    • TXDSCK to 8D13
    • RXDMISO to 9D12
    • MOSI to D11
    • CS to D4
    • RST to D2
    • G0 (IRQ) to D3
  2. Library

  3. Download Arduinothe UNORadioHead -library Receiving:here.

SoftwareSerial Only
Use SoftwareSerial on both Arduinos. Never directly connect APC220 RXD to Arduino TX if they use different logic levels (some APC220 modules are 3.3V-only).here.

Getting started

Arduino Leonardo - Sending

This code is getting the eight servo motors to rotate to 0 degrees and then 90 degrees, one by one.

#include <SoftwareSerial.SPI.h>
SoftwareSerial#include radio(8,<RH_RF69.h>

9);/************ Radio Setup ***************/

// RX,Change TXto 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 434.0
#define RFM69_CS   4  
#define RFM69_INT  3  
#define RFM69_RST  2  
#define LED        13


// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);

int16_t packetnum = 0;  // packet counter, we increment per xmission

void setup() {
  radio.Serial.begin(9600)115200);
  //while (!Serial) delay(1); // Wait for Serial Console (comment out line if no computer)

  pinMode(LED, OUTPUT);
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, LOW);

  Serial.println("RFM69 TX Test!");
  Serial.println();

  // manual reset
  digitalWrite(RFM69_RST, HIGH);
  delay(10);
  digitalWrite(RFM69_RST, LOW);
  delay(10);

  if (!rf69.init()) {
    Serial.println("RFM69 radio init failed");
    while (1);
  }
  Serial.println("RFM69 radio init OK!");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(RF69_FREQ)) {
    Serial.println("setFrequency failed");
  }

  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  rf69.setTxPower(20, true);  // range from 14-20 for power, 2nd arg must be true for 69HCW

  // The encryption key has to be the same as the one in the server
  uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);

  Serial.print("RFM69 radio @");  Serial.print((int)RF69_FREQ);  Serial.println(" MHz");
}

void loop() {
  radio.println(delay(1000);  // Wait 1 second between transmits, could also 'sleep' here!

  char radiopacket[20] = "Hello fromWorld Leonardo!#";
  itoa(packetnum++, radiopacket+13, 10);
  Serial.print("Sending "); Serial.println(radiopacket);

  // Send a message!
  rf69.send((uint8_t *)radiopacket, strlen(radiopacket));
  rf69.waitPacketSent();

  // Now wait for a reply
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf69.waitAvailableTimeout(500)) {
    // Should be a reply message for us now
    if (rf69.recv(buf, &len)) {
      Serial.print("Got a reply: ");
      Serial.println((char*)buf);
      Blink(LED, 50, 3); // blink LED 3 times, 50ms between blinks
    } else {
      Serial.println("Receive failed");
    }
  } else {
    Serial.println("No reply, is another RFM69 listening?");
  }
}

void Blink(byte pin, byte delay_ms, byte loops) {
  while (loops--) {
    digitalWrite(pin, HIGH);
    delay(1000)delay_ms);
    digitalWrite(pin, LOW);
    delay(delay_ms);
  }
}

Arduino UNO - Receiving

#include <SoftwareSerial.SPI.h>
SoftwareSerial#include radio(8,<RH_RF69.h>

9);/************ Radio Setup ***************/

#define RF69_FREQ 434.0
#define RFM69_CS   4  
#define RFM69_INT  3  
#define RFM69_RST  2  
#define LED        13

// RX,Singleton TXinstance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);

void setup() {
  Serial.begin(9600)115200);
  radio.begin(9600)//while (!Serial) delay(1); // Wait for Serial Console (comment out line if no computer)

  pinMode(LED, OUTPUT);
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, LOW);

  Serial.println("RFM69 RX Test!");
  Serial.println();

  // manual reset
  digitalWrite(RFM69_RST, HIGH);
  delay(10);
  digitalWrite(RFM69_RST, LOW);
  delay(10);

  if (!rf69.init()) {
    Serial.println("RFM69 radio init failed");
    while (1);
  }
  Serial.println("RFM69 radio init OK!");

  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(RF69_FREQ)) {
    Serial.println("setFrequency failed");
  }

  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  rf69.setTxPower(20, true);  // range from 14-20 for power, 2nd arg must be true for 69HCW

  // The encryption key has to be the same as the one in the server
  uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);

  Serial.print("RFM69 radio @");  Serial.print((int)RF69_FREQ);  Serial.println(" MHz");
}

void loop() {
 if (radio.rf69.available()) {
    String// msgShould be a message for us now
    uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
    uint8_t len = radio.readStringUntil('\n'sizeof(buf);
    if (rf69.recv(buf, &len)) {
      if (!len) return;
      buf[len] = 0;
      Serial.print("Received [");
      Serial.print(len);
      Serial.print("]: ");
      Serial.println((char*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf69.lastRssi(), DEC);

      if (strstr((char *)buf, "Hello World")) {
        // Send a reply!
        uint8_t data[] = "And hello back to you";
        rf69.send(data, sizeof(data));
        rf69.waitPacketSent();
        Serial.println("Received:Sent a reply");
        Blink(LED, 40, 3); // blink LED 3 times, 40ms between blinks
      }
    } else {
      Serial.println("Receive +failed");
    msg)}
  }
}

void Blink(byte pin, byte delay_ms, byte loops) {
  while (loops--) {
    digitalWrite(pin, HIGH);
    delay(delay_ms);
    digitalWrite(pin, LOW);
    delay(delay_ms);
  }
}

Testing

  1. Open Serial Monitor on the UNO to see received messages, Hello from Leonardo!.
  2. Both radios must be powered on and within range.
  3. Ensure no serial baud mismatch.
  4. Do not connect APC220 to Arduino RX0/TX1 pins while uploading code—use SoftwareSerial instead.