element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Test & Tools
  • Technologies
  • More
Test & Tools
Blog FSK Demodulation with R&S FPC Spectrum Analyzers, or How I Achieved an Optimal Room Temperature
  • Blog
  • Forum
  • Documents
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Test & Tools to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: shabaz
  • Date Created: 20 Jan 2026 9:01 PM Date Created
  • Views 559 views
  • Likes 15 likes
  • Comments 26 comments
  • rohde & schwarz
  • cc1101
  • E07-900MM10S
  • r&s
  • modulation
  • ebyte
  • fpc
  • fpc1000
  • ask
  • rf
  • fpc1500
  • E07-400MM10S
  • demodulation
  • fsk
Related
Recommended

FSK Demodulation with R&S FPC Spectrum Analyzers, or How I Achieved an Optimal Room Temperature

shabaz
shabaz
20 Jan 2026

Introduction

I wrote a review (and created a video) for a Rohde & Schwarz FPC series spectrum analyzer eight years ago, and although I explored some of the demodulation capability back then, I never used it for a real-life scenario. Fast-forward to the cold winter of 2025, and I had a need! This short blog post shows how useful that capability can be.

What was the Problem to Solve?

I have a pretty awful heating system controller at home; it never regulates the temperature all too well, and its user interface is buggy and difficult to use.

The controller relies on a radio transmission to switch the boiler on or off, and I fancied overriding the controller with my own custom system. This would involve reverse-engineering the radio protocol.

I was able to partially figure it out by probing around inside the transmitter, but the transmitter module was a black box (an unlabelled blob). I managed to narrow it down to possibly a Silicon Labs (Silabs) chipset range - perhaps Si443x series, and capture some of the bitstream using a logic analyzer.

image

It was a weird system, it used an out-of-band SPI interface for configuration, but the actual transmission was controlled through a kind of direct signal used for modulation on-the-fly (i.e. not a packet-oriented transfer from the microcontroller to the transmitter chip), at around 9600 bits per second, for a duration of about 176 bits. You can see this in the screenshot below, where firstly some of the purple data (configuration data) is sent together with the blue SPI clock signal, but then a load of purple data is sent without the blue clock signal changing. That clock-less portion of purple data is the direct signal that modulates the transmission, and that period length was measured to be 176 bits long, if the speed is 9600 bits/sec. The yellow signal appears to be an interrupt from the transmitter IC, paced at 9600 Hz, to act as a handshake to let the microcontroller know when it can apply the next data bit.

I didn’t manage to narrow down the SPI content to any specific chip, so I had no idea what frequency or modulation scheme was set up.

image

FPC Configuration

I decided to capture the transmission using the FPC1500 using its Digital Demodulation functionality. Here’s how I did it. The photo below shows in red all the buttons used.

image

