This hands-on lab uses an ESP32 simulation and Python to practice Sigfox concepts: encoding data into 12-byte payloads, managing the 140 message/day budget, measuring power consumption patterns, and calculating battery life for multi-year deployments with different messaging strategies.
50.1 Introduction
⏱️ ~25 min | ⭐⭐ Intermediate | 📋 P09.C11.U04
This hands-on chapter provides practical experience with Sigfox concepts through an interactive ESP32 simulation and Python implementations. You’ll learn how Sigfox handles message constraints, implements low-power operation, and manages daily message budgets.
Learning Objectives
By the end of this lab, you will be able to:
Implement Sigfox 12-byte payload encoding using packed binary structs and fixed-point scaling
Analyze daily message budget utilization against the 140-message subscription limit
Diagnose power consumption bottlenecks by comparing TX, RX, and sleep current contributions
Calculate battery life for different messaging scenarios using energy budget formulas
Construct payload encoders and decoders in Python for environmental and GPS data types
Key Concepts
Sigfox Development Kit: Hardware platforms for Sigfox prototyping including Arduino shields, evaluation boards, and certified development modules.
AT Commands: Serial command interface used to control Sigfox modules; standard commands include AT\(SF (send frame), AT\)DR (data rate query), and AT$T (temperature read).
Payload Construction: Building binary payloads for Sigfox using byte manipulation, struct packing, and hexadecimal encoding in firmware code.
Backend Testing: Verifying message reception using Sigfox backend portal, checking device statistics, and validating callback delivery to application server.
Signal Testing: Measuring received signal quality using backend RSSI data from multiple base stations to assess coverage at test locations.
Hands-on Workflow: Practical development cycle from hardware setup, firmware compilation, device registration, message sending, and backend verification.
Debugging Tools: Methods for troubleshooting Sigfox implementations including AT command testing, backend console inspection, and RF spectrum analysis.
For Beginners: Sigfox Hands-On Lab
This lab guides you through sending your first Sigfox messages and viewing them in the Sigfox cloud platform. You will register a device, transmit sensor data, and see it appear on a dashboard. It is the fastest way to experience how Sigfox turns tiny radio messages from remote sensors into usable data.
Sensor Squad: Hands-On with Sigfox!
“Time to get our hands dirty!” Sammy the Sensor announced excitedly. “In this lab, we build a simulated Sigfox device on an ESP32. I read the temperature and humidity, then we pack everything into exactly 12 bytes – temperature as a scaled integer, humidity as a percentage, battery voltage, message count, status flags, and a timestamp. Every byte counts when you only have twelve!”
“Watch the OLED display as we run the simulation,” Lila the LED said. “You will see the message counter climb toward 140. When it hits the daily limit, I turn red to show that no more messages can be sent. The network just silently drops anything extra. It is a powerful visual reminder of why you need to budget your messages carefully.”
Max the Microcontroller pointed at the code. “Notice how the payload struct uses packed integers – int16 for temperature multiplied by 100, uint16 for humidity, uint8 for flags. We fit five sensor readings plus a timestamp into exactly 12 bytes. Compare that to sending the same data as text: ‘temp=22.5,hum=65.0’ would be 18 characters – already over the limit! Binary encoding is the secret to making Sigfox work.”
“The energy tracking in this lab is my favorite part,” Bella the Battery added. “Each message is transmitted 3 times at 40 milliamps for 2 seconds each – that is 6 seconds total, using 0.067 milliamp-hours per message. With a 2,000 milliamp-hour battery and 24 messages per day, that gives us about 3.4 years of life! But push it to 140 messages per day and battery life drops to just 7 months. This lab lets you experiment with those trade-offs in real time.”
This interactive lab simulates Sigfox ultra-narrowband communication using an ESP32. You’ll learn how Sigfox handles severe message constraints, implements low-power operation, and manages daily message budgets.
Lab Objectives
Apply Sigfox’s 12-byte uplink payload limitation to a real sensor data packing problem
Implement efficient binary payload encoding using scaled integers and bit flags
Assess daily message budget utilization under different reporting intervals
Diagnose power consumption patterns by isolating TX, sleep, and RX energy contributions
Demonstrate ultra-narrowband communication trade-offs through RSSI and timing observations
Configure retry strategies for message transmission failures within budget constraints
Click “Start Simulation” in the Wokwi window above
Observe the OLED display showing:
Current sensor readings (temperature, humidity, battery)
Messages sent today / daily limit (140)
Next scheduled transmission time
TX power state and RSSI signal strength
Press the button to send an immediate message (watch payload encoding)
Monitor Serial output for detailed logs:
Payload byte breakdown
Message transmission timing
Power consumption estimates
Success/failure indicators
Watch LED indicators:
Blue LED: Message transmission in progress
Green LED: Successful transmission
Red LED: Transmission failure or daily limit exceeded
Experiment with scenarios:
Observe how the 12-byte payload is efficiently packed
Watch the daily message counter increment
See what happens when approaching the 140 message limit
Notice the ultra-low power sleep periods between transmissions
50.3.2 Wokwi Code
Copy and paste this code into the Wokwi editor:
diagram.json (Hardware Configuration):
{"version":1,"author":"IoT Class - Sigfox Lab","editor":"wokwi","parts":[{"type":"wokwi-esp32-devkit-v1","id":"esp32","top":0,"left":0,"attrs":{}},{"type":"wokwi-dht22","id":"dht1","top":-30,"left":120,"attrs":{}},{"type":"wokwi-ssd1306","id":"oled1","top":-160,"left":-120,"attrs":{"i2cAddress":"0x3c"}},{"type":"wokwi-pushbutton","id":"btn1","top":100,"left":-150,"attrs":{"color":"green"}},{"type":"wokwi-led","id":"led_tx","top":180,"left":-140,"attrs":{"color":"blue"}},{"type":"wokwi-led","id":"led_rx","top":180,"left":-100,"attrs":{"color":"green"}},{"type":"wokwi-led","id":"led_err","top":180,"left":-60,"attrs":{"color":"red"}},{"type":"wokwi-resistor","id":"r1","top":200,"left":-140,"attrs":{"value":"220"}},{"type":"wokwi-resistor","id":"r2","top":200,"left":-100,"attrs":{"value":"220"}},{"type":"wokwi-resistor","id":"r3","top":200,"left":-60,"attrs":{"value":"220"}}],"connections":[["esp32:TX","$serialMonitor:RX","",[]],["esp32:RX","$serialMonitor:TX","",[]],["dht1:VCC","esp32:3V3","red",["v0"]],["dht1:GND","esp32:GND.1","black",["v0"]],["dht1:SDA","esp32:D15","green",["v0"]],["oled1:VCC","esp32:3V3","red",["v0"]],["oled1:GND","esp32:GND.2","black",["v0"]],["oled1:SCL","esp32:D22","yellow",["v0"]],["oled1:SDA","esp32:D21","green",["v0"]],["btn1:1.l","esp32:D4","blue",["v0"]],["btn1:2.l","esp32:GND.1","black",["v0"]],["led_tx:A","esp32:D25","blue",["v0"]],["led_tx:C","r1:1","blue",["v0"]],["r1:2","esp32:GND.1","black",["v0"]],["led_rx:A","esp32:D26","green",["v0"]],["led_rx:C","r2:1","green",["v0"]],["r2:2","esp32:GND.1","black",["v0"]],["led_err:A","esp32:D27","red",["v0"]],["led_err:C","r3:1","red",["v0"]],["r3:2","esp32:GND.1","black",["v0"]]]}
Trade-off: Slow speed enables extreme range and penetration
What’s the theoretical battery life with 140 messages/day?
TX energy per message: 40 mA x 6 sec (3 transmissions x 2 sec each) = 0.067 mAh
Daily TX energy: 0.067 x 140 = 9.33 mAh
Sleep energy: 0.024 mAh/day (1 uA x 24h)
Total: 9.35 mAh/day
With 2000 mAh battery: 214 days = 0.6 years
With fewer messages (24/day): 0.067 x 24 + 0.024 = 1.63 mAh/day = 3.4 years
Putting Numbers to It
Transmission energy scales linearly with message count. Each Sigfox message is transmitted 3 times at 40 mA for 2 seconds each (6 seconds total): \(E_{\text{msg}} = 40\,\text{mA} \times 6\,\text{s} / 3600\,\text{s/h} = 0.067\,\text{mAh}\). For 140 messages/day: \(E_{\text{daily}} = 140 \times 0.067 = 9.33\,\text{mAh/day}\). Worked example: With a 2000 mAh battery, life = 2000/9.35 = 214 days (0.6 years). Reducing to 24 messages/day drops energy to 1.63 mAh/day, extending life to 1227 days (3.4 years). For 10+ year battery life, use a larger battery (6000 mAh) with infrequent reporting (6 messages/day = 0.43 mAh/day = 14,000 days).
Decision Framework: When to Request Downlink from Sigfox Devices
The Challenge: You have only 4 downlinks per day per device. When should you use them?
Downlink Energy Cost:
Typical uplink-only transmission:
- TX: 40 mA for 6 seconds = 0.067 mAh
- Return to sleep immediately
Transmission WITH downlink request:
- TX: 40 mA for 6 seconds = 0.067 mAh
- RX window 1: Wait 20 seconds at 50 mA = 0.278 mAh
- RX window 2: Wait 20 seconds at 50 mA (if no RX1) = 0.278 mAh
- Total: 0.623 mAh (9.3× more energy than uplink-only!)
Battery impact:
- 24 uplinks/day: 1.6 mAh → 5.1 year battery life
- 4 downlinks/day: 2.5 mAh → 3.3 year battery life (35% reduction)
✗ Data request/response patterns (design uplink-only architecture)
Architecture Patterns:
❌ BAD: Request-Response Pattern
Device: Sends temperature reading (uplink)
Server: Requests full diagnostic report (downlink)
Device: Sends diagnostic data (uplink)
Cost: 2 downlinks/day per device just for diagnostics
→ Uses 50% of daily downlink quota
→ No quota remaining for actual control
✓ GOOD: Scheduled Reporting
Device: Sends temperature + diagnostics in ONE message (uplink)
Server: Passive monitoring, only sends downlink when threshold breached
Device: Receives alert threshold update (downlink ~once per week)
Cost: 0.14 downlinks/day average
→ Uses 3.5% of daily quota
→ 96.5% quota available for emergencies
❌ BAD: Remote Control Pattern
Smart irrigation system with 100 zones:
- Each zone needs "water on/off" command daily
- 100 zones × 2 commands = 200 downlinks/day needed
- Sigfox limit: 4 downlinks/day per device
Result: IMPOSSIBLE with Sigfox
✓ GOOD: Autonomous Control with Cloud Override
Smart irrigation with local controller:
- Controller stores watering schedule locally (uploaded via downlink once per week)
- Device executes schedule autonomously
- Reports daily summary to cloud (uplink)
- Cloud can override schedule via downlink if weather changes
Downlinks needed: 0.14/day (weekly updates)
→ Saves 99.93% of downlink quota
→ Works within Sigfox limits
Downlink Budget Allocation Example (agricultural sensor):
Use Case
Frequency
Downlinks/Day
Priority
Emergency shutdown
1 per year
0.003
Critical
Firmware update trigger
4 per year
0.011
Critical
Threshold adjustment
1 per month
0.033
High
Schedule update
1 per week
0.143
Medium
Manual diagnostic
1 per quarter
0.011
Low
TOTAL AVERAGE
0.201/day
Reserved for burst
3.8/day
Real-World Case Study:
Company: Smart building management (1,000 HVAC sensors)
Original Design (Failed):
Each sensor reports temperature every 10 minutes (140 msgs/day)
Server sends setpoint adjustment every hour (24 downlinks/day)
Server uploads new schedule via downlink once per week (0.14 downlinks/day)
Sensor autonomously switches between profiles based on local time
Server can override via downlink in emergency (< 1 per day average)
Result: 0.14 + 1 = 1.14 downlinks/day average ✓
Battery Life Improvement:
Original design (would have needed Class C LoRaWAN):
- 24 downlinks/day × 0.556 mAh = 13.3 mAh/day
- Battery life: 2000 mAh / 13.3 = 150 days
Redesigned (Sigfox-compatible):
- 1.14 downlinks/day × 0.556 mAh = 0.63 mAh/day
- Plus 140 uplinks: 140 × 0.067 = 9.4 mAh/day
- Total: 10.0 mAh/day
- Battery life: 2000 mAh / 10.0 = 200 days (33% longer)
Key Takeaways:
Downlinks are expensive: 9× more energy than uplinks due to RX windows
Design uplink-only: Store intelligence in device, not cloud
Schedule, don’t command: Upload schedules via rare downlinks, execute locally
Reserve quota: Keep 3 of 4 daily downlinks unused for emergencies
Batch updates: Send multiple configuration changes in one downlink (8-byte payload)
Golden Rule: If your application needs more than 1 downlink per day per device on average, redesign to reduce downlink dependency or choose LoRaWAN/NB-IoT instead.
Interactive Quiz: Match Concepts
Interactive Quiz: Sequence the Steps
🏷️ Label the Diagram
💻 Code Challenge
50.6 Summary
In this hands-on chapter, you learned:
Wokwi Simulation:
How to encode sensor data into Sigfox’s 12-byte payload
Use scaled integers instead of floats to maximize data density
Pack multiple booleans into bit flags
Always calculate battery life before deployment
Test coverage thoroughly before production rollout
Common Pitfalls
1. Not Testing AT Commands Before Writing Firmware
Skipping interactive AT command testing and going directly to firmware integration delays debugging when messages don’t appear in the backend. Always test the basic AT$SF send command manually first to confirm hardware, registration, and coverage before writing application code.
2. Burning Daily Message Budget During Development
Development and testing consume real Sigfox messages from the 140/day budget. Using rapid-fire testing during lab development can exhaust the daily limit before real field testing. Use message rate limiting during development and count test transmissions carefully.
3. Hardcoding Payload Format Without Version Field
Evolving sensor requirements often change payload layout. Without a version byte in the payload, all deployed devices need simultaneous firmware updates when the format changes. Include a 4-bit or 1-byte version field to enable gradual payload format migration.
4. Not Verifying Reception Statistics From Multiple Base Stations
A single backend “message received” doesn’t confirm production-ready coverage. Verify that messages are received by at least 2 base stations to confirm diversity coverage needed for reliable production operation.