Introduction: Using the RFM69/SX1231 in Continuous-Mode (eg. Receiving/sniffing Data From a WL102-341 [433.92MHz] Simple Transmitter)

The following sketch configures a RFM69 module (433MHz) in “Continuous-Mode” to receive OOK data from a simple WL102-341 or similar transmitter. This example uses the RadioHead “#include <RH_RF69.h> “library to configure the RFM69 (over SPI), and the RadioHead “#include <RH_ASK.h>” library to read the raw-pulses coming from the RFM69’s “G2=Data” pin (routed to a separate GPIO on the processor, in this example being D2).

Step 1: Transmitter

I am receiving data from a remote WL102-341 (nominally 433.92MHz) simple transmitter which is also using the RadioHead “#include <RH_ASK.h>” library for it’s transmissions. The photo shows this transmitter.

Step 2: Notes

(1) The below sketch uses bit-rate of 2000bps (this is the actual bit-rate of the transmitted signal). I use an RFM69 OOK Channel-Filter bandwidth of 3.9kHz, but I have not optimised this. (It will also work with Channel-Filter bandwidths of 83kHz or higher, which allow a larger RF frequency tolerance when testing.)

(2) The WL102-341 module transmits OOK with a number of sidebands, as shown in the plot (the wider the Channel-Filter BW used the more sidebands are covered). Note that this OOK signal from my WL102-341 can be received by the RFM69 when set to a frequency anywhere between approx 433.923MHz +/- 4kHz (if using a BW set to 3.9kHz), or the order of +/- 100kHz (if using BW set to 83kHz). (I suspect that if the 3.9kHz bandwidth filter had an infinitely sharp cut-off, the above frequency tolerance would probably be only approx 433.923MHz +/- 2kHz, but with a sloped-cut-off and a near transmitter you get a higher +/-4kHz working allowable frequency tolerance.)

(Note that the two markers shown on the plot are +/- 2kHz from the centre-line.)

Step 3:

(3) Notwithstanding the above, the frequency of the RFM69 can be tuned slightly for optimum performance. eg:

#define RF69_FREQ 433.92300 // for my devices with OOK@2000bps, BW=3.9Hz DCC=4% // still works for frequency varied over approx +/-4kHz (BW set to 3.9kHz) or +/-8.5kHz (BW set to 7.8kHz)

Also note that the optimum frequency may move a little depending on the Channel Filter RxBw you use. (I suspect this may be because of the way the RFM69’s “Low-IF” is adjusted dependent on the RxBw.)

(4) The RFM69 has an inbuilt “Bit Synchronizer”, enabled by using CONFIG_OOK_CONT_SYNC. It is able to tidy-up the pulses on G2(data), BUT the (RegBitrateMsb and RegBitrateLsb) MUST be set correctly for this to work (ie. to 2000bps for this example), otherwise turn-OFF the “Bit Synchronizer” using CONFIG_OOK_CONT_NO_SYNC.

(5) I am using an ESP8266 (D1mini), but this code should work with any sufficiently capable arduino-type microprocessor. The photo with the posting shows the ESP8266 and RFM69HCW mounted on strip-board.

(6) If you want to see the received pulses on an oscilloscope, you can just connect the oscilloscope to the RFM69 G2(data) pin. If you are getting too many pulses (from other transmitters) and your own transmitter is the nearest, then you can “filter-out” the other transmitters by increasing the RFM69 OOK-Threshold so you only see the higher powered pulse on G2(data) – example commands are shown in the below code.

(7) I note finally that there are several “sniffing 433MHz” projects/software repositories on github, which should work fine instead of the RadioHead “#include ” which I am using, but I have not tested any of these other software repositories. (If using these, care should be taken to ensure that they work with the RadioHead “#include ” library being used to configure the RFM69!)

Step 4: Software

#define RFM69_CS D0

#define RFM69_IRQ D8

#define RFM69_RST D1

#define SPI_CK D5 // For info only - not used in below Sketch

#define SPI_MISO D6 // For info only - not used in below Sketch

#define SPI_MOSI D7 // For info only - not used in below Sketch

#define SWITCH_PIN D4

#define rxPin_433 D2 // the data from the RFM69 G2(Data) is routed to this pin!

#define txPin_433 D3 // Just define as unused-pin (as we are not using Tx)

#define pttPin_433 D3 // Just define as unused-pin (as we are not using Tx)

#include <RH_ASK.h> // https://github.com/PaulStoffregen/RadioHead -> I'm using release 1.89 2020/08/05

RH_ASK simple_ASK(2000, rxPin_433, txPin_433, pttPin_433);

// #include "SPI.h" // not nec as included by the below

#include <RH_RF69.h> // https://github.com/PaulStoffregen/RadioHead -> I'm using release 1.89 2020/08/05

// NB. on earlier versions of RadioHead (such as release 1.75 which works on the ATTiny) the...

// ...ESP866 crashed with "ISR not in IRAM" message. This is fixed by editing RH_RF69.ccp and...

// ...changing "void RH_RF69::isr?()" to "void ICACHE_RAM_ATTR RH_RF69::isr?()" in 3 places

RH_RF69 rf69(RFM69_CS, RFM69_IRQ);

#define RF69_FREQ 433.92300 // for my devices with OOK@2000bps, BW=3.9Hz DCC=4%

