Skip to content

Wireless UART with nothing but a microcontroller

October 25, 2018

This post describes how to add a wireless UART transmitter to STM32 microcontrollers. This works with zero additional parts since the RF signal is generated directly by the STM32. Also, a fitting receiver realized with a RTL software defined radio is shown.

Currently I am working on a project that is very constrained in terms of physical size and cost. In that project I need to send the temperature wirelessly over a short distance. My normal approach would be to use something like a nRF24L01 together with a microcontroller and temperature sensor. However, this is not possible since there was neither the space nor the “money” for that solution. Microcontrollers combined with radios were also not possible due to their price. Therefore I thought about alternatives and found this: . In that post the author used a STM32 to transmit Morse codes to a FM radio. Since in this approach the STM sends at 100MHz the question if it is legal is easy to answer… But I liked the general idea. Just route the STMs PLL to the MCO output, attach a wire to it and you are done with your transmitter.

I used the very same idea but tweaked the output frequency to 27MHz, which is an ISM band (so it is legal to send there). Instead of sending audio I simply send data like on a serial port using ASQ modulation (meaning: a one bit turns the transmitter on, a zero bit turns it off), hence the name of the project is WUART (wireless UART).

This is not only saving money and board space but can also be a very handy debug interface while developing the software on the STM32. No need to attach any wires, UARTs, FTDIs and whatnot. Just receive your debug output wirelessly 🙂


I implemented a simple software that reads the internal temperature sensor of the STM32 as well as VDD and prints these numbers in a human readable format over the WUART twice a second.
The code is designed to run on a STM32F051R8 (like on the STM32F0 discovery board) and outputs a frequency that is 4 times that of the HSE’s frequency. So ideally, the HSE clock should be 6.75MHz to achieve a transmission at 27MHz.

To build the project:

sudo apt-get install gcc-arm-none-eabi gdb-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi
hg clone
cd wuart/stm32/libopencm3
cd ../projects/wuart

Please note that we are outputting a square signal onto the MCO pin. This means that we will create lots of harmonics. It is advised to only use this in a shielded environment.


As a receiver any RTL SDR USB dongle can be used that supports the reception of the frequency that is transmitted by the STM32 (check for models and their frequency ranges).

I’ve created the following GRC graph to receive the data (also included in the repository):

Explained from left to right:

  • RTL-SDR source: This module is the driver of the RTL stick. It delivers the raw IQ samples at a rate of 2M. You need to adapt the frequency here depending on the frequency of your transmitter
  • Frequency Xlating FIR filter: This module allows you to shift the frequency of the signal in software (instead of reconfiguring the RTL hardware). Use this to fine-tune the frequency
  • Low Pass Filter: The low pass filter performs a low pass filtering followed by a decimation by the factor of 10. The decimation helps to remove unnecessary system load
  • Complex to Mag: This module converts the complex IQ samples to a real number that can be interpreted as signal strength
  • RMS, Divide and Threshold: These modules perform the ASQ decoding with an adaptive threshold. It looks complicated but is quite simple:
    • The RMS module calculates an averaged RMS. This is used to determine the noise level of your environment (the noise that is present when the transmitter is not transmitting)
    • The divide module calculates the ratio of the currently received signal and the averaged background level determined by the RMS module
    • The threshold module looks at the ratio of current signal and averaged background level. If the current signal is 3x higher than the background noise, we interpret the signal as a ‘1’, otherwise as a ‘0’
  • The thresholded ‘bits’ are then outputted onto STDOUT for further processing. Since we are generating these bits at a rate of 200kHz we will get many of these bits per actual payload bit (since the transmitter is sending the payload bits at a much lower rate)


The stream of bits that falls out of the GNU radio schematic still needs to be “framed” into bytes. For this purpose, the repository of this project also contains a framing software in the subdirectory “dec”. The dec software receives the oversampled raw bits from GNU radio via STDIN (so GNU radio and dec can be piped together) and transforms them into actual payload bits. This works simply by sampling the raw bit that is expected to be in the center of a payload bit. The payload bits are then grouped into bytes and outputted to STDOUT.

To run everything, simply pipe the python file generated by GRC into the dec program.

If everything works as expected, you should see the temperature and voltage measurement strings at the output of your terminal.

Please note that the GNU radio program might need some adaptions regarding the frequency and thresholding. It therefore also includes debugging tools to tap into the intermediate results.



From → Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: