pdf-icon

Arduino Quick Start

2. Devices & Examples

Unit RF433 Arduino Tutorial

1. Preparations

2. Notes

Transceiver Pair
This RF433 set is designed for paired use, requiring one Unit RF433T as the transmitter module and one Unit RF433R as the receiver module.
Pin Compatibility
Since each host device has different pin configurations, please refer to the RF433T Pin Compatibility Table and RF433R Pin Compatibility Table in the product documentation before use, and modify the example program according to the actual pin connections.

3. Example Program

  • In this tutorial, Basic v2.7 with Unit RF433T is used as the transmitter, and CoreS3 with Unit RF433R is used as the receiver. The modules have two circuit connection types: DOUT and DIN. Please modify the pin definitions in the program according to the actual circuit connections.

3.1 RF433T Transmitter

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
#include <driver/rmt.h>
#include <M5Unified.h>

#define RF433TX
#define RMT_TX_CHANNEL  (RMT_CHANNEL_0)
#define RMT_RX_CHANNEL  (RMT_CHANNEL_1)
#define RTM_TX_GPIO_NUM (21)
#define RTM_BLOCK_NUM   (1)
#define RMT_CLK_DIV     (80) /*!< RMT counter clock divider */
#define RMT_1US_TICKS   (80000000 / RMT_CLK_DIV / 1000000)
#define RMT_1MS_TICKS   (RMT_1US_TICKS * 1000)

rmt_item32_t rmtbuff[2048];

#define T0H 670
#define T1H 320
#define T0L 348
#define T1L 642

#define RMT_CODE_H      {670, 1, 320, 0}
#define RMT_CODE_L      {348, 1, 642, 0}
#define RMT_START_CODE0 {4868, 1, 2469, 0}
#define RMT_START_CODE1 {1647, 1, 315, 0}

void initRMT()
{
#ifndef RF433RX

rmt_config_t txconfig;
txconfig.rmt_mode                      = RMT_MODE_TX;
txconfig.channel                       = RMT_TX_CHANNEL;
txconfig.gpio_num                      = gpio_num_t(RTM_TX_GPIO_NUM);
txconfig.mem_block_num                 = RTM_BLOCK_NUM;
txconfig.tx_config.loop_en              = false;
txconfig.tx_config.carrier_en           = false;
txconfig.tx_config.idle_output_en       = true;
txconfig.tx_config.idle_level           = rmt_idle_level_t(0);
txconfig.clk_div                        = RMT_CLK_DIV;  

esp_err_t err1 = rmt_config(&txconfig);
esp_err_t err2 = rmt_driver_install(txconfig.channel, 0, 0); 

if (err1 != ESP_OK || err2 != ESP_OK) {
    Serial.printf("RMT init failed: %d, %d\n", err1, err2);
    return;
}

#else

rmt_config_t rxconfig;
rxconfig.rmt_mode                      = RMT_MODE_RX;
rxconfig.channel                       = RMT_RX_CHANNEL;
rxconfig.gpio_num                      = gpio_num_t(RTM_RX_GPIO_NUM);
rxconfig.mem_block_num                 = 6;
rxconfig.clk_div                       = RMT_CLK_DIV;
rxconfig.rx_config.filter_en           = true;
rxconfig.rx_config.filter_ticks_thresh = 200 * RMT_1US_TICKS;
rxconfig.rx_config.idle_threshold      = 3 * RMT_1MS_TICKS;

esp_err_t err1 = rmt_config(&rxconfig);
esp_err_t err2 = rmt_driver_install(rxconfig.channel, 1024, 0); 

if (err1 != ESP_OK || err2 != ESP_OK) {
    Serial.printf("RMT init failed: %d, %d\n", err1, err2);
}

#endif
}
/*
uint8_t databuff1[5] = {0xdd,0x41,0x53,0x80,0x9f};
uint8_t databuff2[5] = {0xdd,0x41,0x5a,0x80,0x96};
uint8_t databuff3[5] = {0xdd,0x41,0x58,0x80,0x95};
*/