// still works for frequency varied over approx +/-4kHz (BW set to 3.9kHz) or +/-8.5kHz (BW set to 7.8kHz)

#define CONFIG_PACKET_VARIABLE (RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RH_RF69_PACKETCONFIG1_CRCAUTOCLEAROFF)

#define CONFIG_OOK_CONT_SYNC (RH_RF69_DATAMODUL_DATAMODE_CONT_WITH_SYNC | RH_RF69_DATAMODUL_MODULATIONTYPE_OOK | RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE)

#define CONFIG_OOK_CONT_NO_SYNC (RH_RF69_DATAMODUL_DATAMODE_CONT_WITHOUT_SYNC | RH_RF69_DATAMODUL_MODULATIONTYPE_OOK | RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE)

#define CONFIG_RegRxBw3_9 0x46 // BW=3.9kHz DCC=4%

#define CONFIG_RegRxBw7_8 0x45 // BW=7.8kHz DCC=4%

#define CONFIG_RegRxBw83 0xF1 // BW=83khz DCC=1/8%

const RH_RF69::ModemConfig OOK_Rb2Bw3_9 = {CONFIG_OOK_CONT_SYNC, 0x3E, 0x80, 0x00, 0x10, CONFIG_RegRxBw3_9, CONFIG_RegRxBw3_9, CONFIG_PACKET_VARIABLE}; // OOK@2000bps, BW=3.9Hz DCC=4%

const RH_RF69::ModemConfig OOK_Rb2Bw7_8 = {CONFIG_OOK_CONT_SYNC, 0x3E, 0x80, 0x00, 0x10, CONFIG_RegRxBw7_8, CONFIG_RegRxBw7_8, CONFIG_PACKET_VARIABLE}; // OOK@2000bps, BW=7.8Hz DCC=4%

const RH_RF69::ModemConfig OOK_Rb2Bw83 = {CONFIG_OOK_CONT_SYNC, 0x3E, 0x80, 0x00, 0x10, CONFIG_RegRxBw83, CONFIG_RegRxBw83, CONFIG_PACKET_VARIABLE}; // OOK@2000bps. BW=83khz DCC=1/8%

void setup() {

Serial.begin(74880); delay(2000); Serial.println();

if (simple_ASK.init()) Serial.println("simple_ASK OOK-Receiver init OK");

else {Serial.println("simple_ASK OOK-Receiver init failed - hanging..."); while (true) delay(1000);}

Serial.print("simple_ASK Transmition BitRate="); Serial.print(simple_ASK.speed()); Serial.println("bps");

pinMode(RFM69_RST, OUTPUT);

digitalWrite(RFM69_RST, HIGH); delay(50); // NB. RFM69 is HIGH=RESET

digitalWrite(RFM69_RST, LOW); delay(100);

Serial.println("\nrf69 reset done OK");

if (rf69.init()) Serial.println("rf69 radio init OK");

else {Serial.println("rf69 radio init failed - hanging..."); while (true) delay(1000);}

Serial.print("rf69.setFrequency="); Serial.print(RF69_FREQ,4); Serial.println(" MHz");

rf69.setFrequency(RF69_FREQ);

Serial.println("rf69.setTxPower=17");

rf69.setTxPower(17,true); // range from 14-20 for power, 2nd arg must be true for RFM69HCW

rf69.setModemRegisters(&OOK_Rb2Bw3_9);

Serial.println("rf69.setModemConfig=done");

byte bMSB=rf69.spiRead(RH_RF69_REG_03_BITRATEMSB), bLSB=rf69.spiRead(RH_RF69_REG_04_BITRATELSB);

Serial.print("BitRate=0x"); Serial.print(bMSB,HEX); Serial.write(' '); Serial.print(bLSB,HEX);

Serial.print(" = "); Serial.print(32000000/((bMSB*256)+bLSB)); Serial.println("bps");

Serial.print("OP-Mode=0x"); Serial.println(rf69.spiRead(RH_RF69_REG_01_OPMODE),HEX);

Serial.print("DataMode=0x"); Serial.println(rf69.spiRead(RH_RF69_REG_02_DATAMODUL),HEX);

#if (false) // Only enable if you want to reduce the number of pulses when viewing on G2(data) with an oscilloscope.

Serial.print("Changing to fixed OOKPEAK: ");

rf69.spiWrite(RH_RF69_REG_1B_OOKPEAK,0);

byte OOKPEAK=rf69.spiRead(RH_RF69_REG_1B_OOKPEAK);

Serial.print("OOKPEAK=0x"); Serial.print(OOKPEAK,HEX); Serial.print("=B"); Serial.println(OOKPEAK,BIN);

Serial.print("Change Fixed threshold OOKFIX: ");

#define THESHOLD_DB 0x50

rf69.spiWrite(RH_RF69_REG_1D_OOKFIX,THESHOLD_DB); // Fixed threshold value in the OOK demodulator=0x50dB.

Serial.print("OOKFIX=0x"); Serial.println(rf69.spiRead(RH_RF69_REG_1D_OOKFIX),HEX);

#endif

rf69.setModeRx(); // This line is needed [at the end of setup()] to allow "simple_ASK.recv()" to receive stuff

}

void loop() {

uint8_t buf[20], len=sizeof(buf); // must be large enough for whole string (inc. any zeros)

if (simple_ASK.recv(buf, &len)) {buf[len]=0; Serial.print("OOK Got: "); Serial.println((char*)buf);}

}