STM32 Blue Pill at right with my custom Wisol Sigfox Breakout Board at left

Connect STM32 Blue Pill to Sigfox

Are you creating a cloud-connected IoT device for commercial use that’s inexpensive, works with all kinds of sensors, and lasts for a long time on battery power? (中文版)

The STM32 “Blue Pill” microcontroller connected to a transceiver module for the Sigfox IoT network might be the best combination for low-power IoT devices right now.

You can buy the Blue Pill microcontroller for under US$ 2. That’s even cheaper than Arduino Uno. And yet the Blue Pill has a faster processor (based on 32-bit Arm Cortex-M3), supports more input/output ports: UART (3 ports), SPI (2 ports), I2C (2 ports), USB and CAN Bus, operating on 37 General Purpose I/O (GPIO) pins.

Like the Arduino Uno, the Blue Pill is developer-friendly, with open source libraries and sample programs available. What’s the catch? Developer tutorials for the Blue Pill are scarce right now, because the Blue Pill is a recent “invention” by the brilliant hardware engineers in China (although the overall STM32 ecosystem is already very well established).

In this tutorial I’ll give you all the info and (free, open) source code you need to build your own IoT device based on Blue Pill, with real sensors, and connect it to the Sigfox network. By the end of the article you’ll know all about…

  1. Getting the Blue Pill dev kit
  2. Connecting Blue Pill to sensors and Sigfox transceiver
  3. Intro to Blue Pill programming and cocoOS multitasking library
  4. Compiling, running and monitoring programs on Blue Pill
  5. Using free open-source dev tools: Visual Studio Code and PlatformIO
  6. Configuring the Sigfox Backend for uplink and downlink messaging
  7. Soldering tips for Blue Pill

We’ll take the Blue Pill and transform it into a simple IoT device for environmental monitoring that sends temperature, humidity and altitude data to the Sigfox network every few minutes.

The complete source code may be found here…

If you have been following my past articles, you might find the topics here familiar. I have consolidated all the past topics on Blue Pill development and Sigfox connectivity into this single tutorial. Even if you haven’t read my previous articles, just follow me as we walk through each step…

Prepare The Hardware

To try out the Blue Pill code in this tutorial, we’ll need…

Top to bottom: (1) Blue Pill (2) ST-Link (3) SparkFun BME280 (4) Wisol Sigfox Breakout Board (connected to antenna)

1️⃣ Blue Pill: Buy online at AliExpress. Search for stm32f103c8t6 development board

2️⃣ ST-Link V2 USB Debugger (about US$ 2): Connects the Blue Pill to your computer (via USB) to flash the compiled program into the Blue Pill. Buy online at AliExpress, search for st-link v2

3️⃣ [Optional] SparkFun BME280 Sensor: Our Blue Pill will send actual temperature, humidity and altitude data from the BME280 sensor. If you don’t have the sensor, we can configure the program to send simulated sensor data instead.

4️⃣ [Optional] Breakout Board for Wisol Sigfox Transceiver: Our Blue Pill will transmit sensor data to the Sigfox network via the Wisol WSSFM10RxAT module.

If you don’t have the breakout board, the program can simulate the sensor data transmission to Sigfox.

When browsing Sigfox products, click on the “Zone” box to show only products for your region

To buy the Wisol Sigfox Breakout Board, browse the official list of Sigfox developer kits and click the Zone box to filter by your region (e.g. Sigfox Zone RCZ 1 for Europe, RCZ 2 for US).

Choose a breakout board that’s based on Wisol WSSFM10RxAT (where “x” denotes 1, 2, 3 or 4 for the four RCZ zones). And it should be powered by 3.3 volts, not 5 volts.

For example, for Europe you may choose the SNOC BRKWS01. For US, you may choose the Sea Slug Labs Wisol WSSFM10R2 Board.

You may also buy the Wisol Sigfox Breakout Board from the Tindie marketplace:

My Custom Wisol Sigfox Breakout Board

If you can’t find a suitable Wisol Sigfox Breakout Board, you could build your own.

I have published the PCB design for a breakout board in Autodesk EAGLE CAD and Gerber formats.

The design should work with Wisol Sigfox modules for RCZ 1, 2, 3 and 4 (although I have tested only one board for RCZ 4)

U.FL antennas - I tested the one at the top

If you’re making your own breakout board, remember to get the right U.FL antenna for your region: 868 MHz for RCZ 1 (Europe and Middle East), 902 MHz for RCZ 2 (US), 923 MHz for RCZ 3 (Japan), 920 MHz for RCZ 4 (Australia, New Zealand, other parts of Asia).

I have tested this antenna for RCZ 4 (the one at the top of the photo).

Important: Always connect your antenna to your Wisol Sigfox Breakout Board before powering on the Blue Pill. Otherwise you may damage the Wisol module!

Blue Pill (right) connected to Wisol Sigfox Breakout Board (left) on port UART2, and to BME280 sensor (centre) on port SPI1

Connect The Hardware

Follow the above diagram to connect the Blue Pill to the Wisol Sigfox Breakout Board and to the BME280 sensor…

Blue Pill Pin PA4  (SS1)   → BME280 Pin !CS
Blue Pill Pin PA5 (SCK1) → BME280 Pin SCK
Blue Pill Pin PA6 (MISO1) → BME280 Pin SDO
Blue Pill Pin PA7 (MOSI1) → BME280 Pin SDI
Blue Pill Pin 3V3 → BME280 Pin 3.3V
Blue Pill Pin GND → BME280 Pin GND
Blue Pill Pin PA2  (TX2)   → Wisol Pin RX
Blue Pill Pin PA3 (RX2) → Wisol Pin TX
Blue Pill Pin 3V3 → Wisol Pin 3.3V
Blue Pill Pin GND → Wisol Pin GND
Connecting Blue Pill to ST-Link USB Debugger

Note that the Blue Pill ships with the header pins unsoldered. Check the soldering tips at the end of this article.

Connect the Blue Pill to the ST-Link USB Debugger.

Connecting Blue Pill to ST-Link USB Debugger

Note: For the ST-Link, only the bottom row of pins is used. The Micro USB Port of the Blue Pill doesn’t need power — the BME280 sensor and the Wisol Sigfox Breakout Board will be powered by the ST-Link.

Both jumpers should be set to the “0” positions

Ensure that both yellow jumpers on the Blue Pill (BOOT0 and BOOT1 near the Micro USB Port) are set to the 0positions (closer to the Micro USB Port).

Don’t connect the ST-Link to your computer yet, we need to install the Windows drivers for ST-Link, as described below.

For a complete list of pins on Blue Pill and their functions, see this pinout diagram.

Install The Software

Follow the steps below to install OpenOCD (the software that connects to the ST-Link Debugger and displays the debug log for the Blue Pill) and the ST-Link USB Driver (for Windows only)…

For Windows:

  1. Download OpenOCD from the 
    Unofficial OpenOCD release website 
  2. Unzip the downloaded file and copy the OpenOCD files into c:\openocdsuch that openocd.exe is located in the folder c:\openocd\bin
  3. Download the ST-Link USB driver from the 
    ST-Link Driver Website (email registration required)
    Click Get Software
  4. Unzip the downloaded file. Double-click the driver installer: 

For Mac:

  1. Install brew 
    Brew Website
  2. Enter the following in a command prompt:
    brew install openocd

For Ubuntu:

  1. Install the udev rules for the ST-Link
  2. Enter the following in a command prompt:
    sudo apt install openocd

Download The Source Files

Open a Windows, Mac or Ubuntu command prompt and enter:
(For Windows, install git from Git For Windows)

git clone
cd send_altitude_cocoos

Then enter the following into the command prompt…

For Windows:


For Mac and Ubuntu:

chmod +x scripts/*.sh

This creates symbolic links for the source files inside the src folder, and replaces the default cocoOS configuration os_defines.h with our own. Also this installs a subset of the Boost library used by the program (UART Interface specifically).

Install Visual Studio Code and PlatformIO

Download and install Visual Studio Code from
Visual Studio Code Website

For Windows, choose the User Installer

Launch Visual Studio Code.

In the left menu bar, click the Extensions icon.

Install the following extensions:

  1. PlatformIO (by PlatformIO — see above)
  2. C/C++ (by Microsoft — see below)

If the Install button is missing for the C/C++ extension, then it’s already installed.

After installing, click Reload to restart Visual Studio Code

Click File → Open Workspace

Browse to the send_altitude_cocoos folder.

Select workspace.code-workspace

In a while you should have a fully configured Visual Studio Code workspace with PlatformIO. In the Workspace pane at left, double-click on platform.hand uncomment the following line so that you’re using the right features for this article…

#define CONFIG_ARTICLE5  //  Uncomment to support Article #5

Check that the other #define CONFIG_ARTICLE... lines are commented out.

In the Workspace pane at left, double-click on main.cpp and you should see this…

Our Blue Pill IDE — Visual Studio Code with PlatformIO

How Does The Program Read Sensors?

Let’s pause and look at main.cpp. This is the main C++ program that runs on the Blue Pill.

Remember for Arduino the system functions are defined in the Arduino.h library? For Blue Pill we use the open source library libopencm3. You’ll see libopencm3 included at the top of main.cpp.

Overall Flow of the Blue Pill Program. The Altitude Sensor Task is not shown.

To demonstrate how we may read multiple sensors concurrently on Blue Pill (since it’s powerful enough to do so), the program uses the cocoOS multitasking library.

Recall that the BME280 can provide 3 sensor values: temperature, humidity and altitude.

The program creates 3 Sensor Tasks to read the values, one task for each sensor…


Each Sensor Task contains the code to read the sensor value, in the poll_sensor() function. For example, the poll_sensor() function in the Temperature Sensor Task calls the bme.temp() function (from the BME280 library) to read the temperature value from the BME280 via port SPI1...

What happens to the returned sensor values: temperature, humidity, altitude? The Sensor Task creates a Sensor Data Message (thanks to the cocoOS library) and transmits the message to the Network Task

Simplified from
Life of a Sensor Task: Read, Send, Sleep

The Sensor Task loops forever reading the sensor and transmitting the sensor value (after pausing 10 seconds).

cocoOS also provides Semaphores to ensure that our Sensor Tasks won’t clash when reading the same I/O port, like the SPI1 port connected to BME280.

More about Semaphores in this article.

Thanks to cocoOS our sensor code is clean and efficient!

SPI1 Semaphore prevents two tasks from accessing the SPI1 port connected to BME280

How Do We Transmit Sensor Data To Sigfox?

Overall Flow of the Blue Pill Program. The Altitude Sensor Task is not shown.

Recall that the Sensor Task sends Sensor Data Messages to the Network Task.

The Network Task (source code in wisol.cpp) receives the sensor data (temperature OR humidity OR altitude) and aggregates them into a single Sigfox message: temperature AND humidity AND altitude.

To prevent too many messages from being sent over Sigfox, the Network Task includes a Throttle Feature to limit the sending of messages. So we send only what we need, when we need to.

Life of Network Task: Receive, Aggregate, Transmit

The Network Task forwards the outgoing Sigfox message to the UART Task, which manages the Wisol module for transmitting Sigfox messages. Why create another task for UART?

How Do We Handle Wisol UART Commands?

The Wisol module communicates with Blue Pill via the UART port (a.k.a. Serial port) at the slow speed of 9600 bps. Normally the UART Task would have to send a character, wait a while, send another character, wait again, …. Then repeat the process for receiving characters.

But the Blue Pill is designed for multitasking! While sending or receiving characters, the Blue Pill could read some sensor data or compose the next Sigfox message. If you read the UART code in uart.cpp, the UART Task optimises the available time by listening for Interrupts.

The UART Task is notified by the Blue Pill’s UART hardware — hence the “Interrupt” — whenever new characters are ready to be read. The UART Task is no longer busy waiting for data, it can now give up its waiting time to cocoOS, which will schedule another Sensor Task or Network Task to run (if any). The interrupt code is here: stm32/uartint/uartint.cpp.

The Wisol module accepts AT commands for transmitting and receiving Sigfox messages — you can see examples here. The AT commands are not composed in the UART Task, but rather in the Network Task. So that we may reuse the UART Task for other UART duties in future.

Need to learn more about the Network Task and UART Task? Check out this article.

Configure The Blue Pill Program

Before we run the program, there are some settings that we need to configure…

enable_debug();       //  Uncomment to allow display 
// of debug messages in development
// devices. NOTE: This will hang if
// no debugger is attached.
//  disable_debug();  //  Uncomment to disable display 
// of debug messages. For use in
// production devices.

1️⃣ Enable or Disable Debug Mode: By default the program runs in Debug Mode. Debugging messages are displayed on the Blue Pill console to let you know that the program is indeed running. However this requires the ST-Link to be connected. If the ST-Link is not connected, the Blue Pill’s Green LED (labelled PC13) will blink at startup…

✳️ On — ◻️ Off — ✳️ On —— ◻️ Off — ◻️ Stays Off

And hangs there indefinitely waiting for the ST-Link (normally the LED should continue blinking). If you do not wish to use ST-Link for your production Blue Pill: Edit main.cpp, comment out enable_debug(), and uncomment disable_debug() like this…

//  enable_debug();
disable_debug(); // Debug is now disabled.

2️⃣ Set the Sigfox RCZ Region: Edit main.cpp and look for this line of code…

//  Start the Network Task.
setup_wisol(&wisolContext, &uartContext, uartTaskID,
COUNTRY_SG, false);

Change COUNTRY_SG to your country code, e.g. COUNTRY_US. This selects the frequency for Sigfox transmission.

3️⃣ Enable BME280 Simulator: If you have a SparkFun BME280 sensor, skip this step.

If you don’t have the BME280 sensor, you can configure the Blue Pill program to simulate a BME280 sensor and return hardcoded values for temperature, humidity and altitude. Edit platform.h and uncomment all lines that define SIMULATE_BME280. After editing, you should see this:

#define SIMULATE_BME280 // Uncomment to simulate a BME280 sensor

4️⃣ Enable Wisol Simulator: If you have a Wisol Sigfox Breakout Board, skip this step.

If you don’t have a Wisol Sigfox Breakout Board, you can simulate one in the Blue Pill program. Edit platform.h and uncomment all lines that define SIMULATE_WISOL. After editing, you should see this:

#define SIMULATE_WISOL // Uncomment to simulate a Wisol module

The source code for the BME280 and Wisol Simulators may be found here: i2cint.cpp and uartint.cpp .We’re all set to run our Blue Pill program!

Command buttons in the status bar

Build, Upload And Monitor Your Blue Pill Program

Connect the ST-Link (with Blue Pill) to your computer. Notice the buttons at the lower left? (See screen above) We’ll click them now. If the buttons are not visible, click the menu Terminal → Run Task → PlatformIO… to run the commands instead.

Building your Blue Pill program

► Click the ✅️ Build button.

This compiles your Blue Pill program and links it with the libopencm3 library.

The build step produces a Blue Pill executable program.

Uploading your program to the Blue Pill

► Click the ➡️ Upload button.

Our IDE connects to your Blue Pill via the ST-Link USB Debugger and writes the executable into the Flash Memory.

Your program will remain in the Flash Memory even after disconnecting the power. Just like the Arduino.

Connect to view Blue Pill debug log

► Click in the menu: 
Terminal → Run Task

Select 🔗 Connect To STM32 Blue Pill to see the debug log (as displayed by OpenOCD). It works like the Arduino Serial Monitor.

Blue Pill Debug Log showing the execution of the program, just like the Arduino Serial Monitor
Remember to Trash the debug log

When you’re done with the debug log, always click the 🗑️ Trash icon at the right.

This closes the Blue Pill connection so that you can continue uploading programs to the Blue Pill. Unfortunately the ❎️ Close icon doesn’t close the connection — it only hides the debug log, keeping the connection open. So always click the 🗑️ Trash icon.

Blue Pill gets chatty with Sigfox when the lights flash

Watch Blue Pill Run

When the program runs on your Blue Pill, you will see signs of life when the LEDs start flashing like in the video above. The green LED at the top right (PC13) flashes whenever the Network Task is aggregating some sensor data received from multiple Sensor Tasks. Even when you’re using a Simulated BME280 Sensor or Simulated Wisol Sigfox Module.

Debug Log for the Blue Pill, running with a real Wisol Sigfox Breakout Board and real BME280 sensor

The video above shows the debug log for the Blue Pill program running with a real BME280 sensor and a real Wisol Sigfox module. Some highlights…

  1. Note that the sensor data collection never stopstmp >> for temperature, hmd >> for humidity, alt >> for altitude. Even when sending messages to Sigfox. That’s the power of multitasking on Blue Pill!
  2. Every message the program sends to Sigfox includes a Downlink Request. That means the Sigfox cloud will actually wait for our server callback URL to return an 8-byte response message that will be passed back to the device.
  3. Sigfox Downlink takes a long time to complete — up to 1 minute! That’s why we don’t see any acknowledgement of the sent message until 1 minute later. While waiting the program may still run other Sensor Tasks and the Network Task.
  4. Towards the end of the video we can see a successful Sigfox Downlink message received after 1 minute: process_downlink_msg FEDCBA9876543210. We may insert our own code for Sigfox Downlink processing into downlink.cpp.

If you’re using a Simulated BME280 sensor or a Simulated Wisol Sigfox module, you’ll see hardcoded sensor data and Wisol commands. But the overall flow of the messages remains the same.

How does a Sensor Task read and send sensor data? What do the messages in the Debug Log mean? These are explained here, with links to the actual source code…

How does the Network Task receive, aggregate and transmit sensor data? That’s explained here…
Timeout error in Blue Pill Debug Log

You may see this error message in the Debug Log: ERR_SFX_ERR_SEND_FRAME_WAIT_TIMEOUT. That’s because the Blue Pill is sending a Downlink Request to Sigfox and we haven’t configured your device for downlink yet. Let’s do that now…

Configure The Sigfox Backend

Follow the instructions provided by the makers of the Sigfox breakout board for activating the Wisol Sigfox module online. You’ll be guided through the steps to create a user account on the Sigfox Backend portal. (If you’re using a custom-built breakout board, see the screens below)

To activate your custom breakout board: Click Device → New and enter your device ID and PAC (shown in the Blue Pill debug log). Click Register As Prototype

Let’s add a Sigfox callback to handle the downlink request. Log in to the Sigfox Backend: Click Device Type, select your device type, click Callbacks.

Under Device Type → Callbacks, click New then Custom Callback

Click New to create a Sigfox callback.

Select Custom Callback.

Use the settings below to configure the callback.

For the Body field, make sure there are no spaces at the end of each line.

For testing, you may use my Sigfox Downlink Server URL:
Sigfox Callback Configuration

This Sigfox Downlink Server is hosted on my personal Amazon Cloud account and it has been hardcoded to return the downlink message fedcba9876543210 for any device ID. I hope this helps to make your Sigfox Downlink development and testing easier.

Click the Downlink circle to enable downlink

After creating the callback, click the circle in the Downlink column. It should show as a filled circle, not an empty circle.

Sigfox Downlink is now enabled for your Blue Pill!

Callback and Downlink Status under Device → Messages

Check the Blue Pill Debug Log in Visual Studio Code and confirm that your Blue Pill is still running.

Click Device → Messages to check the messages sent by your Blue Pill to Sigfox.

You’ll see two arrows in the Callbacks column:

  • The first arrow should show Callback Status (OK)
  • The second arrow should show Downlink Status (Acked)

This information is useful for troubleshooting problems with our Downlink Server.

If you don’t receive any messages, go to Device → Information, click Disengage Sequence Number

Still not receiving any messages? Sometimes the Sigfox Sequence Number may overflow for your device if your device has transmitted many messages while out of network coverage.

To fix this, go to Device → Information and click Disengage Sequence Number. Your device should be able to send messages to Sigfox now. The Device → Events page may also give you clues why your device has stopped transmitting.

Unleash Your Blue Pill

Breadboard Power Supply at the top

You’re now all set to unleash your powerful new Blue Pill IoT gadget!

Remember to disable debug mode, as mentioned earlier. Otherwise your Blue Pill will stop flashing and wait forever to be connected to an ST-Link.

We have been using the ST-Link to power our Blue Pill. Consider getting a Breadboard Power Supply like the one shown at the top of the photo. Go to AliExpress and search for:

Breadboard Power Supply Module MB-102 Model 830

To build your own Sigfox Downlink Server for handling the callbacks, read the section “Our Downlink Server” in this article.

What’s coming next? Since I teach IoT, please suggest which IoT topics I should write about!

I’m now creating a version of the Sigfox breakout board using the newer InnoComm SN10–12 Sigfox module. If I can resolve the InnoComm procurement issues with my PCB manufacturer (Seeed Shenzhen), I’ll definitely update this tutorial.

I’m also extremely excited about the use of FPGAs for IoT. With FPGAs we could create highly power-efficient IoT devices. I had an amazing experience with the GOWIN FPGA, I’ll be using it soon to create more advanced IoT gadgets.

Would you be interested in a Chinese version of this article? Please let me know!

Stress Testing the Blue Pill with Wisol Sigfox Module and BME280 Sensor. Works perfectly after 12 hours of non-stop operation!

Blue Pill Tips: How To Solder Header Pins To Blue Pill

If you’re experienced in soldering, you can skip this section. But if you haven’t soldered anything before (like me before I started Blue Pill programming), I have some useful tips for beginners soldering the Blue Pill header pins.

The principles of soldering are explained here…

…but I found some steps difficult to execute properly. After some experimenting and tweaking, I found the right tools and techniques for beginners. Here’s what I’m using…

My soldering iron with LEDs, very fine solder wire and soldering kit

Soldering Iron with LEDs: Get a soldering iron with LEDs (so you can see what you’re soldering) and a tiny solder tip. I’m using the Flat Solder Tip that came with the soldering iron. Why Flat Tip and not Pointed Tip? Because a Flat Tip is easier to tap on header pins to heat them up (you’ll see in the video below).

Fine Solder Wire (0.38 mm): I used a very fine solder wire, much finer than the normal ones. They are more “forgiving” if you make mistakes, because you’ll only need to fix the tiny solder dabs of mistakes that you have committed. Instead of big solder blobs that are harder to fix. But note that you will have to touch up the soldering for each pin to provide sufficient solder.

Soldering Kit: Get a soldering stand with magnifying glass. Get a clamp to secure your Blue Pill before soldering. Mount your Blue Pill on a mini-breadboard before soldering. Don’t forget the sponge (the yellow thing in the photo above).

Measure and break the header pins

Ready to solder? Use the technique above to measure the header pins and break into two rows very gently.

Mount the Blue Pill on a breadboard

Carefully align the header pins and mount the Blue Pill on a mini-breadboard. The header pins may become dislodged from the yellow sockets if you rock them back and forth while mounting. To prevent this, use a hard flat non-conductive surface (like my USB hub above) to press down firmly and slowly on the pins.

The Blue Pill may wobble as you solder — stabilise it temporarily with Blu-Tack before soldering. There should be no wobbly parts during soldering.

Secure the mini-breadboard to the soldering clamp. Again, use Blu-Tack to fix any wobbly parts.

Power on the soldering iron and wait for it to heat up. To solder each pin:

  1. Don’t tap the soldering iron on any pins yet. Keep the tip away from any part of the Blue Pill.
  2. Straighten the solder wire.
  3. Tap the solder wire on the soldering iron so that it starts melting (the shiny blob in the video below).
  4. Gently tap the soldering icon on the pin to heat it up. Don’t leave it there for more than a few seconds because you may damage the components connected to the pin. Lift the soldering iron and tap again if necessary.
  5. Push the solder wire towards the space between the pin and the metal ring. If the pin is hot enough, the solder should melt and fill the space.
  6. Repeat the steps until the metal ring is totally covered by solder. Remember: Don’t rest the soldering iron tip on any of the pins for more than a few seconds.
  7. Rotate the clamp to solder the pins on the other side. Always point the soldering iron tip away from any parts mounted on the Blue Pill.
  8. If your hands are shaky, rest them on the soldering clamp while soldering.

Watch the video below a few times and you’ll understand what I mean. This technique is slower because of our fine solder wire, but it works better for older people like me with shaky hands and poor eyesight.

Further Reading

The complete source code for this article is available here…

I got started on Blue Pill programming with this great “Beginning STM32” book by Warren Gay (possibly the only book published on Blue Pill)…

Later as I started digging for more details (like the “Half-Done Interrupt”) the “Mastering STM32” book was valuable. Note that it talks about the entire family of STM32 microcontrollers, and it uses the official STM32 API, not libopencm3. So it might overwhelm you…

The Blue Pill (STM32F103C8) Datasheet and other official docs are here…

And the “The Insider’s Guide To The STM32 ARM®Based Microcontroller” is a terrific intro to the STM32 family…