uint8_t data[5] = {0xAA, 0x55, 0x01, 0x02, 0x03};
void send(uint8_t* buff, size_t size)
{
    rmtbuff[0] = (rmt_item32_t){RMT_START_CODE0};
    rmtbuff[1] = (rmt_item32_t){RMT_START_CODE1};
    for (int i = 0; i < size; i++) {
        uint8_t mark = 0x80;
        for (int n = 0; n < 8; n++) {
            rmtbuff[2 + i * 8 + n] = ((buff[i] & mark)) ? ((rmt_item32_t){RMT_CODE_H}) : ((rmt_item32_t){RMT_CODE_L});
            mark >>= 1;
        }
    }
    for (int i = 0; i < 8; i++) {
         esp_err_t err1 = rmt_write_items(RMT_TX_CHANNEL, rmtbuff, 42, false);
        if (err1 != ESP_OK) {
            Serial.printf("RMT write error: %d\n", err1);
            return;
        }

        esp_err_t err2 = rmt_wait_tx_done(RMT_TX_CHANNEL, pdMS_TO_TICKS(1000));
        if (err2 != ESP_OK) {
            Serial.printf("RMT wait error: %d\n", err2);
            return;
        }
    }
}

void setup()
{
    M5.begin();
    Serial.begin(115200);
    Serial.println("WAIT");
    M5.Display.fillRect(0, 0, 320, 240, WHITE);
    M5.Display.setTextColor(BLACK);
    M5.Display.setFont(&fonts::FreeMonoBold12pt7b);
    M5.Display.setCursor(0, 0);
    Serial.print("initRMT OK");
    M5.Display.println("Unit RF433T init...");
    pinMode(RTM_TX_GPIO_NUM, OUTPUT);
    initRMT();
    delay(100);
    M5.Display.println("Click Btn A send data");
    // rf.begin<PT2262>(26,27).arg<int>(1000);
}

void loop()
{
    M5.update();
    if (M5.BtnA.wasPressed()) {
        Serial.println("SEND");
        send(data, 5);
        for (int i = 0; i < 5; i++) {
            Serial.printf("%02x ", data[i]);
            M5.Display.printf("%02x ", data[i]);
        }
        M5.Display.println("");
    }
    delay(10);
}

3.2 RF433R Receiver

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
#include <M5Unified.h>
#define RX_PIN 1

#define MAX_PULSES 512
volatile unsigned long pulseTimes[MAX_PULSES];
volatile int pulseCount = 0;
volatile unsigned long lastTime = 0;

// START_CODE0: {4868, 1, 2469, 0}
#define START_CODE0_HIGH_MIN 4600
#define START_CODE0_HIGH_MAX 5100
#define START_CODE0_LOW_MIN  2200
#define START_CODE0_LOW_MAX  2700

// START_CODE1: {1647, 1, 315, 0}
#define START_CODE1_HIGH_MIN 1400
#define START_CODE1_HIGH_MAX 1900
#define START_CODE1_LOW_MIN  200
#define START_CODE1_LOW_MAX  450

// RMT_CODE_H (1): {670, 1, 320, 0}
// RMT_CODE_L (0): {348, 1, 642, 0}
#define BIT_TOTAL_MIN 800
#define BIT_TOTAL_MAX 1200
#define BIT_HIGH_THRESHOLD 500

uint8_t receivedData[256];
int receiveCount = 0;
unsigned long lastReceiveTime = 0;

void IRAM_ATTR pulseInterrupt() {
  if (pulseCount < MAX_PULSES) {
    unsigned long currentTime = micros();
    pulseTimes[pulseCount] = currentTime - lastTime;
    lastTime = currentTime;
    pulseCount++;
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);

  M5.Display.fillRect(0, 0, 320, 240, WHITE);
  M5.Display.setTextColor(BLACK);
  M5.Display.setFont(&fonts::FreeMonoBold12pt7b);
  M5.Display.setCursor(0, 0);
  M5.Display.println("Unit RF433R init...");
  Serial.println("Unit RF433R init...");

  pinMode(RX_PIN, INPUT);
  Serial.println("attachInterrupt ...");

  attachInterrupt(digitalPinToInterrupt(RX_PIN), pulseInterrupt, CHANGE);

  M5.Display.print("Serial to view data");
  Serial.println("RF433 Receiver ready");

  lastTime = micros();
}