I took a guess at the frequency being ballpark 868 MHz (easy to see from the length of the antenna wire inside the transmitter, but if you're unsure, just observe a span of spectrum until you see activity) and pressed Freq and set the FPC1500 center frequency to that value.

I pressed Ampt (Amplitude) and set the reference level to -20 dBm. Next, I pressed the Mode button and selected Digital Demodulation. Then I pressed the Meas button, and selected FSK (Frequency Shift Keying; I could have selected ASK [Amplitude Shift Keying] too). Within the Meas menu, you can configure demodulation parameters. I set the Symbol Rate to 9600, and Frequency Deviation to 5 kHz (since I expected it to be around that ballpark), and then set Number of Symbols to 176.

The FPC1500 needs to be told when to trigger to capture the data; to do that, I pressed Sweep, then selected Trigger, then selected IQ Power and set it to -30 dBm, again this was just a guess, it’s not too critical.

To view the captured data, I clicked on Meas again, then clicked on Symbols, for the binary data display whenever the trigger power level occurs.

Capturing the Data

I connected the FPC's RF input to a small 868 MHz antenna and placed it near the transmitter, and voila! The FPC1500 triggered and displayed all the binary data. If you look at the binary symbols in the screenshot, you'll see the signature of a healthy transmission, because it begins with an alternating pattern of ones and zero's, which is almost always a "preamble" sequence to train the receiver to get ready to receive the rest of the bits of data.

image

I manually typed the bit values into my PC (there may be a way to export it, but it’s not a lot of data), and then I was able to match it to the earlier logic analyzer capture. There was a slippage of 6 bits, but that’s not a big deal; I let AI (ChatGPT) figure that out.

Next Steps

Now that I knew the approximate frequency and modulation details, it would be possible to replicate things with a custom transmitter circuit. I decided to use a Texas Instruments CC1101 chip, since that’s super-flexible (and overkill admittedly). I purchased an EBYTE E07-900MM10S module (which contains a CC1101 inside) because it’s low-cost and has pads that are easyish to solder.

I attached the EBYTE module to a Pi Pico module, and wrote code to replicate the transmission. I used the R&S FPC Digital Demodulation functionality to troubleshoot the code, until the symbols looked similar, and then verified that it did indeed control the boiler. That still needs documenting, and so it is a write-up for another day. The photo below shows the EBYTE module dead-bugged onto a Pico-Eurocard board.

image

Circuit Diagram:

image

Summary

The R&S FPC Spectrum Analyzer can trigger on a received radio transmission, and directly convert digital modulation schemes such as ASK and FSK into a decoded bit sequence, and it's just a few button presses to configure it. This can be very helpful when reverse-engineering a radio transmission, or when writing code for a transmitter and using the FPC to check that the transmission is correct. If you don’t have an FPC instrument, an alternative method would be to use a software-defined radio (SDR), but usually there’s a significant learning curve with that. The FPC was far easier to use. It solved my problem and gave me control of my heating system.

Thanks for reading.

  • Sign in to reply

Top Comments

  • shabaz
    shabaz 2 months ago in reply to kmikemoo +1
    Thanks! I wasn't entirely confident the reverse-engineering would work, nor the replication, since I wasn't 100% sure of what I was supposed to be replicating.. I just plugged away at it for a few evenings…
Parents
  • dougw
    dougw 2 months ago

    Pretty slick application of experience and instrumentation.

    Are there just 2 messages (On and Off) ?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz 2 months ago in reply to dougw

    I believe so, but I'm not 100% sure (there may be messages to link sensors etc, but I don't have any other than the transmitter unit). 

    The transmitter unit contains a temperature sensor, and a microcontroller and LCD/buttons to set up timers etc., but it all stinks (it is more complicated than VCRs used to be for setting timer recordings!) and the temperature sensor has very poor granularity too, and warms up in the hand if the transmitter is picked up, or moved, so it's all a mess.

    I simply wrote my own basic algorithm, and I can tweak it over time. This is the algorithm currently:

    Loop while True (forever):

         Convert temperature to a boiler duty cycle (based on a simple curve for now)

         Scale down the duty cycle during daylight hours, since the home is likely to be empty then

         Convert the duty cycle to a PWM state (ON/OFF) and send message to the boiler using the CC1101

         Sleep for 1 minute

    The code is literally that:

    image

    Since I'm using a Pico-W (with WiFi capability) I'm using some API to get the time/date (worldtimeapi,org) and the temperature (open-meteo.com), i.e. I've got no sensors interfaced to the Pico currently, I'm getting the outdoor temperature based on longitude/latitude. I'm still tweaking it to make it more reliable, and will then write it up. It's not great currently, because it's naughty to keep querying an API to get the time/date, and it may error out at some point.

    Example output when running:

    Connected to WLAN, assigned IP address: 192.168.1.53
    Radio configured
    9.8 deg C, time 23:08 on 21/01/2026, 0% duty, boiler OFF
    9.8 deg C, time 23:09 on 21/01/2026, 0% duty, boiler OFF
    9.8 deg C, time 23:10 on 21/01/2026, 0% duty, boiler OFF
    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • shabaz
    shabaz 2 months ago in reply to dougw

    I believe so, but I'm not 100% sure (there may be messages to link sensors etc, but I don't have any other than the transmitter unit). 

    The transmitter unit contains a temperature sensor, and a microcontroller and LCD/buttons to set up timers etc., but it all stinks (it is more complicated than VCRs used to be for setting timer recordings!) and the temperature sensor has very poor granularity too, and warms up in the hand if the transmitter is picked up, or moved, so it's all a mess.

    I simply wrote my own basic algorithm, and I can tweak it over time. This is the algorithm currently:

    Loop while True (forever):

         Convert temperature to a boiler duty cycle (based on a simple curve for now)

         Scale down the duty cycle during daylight hours, since the home is likely to be empty then

         Convert the duty cycle to a PWM state (ON/OFF) and send message to the boiler using the CC1101

         Sleep for 1 minute

    The code is literally that:

    image

    Since I'm using a Pico-W (with WiFi capability) I'm using some API to get the time/date (worldtimeapi,org) and the temperature (open-meteo.com), i.e. I've got no sensors interfaced to the Pico currently, I'm getting the outdoor temperature based on longitude/latitude. I'm still tweaking it to make it more reliable, and will then write it up. It's not great currently, because it's naughty to keep querying an API to get the time/date, and it may error out at some point.

    Example output when running:

    Connected to WLAN, assigned IP address: 192.168.1.53
    Radio configured
    9.8 deg C, time 23:08 on 21/01/2026, 0% duty, boiler OFF
    9.8 deg C, time 23:09 on 21/01/2026, 0% duty, boiler OFF
    9.8 deg C, time 23:10 on 21/01/2026, 0% duty, boiler OFF
    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • shabaz
    shabaz 1 month ago in reply to shabaz

     I've been running the code continuously for the past fortnight, and it's been reliable. The screenshot shows the network activity over a typical 24-hour period (I've been checking this regularly).

    image

    However, for the last day or so (I don't know the precise time on Sunday that it occurred), the network activity is different:

    image

    It may well be API reattemps, but, I have no idea, because I cannot peek at any detailed status, nor observe error codes (there's no display, and no serial interface). Boilers themselves have interfaces (there are at least a couple of popular serial ones). I could implement a serial interface as one option. It could even be an API change (the fact that it occurred on a Sunday could be a smoking gun), although to me it seems the API response still looks approximately what I expect, when I test the API from a web browser).

    I've been working on a separate project to provide general external logging and alarms and data querying. It appears to function, but I'm refining it. At some stage I'll port that to this project.

    For now I could power-cycle the system to see if the traffic goes back to normal, but I'll give it a day or two, to continue to see what happens. Right now it's too warm for the boiler to switch on, but the heartbeat LED indicates that the main code loop is running, and the router log shows that the WiFi has not disconnected. There may well be bugs related to reattempts, but I've improved that greatly recently (not ported that across to the live system yet either) - a good tool is called WireMock, that allows you to simulate API failures, and I've been using that for testing (will write a blog at some point).

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube