As I use 433MHz transmitters for sending sensor data from many of my IoT-nodes, I have made a re-usable Arduino library for this purpose. The transmitted sensor data is picked up by one single receiver (an ESP8266 board) that converts the values to MQTT messages on my local network. In this post I will describe this library, my setup and also a set of new 433MHz transmitters and receivers that I have upgraded to.
Why use 433MHz devices?
Eventually, all data in my IoT-setup ends up as MQTT messages on the local network. With a device connected to WiFi it is possible to create and send MQTT messages directly, but in some circumstances I prefer to use to use 433MHz based communication:
- When the device has to run on batteries. A 433MHz radio device will consume much less power than a WiFi device.
- When a longer range is needed. From my experiments, the 433MHz devices can have better range than the WiFi devices.
- When the data to transmit is just a single value (like a sensor measurement).
The 433MHz chirp signals are picked up by one single ESP8266 board that transforms the sensor data to MQTT messages on my local network.
Arduino Pro Mini 3.3V on batteries
I prefer to use to use Arduino Pro Mini 3.3V clones as battery-powered IoT-nodes. They are very inexpensive ($3) and small but are versatile for handling many measurement tasks. For minimizing the power consumption, I remove the power led (actually crunch it with a small knife) as it can not be turned off programmatically, and turn the device to sleep between measurements (with the Narcoleptic library).
For a typical Pro Mini setup, I will have a 10mA peak during measuring and transmitting. This takes up to 10 seconds. After this, the device is set to sleep for around 15 minutes. In this mode, it consumes about 0,18mA. This way, an Arduino Pro Mini can run for more than a year on 3 AAA batteries (with a total capacity of 3000mAh).
You can modify a Pro Mini to use even lower amounts of energy while in sleep/idle mode by by-passing the regulator. See this article:

The Sensor433 library
I have made a re-usable Arduino library with a transmitter class that can be used on sensor nodes. There is a matching receiver class that decodes received 433MHz signals. There are examples included on a bridge implementation that should be uploaded to a WiFi-connected node. This nodes listen to all transmitted data over 433MHz and transforms them to MQTT messages on the local LAN. The library is available from GitHub:
https://github.com/LarsBergqvist/Sensor433
The library depends on rc-switch which can be installed via the library manager in Arduino IDE.
The transmitters sends a 4-byte data package. This contains the measurement type, the actual measurement value and checksums. The receiver decodes this data and creates an MQTT message containing the measurement value on a MQTT topic that is based on the measurement type received.
Note that due to the small size of the transmitted package (as it is based on the rc-switch protocol), the transmitter can only send a float between -327.67 and + 327.67 or an unsigned int, i.e. a word (a value between 0 and 65535). For my home automation purposes, this is sufficient, though.

The Geeetech transmitters and receivers
I have been using sets of these simple no-name-super-affordable 433MHz TX/RX for a long time:
They operate with ASK/OOK modulation and are very easy to use. A set is available for about $2! With an additional antenna (just a wire of about 17cm length) they have worked ok indoors with ranges up to 10m when powered by 3V devices.
Recently I discovered a higher quality RX/TX-pair from Geeetech:
They cost a little more ($6 for a receiver and transmitter pair if you search online), but I decided to give them a try. It turned out that the range was much better with these components, so I have upgraded my old IoT-nodes with these components. They work in the same way as my previous RX/TX modules, but the receiver needs some additional wiring. Both the receiver and the transmitter have a dedicated pin for the antenna wires. With my previous models I had to do some soldering to attach the antennas.
I have deployed nodes with Pro Mini + a Geeetech transmitter outdoors to measure air and soil-temperatures. The signals travels about 30m through several walls to the indoor receiver without problem. The transmitter works with voltages between 3 and 12V according to the spec sheet. The receiver is labeled with 5V, but it works fine with 3.3V from my ESP8266.
Using the data
The ESP8266 bridge node transforms the values received over 433MHz to MQTT messages. My MQTT subscribers then make the data available in Adafruit IO, Home Assistant and Grafana. See these related posts:
InfluxDB and Grafana for sensor time series
Home Assistant – getting started and using MQTT sensors
A self-hosted MQTT environment for Internet of Things – Part 1
A self-hosted MQTT environment for Internet of Things – Part 2
A self-hosted MQTT environment for Internet of Things – Part 3
Lars, I am using all of your code to send data from sensors, to a mqtt bridge and then home assistant. I have hit a stumbling block which is that I want one of the sensors to send pressure which is a float typically with a value of xxxx.xx. Is it possible to amend sensor433.cpp to do so. Can you suggest what change I could make?
LikeLike
Hi Terry! The packets that are sent with the library have a limitation in the available range. A float can only be between -327.67 and +327.67. I use the sendFloat()-method for temperatures and the range is ok for that purpose. I also have a barometric pressure sensor. I get the value in [Pa] from the sensor and convert it to [hPa] by dividing by 100 before sending it as an integer. I’m losing some accuracy this way, but for my purpose it is sufficient (I can see the weather trends and history).
https://github.com/LarsBergqvist/MQTT_IoT/blob/master/RC_Transmitters/TopFloorClient_RC_433/TopFloorClient_RC_433.ino
LikeLike
Another alternative would be to use an offset for barometric air pressure. As the ground level pressure varies between something like 950 and 1050hPa, you could let the sensor node subtract 900hPa from the sensed value and send the rest as a float (with two decimals, this will fit into the protocol). On the receiver side you can add 900hPa to the value that you get from this node to get the correct pressure value.
LikeLike