int parseData() {
  if (pulseCount < 8) return -1;
  int dataIndex = 0;
  uint8_t data = 0;
  uint8_t bitCount = 0;
  int pulseIndex = 0;
  if (pulseTimes[0] >= START_CODE0_HIGH_MIN && pulseTimes[0] <= START_CODE0_HIGH_MAX &&
      pulseTimes[1] >= START_CODE0_LOW_MIN && pulseTimes[1] <= START_CODE0_LOW_MAX) {

    Serial.println("Found START_CODE0");
    pulseIndex = 2;

    if (pulseIndex < pulseCount - 1 &&
        pulseTimes[pulseIndex] >= START_CODE1_HIGH_MIN && pulseTimes[pulseIndex] <= START_CODE1_HIGH_MAX &&
        pulseTimes[pulseIndex + 1] >= START_CODE1_LOW_MIN && pulseTimes[pulseIndex + 1] <= START_CODE1_LOW_MAX) {

      Serial.println("Found START_CODE1");
      pulseIndex = 4;
      while (pulseIndex < pulseCount - 1) {
        unsigned long highTime = pulseTimes[pulseIndex];
        unsigned long lowTime = pulseTimes[pulseIndex + 1];
        unsigned long totalTime = highTime + lowTime;
        if (totalTime >= BIT_TOTAL_MIN && totalTime <= BIT_TOTAL_MAX) {
          // RMT_CODE_H (1)
          // RMT_CODE_L (0)
          if (highTime > BIT_HIGH_THRESHOLD) {
            data = (data << 1) | 1;
          } else {
            data = (data << 1) | 0;
          }
          bitCount++;
          if (bitCount >= 8) {
            receivedData[dataIndex] = data;
            Serial.printf("%02x ", data);
            dataIndex++;
            data = 0;
            bitCount = 0;
            if (dataIndex >= 5) break;
          }
          pulseIndex += 2;
        } else {
          pulseIndex++;
        }
      }
    }
    if (dataIndex > 0) {
      Serial.println(" END");
      return dataIndex;
    }
  }
  return -1;
}

void loop() {
  if (millis() - lastReceiveTime > 50) {
    noInterrupts();
    int currentPulseCount = pulseCount;
    interrupts();
    if (currentPulseCount > 0) {
      int dataSize = parseData();
      if (dataSize >= 5 &&
          receivedData[0] == 0xAA &&
          receivedData[1] == 0x55 &&
          receivedData[2] == 0x01 &&
          receivedData[3] == 0x02 &&
          receivedData[4] == 0x03 ) {
        receiveCount++;
        Serial.printf("\r\nValid packet received! Count: %d\r\n", receiveCount);
        for (int i = 0; i < dataSize; i++) {
          M5.Display.printf("%02x ", receivedData[i]);
        }
        M5.Display.println("");

        if (receiveCount >= 4) {
          M5.Display.fillRect(0, 20, 320, 220, TFT_GREEN);
          M5.Display.setTextColor(BLACK);
          M5.Display.setCursor(10, 50);
          M5.Display.printf("Received: %d", receiveCount);
        }
      } else if (dataSize > 0) {
        Serial.printf("Received %d bytes but not matching expected pattern\r\n", dataSize);
      }

      noInterrupts();
      pulseCount = 0;
      interrupts();

      lastReceiveTime = millis();
    } else {
      if (receiveCount != 0 && millis() - lastReceiveTime > 2000) {
        Serial.printf("Reset after receiving %d packets\r\n", receiveCount);
        M5.Display.fillRect(0, 20, 320, 220, TFT_RED);
        receiveCount = 0;
      }
    }
  }
  delay(10);
}

4. Compile and Upload

  • Download Mode: Different devices require entering download mode before program burning. This process may vary depending on the main controller device. For details, please refer to the device programming tutorial list at the bottom of the Arduino IDE Getting Started Guide page for specific operations.

  • For CoreS3: Press and hold the reset button (about 2 seconds) until the internal green LED lights up, then release. The device will now enter download mode and wait for programming.

  • Select the device port and click the compile/upload button in the top-left corner of Arduino IDE. Wait for the program to complete compilation and upload to the device.

5. Communication Test

  • When Button A on Basic v2.7 is pressed, it will send a data packet via RF433T. If CoreS3 successfully receives the packet through RF433R, it will print the data via serial port and display it on the screen in real-time.
  • When four successful communications occur between the two devices, the CoreS3 screen will turn green to indicate success.
On This Page