# Novel Bits > Bluetooth LE consulting, training, and tools for engineering teams, plus in-depth guides on how Bluetooth LE actually works. Public Ghost content for AI and LLM tooling. This file includes a bounded export of public pages first, then recent public posts. Append `.md` to any post or page URL to get the content in Markdown (for example, `/example-post.md`). ## Pages ### Bluetooth LE Advertisement Builder URL: https://novelbits.io/ble-advertisement-builder/ Last updated: 2026-03-09T07:47:52.000Z Free Tool # Bluetooth LE Advertisement Builder Build custom advertisement packets or decode raw advertising data. Supports all standard AD types including flags, service UUIDs, device names, and manufacturer data. Build & decode packets 75+ Bluetooth SIG services All standard AD types v1.0.0 What's New? ▼ ### Version 1.0.0 January 21, 2026 - Searchable Service UUID selector with 75+ official Bluetooth SIG services - Input validation with visual feedback on all hex fields - Hybrid combobox for Appearance values with category grouping - Official Bluetooth SIG data sources for companies, appearances, and services Builder Decoder ## Configuration Flags LE General Discoverable LE Limited Discoverable BR/EDR Not Supported LE BR/EDR Controller LE BR/EDR Host Complete Local Name Shortened Name 16-bit Service UUIDs Search for a service or click ▼ to browse ▼ Selected UUIDs (comma-separated) 32-bit Service UUIDs (comma-separated) 128-bit Service UUIDs (comma-separated) Manufacturer Specific Data Company ID + Custom Payload → AD Type 0xFF Company (search by name or hex) Loading company database... ID (Hex) Data Payload (hex) Preview: `` Search for a company or enter a 4-digit hex ID. Use FFFF for testing. TX Power Level (dBm) Appearance Device type shown to scanning devices Search or browse appearances ▼ Value (Hex) Service Data (16-bit UUID) Search or browse services ▼ UUID (hex) Data (hex) ## Output 0 / 31 bytes Format Hex Hex (spaced) C Array Copy `` Clear Download JSON ### Resources - [Bluetooth Assigned Numbers](https://www.bluetooth.com/specifications/assigned-numbers/?ref=novelbits.io) - [BLE Advertisement Tutorial](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/) ## Decode Advertisement Paste a hex string from a Bluetooth LE sniffer or scanner to decode its contents. Decode Clear ### Bluetooth LE Unplugged™ URL: https://novelbits.io/ble-unplugged-course/ Last updated: 2026-08-16T16:28:52.000Z Bluetooth LE Unplugged™ # Learn Bluetooth LE Without an SDK Skip the embedded C. Skip the toolchain headaches. Get hands-on with real hardware today. Whether you're a mobile developer trying to understand the device side, an engineer adding wireless to your first product, or a technical leader reconnecting with hands-on work, this course gives you everything you need. [Enroll Now · Real Hardware Shipped to Your Door](#pricing) [or preview 5 free lessons →](https://learn.novelbits.io/courses/ble-unplugged?ref=novelbits.io) **15,000+** monthly readers • **200+** in-depth tutorials • **12+ years** of Bluetooth LE expertise ## Tried Learning Bluetooth LE Before? ✕ **Dev kits require embedded C**. Nordic, TI, and Espressif boards need SDK setup, toolchains, and debugging. You wanted to learn Bluetooth LE, not fight compiler errors. ✕ **Most courses are theory-only**. You watch videos but never actually do anything. When it's time to build, you're on your own. ✕ **You only see one side of the connection**. Most tutorials show either the central or the peripheral, never both. You never get the full picture of how both sides work together. There's a better way. ## Who Is This Course For? Whether you're embedded or not, if you want to understand Bluetooth LE, this is for you. ### 🚀 New to Bluetooth LE **Developers from any background** who want to understand how Bluetooth LE actually works, whether you're coming from embedded, web, or just curious about wireless protocols. - Embedded engineers adding wireless to their products - Students, makers, and hobbyists learning IoT - Career switchers exploring hardware ### 📱 Mobile & App Developers **iOS, Android, and cross-platform developers** who build apps that connect to Bluetooth LE devices, and want to finally understand what's happening on the other side. - Debug connection issues from both sides - Understand why GATT operations fail - Stop guessing what the peripheral is doing ### 📊 Technical Leaders Who Miss Building **Engineering managers, tech leads, and architects** who've drifted from hands-on work and want to reconnect, without the time investment of learning a new SDK. - Manage engineers but rarely touch code anymore - Want to stay technically credible with your team - Looking for a weekend project that's actually fun ### ⚙️ Building Professional Products **Embedded engineers, IoT developers, and hardware teams** who want to prototype quickly or upskill their whole team, without committing to a specific chipset. - Rapidly prototype before choosing a platform - Get PMs, QA, and devs speaking the same language - Vendor-neutral skills that transfer anywhere ## A Completely New Approach to Learning Bluetooth LE ### 🎯Production hardware, not a simulator The dongles you learn on are the same ones you can build with. They work for the exercises *and* for real applications, so nothing you practice on gets thrown away when you start building. ### 🔌Two dongles = complete control You run both the central and peripheral. See exactly what happens on each side of the connection, no mysteries, no guessing. ### ⚡No embedded programming required Simple AT commands work on Windows, macOS, and Linux. No SDKs, no compilers, no toolchain headaches. If you can type, you can learn. ### 🚀From learning to production These aren't hobbyist dev boards; they're the same dongles used in real commercial and industrial Bluetooth LE products. Learn on production-grade hardware you can actually deploy. ## What You'll Build Hands-on projects you'll complete during the course 📡 **A working Bluetooth LE scanner** Discover nearby devices, decode advertising packets, and understand what's being broadcast around you. 🔧 **Your own custom peripheral** Create a GATT server with custom services and characteristics that any phone or computer can connect to. 🔗 **A two-device connection** Establish and manage a real Bluetooth LE connection between two dongles, and see both sides of the conversation. 🐍 **Python automation scripts** Automate scanning, connections, and data collection for testing or data logging applications. *(Professional tier)* 🔐 **A secured, bonded connection** Implement pairing, bonding, and encryption. Understand how security actually works in practice. *(Professional tier)* 🔍 **Packet captures in Wireshark** Capture live Bluetooth LE traffic and analyze every byte at the protocol level. *(Expert tier)* ## What You'll Learn Hands-on skills you can apply immediately ### Starter Tier ✓ Bluetooth LE Architecture Protocol stack, terminology, and how Bluetooth LE differs from Classic Bluetooth ✓ Advertising & Scanning Create custom advertisements, discover nearby devices, decode advertising packets ✓ Connections & Parameters Establish connections, understand intervals, latency, and timeout settings ✓ GATT Fundamentals Services, characteristics, and descriptors: the foundation of Bluetooth LE data exchange ✓ Reading & Writing Data Read, write, notify, and indicate operations with real hardware ✓ Troubleshooting Diagnose common connection failures and data transfer issues ### Professional Tier (Everything in Starter, plus...) + Security & Pairing Pairing methods, bonding, and encryption in practice + Performance Optimization MTU negotiation, throughput tuning, and connection parameter optimization + Privacy and Address Management GAP address types, Resolvable Private Addresses (RPA), and the IRK-based privacy mechanism + Python Automation Script your dongles for testing and data collection + CTF Challenges Test your skills with hands-on capture-the-flag exercises and gamified learning + Certificate of Completion Earn your certificate by passing the final assessment ### Expert Tier (Everything in Professional, plus...) ★ Raytac Sniffer Dongle Professional packet capture hardware included ★ Packet Analysis with Wireshark Capture and analyze Bluetooth LE traffic at the protocol level ★ Deep-Dive Packet Capture Lessons Step-by-step tutorials on setting up sniffers, filtering traffic, debugging connection issues, and interpreting protocol exchanges ★ 2 Hours 1-on-1 Consulting Direct access to the instructor for your specific project needs ## Production-Grade Hardware Included As an official BleuIO distributor, we ship you the same hardware used in real commercial and industrial Bluetooth LE products, not a hobbyist dev board you'll never use again ![BleuIO USB Dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/Dual-Dongles---STD.png) Included in: Starter Professional Expert ### BleuIO Standard USB Dongles (×2) - Bluetooth LE 5.0 with 8 simultaneous connections - AT command interface, no embedded programming - Works on Windows, macOS, and Linux - 150m+ range at maximum TX power - FCC, CE, KC, RoHS certified - Used in real commercial products: industrial sensors, asset trackers, medical devices ![Raytac Sniffer Dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/12/Raytac-v3.png) Included in: Expert ### Raytac MDBT50Q-CX Sniffer - Packet capture with Wireshark - See every byte over the air - nRF Sniffer compatible firmware - FCC, CE, IC pre-certified **📦 Free shipping included!** Ships within 5 business days. [See FAQ for shipping countries.](#faq-shipping-countries) 💡 **Don't let the simplicity fool you.** These dongles aren't toys. The same BleuIO hardware is deployed in commercial products worldwide: industrial sensors, asset tracking systems, and medical devices. You're learning on production-grade tools, not throwaway dev boards. ## Why This Course? See how Bluetooth LE Unplugged™ compares to other learning options | Feature | Bluetooth LE Unplugged™ | YouTube / Free | Udemy Courses | Dev Kit + SDK | | ---------------------------- | ----------------------- | ------------------- | ------------------- | -------------------- | | Real hardware included | ✓ 2 dongles | ✕ | ✕ | $50–500 extra | | No embedded C required | ✓ | ✕ Usually SDK-based | ✕ Usually SDK-based | ✕ Required | | See both sides of connection | ✓ Central + Peripheral | ✕ | ✕ | Requires 2 boards | | Hands-on exercises | ✓ Every lesson | ✕ Watch only | Sometimes | DIY | | Works on Mac/Win/Linux | ✓ | Varies | Varies | ✕ Often Windows-only | | Structured curriculum | ✓ Progressive | ✕ Scattered | ✓ | ✕ Docs only | | Production-grade tools | ✓ | ✕ | ✕ | ✓ | | Time to first connection | \~10 minutes | Hours | Hours | Hours (SDK setup) | ## Choose Your Path All tiers include real hardware shipped to your door. [See shipping countries.](#faq-shipping-countries) **🎓 Try before you buy**: [Preview 5 free lessons](https://learn.novelbits.io/courses/ble-unplugged?ref=novelbits.io) on the learning platform. See the hands-on exercises, terminal output, and teaching style for yourself. **💰 Hardware included**: Two BleuIO Standard dongles ship with your course. No separate purchase needed. Starter $199 one-time payment ⏱️ \~5.5 hours 📚 7 modules 📝 37+ lessons What's included: - 📦 **2× BleuIO Standard USB dongles** - ⏱️ Complete in **one weekend** - ✓ Bluetooth LE architecture & fundamentals - ✓ Advertising, scanning & connections - ✓ GATT operations hands-on - ✓ Troubleshooting common issues - ✓ Downloadable code examples - ✓ Lifetime access & free shipping [Enroll Now – $199](https://novelbits.myshopify.com/cart/51732523319595:1?ref=novelbits.io) Most Popular Professional $399 one-time payment ⏱️ \~12 hours 📚 12 modules 📝 69+ lessons Everything in Starter, plus: - 🎓 **Certificate of Completion** - ⏱️ Complete in **2-3 weeks** - + Security, pairing & bonding deep dive - + Performance optimization & MTU tuning - + Privacy and address management (RPA, IRK, bonding) - + Python automation scripts - + Hands-on challenges & quizzes - + Quick reference cheat sheets [Enroll Now – $399](https://novelbits.myshopify.com/cart/51732544323883:1?ref=novelbits.io) Premium Expert $999 one-time payment ⏱️ \~16 hours 📚 15 modules 📝 93+ lessons Everything in Professional, plus: - ⚡ **Limited to 20 spots** - 📦 **Raytac sniffer dongle** - ★ **2 hours 1-on-1 consulting** - ⏱️ Complete in **3-4 weeks** - + Packet analysis with Wireshark - + Deep-dive sniffer setup lessons - + Protocol debugging techniques - + Priority email support - + Access to private community [Enroll Now – $999](https://novelbits.myshopify.com/cart/51732548878635:1?ref=novelbits.io) 📦 **Hardware ships within 5 business days.** [See shipping countries.](#faq-shipping-countries) 🛡️ **30-Day Money-Back Guarantee** Not satisfied? Return the dongles (unopened or gently used) for a full refund. No questions asked. ## Your Instructor ![Mohammad Afaneh](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/MAfaneh_Enhanced_Photo.jpg) ### [Mohammad Afaneh](https://www.linkedin.com/in/mafaneh/?ref=novelbits.io) Founder of **[Novel Bits](https://novelbits.io/)** and the **[Bluetooth Developer Academy](https://novelbits.io/academy)**. With over 20 years of experience in embedded systems and wireless protocols, Mohammad has helped thousands of engineers master Bluetooth LE through his blog, courses, and consulting work. - 15,000+ monthly readers at novelbits.io - Author of comprehensive Bluetooth LE tutorials - Consultant to Fortune 500 companies - Speaker at embedded systems conferences > "I created this course because I was frustrated with how hard it was to learn Bluetooth LE. Every resource assumed you had a dev kit, an SDK, and embedded C experience. I wanted something anyone could pick up and start learning immediately, using real, production-grade hardware they could actually deploy in commercial products, not hobbyist toys they'd never touch again." ## Trusted by Engineers at Leading Companies What clients say about Mohammad's Bluetooth LE training "This training was SO good and thorough! The best part was his willingness to brainstorm on various ways to solve problems... Mohammad's knowledge of Bluetooth Low Energy is nothing short of **encyclopedic**." JB **Joe Baumgarte** Delta Faucet Company "Mohammad is passionate and extremely knowledgeable about Bluetooth LE. What impressed us the most was the **hands-on approach** taken during the training. The training materials and resources provided were top-notch." DN **David Newby** Allegion "Overall I would **highly recommend** this training to anyone looking to get a good understanding of Bluetooth fundamentals. The hands-on exercises made complex concepts click." MK **Michael Kraft** HP Tuners ## Frequently Asked Questions Do I need prior Bluetooth experience? Not at all. This course starts from zero. If you've never touched Bluetooth LE, you're in the right place. Basic programming knowledge is helpful but not required. I build iOS/Android apps that connect to Bluetooth LE devices. Will this help me? Absolutely! Understanding what's happening on the peripheral side makes you a much better mobile developer. You'll finally understand why connections drop, why GATT operations fail, and how to debug issues that span both sides. The dual-dongle approach lets you see exactly what the device is doing when your app sends commands. No more guessing. I'm a technical manager who hasn't coded in years. Will I be able to follow along? Absolutely! This course is designed for exactly that situation. The BleuIO dongles use simple AT commands: no complex toolchains, no embedded C, no IDE setup. If you can type commands in a terminal, you can build working Bluetooth LE devices. Many technical leaders take this course to reconnect with hands-on work, and you'll be surprised how quickly it comes back. Will this help me lead my team better, or is it just for personal learning? Both! You'll gain hands-on understanding that helps you make better architectural decisions, evaluate vendor claims, and have more credible technical conversations with your team. Many managers find that reconnecting with hands-on work actually makes them better technical leaders: you can speak from recent experience, not decade-old memories. Do I need to know embedded C or use an SDK? No! That's the whole point. The BleuIO dongles use simple AT commands, so you can control them from a serial terminal, Python script, or even a web browser. No compilers, no SDKs, no frustration. What operating systems are supported? Windows, macOS, and Linux. The dongles appear as USB serial ports, which are supported everywhere. When will my hardware ship? All orders ship within 5 business days from our US warehouse. International orders typically arrive within 1-3 days after shipping. For Expert tier, the Raytac sniffer dongle ships with your BleuIO dongles. Which countries do you ship to? We currently ship to 28 countries: - **Americas:** United States, Canada - **Europe:** United Kingdom, Germany, France, Netherlands, Ireland, Belgium, Austria, Sweden, Denmark, Finland, Norway, Switzerland, Poland, Italy, Spain, Portugal, Czechia, Romania, Estonia - **Asia-Pacific:** Australia, New Zealand, Hong Kong, Singapore, Japan, South Korea, Taiwan International orders typically arrive within 1-3 business days after shipping (Asia-Pacific may take 6-10 business days). We may expand to additional countries based on demand. Contact us if your country isn't listed. What's your refund policy? We offer a voluntary 30-day money-back guarantee: if you're not satisfied, return the dongles (unopened or gently used) for a full refund. EU and EEA customers also have a statutory 14-day right of withdrawal; see our [EU Right of Withdrawal](https://novelbits.io/eu-right-of-withdrawal/) page. How long do I have access? Lifetime access. Once you enroll, you can revisit the content anytime, including all future updates. Can I use these dongles with my own projects after the course? Absolutely! These are production-grade tools, not training wheels. The same BleuIO hardware is deployed in commercial products: industrial sensors, asset trackers, and medical devices. You can use them for prototyping, testing, or even deploying in your own applications. Can I connect to other Bluetooth LE devices (not just the dongles)? Yes! The BleuIO dongles work with any Bluetooth LE device. You can scan for and connect to fitness trackers, smart home devices, beacons, or any other Bluetooth LE peripheral. The course includes exercises with the two dongles talking to each other, but the skills transfer to any device. When will the full course content be available? Bluetooth LE Unplugged launched on April 20, 2026\. Nothing is drip-fed: every module in your tier is available immediately upon enrollment (7 modules on Starter, 12 on Professional, 15 on Expert). Your hardware ships within 5 business days, so you can start experimenting right away. What software do I need to get started? Just a serial terminal, any will do. The dongles appear as USB serial ports and respond to simple text commands. For Python automation (Professional and Expert tiers), you'll need Python 3.6+. Everything else is covered in the course. ## Ready to Skip the SDK and Start Building? Enroll today and get hands-on Bluetooth LE training, from 7 modules on Starter up to 15 on Expert, plus real hardware shipped to your door. Your dongles ship within 5 business days, so you can start experimenting while you work through the lessons. [See shipping countries.](#faq-shipping-countries) [View Pricing · From $199](#pricing) [View Curriculum](#curriculum) 🛡️ 30-day money-back guarantee: return dongles for a full refund. ### BlueJoule: How Efficient Is Your Bluetooth LE Chip? Really? URL: https://novelbits.io/bluejoule/ Last updated: 2026-08-08T17:14:19.000Z Open Source Benchmark # BlueJoule: How Efficient Is Your Bluetooth LE Chip? Really? Vendor datasheets tell one story. Real-world measurements tell another. [View Benchmark Results](https://github.com/em-foundation/BlueJoule/blob/main/docs/ReadMore.md?ref=novelbits.io#medalists----) [Watch the Webinar](#webinar) An open specification from [The EM Foundation](https://www.openem.org/?ref=novelbits.io), with measurements contributed by [Novel Bits](https://novelbits.io/) ## The Problem with Comparing Chips ? **Datasheets show best-case specs.** Sleep currents and TX power listed in isolation don't tell you how much energy your application will actually consume. ? **No standardized comparison method.** Every vendor measures differently. How do you compare a Nordic chip to a TI chip to a Silicon Labs chip fairly? ? **Real-world results vary wildly.** SDK optimizations, firmware configuration, and radio scheduling all affect actual energy consumption in ways datasheets can't capture. BlueJoule solves this. ## What Is BlueJoule? A standardized, open-source benchmark for measuring real-world Bluetooth LE energy consumption 📏 ### Standardized Workload Every chip runs the exact same test: Bluetooth LE advertising at a fixed interval and TX power, with a standardized payload containing the "BlueJoule" local name. ⚡ ### Real Measurements No calculated estimates. We measure actual energy consumption using precision instruments like the Joulescope JS220 and Nordic PPK2. ⚖️ ### Fair Comparison Same test, same conditions, same methodology. Finally compare chips from different vendors on a level playing field. 🔓 ### Open Source All sample applications, measurement scripts, and methodology are open source. Verify our results, submit your own, or adapt for your needs. ## Meet the EM•erald A gamified unit of energy efficiency Instead of comparing raw microjoules or milliamp-hours, BlueJoule scores chips in **EM•eralds**, a unit designed to be intuitive and meaningful. EM•eralds = 80 ÷ J/day 🔋 **1 EM•erald ≈ 1 CR2032-month** A chip scoring 12 EM•eralds could theoretically run for 12 months on a single CR2032 coin cell (under the benchmark workload). 📊 **Higher is better** More EM•eralds = more efficient. Simple to compare, easy to understand. 💎 EM•eralds Benchmark #1 ## Bluetooth LE Advertising The first BlueJoule benchmark focuses on advertising, the most common Bluetooth LE use case for beacons, sensors, and low-power devices. ### Test Parameters Advertising Interval 1 second (1Hz) TX Power 0 dBm Supply Voltage Optimal (varies by device) Payload Size 19 bytes Advertising Type Non-connectable, non-scannable Channels 37, 38, 39 (all primary) #### Advertising Payload Structure `02 01 06 | 0a 08 42 6c 75 65 4a 6f 75 6c 65 | 04 ff d3 08 ff` **Flags:** LE General Discoverable + BR/EDR Not Supported **Local Name:** "BlueJoule" **Manufacturer Data:** Novel Bits (0x08D3) [View Current Results →](https://github.com/em-foundation/BlueJoule/blob/main/docs/ReadMore.md?ref=novelbits.io#medalists----) ## More Benchmarks Coming The advertising benchmark is just the beginning. We're developing additional benchmarks to cover the full spectrum of Bluetooth LE use cases. Live Now ### Advertising Bluetooth LE advertising, the foundation for beacons, asset trackers, and sensor nodes. Planned ### Connections Connected data transfer, measuring energy for bidirectional communication between central and peripheral. Planned ### Scanning Active and passive scanning, important for central devices and gateways that discover nearby peripherals. Planned ### High-Speed PHYs 2M PHY and Coded PHY benchmarks, comparing long range and high throughput modes. Future ### Bluetooth LE Audio LC3 codec streaming, the next generation of Bluetooth audio with improved efficiency. Future ### Direction Finding AoA/AoD benchmarks, measuring the energy cost of precise indoor positioning. Have a benchmark idea? [Get involved](#community) and help shape the roadmap. ## Measured with EM•Scope Our open-source power measurement and analysis tool 1 📡 emscope grab Capture power data from your measurement hardware 2 🔍 emscope scan Analyze and extract energy metrics 3 📊 emscope view Visualize power profiles and results 4 📦 emscope pack Package results for submission ### Supported Measurement Hardware **Joulescope JS220** High-precision energy analyzer **Nordic PPK2** Power Profiler Kit II ## Watch the BlueJoule Webinar Learn about the methodology, see live measurements, and understand how to interpret the results ### What You'll Learn - Why vendor datasheet comparisons fall short - The BlueJoule benchmark methodology explained - How EM•eralds are calculated and what they mean - Live demonstration of EM•Scope measurements - Walkthrough of results for popular chips - How to submit your own benchmark results ### Get Access to the Recording Email Send Me the Recording We'll also keep you updated on new benchmarks and results. **⚠️ Note about benchmark results:** The results shown in the webinar recording reflect measurements at the time of recording. BlueJoule is a living benchmark: new chips are added, firmware is optimized, and scores may change. Always check the [GitHub repository](https://github.com/em-foundation/BlueJoule/blob/main/docs/ReadMore.md?ref=novelbits.io#medalists----) for the latest results. ### Thank You! Check your inbox for the webinar recording link. We'll also keep you updated on new benchmarks and results. ## Get Involved BlueJoule is an open community effort. Here's how you can contribute. 📤 ### Submit Your Results Have a chip we haven't benchmarked? Run the benchmark application, capture your measurements, and submit via pull request. We'll verify and add your results to the leaderboard. [View submission guidelines →](https://github.com/em-foundation/BlueJoule/blob/main/docs/ReadMore.md?ref=novelbits.io#contributing) 🏭 ### Chip Vendors Want your chip on the leaderboard? Provide a sample application that implements the benchmark specification and submit your own measurements, or we can measure it for you. Either way, your customers get real-world efficiency data. [View benchmark specification →](https://github.com/em-foundation/BlueJoule/blob/main/docs/ReadMore.md?ref=novelbits.io#application) 💡 ### Suggest Benchmarks Have an idea for a new benchmark? Start a discussion to propose methodology, suggest test parameters, or share improvements to existing benchmarks. [Start a discussion →](https://github.com/em-foundation/BlueJoule/discussions?ref=novelbits.io) 🐛 ### Report Issues Found a bug in the firmware or measurement tools? Spot an error in the results? Let us know so we can fix it and maintain accuracy. [Report an issue →](https://github.com/em-foundation/BlueJoule/issues?ref=novelbits.io) 📦 ### BlueJoule Repository Firmware, measurement scripts, methodology documentation, and results, all open source. [ ⭐ View on GitHub ](https://github.com/em-foundation/BlueJoule?ref=novelbits.io) ## Frequently Asked Questions ### The Benchmark What exactly does BlueJoule measure? BlueJoule measures the total energy consumption of a Bluetooth LE chip running a standardized workload. For the advertising benchmark, this includes the energy for sleep periods plus the energy for each advertising event (wakeup, radio TX on all three primary channels, and return to sleep). What do EM•eralds actually mean? EM•eralds are a unit of energy efficiency. The formula is `80 ÷ J/day`, which means 1 EM•erald roughly equals 1 month of runtime on a CR2032 coin cell battery (under the benchmark workload). A chip scoring 24 EM•eralds could theoretically run for 2 years on a single CR2032. Why might results differ from datasheet specs? Datasheets typically list individual parameters (sleep current, TX current at specific power levels) under ideal conditions. BlueJoule measures the complete system including firmware overhead, radio scheduling, oscillator startup, and real-world transitions. These factors can significantly impact total energy consumption. Why does supply voltage vary between devices? BlueJoule cares about energy (voltage × current), not just current draw. Leaderboard entries use whatever voltage gives the most optimal energy consumption. While we test at 3.0V for datasheet comparisons, lower voltage devices (like emerging 1.5V chips) can achieve better energy efficiency even if their current consumption is slightly higher. How are measurements taken and analyzed? We capture approximately 10 raw advertising events at 1Hz and analyze them to extract two key metrics: average sleep current and average event energy. With these values, we can compute energy consumption for any event period, from 1 second to 10 seconds and beyond, then calculate J/day and convert to EM•eralds. Can vendors optimize their firmware for better scores? Yes, and that's encouraged! The benchmark uses vendor SDKs with reasonable optimizations enabled. If a vendor releases an improved SDK or someone finds a better configuration, we welcome updated submissions. This drives the industry toward better efficiency. What about DC-DC vs LDO configurations? Where chips support both DC-DC converter and LDO regulator modes, we typically test the most efficient configuration (usually DC-DC). The configuration is documented for each result so you can see exactly what was tested. ### Getting Involved How do I submit benchmark results for my chip? Fork the [BlueJoule repository](https://github.com/em-foundation/BlueJoule?ref=novelbits.io), run the benchmark application on your platform, capture measurements using EM•Scope, and submit a pull request with your results. Chip vendors are especially encouraged to submit results for new or missing chips. What measurement hardware do I need? You'll need either a **Joulescope JS220** (\~$999) or **Nordic PPK2** (\~$99). The PPK2 is more affordable and sufficient for most measurements. Both are supported by EM•Scope. My chip isn't supported yet. What can I do? If you're a chip vendor, provide a sample application that implements the benchmark specification and we'll measure it and add your results. If you're an engineer wanting to test a chip, check the repository for existing implementations or start a discussion to request support for your platform. Can I use BlueJoule results in my marketing materials? Yes, with attribution. Please link to the GitHub repository and include the benchmark date, as results may change over time. We recommend phrases like "BlueJoule benchmark, \[date\]" with a link to the [BlueJoule repo](https://github.com/em-foundation/BlueJoule?ref=novelbits.io). Who is behind BlueJoule? BlueJoule is an open benchmark specification published by [The EM Foundation](https://www.openem.org/?ref=novelbits.io), a non-profit organization focused on transparent energy efficiency benchmarking. The Foundation owns the specification and the BlueJoule name. [Novel Bits](https://novelbits.io/), a company specializing in Bluetooth LE training and consulting, contributes benchmark measurements and builds tooling against the specification. Both operate independently from chip vendors. Is BlueJoule affiliated with any chip vendor? No. Both The EM Foundation and Novel Bits operate independently from chip manufacturers. We don't receive funding from vendors for favorable results. Our goal is accurate, transparent benchmarking that helps engineers make informed decisions. Where can I get help or ask more questions? Start a discussion on the [GitHub repository](https://github.com/em-foundation/BlueJoule/discussions?ref=novelbits.io) for technical questions or general inquiries. ## About BlueJoule BlueJoule is an open benchmark specification published by The EM Foundation. Novel Bits contributes measurements and builds tooling against it. ![The EM Foundation logo](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/12/EM-Foundation-logo-full.png) ### The EM Foundation A non-profit organization that promotes, sustains, and evolves programming technology for use within the broader embedded systems community. This charter includes the openly-available EM•Scope tooling used for quantifying energy efficiency within ultra-low-power applications. [Learn more at openem.org →](https://www.openem.org/?ref=novelbits.io) ![Novel Bits logo](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/12/Novel-Bits-Logo.png) ![Novel Bits logo](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/White-Logo-1.png) ### Novel Bits A Bluetooth LE consultancy providing development services, technical training, and protocol expertise to product companies and engineering teams worldwide. Novel Bits helps organizations bring wireless products to market while also fostering a thriving community of embedded developers. [Learn more at novelbits.io →](https://novelbits.io/) ## Ready to See How Your Chip Stacks Up? Explore the benchmark results, watch the methodology webinar, or contribute your own measurements to the community. [View Benchmark Results](https://github.com/em-foundation/BlueJoule/blob/main/docs/ReadMore.md?ref=novelbits.io#medalists----) [GitHub Repository](https://github.com/em-foundation/BlueJoule?ref=novelbits.io) ### See What Your Bluetooth LE Device Is Actually Doing URL: https://novelbits.io/home/ Last updated: 2026-08-09T16:47:52.000Z Official Training Partner: Silicon Labs & Nordic Semiconductor # See What Your Bluetooth LE Device Is Actually Doing Most teams stuck on a Bluetooth LE problem cannot see the air at all. I get a professional sniffer running against your device, then help you work out what to capture next. [Book a Scoping Call](https://calendly.com/novelbits/bluetooth-le-debugging-scoping-call?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=homepage-hero) [See What a Debug Block Includes](https://novelbits.io/consulting/?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=homepage-hero-secondary) ✓ Consulting • ✓ Team training • ✓ Tools and test equipment ## Trusted by Leading Companies Worldwide Teams at these companies have worked with me on Bluetooth LE. ![Nordic Semiconductor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nordic-semi-mono.png) ![Microsoft](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/microsoft-transparent.png) ![Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/silicon-labs-mono.png) ![Delta Faucet](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/delta-faucet-transparent.png) ![Allegion](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/allegion-transparent.png) ## Your Device Fails and the Logs Do Not Say Why App logs and an HCI trace reason from data that never contained the answer. No amount of analysis, AI-assisted or otherwise, recovers what was never captured. The capture you need usually turns out to be the one you did not think to take. ## The Bluetooth LE Debug Block A professional sniffer on loan, and someone who knows which capture to take next. First you can see the air, then you have judgment on what you are looking at. 1 ### See the air A professional sniffer, on loan, running against your device in your environment. The loaner ships within the United States only. 2 ### Know what to capture What your current data can actually tell you, which is usually less than you think, and exactly what to capture next: with what, under what conditions, in what order. 3 ### Get a written finding The root cause where one is established, or the remaining candidates and what would tell them apart, plus how big the problem is and who should own it. ### Start where you're stuck Begin by getting you capturing, then buy days against the problem only if you need them. ### Capture & Triage Day $2,500 One day. We get a professional sniffer running against your device and leave you with a capture plan. Not a diagnosis, and often the plan alone is enough. Sniffer on loan for two weeks, credited in full against a Debug Block booked within 30 days. Recommended ### Debug Block $12,500 Five days drawn down in half-day increments, across the rounds it takes. You capture, I analyze, I specify what to capture next. Loaner extended to eight weeks, yours to use freely without drawing down the day bank. ### Additional Days $2,500 / day The block buys days, not an outcome. When it runs out you can buy more, or stop. Available in half-day increments. It is evidence, not assurance. Findings are what was observed, in the captures provided, under the conditions provided. You own the claim you make from it. [Book a Scoping Call](https://calendly.com/novelbits/bluetooth-le-debugging-scoping-call?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=homepage-debugblock) [Full scope, and Bluetooth LE power and battery-life work →](https://novelbits.io/consulting/?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=homepage-debugblock-more) ## What Clients Say About Working With Me These are training engagements, not Debug Blocks. The Debug Block puts the same instruments, and the same judgment, on your specific problem. AP Al Pappa Sr. Technical Architect, Ziosk > …The training included hands-on sessions where we updated firmware for a BLE device and were able to see the BLE advertisements from our changes. > > I especially liked the BLE packet and spectrum analyzer tooling where we were able to see all the radio traffic with BLEs. Steve Ranta Xbox Accessories Technologist, Microsoft > …He demonstrated his extensive knowledge of Bluetooth and was able to answer many of our questions as they came up during the training. Jarrett Bartlett Lead Hardware engineer at Delta Faucet Company > …Mohammad was able to answer every question the group had and could even provide real world examples on most things. > > I'm a hardware engineer, but I still found a ton of value in using the development kits and sniffers provided by Mohammad. ![Mohammad Afaneh, Bluetooth LE Expert and Founder of Novel Bits](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/MAfaneh_Enhanced_Photo.jpg) ## Your Bluetooth LE Expert I'm Mohammad Afaneh. I've spent the last decade helping engineers master Bluetooth LE development. Since founding Novel Bits in 2015, I've trained developers at companies ranging from startups to Fortune 500s, published three books, and built the Bluetooth Developer Academy. ![Nordic Semiconductor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nordic-semi-mono.png) Official Training Partner ![Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/silicon-labs-mono.png) Official Training Partner [Read My Story →](https://novelbits.io/about/) ## Also From Novel Bits ### Bluetooth Developer Academy Self-paced video courses covering Bluetooth LE fundamentals through LE Audio, Mesh, and Direction Finding. Moving to a new platform right now, so sign-ups are paused. [Join the waitlist →](https://novelbits.io/academy/) ### Recommended Tools & Test Gear Professional sniffers, dev kits, dongles, and test equipment I use and recommend for Bluetooth LE work. [See what I use →](https://novelbits.io/recommended-products/) ### Team Training Tailored Bluetooth LE training for engineering teams. Not currently taking new bookings, but the curriculum is there if you want to see what a workshop covers. [See the curriculum →](https://novelbits.io/training/) ## Free Bluetooth LE Crash Course Master the fundamentals in 12 daily emails ### Everything You Need to Get Started From how devices discover each other to security and privacy. Get a solid foundation in Bluetooth LE before diving into code. - 12 daily lessons covering radio basics through security - Downloadable one-page cheat sheet included - No account needed, delivered to your inbox Start the Free Course Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ![Bluetooth LE Cheat Sheet preview](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/cheat-sheet-page1-1.png) ## Popular Bluetooth LE Guides [ Fundamentals The Complete Guide to Bluetooth Low Energy Everything you need to know about Bluetooth LE: architecture, GAP, GATT, security, and more. ](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) [ Protocol GATT Services and Characteristics How to design custom GATT services, work with characteristics, and build real Bluetooth LE profiles. ](https://novelbits.io/bluetooth-gatt-services-characteristics/) [ Hands-On Bluetooth LE Sniffer Tutorial Capture and analyze Bluetooth LE packets using affordable hardware and Wireshark. ](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) ## Frequently Asked Questions What actually happens in a Debug Block? We start by getting a professional sniffer running against your device in your environment, because most teams stuck on a Bluetooth LE problem cannot see the air at all. From there it runs in rounds: you capture, I analyze, I specify what to capture next. You get a written finding, either the root cause where one is established, or the remaining candidates and what would tell them apart. Where do you ship the loaner sniffer? The loaner ships within the United States only. If you are outside the US, the analysis side of the engagement still works: you capture with your own hardware and I tell you what to capture and what it means. Book a scoping call and we will work out whether that fits your problem. Which chipsets do you support? I'm chipset-agnostic. Engagements work with whatever hardware your team has chosen, and the Academy covers Nordic Semiconductor, Silicon Labs, TI, and Renesas platforms. What's the difference between consulting and the Academy? Consulting is hands-on expert help for your specific project, including debugging, capture analysis, power work, and architecture guidance. The Academy is self-paced video courses for individual learning. Many teams use both: the Academy for foundational knowledge, consulting for project-specific problems. ## Stuck on Something You Cannot See? Book a scoping call and we will work out whether a Debug Block fits your problem, and what it would take. [Book a Scoping Call](https://calendly.com/novelbits/bluetooth-le-debugging-scoping-call?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=homepage-footer) [See What's Included](https://novelbits.io/consulting/?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=homepage-footer-secondary) ### BleuIO USB Dongles - Official US Distributor URL: https://novelbits.io/bleuio/ Last updated: 2026-04-08T17:51:00.000Z 🇺🇸 Official US Distributor # BleuIO USB Dongles The simplest way to develop, test, and prototype Bluetooth LE applications. AT command interface — no embedded C required. [Shop Now](#shop) [Getting Started Guide](https://novelbits.io/bleuio-getting-started-guide/) ✓ Ships to all 50 US states • ✓ Bluetooth LE 5.0/5.2 • ✓ CE, FCC, RoHS compliant ## Why Developers Love BleuIO Get started with Bluetooth LE in minutes, not weeks. ⚡ ### Zero Setup Required Plug in via USB, open a terminal, and start sending AT commands. No drivers, no SDK installation, no compilation. 🔌 ### 8 Simultaneous Connections Connect to up to 8 Bluetooth LE peripherals from a single dongle—perfect for multi-device testing and orchestration. 🐍 ### Python & JavaScript Libraries Official libraries for Python (bleuio-py) and JavaScript (npm bleuio) enable rapid scripting and automation. 📡 ### Central & Peripheral Modes Switch between Central and Peripheral roles with a single command. Scan, advertise, connect, and exchange data. ## Shop BleuIO Dongles 🇺🇸 **US orders only** — Ships from Indiana. Free shipping over $75! Best Value ![BleuIO Pro 2-Pack - Blue and White](https://downloads.novelbits.io/images/products/bleuio-pro-2-pack.png) ### Pro 2-Pack Two BleuIO Pro dongles—one Blue, one White. Perfect for testing Central and Peripheral roles simultaneously. Includes free shipping. - 1 Blue + 1 White BleuIO Pro - Bluetooth LE 5.2 with 1M/2M PHY - Free shipping included - Save $11 vs. buying individually $79 ![BleuIO Standard USB Dongle - Black or White](https://downloads.novelbits.io/images/products/bleuio-std-choices.png) ### BleuIO Standard Bluetooth LE 5.0 USB dongle with AT command interface. Perfect for development, prototyping, and testing. - Bluetooth LE 5.0 - 8 simultaneous connections - Custom firmware capable - Black or White $29 ![BleuIO Pro USB Dongle - Blue or White](https://downloads.novelbits.io/images/products/bleuio-pro-choices.png) ### BleuIO Pro Enhanced version with Bluetooth LE 5.2, adjustable TX power, extended advertising, and 2 Mbps throughput. - Bluetooth LE 5.2 with 2M PHY - 18 TX power levels (-50 to +6 dBm) - Extended advertising (1650 bytes) - Programmable LED + OTA updates - Blue or White $45 ### Need More Dongles? We offer volume discounts for bulk orders. [Contact us](https://novelbits.io/contact/) for custom pricing on orders of 10 or more units. ## What Can You Build? BleuIO powers development across industries #### Rapid Prototyping Build working Bluetooth LE prototypes in hours, not weeks #### Device Testing Test your Bluetooth LE products against real-world scenarios #### Educational Labs Teach Bluetooth LE concepts with hands-on exercises #### Beacon Development Create and test iBeacons and Eddystone beacons #### Sensor Networks Prototype multi-device sensor data collection systems #### Production Testing Automate quality assurance for Bluetooth LE products ## Technical Specifications #### Wireless - **Bluetooth Version:** 5.0 (Standard), 5.2 (Pro) - **PHY:** 1M (Standard), 1M/2M (Pro) - **Range:** Up to 150m+ (Pro at max TX power) - **Connections:** 8 simultaneous - **Advertising:** Legacy (both), Extended (Pro) #### Interface - **Connection:** USB 2.0 - **Protocol:** AT Commands (serial) - **Baud Rate:** 57600 (default) - **Libraries:** Python, JavaScript - **Platforms:** Windows, macOS, Linux #### Certifications - **CE:** Europe - **FCC:** United States - **RoHS:** Environmental - **Bluetooth SIG:** Qualified ## Getting Started Resources Everything you need to start building with BleuIO 📖 ### Getting Started Guide Step-by-step tutorial covering setup, scanning, advertising, and making your first connection. [Read the guide →](https://novelbits.io/bleuio-getting-started-guide/) 📡 ### Advertising Deep Dive Master custom advertising packets, iBeacons, scan response, and advertising parameters. Coming Soon 📋 ### AT Command Reference Complete reference for all BleuIO AT commands with examples and parameter descriptions. [View documentation →](https://www.bleuio.com/getting%5Fstarted/docs/commands/?ref=novelbits.io) 🎓 ### Bluetooth LE Unplugged Comprehensive course bundle with 2 BleuIO dongles included. Perfect for structured learning. [Learn more →](https://novelbits.io/ble-unplugged-course/) ## Frequently Asked Questions How fast will my order ship? Orders placed before 2 PM EST typically ship the same business day. Standard shipping (USPS First Class) delivers in 3-5 business days. Priority shipping (1-3 days) is available at checkout for $12.99. How much is shipping? Standard shipping is $5.99, free on orders over $75\. Priority shipping (1-3 days) is $12.99\. The Pro 2-Pack qualifies for free shipping. Where do you ship? We ship to all 50 US states including Alaska and Hawaii. **We do not ship internationally or to US territories (Puerto Rico, Guam, etc.).** For international orders, please purchase directly from [BleuIO.com](https://www.bleuio.com/?ref=novelbits.io) in Sweden. What's the difference between Standard and Pro? BleuIO Pro offers Bluetooth LE 5.2 (vs 5.0), 2 Mbps throughput (vs 1 Mbps), 18 adjustable TX power levels (-50 to +6 dBm), extended advertising up to 1650 bytes, programmable LED, and OTA firmware updates. Both models support 8 simultaneous connections and custom firmware. Do I need any special drivers? No. BleuIO appears as a standard USB serial device (CDC/ACM). It works out-of-the-box on Windows, macOS, and Linux without additional driver installation. Can I use BleuIO with my existing Bluetooth LE devices? Yes! BleuIO can scan, connect, and interact with any standard Bluetooth LE device. Use it to test your products, debug connections, or prototype new features. Do you offer wholesale pricing? Yes. We offer volume discounts starting at 10 units, and custom pricing for larger orders. [Contact us](https://novelbits.io/contact/) for wholesale inquiries. ## Ready to Start Building? Get your BleuIO dongle today and start developing Bluetooth LE applications in minutes. [Shop Now](#shop) [Read the Guide](https://novelbits.io/bleuio-getting-started-guide/) ### Contact Us URL: https://novelbits.io/contact/ Last updated: 2026-08-09T05:49:40.000Z # Get in Touch Have a question about Bluetooth LE, our courses, or BleuIO dongles? We're here to help. ## What We Can Help With Common topics we assist with #### 📚 Course Questions Which course is right for me? How do I access my course? Certificate requests. #### 📡 RFcreations Sniffers Sniffer orders, shipping status, setup assistance, firmware questions. #### 🔧 Technical Support BleuIO setup help, AT command questions, troubleshooting connections. #### 💼 Business Inquiries Consulting, corporate training, bulk orders, returns, invoices, sponsorships. #### 📖 Book Inquiry Report errors or typos, ask questions about book content, or request companion resources. #### ⚡ PowerScope Waitlist questions, early-access requests, and anything about the coming-soon release. #### 📊 LogScope Installation help, RTT debugging questions, license activation. #### 📝 Content Requests Blog topic suggestions, tutorial requests, documentation feedback. ## Send Us a Message Fill out the form below and we'll get back to you within 1-2 business days. Your Name Email Address Subject Select a topic... Course Question Book Inquiry (Errors, Questions, Feedback) Content Correction (Blog or Guide Error) RFcreations Sniffer (Order / Support) BleuIO Order / Shipping PowerScope (License / Support) LogScope (Support) blueAI (Enterprise / Private Deployment / Beta) Technical Support Business Inquiry / Consulting Partnership Opportunity Other Your Message Send Message We respect your privacy and will never share your information. ✅ #### Message Sent Thanks for reaching out! We'll get back to you within 1-2 business days. ## Connect With Us Follow us for Bluetooth LE tips, updates, and community discussions. [ LinkedIn ](https://www.linkedin.com/company/novelbits/?ref=novelbits.io) [ GitHub ](https://github.com/novelbits?ref=novelbits.io) [ YouTube ](https://www.youtube.com/@novelbits?ref=novelbits.io) ## Frequently Asked Questions Do you offer consulting services? Yes! We offer Bluetooth LE consulting for product development, code reviews, and architecture guidance. Learn more on our [consulting page](https://novelbits.io/consulting/) or use the contact form above to tell us about your project. Can I get a refund on a course? Refund policies vary on a course-by-course basis. Please check the terms on the specific course page for details. If you have questions, use the contact form above and we'll be happy to help. Do you offer corporate training? On-site team training is not currently taking new bookings. You can see the full curriculum on our [training page](https://novelbits.io/training/), and if you want your team on the list for when it reopens, use the contact form above. How do I report a bug or issue with the website? Please use the contact form above with a description of the issue, including the page URL and any error messages you see. Screenshots are helpful! Can I contribute a guest post? We occasionally accept guest posts from Bluetooth LE experts. Use the contact form above with a brief pitch including your topic idea and writing samples. ### RFcreations Bluetooth Sniffers and Test Tools URL: https://novelbits.io/rfcreations/ Last updated: 2026-04-08T17:50:53.000Z ![RFcreations Logo](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-logo-white.png) Exclusive North American Distributor # RFcreations Bluetooth Protocol Analyzers & Test Equipment Professional-grade sniffers and test equipment from RFcreations. Novel Bits is your exclusive North American source for support and fast shipping. [Book a Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) [View Products](#shop) All pricing standardized — no markup • Direct support from Novel Bits • Ships from US warehouse ## Why Engineers Choose RFcreations Industry-leading Bluetooth test solutions for development, debugging, and certification. 📡 ### Full 2.4 GHz ISM Band Coverage Capture and analyze the entire 2.4 GHz spectrum simultaneously. See Bluetooth, Wi-Fi, Zigbee, and interference sources in one view. 🔍 ### Multi-Standard Protocol Analysis blueSPY software provides concurrent decoding of Bluetooth Classic, Bluetooth LE, and LE Audio — all three standards analyzed simultaneously. 📱 ### Portable Options Available mini-moreph features autonomous capture mode — power via USB battery, no laptop required. Pairs with Android companion app for field captures. 🎯 ### Channel Sounding Support The morephCS is validated by Bluetooth SIG for Channel Sounding PHY testing — essential for next-gen ranging and positioning applications. ## Product Lineup Professional Bluetooth test equipment for every use case ### Protocol Analyzers Capture and decode Bluetooth traffic in real-time Most Popular ![RFcreations mini-moreph](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-mini-moreph.png) ### mini-moreph Compact wideband Bluetooth 6.0 protocol analyzer that captures the entire 2.4 GHz ISM band. Features autonomous capture mode for field testing — no laptop required. - Full 2.4 GHz ISM band capture - USB-powered — no external power needed - Autonomous capture mode supported - Android companion app for field captures - Works with blueSPY on Windows, macOS, Linux [Request Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) ![RFcreations moreph30](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-moreph30.jpg) ### moreph30 Wideband 2.4 GHz signal analyzer and generator designed for PHY layer testing. Supports all Bluetooth 6.0 RF-PHY test cases with no additional test equipment required. - All BT 6.0 PHY test cases supported - Built-in 6GHz CW signal generator - Ultra-linear RX/TX chain - USB + Ethernet interfaces [Request Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) ![RFcreations audiopod](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-audiopod.png) ### audiopod USB-powered audio measurement tool for LE Audio and Auracast testing. Measure end-to-end latency including presentation delay — essential for LE Audio compliance. - LE Audio latency measurements - Presentation delay testing - Multiple audio interfaces (analog, S/PDIF, I2S) - Integrates with mini-moreph/moreph30 [Request Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) ### Advanced Test Equipment Specialized tools for RF testing and certification ![RFcreations morephE](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-morephe.png) ### morephE RF record/playback expansion for moreph30\. Record the entire 2.4 GHz ISM band for up to 4 hours, then play back to create reference RF environments for repeatable testing. - Record up to 4 hours (90MHz bandwidth) - Full ISM band playback - Create reference RF environments - Requires moreph30 [Request Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) New ![RFcreations morephCS](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-morephcs.jpg) ### morephCS Channel Sounding Physical Layer RF Tester for moreph30\. Validated at Bluetooth SIG IOP sessions — supports all CS RF-PHY and CS Layer test cases. - All CS RF-PHY test cases supported - Used at Bluetooth SIG IOP sessions - Export raw IQ data + spectrograms - Requires moreph30 [Request Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) ## blueSPY Protocol Analyzer Software Concurrent multi-standard Bluetooth protocol analyzer — perpetual license, no recurring fees ![blueSPY Protocol Analyzer Software Screenshot](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/bluespy-screenshot.jpg) 🖥️ ### Cross-Platform Works on Windows, macOS, and Linux. Compatible with mini-moreph and moreph30 hardware platforms. 📊 ### Multi-Standard Decoding Simultaneously decode Bluetooth Classic, Bluetooth LE, and LE Audio. No switching between modes required. 🔬 ### Deep Packet Analysis Full protocol stack decoding from PHY layer through application profiles. See exactly what's happening on the air. 💾 ### Capture & Export Record sessions for later analysis. Export to standard formats for documentation and compliance reporting. [Download blueSPY Free →](https://www.rfcreations.com/bluespy-software?ref=novelbits.io) ## Frequently Asked Questions Why purchase through Novel Bits? Novel Bits is the exclusive and official distributor for RFcreations in North America. All pricing is standardized — no markup is added by going through our distribution channel. You get direct support from the Novel Bits team plus faster shipping from our US warehouse. How do I get pricing information? Book a demo call or [contact us](https://novelbits.io/contact/) to discuss your requirements and receive a customized quote. Pricing varies based on products and quantities needed. Do you offer training on RFcreations products? Yes! Novel Bits is the official Bluetooth LE training partner for RFcreations. We can provide training sessions on how to use the hardware and software effectively. RFcreations sniffers are also used in our hands-on training courses. What's the difference between mini-moreph and moreph30? The mini-moreph is a compact, USB-powered analyzer perfect for desktop use and field testing. The moreph30 is a more advanced wideband signal analyzer and generator with additional capabilities like signal generation and expansion options (morephE). Choose mini-moreph for most debugging needs; moreph30 for advanced RF testing. Do you ship internationally? Novel Bits serves North America (US, Canada, and Mexico). For orders outside North America, [contact us](https://novelbits.io/contact/) and we'll connect you with the right distributor for your region. Is there ongoing support after purchase? Absolutely. Novel Bits provides direct technical support for all RFcreations products purchased through us. We're here to help you get the most out of your test equipment. ## Ready to Elevate Your Bluetooth Testing? Schedule a demo to see RFcreations tools in action and discuss your specific testing requirements. [Book a Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) [Contact Us](https://novelbits.io/contact/) ### Newsletter URL: https://novelbits.io/newsletter/ Last updated: 2026-08-09T05:56:09.000Z # Weekly Bluetooth & UWB Newsletter Stay ahead with the latest Bluetooth LE development tips, industry news, specification updates, and product announcements—delivered to your inbox every Friday. 📬 Every Friday ## Join 9,500+ Developers Free weekly insights. Unsubscribe anytime. Email Address First Name (optional) Subscribe for Free No spam. Unsubscribe with one click. 9,500+ Subscribers 290+ Issues Sent 40-50% Open Rate ## What You'll Get Every Week Curated content to help you build better Bluetooth products 📰 ### Industry News The latest announcements from Bluetooth SIG, chip vendors, and major players in the wireless ecosystem. 💡 ### Development Tips Practical advice, code snippets, and best practices for embedded and mobile Bluetooth LE development. 📋 ### Specification Updates Summaries of new Bluetooth Core Spec releases, profiles, and what they mean for your projects. 🛠️ ### Tool Reviews Hands-on reviews of development boards, sniffers, SDKs, and other tools for Bluetooth development. 🎯 ### UWB Coverage Ultra-Wideband technology updates, including Apple/Android integration and positioning use cases. 🔗 ### Curated Links The best articles, tutorials, and resources from around the web—so you don't miss anything important. 📚 **Want to learn Bluetooth LE from scratch?** Our free 12-day crash course covers everything from radio basics to security — plus you'll get a downloadable cheat sheet. [Start the Crash Course →](https://novelbits.io/bluetooth-le-crash-course/) ## Sample Topics We Cover A taste of what you'll find in our weekly newsletter Recent Issue Channel Sounding: The Future of Bluetooth Ranging Deep dive into Bluetooth's new secure distance measurement feature and how it compares to UWB. Recent Issue Nordic nRF54 Series: What's New for Developers Hands-on first look at the nRF54L15 and what it means for your next project. Popular Topic Optimizing Bluetooth LE Throughput: Beyond the Basics Advanced techniques for maximizing data transfer rates in real-world applications. Popular Topic Auracast: LE Audio's Broadcast Revolution How Bluetooth LE Audio is changing public audio and what developers need to know. ## Ready to Stay in the Loop? Join developers from Nordic, Silicon Labs, Apple, and more. Subscribe for Free ## Never Miss a Bluetooth Update Again Join 9,500+ developers getting weekly Bluetooth & UWB insights delivered straight to their inbox. [Subscribe Now](#) ### You're Subscribed! URL: https://novelbits.io/thank-you-newsletter/ Last updated: 2026-02-19T06:17:32.000Z 📬 # You're Subscribed! Thanks for joining the Bluetooth & UWB Newsletter. You'll receive your first issue on Friday. Check your inbox for a confirmation email. If you don't see it, check your spam folder. [Browse the Blog](https://novelbits.io/blog) [Explore Academy](https://novelbits.io/academy) You can unsubscribe anytime with one click. ### Thank You! URL: https://novelbits.io/thank-you-sniffer/ Last updated: 2026-02-19T06:17:29.000Z 🎁 # Thank You! Your Bluetooth LE Sniffer Guide is on the way to your inbox. If you don't see it within a few minutes, check your spam folder. [Browse the Blog](https://novelbits.io/blog) [Explore Academy](https://novelbits.io/academy) ### Thank You! URL: https://novelbits.io/thank-you-code/ Last updated: 2026-04-08T18:07:29.000Z 📦 # Thank You! Your code download is on the way to your inbox. If you don't see it within a few minutes, check your spam folder. [Browse the Blog](https://novelbits.io/blog) [Explore Academy](https://novelbits.io/academy) ### Thank You for Your Order! URL: https://novelbits.io/thank-you-order/ Last updated: 2026-02-19T06:17:22.000Z 🎉 # Thank You for Your Order! Your copy of Intro to Bluetooth Low Energy (2nd Edition) is on its way. Check your inbox for confirmation and download links. [Book Resources](https://novelbits.io/intro-ble-2nd-edition-resources) [Explore Academy](https://novelbits.io/academy) Questions about your order? [Contact us](https://novelbits.io/contact) ### Preferences Saved! URL: https://novelbits.io/thanks-for-sharing/ Last updated: 2026-04-08T18:07:28.000Z 🎛️ # Preferences Saved! Your email preferences have been updated. You'll only receive content relevant to your selections. [Back to Home](https://novelbits.io/) [Browse Blog](https://novelbits.io/blog) ### Blog URL: https://novelbits.io/blog/ Last updated: 2026-01-13T14:38:01.000Z _No content available._ ### BleuIO Explorer URL: https://novelbits.io/bleuio-explorer/ Last updated: 2026-04-08T17:51:02.000Z Free Tool # BleuIO Explorer A browser-based Bluetooth LE development tool. Scan for nearby devices, connect and explore GATT services, read/write characteristics, and configure custom advertising — no SDK required. Scan & connect to devices Explore GATT services Works with BleuIO USB dongle × 💻 ### Best on Desktop BleuIO Explorer works best on a desktop browser with Web Serial API support (Chrome, Edge, or Opera) to connect to the BleuIO USB dongle. Chrome Edge Opera v1.0.0 What's New? ▼ ### Version 1.0.0 January 21, 2026 - Hybrid combobox for Company ID with search and browse functionality - Hybrid combobox for Appearance values with category grouping - Official Bluetooth SIG data sources (3,900+ companies, 340+ appearances) - Popular companies quick-select on focus Beta This tool is in active development. Some features may not work as expected. ⚠️ **Browser Not Supported** Web Serial API requires Chrome 89+, Edge 89+, or Opera 75+. Please use a supported browser. ![BleuIO Pro USB Dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/bleuio-pro-blue-1.png) ### Need a BleuIO Dongle? Get your BleuIO USB dongle to start exploring Bluetooth LE devices. Perfect for learning, prototyping, and development — works instantly with no SDK required! [ Shop Now ](https://novelbits.io/bleuio/) 🎯 Want another dongle for dual-device testing? [Get BleuIO →](https://novelbits.io/bleuio/) Reconnect on refresh 1\. Open Port 2\. Verify Dongle 3\. Configure 4\. Ready 🔌 Connection Failed **Tips:** Close other apps using the port • Reconnect the dongle • Select the correct port Dismiss Product Firmware Chip Role MAC Address 🔍 Scanner 🔗 Connections 📊 GATT Explorer 📢 Advertiser Duration: sec Filter: Min RSSI: dBm Hide unknown #### Connected Disconnect Beacon/Non-connectable 📡 ### 🔍 ### Scanning for devices... Looking for nearby Bluetooth LE devices. Cancel Connected Explore GATT Disconnect 🔗 ### No connected devices Scan for devices and connect to see them here. **Exploring:** Show HEX values ▶ UUID: UUID: Read Write Write No Resp Notify Indicate HEX Text 📊 ### #### Advertisement Type Type Connectable Non-Connectable (Beacon) Scannable #### Advertisement Data **Note:** Advertising flags (LE General Discoverable, BR/EDR Not Supported) are automatically set by the BleuIO dongle firmware. Device Name (Complete Local Name) Example: "My BLE Device" or "Sensor-01" Displayed when scanning. Max \~20 chars recommended. Manufacturer Specific Data Company ID + Custom Payload → Auto-formatted as AD Type 0xFF Company (search by name or hex ID) Loading company database... ID (Hex) Data Payload (Hex bytes) Preview: Search for a company (Apple, Nordic, etc.) or enter a 4-digit hex ID. Use FFFF for testing. Service UUID (16-bit) Search: "Battery", "Heart", "Environmental" or enter UUID like "180F" ▼ Member Advertises that this device offers this service. Helps with filtering during scan. #### Advertising Interval Min Interval (ms) Max Interval (ms) #### Raw Advertisement Data (Advanced) Complete AD Structure (Hex) Format: Length:Type:Data for each AD element. Leave empty to use fields above. Example: 02:01:06:09:09:4D:79:44:65:76:69:63:65 = Flags (06) + Name "MyDevice". When set, this overrides all fields above. #### Packet Size Advertising Data / bytes (+3 flags) Scan Response /31 bytes ⚠️ #### 📋 AT Command Log Clear ### Privacy Policy URL: https://novelbits.io/privacy/ Last updated: 2026-02-19T06:18:30.000Z [← Back to Home](https://novelbits.io/) Last updated: January 2026 This Privacy Policy describes how your personal information is collected, used, and shared when you visit Novel Bits ([novelbits.io](https://novelbits.io/)) or the Bluetooth Developer Academy ([academy.novelbits.io](https://academy.novelbits.io/?ref=novelbits.io)) (collectively, "the Site"). ## Personal Information We Collect When you visit the Site, we automatically collect certain information about your device, including information about your web browser, IP address, time zone, and some of the cookies that are installed on your device. Additionally, as you browse the Site, we collect information about the individual web pages or products that you view, what websites or search terms referred you to the Site, and information about how you interact with the Site. We refer to this automatically-collected information as "Device Information." We collect Device Information using the following technologies: - **Cookies** are data files that are placed on your device or computer and often include an anonymous unique identifier. For more information about cookies, and how to disable cookies, visit [allaboutcookies.org](http://www.allaboutcookies.org/?ref=novelbits.io). - **Log files** track actions occurring on the Site, and collect data including your IP address, browser type, Internet service provider, referring/exit pages, and date/time stamps. - **Web beacons, tags, and pixels** are electronic files used to record information about how you browse the Site. When you make a purchase through the Site, we use PayPal and/or Stripe for payment processing. We do not store any of your payment information directly. When we talk about "Personal Information" in this Privacy Policy, we are talking about both Device Information and Order Information. ## How Do We Use Your Personal Information? We use the Order Information that we collect generally to fulfill any orders placed through the Site (including processing your payment information, arranging for shipping, and providing you with invoices and/or order confirmations). Additionally, we use this Order Information to: - Communicate with you - Screen our orders for potential risk or fraud - When in line with the preferences you have shared with us, provide you with information or advertising relating to our products or services We use the Device Information that we collect to help us screen for potential risk and fraud (in particular, your IP address), and more generally to improve and optimize our Site (for example, by generating analytics about how our customers browse and interact with the Site, and to assess the success of our marketing and advertising campaigns). ## Sharing Your Personal Information We share your Personal Information with third parties to help us use your Personal Information, as described above. For example, we use Google Analytics to help us understand how our customers use the Site. You can read more about how Google uses your Personal Information at [google.com/policies/privacy](https://www.google.com/intl/en/policies/privacy/?ref=novelbits.io). You can also opt-out of Google Analytics at [tools.google.com/dlpage/gaoptout](https://tools.google.com/dlpage/gaoptout?ref=novelbits.io). We may also share your Personal Information to comply with applicable laws and regulations, to respond to a subpoena, search warrant or any other lawful request for information we receive, or to otherwise protect our rights. ## Behavioral Advertising We may use your Personal Information to provide you with targeted advertisements or marketing communications we believe may be of interest to you. For more information about how targeted advertising works, visit the Network Advertising Initiative's educational page at [networkadvertising.org](https://www.networkadvertising.org/understanding-online-advertising/how-does-it-work?ref=novelbits.io). You can opt out of targeted advertising by: - **Google:** [google.com/settings/ads](https://www.google.com/settings/ads/anonymous?ref=novelbits.io) - **Digital Advertising Alliance:** [optout.aboutads.info](http://optout.aboutads.info/?ref=novelbits.io) ## Do Not Track Please note that we do not alter our Site's data collection and use practices when we see a Do Not Track signal from your browser. ## Your Rights If you are a European resident, you have the right to access personal information we hold about you and to ask that your personal information be corrected, updated, or deleted. If you would like to exercise this right, please [contact us](https://novelbits.io/contact/). Additionally, if you are a European resident, we note that we are processing your information in order to fulfill contracts we might have with you (for example, if you make an order through the Site), or otherwise to pursue our legitimate business interests listed above. Please note that your information may be transferred outside of Europe, including to the United States. ## Data Retention When you place an order through the Site, we will maintain your Order Information for our records unless and until you ask us to delete this information. ## Minors The Site is not intended for individuals under the age of 18. ## Changes We may update this privacy policy from time to time in order to reflect changes to our practices or for other operational, legal, or regulatory reasons. ## Contact Us For more information about our privacy practices, if you have questions, or if you would like to make a complaint, please [contact us](https://novelbits.io/contact/). ### Terms & Conditions URL: https://novelbits.io/terms/ Last updated: 2026-06-19T14:01:57.000Z [← Back to Home](https://novelbits.io/) Last updated: January 2026 **By using our websites novelbits.io or academy.novelbits.io, you are consenting to our terms and conditions as outlined below.** Please also review our [Privacy Policy](https://novelbits.io/privacy/). ## Overview The terms "we," "us," and "our" refer to Novel Bits LLC. The term "the Site" refers to novelbits.io and academy.novelbits.io. The terms "user," "you," and "your" refer to site visitors, customers, members, and any other users of the site. ## Service Bluetooth Developer Academy is a membership site for online training, courses, resources, and other content relating to developing Bluetooth Low Energy products and applications (the "Service"). Use of academy.novelbits.io, including all materials presented herein and all online services provided by Novel Bits LLC, is subject to the following Terms and Conditions. These Terms and Conditions apply to all site visitors, customers, and all other users of the site. By using the Site or Service, you agree to these Terms and Conditions, without modification, and acknowledge reading them. Parties agree that the Service is in the nature of education. The scope of services provided by Novel Bits LLC according to this Agreement is limited to those listed on the academy.novelbits.io website. Novel Bits LLC reserves the right to substitute services equal to or comparable to the services listed if the need arises, without prior notice. ## Use of the Site and Service To access or use the Site, you must be 18 years of age or older and have the requisite power and authority to enter into these Terms and Conditions. Children under the age of 18 are prohibited from using the Site. Information provided on the Site and in the Service related to membership sites and other information is subject to change. Novel Bits LLC makes no representation or warranty that the information provided, regardless of its source (the "Content"), is accurate, complete, reliable, current, or error-free. Novel Bits LLC disclaims all liability for any inaccuracy, error, or incompleteness in the Content. ## Account Creation In order to use the Service, you will be required to provide information about yourself including your name, email address, username and password, and other personal information. You agree that any registration information you give to Novel Bits LLC will always be accurate, correct, and up to date. You must not impersonate someone else or provide account information or an email address other than your own. Your account must not be used for any illegal or unauthorized purpose. You must not, in the use of the Service, violate any laws in your jurisdiction. ## Lawful Purposes You may use the Site and Service for lawful purposes only. You agree to be financially responsible for all purchases made by you or someone acting on your behalf through the Site. You agree to use the Site and to purchase services or products through the Site for legitimate, non-commercial purposes only. You shall not post or transmit through the Site any material which violates or infringes the rights of others, or which is threatening, abusive, defamatory, libelous, invasive of privacy or publicity rights, vulgar, obscene, profane, or otherwise objectionable, contains injurious formulas, recipes, or instructions, which encourages conduct that would constitute a criminal offense, give rise to civil liability, or otherwise violate any law. ## Refusal of Service The Services are offered subject to our acceptance of your order or requests. We reserve the right to refuse service to any order, person or entity, without the obligation to assign a reason for doing so. No order is deemed accepted by us until payment has been processed. We may at any time change or discontinue any aspect or feature of the Site or Service, subject to us fulfilling our previous responsibilities to you based on acceptance of your payment. ## Order Confirmation We will email you to confirm the placement of your order and with details concerning product delivery and ongoing payments. In the event that there is an error in this email confirmation, it is your responsibility to inform us as soon as possible. ## Duration of Agreement Once confirmed, we will provide you access to the purchased Service. You agree and understand that access to the Service may at times be influenced and affected by third parties that we use to provide the Service (web hosting, membership site plugins, etc.). You agree and understand that no breach of contract action may be initiated against Novel Bits LLC when there are reasonable delays in the access of the Service. Novel Bits LLC reserves the right to terminate the Service, and/or access to certain features of the Service, with or without prior notice to you. We will make reasonable efforts to provide notice but are not required to do so under the terms of this agreement. **Lifetime Access** is for the lifetime of the Service. If for any reason, Novel Bits LLC should dissolve or cease to exist, then your access to the Service terminates. For **annual subscriptions**, you will receive 365 days of access. You may cancel the automatic renewal of your annual subscription at any time and your access to the Site will end at the end of the current contracted term. **Subscriptions renew automatically unless you stop your membership, in which case your membership and access to the Site will stop at the end of the billing period.** ## Cancellations & Refunds If you are a consumer in the EU or EEA, you have a statutory 14-day right of withdrawal on distance purchases. See our [EU Right of Withdrawal & Returns](https://novelbits.io/eu-right-of-withdrawal/) page for how to exercise it and how refunds are handled. Nothing in these Terms limits the statutory rights you have as a consumer. For online courses and other digital educational content, your right of withdrawal ends once you give your express consent to begin and access the materials, acknowledging that you lose that right by doing so. Apart from any statutory right of withdrawal or a voluntary guarantee we offer, we are not able to provide refunds for digital content once you have accessed it. **For subscriptions, it is your responsibility to cancel your account in good time should you no longer require the Service and not wish to be billed further.** ## Product Description We endeavor to describe and display the Service as accurately as possible. While we try to be as clear as possible in explaining the Service, please do not accept that the Site is entirely accurate, current, or error-free. From time to time we may correct errors in pricing and descriptions. We reserve the right to refuse or cancel any order with an incorrect price listing. ## Material You Submit to the Site You shall not upload, post, or otherwise make available on the Site any artwork, photos, or other materials (collectively "Materials") protected by copyright, trademark, or other proprietary rights without the express written permission of the owner of the copyright, trademark, or other proprietary rights, and the burden of determining that any Materials are not so protected rests entirely with you. As a feature of the Service, Novel Bits LLC may provide access to a community or social media platforms in conjunction with the Service. Novel Bits LLC is not required to provide a community platform and has complete discretion with regards to the platform, and the nature of the interaction, dependent on the Service. You agree that your use of these community and social media platforms is a privilege and Novel Bits LLC may limit or deny access to these platforms for misconduct that includes but is not limited to being inappropriate, rude, violent, or threatening. ## Intellectual Property Rights We claim no intellectual property rights over the material you supply to Novel Bits LLC. You retain copyright and any other rights you may rightfully hold in any content that you submit through the Site or Service. The Site and Service contain intellectual property owned by Novel Bits LLC, including trademarks, copyrights, proprietary information, and other intellectual property. Novel Bits LLC's copyrighted and original materials are provided to you as part of the Service for your individual use only and a single-user license. All intellectual property, including Novel Bits LLC's copyrighted materials, shall remain the sole property of Novel Bits LLC. No license to sell or distribute our materials is granted or implied. **You may not modify, publish, transmit, participate in the transfer or sale of, create derivative works from, distribute, display, reproduce or perform, or in any way exploit in any format whatsoever any of the Site or Service Content or intellectual property, in whole or in part, without our prior written consent.** We reserve the right to immediately remove you from the Service, without a refund, if you are caught violating this intellectual property policy. ## Changed Terms We may at any time amend these Terms and Conditions. Such amendments are effective immediately upon notice to you by us posting the new Terms and Conditions on this Site. Any use of the Site or Service by you after being notified means you accept these amendments. We reserve the right to update any portion of our Site and Service, including these Terms and Conditions, at any time. ## Limitation of Liability You agree that under no circumstances shall we be liable for direct, indirect, incidental, consequential, special, punitive, exemplary, or any other damages arising out of your use of the Site or Service. Additionally, Novel Bits LLC is not liable for damages in connection with (i) any failure of performance, error, omission, denial of service, attack, interruption, deletion, defect, delay in operation or transmission, computer virus, or line or system failure; (ii) loss of revenue, anticipated profits, business, savings, goodwill or data; and (iii) third party theft of, destruction of, unauthorized access to, alteration of, or use of your information or property, regardless of our negligence, gross negligence, failure of an essential purpose and whether such liability arises in negligence, contract, tort, or any other theory of legal liability. In no event shall Novel Bits LLC's cumulative liability to you exceed the total purchase price of the Service you have purchased from Novel Bits LLC, and if no purchase has been made, Novel Bits LLC's cumulative liability to you shall not exceed $100. ## Third-Party Resources The Site and the Service may contain links to third-party websites and resources. You acknowledge and agree that we are not responsible or liable for the availability, accuracy, content, or policies of third-party websites or resources. Links to such websites or resources do not imply any endorsement by or affiliation with Novel Bits LLC. ## Indemnification You shall indemnify and hold us harmless from and against any and all losses, damages, settlements, liabilities, costs, charges, assessments, and expenses, as well as third party claims and causes of action, including, without limitation, attorney's fees, arising out of any breach by you of any of these Terms and Conditions, or any use by you of the Site or Service. ## Entire Agreement This Agreement constitutes the entire agreement between you and Novel Bits LLC pertaining to the Site and Service and supersedes all prior and contemporaneous agreements, representations, and understandings between us. No waiver of any of the provisions of this Agreement by Novel Bits LLC shall be deemed, or shall constitute, a waiver of any other provision, whether or not similar, nor shall any waiver constitute a continuing waiver. No waiver shall be binding unless executed in writing by Novel Bits LLC. ## Severability If any term, provision, covenant, or condition of this Agreement is held by an arbitrator or court of competent jurisdiction to be invalid, void, or unenforceable, the rest of the Agreement shall remain in full force and effect and shall in no way be affected, impaired, or invalidated. ## Contact Us All notices, requests, demands, and other communications under this Agreement shall be in writing and properly addressed as follows: **Novel Bits LLC** PO Box 698 Fishers, IN 46038 United States of America You may also [contact us online](https://novelbits.io/contact/). ### Bluetooth Developer Academy URL: https://novelbits.io/academy/ Last updated: 2026-08-09T03:15:09.000Z Relaunching Soon # Same Academy. Better platform. We're moving the Bluetooth Developer Academy to a brand new learning platform — faster, cleaner, and built for the way developers actually study. All 35+ courses and 300+ hours of content come with us. Drop your email and we'll let you know the moment it's live. [Notify Me](#waitlist) [Meet Your Instructor](#about) [Already a member? Log in →](https://academy.novelbits.io/login/?ref=novelbits.io) Get on the Waitlist ## Be first in line when we relaunch No spam. One email when the new platform goes live, and that’s it. Email address Notify me when it’s live While you wait, you’ll also get my weekly Bluetooth & UWB newsletter. Unsubscribe with one click anytime. ✉️ #### You’re on the list We sent a confirmation email to . Click the link in that email to confirm, and we’ll let you know the moment the new Academy is live. Don’t see it? Check your spam folder. 35+ Video Courses 200+ Companies Trained 300+ Hours of Content Official Training Partner ![Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/silicon-labs-mono.png) ![Nordic Semiconductor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nordic-semi-mono.png) ## Sound Familiar? I've been exactly where you are. That's why I created the Academy. 😩 You don't have time to read all 3,000+ pages of the Bluetooth Specification 🔍 You're sick of wasting hours searching for answers that don't exist online 📚 Vendor documentation leaves you with more questions than answers 🔄 You need to transition from Bluetooth Classic to Bluetooth LE quickly ![Mohammad Afaneh](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/MAfaneh_Enhanced_Photo.jpg) Mohammad Afaneh Founder, Novel Bits 10+ Years Bluetooth LE Published Author Silicon Labs Partner ## Why I Created This Academy I've been developing Bluetooth LE products since 2014\. I've experienced every stage of the learning curve - from complete beginner to shipping commercial products used by thousands. **I've felt the pain of the enormous learning curve associated with Bluetooth LE development.** I wasted days and weeks getting up to speed while struggling with poor or non-existent resources. That's why I created the Bluetooth Developer Academy - so you don't have to learn the hard way. My goal is to get you up to speed with Bluetooth LE best practices and keep you current on the latest technology, so you can tackle your projects confidently and ship on time. ## What You Get as a Member Everything you need to accelerate your Bluetooth LE development 🎬 ### 35+ Video Courses In-depth courses from foundational concepts to advanced implementations on Nordic, Silicon Labs, iOS, and Android. 💬 ### Private Community Forum Get your questions answered by Bluetooth experts. Connect with developers from 200+ companies worldwide. 🛠 ### Practical Code Examples Downloadable source code and step-by-step walkthroughs of real embedded and mobile Bluetooth LE projects. ## Exclusive Hands-On Series Members-only deep-dives with real lab data, full methodology, and practical insights [ Members Only Browse All Academy Series → RF chamber experiments, Bluetooth LE sniffer deep-dives, and more — exclusive content you won't find anywhere else. ](https://novelbits.io/academy-series/) ## What Topics Are Covered? From fundamentals to advanced topics across multiple platforms ### Foundations ✓ Core Foundations of Bluetooth LE ✓ Bluetooth LE Security Deep Dive ✓ GATT Protocol Masterclass ✓ Advertising & Scanning ### Mobile Development ✓ iOS CoreBluetooth (Swift) ✓ Android Bluetooth LE (Kotlin) ✓ Android Bluetooth LE (Java) ✓ Mobile App Architecture ### Embedded Development ✓ nRF Connect SDK ✓ nRF5 SDK ✓ Silicon Labs EFR32 ✓ Custom GATT Services ### Advanced Topics ✓ LE Audio & Auracast ✓ Bluetooth Mesh ✓ Direction Finding (AoA/AoD) ✓ Extended Advertising ## What Members Are Saying "The Academy is professionally constructed and I would compare it to an at-your-own-pace college course. Anyone wanting to get serious about Bluetooth should sign up. It's easily well worth the money." RA Roberto Andaya Hardware Engineer, SlateSafety "A helpful collaboration of developers that is very industry-specific. No fluff or annoying sales pushing. Highly recommended for all Bluetooth developers!" MN Mark Nichols Founder, Spanalytics "A wealth of resources for Engineers serious about designing Bluetooth LE products. Mohammad is VERY active and personally helps engineers with their design challenges." DB Dirk Buijsman Firmware Team Lead, Steelcase ## Is the Academy Right for You? ### ✓ The Academy IS For You If... - ✓ You're an embedded or mobile developer adding Bluetooth LE to your skill set - ✓ You want to understand Bluetooth LE deeply, not just copy/paste code - ✓ You value structured, professional training over random tutorials - ✓ You want access to experts for ongoing support ### ✗ The Academy is NOT For You If... - ✗ You're looking for free content only - ✗ You want someone to do the work for you - ✗ You're looking for Bluetooth Classic training - ✗ You expect overnight results without practice Don’t Miss the Relaunch ## Get notified when we’re back We’ll send one email when the new Academy is live. That’s the only thing you’ll get from us. Email address Notify me when it’s live While you wait, you’ll also get my weekly Bluetooth & UWB newsletter. Unsubscribe with one click anytime. ✉️ #### You’re on the list We sent a confirmation email to . Click the link in that email to confirm, and we’ll let you know the moment the new Academy is live. ### Need Team or Corporate Access? We offer volume discounts for teams. Get your entire Bluetooth development team trained. [Contact for Team Pricing](https://novelbits.io/contact/) ## Frequently Asked Questions What's happening with the Academy right now? + We're migrating the Bluetooth Developer Academy to a brand new learning platform — faster video player, smoother lesson navigation, and a much better foundation overall. New sign-ups are paused while we rebuild. All 35+ courses and 300+ hours of content come with us. Existing members can keep using the current platform until we cut over (we'll email you with details before the switch). What skill level is required? + The Academy is designed for all skill levels. Start with "Core Foundations of Bluetooth Low Energy" if you're a beginner, or jump into platform-specific courses if you already have the basics. What platforms are covered? + We cover Nordic (nRF5 SDK, nRF Connect SDK), Silicon Labs, Texas Instruments, iOS (Swift), and Android (Kotlin/Java). New platforms are added based on member requests. Do I get access to all courses? + Yes! All membership plans include full access to every course, the community forum, downloadable source code, and any new courses added during your membership. What if I have questions while learning? + Post your questions in the private community forum and get answers from Mohammad and other experienced Bluetooth developers. You're never stuck learning alone. Can I cancel anytime? + Yes. Cancel anytime and your access continues until the end of your billing period. No long-term contracts or commitments. [Already a member? Log in →](https://academy.novelbits.io/login/?ref=novelbits.io) ## Not Ready to Commit? Start with the Free Crash Course Get a solid foundation in Bluetooth LE fundamentals with our free 12-day email course. No account needed — and you'll get a downloadable cheat sheet at the end. [Start the Free Crash Course →](https://novelbits.io/bluetooth-le-crash-course/) ## Be First to Know When We Relaunch The Academy is moving to a brand new platform. Drop your email and we'll let you know the moment it's live. [Join the Waitlist](#waitlist) [Already a member? Log in →](https://academy.novelbits.io/login/?ref=novelbits.io) ### About Mohammad Afaneh URL: https://novelbits.io/about/ Last updated: 2026-08-09T05:56:12.000Z ![Mohammad Afaneh](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/MAfaneh_Enhanced_Photo.jpg) # Hi, I'm Mohammad Founder of Novel Bits & the Bluetooth Developer Academy I've spent the last decade helping engineers master Bluetooth Low Energy development. What started as a personal blog in 2015 has grown into a comprehensive learning platform read by engineers at companies from startups to Fortune 500s, with 9,500+ subscribers on the weekly newsletter. [ ](https://www.linkedin.com/in/mafaneh?ref=novelbits.io "LinkedIn") [ ](https://www.youtube.com/@novelbits?ref=novelbits.io "YouTube") ## My Story I've been developing embedded software and firmware since 2006, working with companies like Allegion (Schlage locks), Motorola, Technicolor, and Denon & Marantz. Throughout my career, I've worked on wireless electronic door locks, satellite receivers, wireless doorbells, and various IoT products. My journey into Bluetooth Low Energy began in 2014 when I was tasked with adding Bluetooth LE connectivity to a product. I quickly discovered that learning resources were scattered, documentation was dense, and practical examples were hard to find. I spent countless hours piecing together information from specifications, forums, and trial-and-error. That frustration sparked an idea: *what if I could create the resource I wished I had?* In July 2015, I left my full-time job to start Novel Bits with a simple mission: make Bluetooth LE accessible to every developer. What began as blog tutorials evolved into comprehensive video courses, three published books, and a thriving community of Bluetooth developers. Today, Novel Bits is an official training partner of Nordic Semiconductor and Silicon Labs, and the Bluetooth Developer Academy has helped engineers at companies ranging from startups to Fortune 500s ship Bluetooth products faster. ## Background & Credentials A combination of academic foundation and hands-on industry experience 🎓 ### MSc, Purdue University Electrical & Computer Engineering Digital Signal Processing **4.0 GPA** 💼 ### 20+ Years Experience Embedded software & firmware development since 2006 📜 ### 2 US Patents Innovation in content delivery and metadata systems 🔒 ### Allegion (Schlage) Wireless electronic door locks 📡 ### Motorola Embedded systems development 📺 ### Technicolor Satellite receivers & set-top boxes 🎵 ### Denon & Marantz Audio/video equipment firmware ## Published Books Helping developers learn Bluetooth LE through comprehensive guides [ 📘 Intro to Bluetooth Low Energy 2nd Edition • 2023 ](https://www.amazon.com/Intro-Bluetooth-Low-Energy-weekend/dp/B0CLHBLSG2?ref=novelbits.io) [ 📗 Bluetooth 5 & BLE: A Developer's Guide 2017 ](https://www.amazon.com/Bluetooth-Low-Energy-Developers-Guide-ebook/dp/B07PKVKJVK?ref=novelbits.io) [ 📙 Intro to Bluetooth Low Energy 1st Edition • 2018 ](https://www.amazon.com/Intro-Bluetooth-Low-Energy-easiest-ebook/dp/B07KTDG6KG?ref=novelbits.io) Official Training Partner ![Nordic Semiconductor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nordic-semi-mono.png) ![Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/silicon-labs-mono.png) ## Stuck on Something You Cannot See? Most teams stuck on a Bluetooth LE problem cannot see the air at all. I get a professional sniffer running against your device, then help you work out what to capture next. [See what a Debug Block includes](https://novelbits.io/consulting/) ### Free Bluetooth LE Courses URL: https://novelbits.io/free-courses/ Last updated: 2026-08-09T05:56:10.000Z 100% Free • No Credit Card Required # Free Bluetooth LE Courses Get started with Bluetooth Low Energy development through our free, sponsor-supported courses. Learn to develop for platforms like Nordic, Silicon Labs, and Renesas—at zero cost. ## Start Learning Today Video lessons, practical examples, and downloadable resources included 12-Day Email Course ### Bluetooth LE Crash Course Master the fundamentals in 12 daily emails. From how devices discover each other to security and privacy — get a solid foundation before diving into code. - 12 daily lessons covering radio basics through security - Downloadable one-page cheat sheet included - No account needed — delivered straight to your inbox [Start the Free Course →](https://novelbits.io/bluetooth-le-crash-course/) Join 9,500+ developers already learning with us ![Bluetooth LE Cheat Sheet preview — included free with the crash course](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/cheat-sheet-page1-1.png) ## Hands-On Video Courses Already enrolled? [Sign in to access your courses →](https://academy.novelbits.io/login/?ref=novelbits.io) ![nRF54L15 Deep Dive](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/04/final-photo.jpg) ![Nordic Semiconductor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Nordic-Semi---Horizontal-v2.png) Free Course ### nRF54L15 Deep Dive Learn the key hardware features of Nordic Semiconductor's nRF54L15 by building a heart rate monitor from scratch. 8 modules, 23 hands-on lessons covering SAADC, DPPI, GRTC, Bluetooth LE, security, and power measurement. [Enroll Free →](https://learn.novelbits.io/courses/nrf54l15-deep-dive?ref=novelbits.io) ![Ultra-Low Power Scalable Bluetooth Systems](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nordic-pawr-featured.png) ![Nordic Semiconductor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Nordic-Semi---Horizontal-v2.png) Free Course ### Ultra-Low Power Scalable Bluetooth Systems Learn to build ultra-low power Bluetooth LE systems using Nordic's PAwR (Periodic Advertising with Response) feature. Create a complete weather station project. [Enroll Free →](https://academy.novelbits.io/register/nordic-pawr-weather-station-ble/?ref=novelbits.io) ![Energy Harvesting and Ambient IoT](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/From-Light-to-BLE-A-Practical-Guide-to-Energy-Harvesting-for-Ambient-IoT.png) ![Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Silicon-Labs-1.png) Free Course ### Energy Harvesting and Ambient IoT A practical guide to energy harvesting techniques for ambient IoT applications. Learn to build battery-free devices powered by light, motion, or thermal energy. [Enroll Free →](https://academy.novelbits.io/register/practical-guide-to-energy-harvesting-for-ambient-iot-silicon-labs/?ref=novelbits.io) ![Bluetooth Channel Sounding](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/channel-sounding-featured.png) ![Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Silicon-Labs-1.png) Free Course ### Bluetooth Channel Sounding Master Bluetooth's newest ranging technology. Learn how Channel Sounding enables centimeter-level distance measurement for secure access and asset tracking. [Enroll Free →](https://academy.novelbits.io/register/free-course-bluetooth-channel-sounding-silicon-labs/?ref=novelbits.io) ![Renesas DA14531 Temperature Sensor Beacon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Course-Featured-Image-v2.png) ![Renesas](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Renesas.png) Free Course ### Renesas DA14531 Temperature Sensor Beacon Build a complete temperature sensor beacon from scratch using the ultra-low-power Renesas DA14531 SoC. Includes hardware setup and firmware development. [Enroll Free →](https://academy.novelbits.io/register/free-course-building-a-temperature-sensor-beacon-using-renesas-da14531-soc/?ref=novelbits.io) ## Why Learn With Us? 🎓 ### Expert Instruction Courses sponsored by industry leaders like Nordic, Silicon Labs, and Renesas 💻 ### Hands-On Projects Build real working devices with downloadable source code and step-by-step guidance 🚀 ### Career Growth Add in-demand Bluetooth LE skills to your resume with completion certificates ## Ready for More? Join the Bluetooth Developer Academy for 35+ premium courses, a private community forum, and ongoing support from Bluetooth experts. [Explore the Academy →](https://novelbits.io/academy/) ## Posts ### Four Bluetooth LE Advertising Decisions, Priced in Joules URL: https://novelbits.io/bluetooth-le-advertising-energy-four-decisions/ Last updated: 2026-08-07T02:24:41.000Z Somewhere in your product there’s a battery estimate. Someone wrote it in a spreadsheet, probably early, probably before the firmware existed, and it’s been quoted in meetings ever since. Then the firmware got written. Along the way, four decisions were made about how your device advertises. What transmit power to use. What to put in the advertising payload. Whether to be scannable. How often to advertise. Each of those was made by a different person on a different day for a different reason, and not one of them was made in front of the spreadsheet. So I put a Nordic Semiconductor nRF54L15 on a power measurement kit and priced all four. Here’s the headline. Three of the four change what a single advertising event costs, and the transmit power dial is not symmetric: it costs substantially more to turn up than it refunds when you turn it back down. The fourth decision, the interval, doesn’t change the price of an event at all. It changes how many of them you pay for. That fourth result is the dull one, and it’s in the table deliberately. A bench that can’t show you a lever doing nothing hasn’t earned your trust when it shows one doing something. ## The table Every row is the same board, the same session, the same firmware, at 1.8 V, on nRF Connect SDK v3.3.0\. Energy is attributed to each Bluetooth LE advertising event rather than averaged across the whole capture, so these are per-event figures covering all three primary advertising channels (37, 38 and 39). Unless a row says otherwise, the device advertises non-connectable and non-scannable on the LE 1M PHY with 17 bytes of advertising data, once per second. ![An nRF54L15-DK development kit wired to a Nordic Power Profiler Kit II on a workbench, with power leads into the kit's VIN, VOUT and GND terminals.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/08/nrf54l15-dk-ppk2-bench.jpg) The rig behind every row in the table: an nRF54L15-DK (PCA10156 v1.0.0) powered through a Nordic Semiconductor Power Profiler Kit II at 1.8 V. **Every row is a single 30-second capture.** That matters for how hard you’re allowed to lean on any one of them, and I’ll come back to it immediately. | Decision | Setting | Energy per advertising event | | ------------------ | ----------------------------- | ---------------------------- | | **Transmit power** | +8 dBm | 31.65 µJ | | | +4 dBm | 20.73 µJ | | | 0 dBm | 15.80 µJ | | | \-8 dBm | 11.80 µJ | | | \-20 dBm | 10.98 µJ | | | \-40 dBm | 9.32 µJ | | **Payload** | 17 bytes of advertising data | 15.49 µJ | | | 27 bytes (a new 8-byte field) | 18.79 µJ | | **Scannable** | Not scannable | 15.49 µJ | | | Scannable | 23.33 µJ | | **Interval** | 100 ms | 15.68 µJ | | | 200 ms | 15.35 µJ | | | 500 ms | 15.58 µJ | | | 1 s | 15.19 µJ | | | 2 s | 15.56 µJ | Let’s read down the interval block, then read down the transmit power block. That contrast is the post. ![Range of per-event energy for each of the four decisions. Transmit power spans 22.33 µJ, scannability 7.84, payload 3.30, and the advertising interval only 0.49, which sits entirely inside the bench’s ±5.8% resolvable band.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/08/fig-four-decisions-range-1.png) The full measured range of each decision. The interval’s whole span fits inside what this bench can resolve. **First, notice that the same configuration appears three times at three different numbers.** The 0 dBm row, the 17-byte row and the 1 s row are all the same advertiser, and they read 15.80, 15.49 and 15.19 µJ. That spread is about 4%, and it’s not a finding about anything. It’s the bench. I’ve left it visible rather than averaging it away, because it’s the most useful thing on the page: it tells you how much of any other number here you should believe. Which brings me to the two things you need before the rest of it means anything. **The resolvable difference on this rig is about 5.8%, and that’s a lower bound, not a margin of error.** I got it by running identical firmware eight times. But those eight repeats share one build and one flash, so they measure the easiest comparison the bench can make, while every comparison in the table above crosses a rebuild and a reflash. When I’ve measured the same non-scannable configuration across separate sessions, it’s spanned about 6%, which is wider than the floor derived from the repeats. So: anything under about 6% isn’t a result, it’s the bench breathing. **Second, the basis.** These figures are computed on the same sample basis that Nordic’s Power Profiler applies by default, which includes its spike filter for the artifact the PPK2 produces when it switches current ranges. I have a further correction of my own on top of that, and with it these levels come out around 8 to 20% lower. I’m publishing without it, for a plain reason rather than a noble one: my correction has no independent validation yet, and Nordic’s default does. If you saw my Bluetooth LE post on scan responses earlier this week, its absolute figures were on my corrected basis, which is why a non-scannable advertiser reads 13.42 µJ there and 15.49 µJ here. Most of that gap is the basis and the rest is that they’re separate captures, which is exactly the 6% I just described. One more thing about the rig, since it’s part of what I measured: the board is instrumented, and those connections are on the meter throughout. They’re inside every number here. ## Decision one: transmit power, and why it’s a one-way street Raising transmit power costs about four times what turning it back down gives you. Going from 0 dBm up to +8 dBm adds 15.86 µJ to every advertising event, which is roughly a doubling. Coming back down 8 dB from 0 dBm returns 3.99 µJ. That’s a ratio of about four to one, and it held between 3.6 and 4.1 under every way I tried correcting the capture, including not correcting it at all. Read that as robust to method rather than repeated, though: it’s one ladder, run once per setting, reanalyzed several ways. It isn’t the ladder measured twice. Most of the asymmetry is just decibels doing what decibels do. This dev kit mounts the QFN package, which the datasheet rates at 7 dBm typical output, so going up from 0 dBm buys about 4 mW more on paper while coming down 8 dB gives back well under 1 mW. That alone predicts nearly five to one. Read that as nominal rather than firm, though: the same datasheet rates RF power accuracy at plus or minus 2 dB, and running the arithmetic at those edges spreads the on-paper prediction from under three to one to over eight to one. The measured four to one is worth being careful about, because the obvious explanation is wrong. It isn’t the radio’s fixed costs. A cost that’s identical at every power setting cancels out of both differences, so it can’t move the ratio at all, in either direction. What’s actually going on is that the current the radio draws doesn’t scale with the power it puts out, and you don’t have to take my bench’s word for that. Nordic’s datasheet lists radio current at 3.7 mA at 0 dBm and 9.1 mA at maximum for this package. Radiated power over that step rises about five-fold while the current rises less than two and a half. Their own typicals describe a transmit chain that is around nine percent efficient at 0 dBm and about eighteen percent at the top, and it stays that way after you subtract the 1.2 mA the radio still draws at -40 dBm. So it isn’t a fixed cost hiding in the numbers either. That also gives the four to one something to stand on, which matters because the accuracy band above means my bench can’t establish it alone. Nordic’s radio-only currents predict about 3.6 to one for this package. Their Online Power Profiler, set to the same board, voltage, payload and interval, predicts about 3.2\. I measured 3.97\. Three independent routes, same shape. Then the ladder flattens. The remaining 32 dB, from -8 dBm down to -40 dBm, returns about 2.5 µJ in total, and somewhere between 1.4 and 2.6 depending on how you correct the meter, because so little is left by then that the correction starts to dominate. Thirty-two more decibels bought less than the first eight did. Whatever’s left by then clearly isn’t tracking how loud you transmit, and I measured it at the supply pin, so I can tell you it’s there without telling you which block it is. The practical shape is worth sitting with. If you’re at 0 dBm and worried about battery, transmit power isn’t where your next microjoule is. But if somebody asks you to turn it up, that’s the expensive direction, and it’s the one that gets chosen under pressure. Transmit power tends to get raised late, after a field report about a dead spot in a stairwell. It’s a one-line change, it rarely goes back through a power review, and the estimate in that spreadsheet doesn’t move. At one advertising event per second, that one-line change adds about 8.8 µA of average current, or roughly 0.2 mAh a day, for the life of the product. One honest caveat on the top row. +8 dBm is a real setting on this part, not an out-of-range request: nRF Connect SDK exposes the range as -8 to +8 dBm for this board, and Nordic’s own benchmark configuration for it selects +8\. What the QFN package on this kit is rated to deliver is 7 dBm typical, and Nordic documents the split plainly: 8 dBm for the CSP variants, 7 dBm for the QFN ones. Nothing at build time or run time warns you about the difference. So read the top row as the energy cost of asking for +8 dBm. I measured what the radio drew, not what left the antenna. ## Decision two: payload, and the two bytes before your first byte Adding eight bytes to your advertising payload can cost you eight bytes on air, or ten. It depends where you put them. Advertising data is a list of AD structures, and each one carries a length octet and a type octet in front of its data. Append eight bytes to a field that’s already there and you transmit eight more. Add them as a brand new field and you transmit ten. I measured the second case. Advertising data went from 17 bytes to 27, the packet on air went from 33 bytes to 43, and the time on air per packet went from 264 µs to 344 µs. Since the event repeats on all three channels, that’s 792 µs of air becoming 1,032 µs. The energy went up by **3.30 µJ per advertising event**. Now, how much should you trust that? Less than two significant figures suggests. The baseline it’s subtracted from is a single capture, and it happens to sit high against repeats of the same configuration, so re-anchoring on the repeat average would move the per-byte figure by about 16%. Carry it as roughly a third of a microjoule per added byte and don’t build a spreadsheet on the second digit. That’s still enough to answer the question people actually ask, which is whether a new field costs anything worth caring about. The framing arithmetic underneath it is much firmer than the energy, and it’s worth separating the two. One octet is 8 µs on the LE 1M PHY, and the packet is preamble, access address, header, advertiser address, your data, and CRC. Work that out for a three-channel advertising event and you get 384 µs with no advertising data, 744 µs at 15 bytes, and 1,128 µs at the 31-byte legacy maximum. Those are exactly the numbers the Bluetooth Core Specification publishes in its own table for the same cases. So the airtime side isn’t my measurement at all, it’s arithmetic you can check against the specification. I did also compare that airtime model against the measured transmit plateau, and it lands within about 4%. I want to be careful about how much that’s worth, though, because it looks like more than it is: both halves come from the same captures on the same meter, so it isn’t an independent check, and 4% is inside the floor I quoted earlier, which means the comparison couldn’t really have failed. What it genuinely tests is the airtime model, and it’s how I caught myself getting the byte count wrong the first time. The packaging is the part nobody costs. Two new 4-byte fields are two AD structures, so twelve octets of air for eight bytes of data. Manufacturer-specific data is the sharpest version, because the specification requires the first two data octets to be your assigned company identifier. A brand new manufacturer-data field spends four octets on air before your first useful byte: length, type, and two of company ID. Here’s the part I didn’t expect. Ten more bytes on air is 30% more time transmitting, and it cost 21% more energy. Payload is cheaper than proportional, and the reason is specifically that some of an advertising event isn’t transmission at all. The ramp on either side of the packet, and the fixed cost of waking up and running the event three times, are there whether you send one byte or thirty-one. So your payload gets diluted by everything around it that isn’t sending your payload. Count airtime, then, because airtime is the thing that moves. And treat adding a field as cheap in isolation and expensive by accumulation. Eight bytes is a counter and a short name. Nobody reviews it. It rides along on every advertising event for the life of the product. ## Decision three: scannable, and the number your room writes for you Making that same advertiser scannable took it from 15.49 µJ to 23.33 µJ per event, about half again. But that number isn’t really mine to give you, and this is the most important sentence in the section: **it’s a property of the room I measured it in.** Packets per event went from exactly 3.0 to an average of 4.6, and varied by 28% across the capture. Those extra packets are scan requests arriving from whatever phones and gateways happened to be nearby, and the responses my device sent back. I’ve measured the same comparison anywhere from about 42% to 60% depending on which baseline capture I anchor on and what the room was doing at the time. Move the board somewhere quiet and it falls. Move it into a warehouse full of scanners and it climbs. Three separate things are bundled inside that gap: - **Opening the receive window after each packet.**Independent of your environment. - **Receiving the scan requests that arrive.** Depends on your environment, and unavoidable. - **Transmitting the scan responses.** Depends on your environment, and the only one you can switch off. A desk can’t separate the first from the second, because ambient scan traffic isn’t something you can turn off by putting your own phone in a drawer. Splitting them takes an RF chamber, and that measurement is scheduled. The third one is genuinely controllable: the advertising filter policy restricts scan-request processing to devices on your Filter Accept List, and with an empty list your device listens but answers nobody. I wrote about that in detail earlier this week, including the way it fails silently on Zephyr if you enable the advertising option without also enabling the accept list. The row above is a non-connectable scannable advertiser, which is the clean version of the question. If your device is connectable and undirected on **legacy** advertising, you don’t get to choose: there’s no connectable, undirected, non-scannable legacy advertising PDU, so you’re scannable whether you wanted to be or not, and the receive window is open regardless because that’s how anything connects to you. The filter policy stops the responding. It never stops the listening. On **extended** advertising you do get a choice. The specification defines a connectable undirected event type there that ignores scan requests outright, which is the one thing the filter policy can’t do for you. It isn’t free, since your connection window moves onto a secondary channel, but if you’re already on extended advertising it’s worth knowing the option exists. And connectable, undirected is what most peripherals do. Plenty of them put nothing useful in the scan response and are still sending one every time, on a device whose battery someone already promised a customer. The exception is real, and you’ll know if it’s you. If you deliberately use the scan response because 31 bytes wasn’t enough, you need those answered. That isn’t a saving, it’s a price. ## Decision four: interval, which doesn’t do what the other three do Now let’s look at the interval block again, with what it did to the average current beside it. | Interval | Energy per event | Average current | Charge per day | | -------- | ---------------- | --------------- | -------------- | | 100 ms | 15.68 µJ | 86.8 µA | 2.1 mAh | | 200 ms | 15.35 µJ | 46.4 µA | 1.1 mAh | | 500 ms | 15.58 µJ | 23.4 µA | 0.56 mAh | | 1 s | 15.19 µJ | 14.4 µA | 0.35 mAh | | 2 s | 15.56 µJ | 10.6 µA | 0.26 mAh | ![Two panels against advertising interval. Top: energy per event stays flat at about 15.5 µJ from 100 ms to 2 s, inside the ±5.8% band, in both sessions. Bottom: average current falls from 86.8 µA to 10.6 µA, less steeply than the event rate, leaving a widening gap.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/08/fig-interval-current-draw.png) Same five captures, read two ways. The price of an event holds still; the number of events is what moves. The advertising interval changed by a factor of twenty. The energy per event moved about 3%, which is inside the floor. I can’t tell those five numbers apart. That’s a claim about my bench, not about physics, so let me put a number on it. The smallest per-event effect this setup could have resolved is about 0.9 µJ, so if the interval does change the cost of an event, it does so by less than that. Here’s the cleanest way I can put the same point: my eight repeats at a *single* interval spanned 4.7%, which is wider than the 3.2% I measured across a twentyfold change in interval. Changing the interval moved the number around less than not changing anything did. I also went back two days later and re-ran part of the sweep from fresh builds, because a flat line is exactly the sort of result that deserves doubting once. Not the whole ladder: 100 ms, 150 ms, 2 s, and a control at the default. Same answer, and across both sessions nine captures from 100 ms to 2 s span 15.19 to 15.77 µJ. **So the interval isn’t a lever on the price of an advertising event, as far as I can measure. It’s a lever on the quantity.**Three of these four decisions change what you pay each time. This one changes how many times you pay. That sounds like a distinction without a difference until you try to use the table. If you want a cheaper event, transmit power and payload and scannability are your dials and their effects compose. If you want a smaller drain on the battery, the interval is the dial, and it works by multiplication rather than by making anything cheaper. On my board it’s also by far the biggest one, and even a 0.9 µJ effect hiding under my floor would be about 5% of the 100 ms average, against a lever worth a factor of eight. Two things fell out of the sweep that I wasn’t looking for. **The interval you ask for isn’t the interval you get.**At a nominal 100 ms I counted 286 advertising events in 30 seconds rather than 300\. That’s not drift and it isn’t a bug. For undirected advertising the specification requires a small random delay, up to 10 ms, to be added between advertising events, so that two devices that start in lockstep don’t stay there and keep colliding. If that delay is spread evenly, it averages 5 ms, which predicts 286 events. I counted 286\. At a nominal 200 ms it predicts 146, and I counted 146. That’s the one genuinely independent cross-check in this whole post, because the prediction comes from the specification and the count comes from the capture. The exact distribution is up to the controller, so treat the 5% over-count at 100 ms as the shape rather than as your number. But if you’ve ever budgeted advertisements per day by dividing 86,400 by your interval, you’ve been quietly over-counting. Nordic's own Online Power Profiler lands in the same place: set a 100 ms advertising interval and it reports an event interval of 105.00 ms straight back at you. There is something you can do about it, at least on Nordic silicon. The SoftDevice Controller exposes a vendor-specific command, `sdc_hci_cmd_vs_set_adv_randomness`, that sets the maximum delay directly, and passing zero removes it altogether. It’s a runtime call rather than a build-time option, and it isn’t exotic: Zephyr’s own Bluetooth Mesh implementation uses it to take the randomness off its Friend advertising set. The specification mandates that delay for a reason, though, so know what you’re giving up before you switch it off. Mandates is the precise word: the requirement is written as a shall, so zeroing the randomness on undirected advertising puts you outside the specification rather than merely off the beaten path. It exists so two devices that power up together don’t stay in lockstep and collide on every event forever. **Lengthening the interval stops paying, and you can watch it stop.** The event rate falls by a factor of 19 from 100 ms to 2 s. The average current falls by a factor of 8\. Those would be equal if the radio were the only thing drawing current, and they aren’t, because something on that board keeps drawing current between advertising events. On my setup it’s about 6 µA, and I know that two ways: it falls out of the interval sweep as an intercept, and four captures where advertising failed to start altogether read 6.2 µA directly. Those two agree to better than 1%. What I’m not going to do is tell you what it is. Some of it is the sleeping chip, some of it is my own instrumentation, and I haven’t separated them. Naming it before separating it is exactly the mistake this whole exercise exists to avoid, and it would be an easy sentence to write. Take the shape rather than my number. There’s an interval past which your radio stops being your problem, and past that point the work moves to your sleep mode, your low-frequency clock, and whatever else your firmware wakes up to do. On my board the radio is most of the average at 100 ms and a minority of it at 2 s. Where your own crossover sits is a measurement, not a constant, and it’s one of the more valuable half hours you can spend. ## What to do with this Four decisions, in the order I’d question them on an existing product: 1. **Interval first**, because it’s the only multiplicative one and it’s usually left at a default nobody chose deliberately. Going from 100 ms to 1 s cut the average current by a factor of six on my board. Nothing else here is close. 2. **Scannability next.** If you’re not connectable, the question is whether to be scannable at all. If you are connectable on legacy advertising, the filter policy is your lever, and if you’re on extended advertising you can decline scan requests outright. Whichever applies, your own environment sets the price, so measure it where the product actually lives rather than at your desk. 3. **Transmit power third**, and mostly defensively: know what raising it costs before someone raises it. It’s worth about four times as much going up as coming down. 4. **Payload last**, because a third of a microjoule per byte per event is small, and it’s also permanent, and it’s the only one of the four that tends to grow quietly over a product’s life. And then go back and look at the estimate in the spreadsheet. ## What I didn’t measure Being clear about the edges of a table is most of what makes it worth citing. - **Every row is one 30-second capture rather than an average of repeats, and the transmit power ladder was run once per setting.** - **Temperature was not controlled or recorded.** - **One board and one unit, so nothing here establishes part-to-part variation.** - **Everything is legacy advertising on the LE 1M PHY. Extended advertising, the LE 2M PHY and the LE Coded PHY are all still ahead of me, and larger payloads need extended advertising to exist at all.** - **Ambient scan traffic was uncontrolled, and it is a real input to the scannable rows rather than noise around them.** - **The per-byte payload cost rests on a single pair of payload sizes, so it is a cost I measured rather than a rate I proved. Turning it into a rate needs two more points on that axis.** - **The transmit power figures come from an SDK setting whose delivered output I did not verify with a spectrum analyzer.** And every figure here is energy drawn on my board, in my room, with my instrumentation, on one SDK version. The reason to publish the conditions in this much detail is so you can tell which of these numbers might transfer to your product and which certainly won’t. --- *If you’d like the next one of these, the* [*Novel Bits newsletter*](https://novelbits.io/newsletter/) *is where they land first. Next in this series: what happens to all of this on extended advertising and the other PHYs.* ### Why Battery Percentage Can't Predict a Bluetooth LE Brown-Out URL: https://novelbits.io/battery-percentage-bluetooth-le-brownout/ Last updated: 2026-07-30T15:26:24.000Z Somewhere in your coin-cell product’s firmware, the device reads its own battery and reports a level: a percentage over the Bluetooth LE Battery Service, a bar in an app, a number on your fleet dashboard. The number looks fine. Then units in the field start resetting, and the battery telemetry never warned you. I’ve found that this catches a lot of teams off guard, and it is not a firmware bug. The level your device reports is measured at rest, and the failure happens under load. Worse, battery percentage is answering the wrong question. It estimates how much energy is left in the cell. Your Bluetooth LE device doesn’t brown out when it runs low on energy. It browns out when the voltage sags too far during a transmit, and that is a different thing entirely. Let me walk through what your battery percentage actually measures, why it is blind to the failure that takes your device down, what the real cutoff looks like on the bench, and what you can do about it. ## What your battery percentage actually measures Start with how that number gets made. Most coin-cell devices don’t have a dedicated fuel-gauge chip; it costs money and board space they don’t have. Instead the firmware reads the supply voltage through the SoC’s ADC (directly, or through a resistor divider) and maps that voltage to a percentage using a discharge curve. That percentage is what gets reported, often as a 0 to 100% Battery Level over the Bluetooth LE Battery Service, or pushed to your cloud as battery telemetry. Two things about that measurement decide everything that follows. First, it is a voltage reading taken at rest. The ADC conversion is a brief, low-current sample, and firmware almost always takes it between radio events, not in the middle of a transmit. So the reported number is built from the resting voltage, the same value a multimeter on the bench would show, and it never sees the dip that happens under load. Second, that percentage tracks the wrong physical quantity. It estimates energy remaining, and energy remaining is not what fails first. Your device browns out when the voltage sags under a current pulse, and how far it sags is set by the cell’s resistance, a separate property from its remaining charge. So even a more capable gauge that counts charge in and out (a coulomb counter, the kind you find in a phone and rarely on a coin cell) tracks energy more accurately and still misses the loaded-voltage margin that decides whether the next transmit browns out the chip. So whether your reported percentage is crude or precise, it is blind to the failure mode that takes the device down. To see why, let’s look at what the cell does under load. ## A coin cell is not a fuel tank The reason that resting reading misleads you sits in the battery itself. The intuition that gets people into trouble, the same one behind both a “2-year battery life” estimate and a battery-percentage gauge, treats the cell like a fuel tank: it holds X amount of energy, you burn it at some rate, and the device runs until the tank hits empty. A real battery doesn’t behave that way. A more accurate model is an ideal voltage source in series with a resistor, called the **internal resistance (ESR)** of the cell (you’ll also see it written as internal resistance or R\_int; Qoitech and capacitor datasheets tend to use “ESR,” for equivalent series resistance). The voltage you actually see at the terminals is: ``` V_terminal = OCV − (I × ESR) ``` where **OCV** is the open-circuit voltage (the voltage with no load) and **I** is the current you’re drawing. This is the standard Thevenin model of a cell, and it has two consequences that matter a lot for coin cells. First, the voltage measured with no load is the OCV. On a coin cell the OCV holds up well for most of the discharge and sags only gradually, and even deep into the cell’s life it stays above the chip’s minimum operating voltage. That is exactly the voltage your at-rest ADC sample reads, and it is why a resting reading almost always looks survivable, right up until the device stops working. Second, the term that actually bites is `I × ESR`, and **the ESR is not constant.** A fresh CR2032 has an internal resistance on the order of 10 Ω (Energizer’s datasheet plots it as a curve that starts around 5 to 15 Ω, not a single spec). As the cell discharges, that resistance climbs, and near end of life it climbs steeply. TI measured this climb directly in their [coin-cell application note](https://www.ti.com/lit/an/swra349/swra349.pdf?ref=novelbits.io) (SWRA349): the internal resistance sits in the 10 to 15 Ω range through mid-life, then spikes past 45 Ω toward end of life. The stock Energizer CR2032 profile I used on the bench carries that same curve further still, climbing past 100 Ω as the last of the capacity is used (it’s the curve plotted just below). So as the cell ages, every milliamp you draw costs more and more voltage. The OCV (what your gauge reads) looks fine. The loaded voltage (what the chip sees) is quietly collapsing. ![Internal resistance of a CR2032 versus capacity used: flat for most of life, then a steep hockey-stick climb near end of life.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/fig1-esr-vs-capacity-2.png) A CR2032’s internal resistance (ESR) stays low and roughly flat for most of its life, then climbs steeply near end of life, from about 9 Ω fresh to over 100 Ω when nearly empty. Source: Energizer CR2032 discharge profile (Qoitech battery library), consistent with TI SWRA349. ## Bluetooth LE is close to the worst-case load Bluetooth LE makes this problem sharper. It was designed to sip power by sleeping most of the time and waking for very short bursts to transmit or receive. That’s great for average current. It’s rough on a high-resistance cell. The reason: the cell doesn’t care about your average current during those bursts. It sees a short, tall **current pulse**. On an efficient part like the [Nordic nRF54L15](https://novelbits.io/nrf54l15-unboxing-first-impressions/), a 1 Mbps (LE 1M PHY) transmit at 0 dBm draws roughly 4 to 5 mA of total current at 3 V (Nordic’s system figure; the radio block alone is about 3.7 mA in the datasheet). On top of that, the on-chip DC/DC converter recharges its input in brief, higher current bursts, so the current drawn at the chip during a wake is spikier than the average suggests. On a real board, though, the fastest of those spikes come from the DC/DC converter switching, and the board’s decoupling capacitors supply them, not the cell. What the cell actually delivers is the smoother average of the transmit burst, and it’s that burst current, sustained over a few hundred microseconds to a couple of milliseconds, that sags a high-resistance cell. Now multiply that pulse by a rising internal resistance. A burst that was a non-event when the cell was fresh (a few milliamps across 10 Ω is a few tens of millivolts of droop) becomes a cliff when the same burst hits 100 Ω late in life. A quick illustrative example (round numbers; we’ll confirm them on the bench below): - Suppose late in life the internal resistance has climbed to about 90 Ω. - A transmit burst pulls a 15 mA pulse (the radio draw plus the converter’s input current during the burst, which runs above the 4 to 5 mA quoted earlier because a buck converter draws more input current as the rail sags toward end of life). - The droop during that pulse is 15 mA × 90 Ω = 1.35 V. - Starting from a resting 2.3 V, the rail the chip actually sees during the burst is 2.3 − 1.35 = about 0.95 V. That 0.95 V is the number that decides whether your device lives. And it shows up only during the burst, for a few hundred microseconds, which is exactly the moment your at-rest battery reading skips over. ## The cliff: where the chip gives up Every Bluetooth LE chip has a voltage floor, and crossing it briefly is enough to take the device down. For the Nordic nRF54L15, the numbers (from the [datasheet](https://docs.nordicsemi.com/r/bundle/ps%5Fnrf54l15/page/chapters/recommended%5Fop%5Fconditions.moonlight/doc/recommended%5Fop%5Fconditions.html?ref=novelbits.io)) are: - **Operating supply range:** 1.7 V to 3.6 V. - **Brown-out reset (while running):** the chip resets when VDD falls into roughly the [**1.57 V to 1.64 V**](https://docs.nordicsemi.com/r/bundle/ps%5Fnrf54l15/page/%5Ftmp/nrf54l15/autodita/regulators/parameters.power%5Ffail.html?ref=novelbits.io) band (specified as a range, not a single value). - **Clean power-on restart:** needs about **1.75 V** at VDD. - **Power-fail comparator (POF):** a configurable early-warning threshold you can set anywhere from **1.7 V to 3.2 V** in 100 mV steps. Let’s put the two halves together. The illustrative 0.95 V burst-time rail from the last section is well under the 1.57 to 1.64 V brown-out band. The chip resets. When it tries to come back up, it needs 1.75 V to restart cleanly, but the next transmit burst drags it down again. You get a device that boots, transmits, browns out, and reboots, over and over, while its own battery reading, taken at rest, still reports a voltage well above the 1.7 V floor. One more useful detail: the nRF54L15 runs the whole radio off a single VDD rail (1.7 to 3.6 V) with a single-inductor DC/DC converter, and there’s no separate higher-voltage requirement for higher transmit power. So the failure here is purely the loaded-voltage droop, not a “you need more volts for more dBm” effect. ## What this looks like on the bench That is the arithmetic. Here is the same failure on real silicon. I built a rig that swaps the coin cell for two instruments: one that can fake a depleting cell, and one that can watch the rail sag under load. ![Measurement rig: a Qoitech Otii Ace battery emulator feeds a Joulescope JS320 in-line ammeter into an nRF54L15-DK, which runs the real firmware and browns out.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/fig0-measurement-rig-1.png) The bench rig: a Qoitech Otii Ace emulates a depleting CR2032 and sags the rail under load, a Joulescope JS320 sits in line as the ammeter, and the supply feeds an nRF54L15-DK at its current-tap header so the real firmware browns out for real. Device images courtesy of Qoitech, Joulescope, and Nordic Semiconductor. The **battery emulator** is the piece that makes this honest. Per Qoitech, the “[Otii Battery Toolbox](https://www.qoitech.com/battery-toolbox/?ref=novelbits.io)emulates the total ESR,” and it “will adjust the output voltage depending on the load, just like a real battery with internal resistance.” So it can hold a chosen state of charge and sag the rail under load the way an aging cell would, which a bench power supply (a stiff, ideal source) simply cannot do. A lab supply would happily hold a perfect rail, and you would never see the failure. One caveat on reading the traces that follow: the millisecond-scale sag is the emulator faithfully doing its job, reproducing the cell’s rising end-of-life resistance under load. The finer sub-millisecond wiggles are the emulator’s own regulation and the test leads, not real cell behavior, so read the envelope, not the fuzz. The **measurement matters**, too, though for a subtler reason than raw speed. The current signal lives in two places at once: a sleep current down in the microamps, and a transmit burst up in the milliamps. What you want is an instrument that holds both in one trace without averaging the burst into a harmless-looking number. The Otii Ace is itself a source-measure unit, reading current and voltage across that whole range while it sources, so it can carry this on its own. In my rig a [Joulescope JS320](https://www.joulescope.com/products/js320?ref=novelbits.io) sits in line as the ammeter, because it is the instrument my bench and analysis tooling are built around, not because the emulator falls short as a meter. One clarification is worth making, because it is easy to get wrong: the brown-out itself is a voltage event, and a relatively slow one. The sag that trips the chip plays out over hundreds of microseconds to a couple of milliseconds, set by the average current of the transmit burst against the cell’s resistance, so a modest sample rate captures it perfectly well. The very fastest current spikes, the sub-microsecond ones from the DC/DC converter, are absorbed by the board’s decoupling capacitors and never reach the cell. So the high-speed current trace is not what reveals the brown-out. The rail voltage is, and you can see that sag without a fast meter. Then I swept the emulated state of charge from full down toward empty and watched two voltages at once: the **resting voltage**(what your battery gauge would read) and the **worst transmit-time dip** (what the chip actually sees): - **100%, 50%, 20% state of charge:** clean. The device advertised normally and the worst transmit-time dips stayed well above the floor (3.13 V, 2.84 V, 2.57 V respectively). - **About 10%:** still clean, but the margin is shrinking: the cell rests at 2.60 V and the worst dip is down to 2.25 V. - **About 5%, the edge:** the cell rests at 2.43 V, comfortably above the 1.7 V minimum, so an at-rest reading says fine. But the worst transmit-time dip reached 1.80 V, just above the brown-out band. - **About 4%:** the cell rests at 2.37 V, yet the worst dips hit 1.66 V, right at the top of the 1.57 to 1.64 V band, and intermittent resets started appearing. - **About 3%:** the cell still rests at 2.29 V, well above the 1.7 V floor, but the worst dips crashed to 0.95 V, far below the band. Confirmed reset-cycling: the device was rebooting on its transmit bursts. This is the gap in one place. At 3% state of charge, a battery gauge sampling the rail at rest reads about 2.29 V and reports a device that is alive and has voltage to spare. The chip, hit by a transmit burst at that same moment, sees 0.95 V and resets. Same battery, same instant, two completely different stories, and the reported number is telling you the wrong one. There’s an irony in that gap. The Bluetooth LE Battery Service spec defines Battery Level 0% as the point where the battery is “unable to power the device.” By that definition the cell at 3% has already hit 0%: it can no longer carry the chip through a transmit without browning it out. A voltage-based percentage just doesn’t see it, because it reads the rail at rest, while the spec’s own definition of empty is about whether the device can actually run. The tell wasn’t the average current, either. During reset-cycling the average current actually reads *higher*, not lower, because the chip keeps waking to pay the reboot inrush instead of sleeping between advertisements. So an “average current” view makes a dying device look busy and healthy. Judge “alive” by whether the device is still doing its job, not by a resting voltage and not by how much current it’s drawing. One honest caveat: the exact percentage where this happens is not a universal constant. It depends on the specific cell’s resistance curve and on your device’s pulse profile. The profile I used is the stock published Energizer CR2032 model, not one I aged or edited, and its end-of-life resistance climbs past 85 Ω, so treat the single-digit numbers above as “this is the shape of the failure,” not “every CR2032 dies at exactly 3%.” The point that holds for every coin cell is the one in the intro: the device stops working before the cell is empty, and no resting battery reading sees it coming. ![Loaded voltage versus state of charge: the resting voltage stays above 2.2 V while the worst transmit-burst dip falls off a cliff and crosses the brown-out band at single-digit state of charge.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/fig2-loaded-voltage-vs-soc-3.png) What your gauge reads versus what the chip sees. The resting voltage (the value an at-rest ADC sample reports) stays comfortably above the chip’s 1.7 V floor for the whole sweep, but the worst transmit-burst dip falls off a cliff and crosses the nRF54L15 brown-out band (1.57 to 1.64 V) at around 4 to 5% state of charge. Source: bench capture, Otii Ace (stock CR2032 profile) plus Joulescope JS320 plus nRF54L15-DK. That chart traces the trend across state of charge. Here is the same story as a live current-and-voltage trace, healthy at full charge and browning out at 3%: ![Current and voltage waveforms at 100% and 3% state of charge: at full charge the chip sleeps and the rail holds steady; at 3% the transmit bursts crash the rail through the brown-out band and the chip reset-cycles.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/fig-brownout-current-voltage.png) Current and rail voltage on one 1 MS/s timeline, healthy (100%) versus brown-out (3%). At 3% the transmit bursts drag the rail through the brown-out band, to 1.09 V in this capture. The brown-out is the sag envelope, which shows up at any modest sample rate; the high-speed timeline is here to show the current pulse driving it, not because you need that speed to catch the dip. Dip depth varies run to run (the sweep above reached 0.95 V); both sit well below the band. Source: Otii Ace (stock CR2032 profile), Joulescope JS320, nRF54L15-DK. ## So when does the battery “really” die? The reframe is this: for a pulsed Bluetooth LE load on a coin cell, end of life is the moment the transmit-time droop first crosses the chip’s brown-out band, and that moment arrives with meaningful capacity still sitting in the cell. In my run that moment arrived around 4 to 5% state of charge, with the cell still resting above 2.3 V. Your **usable** capacity is smaller than your **rated** capacity, and the gap is set by your transmit-burst current times the cell’s end-of-life resistance. The bigger your bursts and the higher the cell’s late-life resistance, the more capacity you leave stranded. That’s the energy you never get to use, and it’s why both dividing rated mAh by average current and trusting a resting battery percentage overestimate how long the device keeps working. Here is why that reframe is worth the trouble. Once you know the device quits at the brown-out cliff and not at empty, three things change for you as the developer. The battery-life number on your box becomes one you can defend, because you sized it against usable capacity instead of the headline mAh. You can reproduce the failure on your own bench, on purpose, before a customer hits it in the field as a mystery reset. And you know which lever to pull: the fix is to hold the loaded voltage up during the burst and to warn on the right signal, not to chase a phantom firmware bug or trust a battery percentage that can’t see the cliff. ## A brown-out costs more than a reset Watching the device reboot makes a brown-out look like a recoverable nuisance. Often it isn’t, and the reset is the least of what it does. The one that should worry you most is a brown-out that lands in the middle of a flash write. A reboot is recoverable; a half-finished write to non-volatile memory is not. If the rail collapses while your firmware is saving bonding keys, a settings change, or a log entry, you can corrupt that data or leave the device stuck in a bad state. This is the real reason the chip carries a power-fail comparator (POF): it lets you stop and shed load before the rail reaches the brown-out band, instead of finding out about the damage after the next reset. The failure also feeds itself. Reset-cycling keeps the chip awake and drawing far more current than it would asleep, so it runs through the sliver of capacity that’s left much faster than a sleeping device would. The more it browns out, the quicker it drives the cell toward the steep end of the resistance curve, where it browns out more easily still. If your product holds a connection instead of just advertising, there’s one more cost. Each reset drops the Bluetooth LE connection, the link falls over on a supervision timeout and the device has to reconnect, and anything kept only in RAM (counters, buffered samples, session state) is lost every time. ## What you can do about it The good news: this is a well-understood problem with known fixes. Let’s go through the ones that matter most: - **Add a reservoir capacitor across the cell.** This is the single highest-leverage fix. A capacitor in parallel with the coin cell supplies the transmit pulse, so the cell only has to deliver the average current and recharge the cap slowly between bursts. TI’s coin-cell app note found this can recover more than 40% of usable capacity on poor-quality cells, and a real Bluetooth LE design typically needs something in the tens of microfarads (roughly 20 to 50 µF), not a huge bank. - **Bring down the transmit-burst current** where your link budget allows, by reducing transmit power or [sending fewer/shorter events](https://novelbits.io/ble-connection-intervals/). [Minimizing average current](https://novelbits.io/ble-power-consumption-optimization/) still matters most for total runtime, but the burst current is what sets the brown-out cliff. - **Warn on the power-fail comparator (POF), not on a battery percentage.** Set the POF above the brown-out band so the device gets a warning interrupt and can shed load (skip a transmit, drop to a safe state, flag low battery) before it resets. The POF watches the actual rail; a reported percentage derived from a resting sample does not, so it is the POF, not the percentage, that should drive your low-battery behavior. Just don’t mistake it for a fuel gauge: the POF is a comparator that fires a single warning when the rail crosses a threshold you set, an end-of-life alarm you act on, not a continuous read of how much runtime is left. It also has to be enabled in firmware; it is off by default. - **Don’t trust a rest-voltage percentage as your field health signal.** If you report battery level over the Bluetooth LE Battery Service or to a dashboard, understand that it tracks energy at rest, not the loaded-voltage margin that fails first. Treat a falling level as “schedule a replacement,” never as “the device is still operating fine until this hits zero.” - **Derate usable capacity in your battery-life math.**Don’t divide the full rated mAh by your average current. Assume you lose the last chunk to rising resistance, and size accordingly. - **Pick cells by their behavior under load,** not just by the headline mAh. Two cells with the same rated capacity can have very different late-life resistance. ## How to see it before your customer does Fixing this is the easy part. Seeing it during development is the hard part, because a bench power supply will happily hold a perfect rail right up until the moment you’d never reach in the field, and your device’s own battery reading will agree with it. You need to reproduce a depleting, high-resistance cell. There are two ways to get there. The first is **hardware in the loop**: a battery emulator that replays a real cell’s discharge and resistance curves and physically makes your board brown out, the way the [Otii rig](https://www.qoitech.com/otii-ace/?ref=novelbits.io) above did. This is the most convincing because your actual firmware actually resets, which surfaces the real failure modes (brown-out handlers, capacitor sizing, the POF configuration, and whatever your battery-level reporting does as the rail sags). The second is **projection from a measurement**: take a measured current trace of your device and combine it with a cell’s published resistance-vs-capacity curve to compute the loaded-voltage dip and the runtime, before you ever wire up an emulator. Because the cell models are public data (Qoitech, for example, publishes a [library of battery profiles](https://github.com/qoitech/otii-battery-profiles?ref=novelbits.io) as plain files), this kind of projection can live in software. That second path is the one we’re building toward in **PowerScope**, our power-profiling extension for VS Code (coming soon). The premise is to profile power where you already write firmware, so it happens continuously as you develop, not once in a while on a lab bench. Most power tools hand you a current trace and leave you to work out which part of your firmware caused each spike. PowerScope does the reverse: it lines each current pulse up against the Bluetooth LE event behind it, so you can see which advertising or connection event actually spent the energy, and how much. It runs off the affordable meters already on your bench, the [Nordic Power Profiler Kit II](https://www.nordicsemi.com/Products/Development-hardware/Power-Profiler-Kit-2?ref=novelbits.io) or a Joulescope, not a rack of lab instruments. The piece still in progress is the projection: take that same capture, lay it over a published cell model, and read off a defensible battery-life number and an honest brown-out warning, without re-wiring the bench for every what-if. The aim is to turn the bench exercise above into something you run on every build, so a power regression gets caught the same way a failing test would. It is not out yet, but it is coming soon; until it ships, the bench work in this post is how you get there today. Both get you to the same place: a battery-life claim, and a battery-level report, that survive contact with a real coin cell. ## Summary Let’s recap what we covered: - The battery level your device reports is a voltage reading taken at rest, and it estimates energy remaining. Your device browns out under load, when the voltage sags, so the reported percentage is blind to the failure that takes it down. - A coin cell is not a fuel tank. Its terminal voltage under load is `OCV − (I × ESR)`, and the **internal resistance (ESR)** rises steeply near end of life. - Bluetooth LE draws short, tall current pulses, and those pulses hitting a rising resistance cause a large transmit-time voltage droop, even while the resting voltage looks fine. - A chip like the nRF54L15 brown-out-resets around 1.57 to 1.64 V, so a single deep droop can take the device down and trigger reset-cycling. On the bench, an emulated CR2032 drove an nRF54L15 into reset-cycling at single-digit state of charge (around 3 to 5%), while the resting voltage still read above 2.2 V. - The fixes are a reservoir capacitor, lower transmit-burst current, warning on the power-fail comparator instead of the battery percentage, honest capacity derating, and picking cells by their behavior under load. With this, you can size your next coin-cell product around the capacity you can actually use, report a battery level you can trust, and catch the brown-out cliff on your bench instead of in the field. ![Mohammad Afaneh, Novel Bits](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/size/w300/2025/11/MAfaneh_Enhanced_Photo.jpg) Bluetooth LE Power & Battery-Life Consulting I help product teams measure real current draw, diagnose brown-outs, and turn battery-life claims into defensible, bench-verified numbers. [Get in touch →](https://novelbits.io/consulting/) ### Hands-On with the nRF54L15 Tag: Dual-Antenna Channel Sounding in a Coin-Cell Package URL: https://novelbits.io/nrf54l15-tag-channel-sounding/ Last updated: 2026-06-25T12:36:09.000Z Bluetooth Channel Sounding is having a moment. Devices like Google’s Pixel 10 and Pixel Watch 4 can do it today, Apple is bringing it to iPhone, and the question I keep hearing from developers is a practical one: what hardware do I actually prototype with? Nordic Semiconductor’s answer is the **nRF54L15 Tag**. It’s a 33 mm, coin-cell-powered tag that puts the ultra-low-power nRF54L15 SoC on a tiny round board, with one feature you won’t find on a standard development kit: two antennas. That second antenna is the whole story. It’s what makes the Tag the first Nordic board you can use to prototype multi-antenna Channel Sounding designs for trackers and asset tags. In this post, and in the [walkthrough video](#watch-the-hands-on-demo), I’ll unbox the Tag, walk through what’s on the board, flash it with Channel Sounding Reflector firmware, and range against it from an Android phone, with an early look at the iPhone path on iOS 27 too, all from a single firmware build. Let’s take a closer look. ## Watch the hands-on demo ## What’s in the box The kit is about as minimal as it gets: the Tag itself, a CR2032 coin-cell battery, and a small intro card. That’s intentional. The Tag is a **prototyping platform**, not a finished product, and the whole design is optimized to stay small and cost-effective. ![Back of the Tag with the CR2032 installed](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/tag-back.jpg) The back of the Tag with the CR2032 coin cell installed, alongside the Nordic branding and the debug header on the right edge. To power it up, you pull the isolator tab that separates the battery from the contacts. The RGB LED starts blinking, which tells you the Tag is running its preprogrammed firmware: the Peripheral LBS (LED Button Service) sample. If you open [nRF Toolbox](https://www.nordicsemi.com/Products/Development-tools/nRF-Toolbox?ref=novelbits.io) on your phone and scan, you’ll see it advertising as “Nordic\_LBS,” and toggling the button in the app changes the LED color on the Tag. One thing to note: that out-of-the-box LBS firmware isn’t power-optimized. It’s there so you can confirm the Tag works before you flash it with something else. ## A tour of the board The Tag packs a surprising amount onto a 33 mm circle. Let’s go through what’s on it. ![Front of the nRF54L15 Tag](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/tag-front.jpg) The front of the nRF54L15 Tag: the nRF54L15 SoC at center, the two 2.4 GHz antennas (ANT1 and ANT2), the onboard sensors, the RGB LED and user button, and labeled GPIO pads. At the center is the [**nRF54L15 SoC**](https://www.nordicsemi.com/Products/nRF54L15?ref=novelbits.io), Nordic’s ultra-low-power multiprotocol wireless chip. It has 1.5 MB of non-volatile memory and 256 kB of RAM, which is a lot of headroom for a coin-cell device, and a next-generation 2.4 GHz radio. On the protocol side, it supports Bluetooth LE, Bluetooth Channel Sounding, Bluetooth Mesh, Matter, Thread, Zigbee, NFC, and 2.4 GHz proprietary, so you’re not locked into a single ecosystem. Around the SoC, you’ll find three sensors, each chosen for a specific job: - **A Bosch BMI270 six-axis inertial measurement unit (IMU)**, combining a high-accuracy accelerometer and gyroscope. This is the sensor you’d use for motion tracking, gesture recognition, and collecting training data for edge AI. - **An Analog Devices ADXL367 low-power accelerometer**, whose job is to wake the Tag from deep sleep when it detects motion. That’s a key trick for battery life: the Tag can sleep most of the time and only spin up when something actually moves. - **A Bosch BME688 environmental sensor**, which measures temperature, humidity, air pressure, and gas. This is what makes the Tag useful for smart-home and Matter applications. You also get a user-programmable RGB LED and a user button, plus exposed GPIO and footprints for adding your own components: a second button, a reset button, a buzzer, or external memory. Those parts are left unpopulated to keep the kit cost-effective, but the pads are there if you want to expand. And then there are the **two 2.4 GHz chip antennas** and an RF switch. This is the headline feature, and we’ll dig into why it matters shortly. What you won’t find is an onboard debugger, which is part of how the board stays this small. To program and debug the Tag, you have two options: - Plug it into the DEBUG OUT port of an nRF54L Series or nRF91 Series development kit. - Use a SEGGER J-Link debugger with SEGGER’s 10-pin Needle Adapter, which connects directly to the Tag’s 10-pin SWD footprint. One detail that tripped me up at first: when you dock the Tag into a development kit, the kit doesn’t power it by default. Keep the CR2032 in place (or supply 3.3 V through the kit, but never both at the same time, since that can damage the board). If you want to go deeper on the hardware, Nordic publishes the Tag’s full design package, schematics, PCB layout, and bill of materials (BoM), on the [nRF54L15 Tag Downloads page](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-Tag/Downloads?lang=en&ref=novelbits.io#infotabs). It’s a useful reference whether you want to design your own Channel Sounding tag or just check how this one is put together. ## Where the Tag fits Before we get into Channel Sounding specifically, it’s worth framing what this board is for. The Tag is built for prototyping small, battery-powered wireless products: trackers, asset tags, key fobs, smart rings, beacons, and remote controls. Anything where size and battery life matter, and where the device might want to know how far away it is from something. A good real-world reference point is [Chipolo](https://chipolo.net/?ref=novelbits.io), whose Bluetooth trackers Nordic cites as built on the nRF54L15 SoC. The Tag is essentially the platform you’d reach for to prototype a product in that class. Because the nRF54L15 is multiprotocol, the same board also covers two other areas: edge AI (using the IMU) and Matter smart-home devices (using the environmental sensor). We’ll touch on the samples for those later. ## A quick Channel Sounding refresher Let’s step back for a minute and cover what Channel Sounding does, because the dual-antenna story only makes sense once that’s clear. Channel Sounding measures the distance between two Bluetooth LE devices. One device acts as the **Initiator** (typically a phone), and the other acts as the **Reflector** (typically a small embedded device like a tag). The Initiator sends a series of tones, the Reflector sends them back, and the Initiator works out the distance from how the signal’s phase and amplitude change across the channels of the 2.4 GHz band. This is called phase-based ranging. The reason this matters is that it’s a direct measurement, not a guess. In the past, you might have used signal strength (RSSI) to guess at distance, but RSSI is easily thrown off by interference and obstacles. Channel Sounding measures distance directly, and in practice it can reach sub-meter accuracy. The Reflector role is the natural fit for a tag. Reflectors typically do less of the heavy lifting than Initiators, which usually run the ranging algorithm, so they tend to need less processing power. That keeps a battery-operated, pocket-sized device efficient and long-lived, which is exactly the kind of device the Tag is built to model. I covered the fundamentals in two earlier posts, so I won’t re-tread all of that here. If you want the deeper background, start with these: - [Introduction to Channel Sounding](https://novelbits.io/introduction-to-channel-sounding/) - [Bluetooth Channel Sounding Applications](https://novelbits.io/bluetooth-channel-sounding-applications-nrf54l15/) What those posts didn’t dig into is the second antenna, and that’s exactly what the Tag is built to explore. ## Why two antennas matter In the real world, a radio signal rarely travels in a clean straight line. It bounces off walls, furniture, and people, so the Reflector hears a mix of the direct path and a collection of reflections arriving slightly later. That multipath is the enemy of an accurate distance estimate, because the algorithm has to separate the signal that took the direct route from everything that bounced around to get there. This is where the second antenna earns its place. With two antennas and an RF switch, the Tag can sample the incoming signal across more than one antenna path. That gives a ranging algorithm more information to work with, which improves the robustness and stability of the distance measurement, especially indoors where a clean line-of-sight path isn’t guaranteed. There are really two payoffs here. - **Robustness.** More than one antenna path means the algorithm is less likely to be fooled by a strong reflection, so your distance numbers hold up better in a cluttered room. - **More advanced ranging.** With multiple antennas available, Find Hub’s Precision Finding can take advantage of both of them when you’re locating a nearby device, though that’s still an emerging capability on the platform side. And for your own designs, the Tag gives you a place to develop and test multi-antenna ranging algorithms before you commit to building custom hardware. That last point is the real reason the Tag exists. Up to now, if you wanted to experiment with multiple antenna paths for Channel Sounding on Nordic silicon, you didn’t have an off-the-shelf board to do it on. The Tag is that board. ## Getting started: flashing the Channel Sounding Reflector Let’s get the Tag running as a Channel Sounding Reflector and range it from an Android phone. Here’s what you’ll need: - The nRF54L15 Tag plus its CR2032 battery - An nRF54L Series or nRF91 Series development kit (or a J-Link), plus a USB-C cable - [nRF Connect for VS Code](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-VS-Code?ref=novelbits.io) with [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK?ref=novelbits.io) (NCS) v3.3.0 or newer - A Channel Sounding-capable Android phone (such as the Google Pixel 10) with [nRF Toolbox](https://www.nordicsemi.com/Products/Development-tools/nRF-Toolbox?ref=novelbits.io) installed, to range against the reflector In the nRF Connect for VS Code extension, the build is a handful of steps: 1. **Create a new application** from the [**Bluetooth LE Channel Sounding Reflector with Ranging Responder**](https://nrfconnectdocs.nordicsemi.com/ncs/latest/nrf/samples/bluetooth/channel%5Fsounding/ras%5Freflector/README.html?ref=novelbits.io)sample. Ranging Responder (RRSP) is the role the Tag plays in the Ranging Profile: it serves the ranging data over the GATT-based Ranging Service (RAS) so the phone can collect what it needs. 2. **Set the board target** to `nrf54l15tag/nrf54l15/cpuapp` so the firmware is built for the Tag, not a development kit. 3. **Add the `android_ranging.conf` Kconfig fragment** (under Extra Kconfig fragments in the build configuration). Nordic ships this as the configuration required for Android 16 ranging: it makes the reflector bondable (Android ranging needs a bond, and the base sample isn’t) and sets the maximum antenna paths to two. Without it, the Tag won’t pair and the phone won’t range. See Nordic’s [Building for testing with Android 16 ranging module](https://nrfconnectdocs.nordicsemi.com/ncs/latest/nrf/samples/bluetooth/channel%5Fsounding/ras%5Freflector/README.html?ref=novelbits.io#building-for-testing-with-android-16-ranging-module) instructions. The Tag’s antenna-switch devicetree overlay already ships in the sample’s board files, so that part is applied automatically once you pick the Tag board target. 4. **Build the sample.** 5. **Dock the Tag** into your development kit’s DEBUG OUT port (powered by the CR2032) and **flash it** the same way you’d program the SoC on the kit itself. ![Tag docked into an nRF54L15 DK](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/06/tag-debug.jpg) The Tag docked into an nRF54L15 DK’s DEBUG OUT header for programming and debugging. Once it’s flashed, you can detach the Tag and confirm it’s running. Open nRF Toolbox and you should see the Tag advertising as a Channel Sounding Reflector, ready to range against an Initiator. That’s it. The Tag is now a Channel Sounding Reflector, ready to range against an Initiator. If you want to update the firmware later without docking the Tag again, you can also build the sample with Over-the-Air Device Firmware Update (OTA DFU) support, which lets you push new firmware to the Tag straight from your phone. ## What else you can build with the Tag The Channel Sounding Reflector is one starting point, but several other nRF Connect SDK samples list the Tag as a supported target. A few worth knowing about: - **Bluetooth Fast Pair: Locator tag.** This is a Google Find Hub-compatible tracker, and it’s the natural next step if you’re building a Find My-style device. It’s also where the dual antennas pay off, since Find Hub’s Precision Finding can take advantage of them. - **Edge AI gesture recognition.** From Nordic’s Edge AI Add-on for nRF Connect SDK, this sample uses the Tag’s BMI270 IMU to recognize gestures like swiping, shaking, tapping, and rotating, all with an on-device machine learning model. It’s a good showcase of running edge AI on a coin-cell device. - **Matter weather station.** This one turns the BME688 environmental sensor into a Matter accessory that periodically measures temperature, air pressure, and humidity, which you can then read from a Matter controller. Each of these targets the same `nrf54l15tag/nrf54l15/cpuapp` board, so they’re a quick way to spin up a proof of concept across Find My, edge AI, and Matter from a single piece of hardware. That flexibility is a big part of the Tag’s appeal: one small board, several very different demos. ## Testing Channel Sounding from a phone The fun part is seeing real distance numbers come back, and you don’t need a lab bench to do it. A Channel Sounding-capable Android phone, like the Google Pixel 10, can act as the Initiator and range against the Tag directly. With the Tag running the Reflector firmware and nRF Toolbox installed on the phone, you connect to the Tag and watch the distance update as you move it around the room. It’s a genuinely satisfying demo, and it’s the clearest way to show what Channel Sounding really is: the phone isn’t guessing from signal strength, it’s measuring the signal itself to work out how far away the Tag is. This is also where you start to appreciate the dual-antenna design. Ranging that holds steady as you walk around a furnished room, rather than jumping around, is exactly the kind of robustness those two antennas are there to provide. I’ll walk through the phone-side setup step by step in the [walkthrough video](#watch-the-hands-on-demo). ## Ranging from an iPhone, too (iOS 27 beta) The Tag ranges against Android today. The question I really wanted to answer was whether the same Tag could range against an iPhone. As of iOS 27, Apple has added Channel Sounding to iPhone, introduced at WWDC 2026 in the session [Find your accessory with Bluetooth Channel Sounding](https://developer.apple.com/videos/play/wwdc2026/369/?ref=novelbits.io). The APIs live in both Core Bluetooth and NearbyInteraction, and the hardware requirement is an iPhone with Apple’s N1 networking chip, which means the iPhone 17 family. The N1 brings Bluetooth 6 to the iPhone, and Channel Sounding is a Bluetooth 6 feature. iOS 27 is still in beta. Earlier betas were not returning ranging results at all; building a small app against the NearbyInteraction Channel Sounding configuration on an iPhone 17, the APIs now do hand back distance values, which is real progress. The accuracy isn’t there yet, though: at close range the readings come back several meters high and noisy, the signature of coarse round-trip timing rather than precise phase-based ranging. So treat the iPhone side as a promising preview, not a precise measurement, and expect it to tighten as iOS 27 matures. (This is my own testing on a beta OS, not a Nordic-validated result, and it is distance only.) The interesting part was what it took to make one Tag talk to both phones, because the two platforms ask for different things on the wire. The Reflector firmware we flashed earlier hands its ranging data to the phone over a normal Bluetooth LE connection, through a GATT service called the Ranging Service (RAS). That is the path an Android phone like the Pixel 10 uses: it reads the raw measurements off the Tag and computes the distance itself. The iPhone expects Inline PCT Transfer (IPT) instead, a Channel Sounding feature defined in the Bluetooth Core Specification, where the Reflector folds its contribution into the radio tones themselves rather than relaying it over GATT, so the phone works out the distance from the signal alone. Inline PCT was added in Bluetooth 6.3, so the iPhone path specifically requires Bluetooth 6.3 and Inline PCT. Nordic ships these as two separate samples: a RAS reflector for Android, and an Inline PCT reflector for iPhone. But the spec treats Inline PCT as an optional, negotiated capability, which means one reflector is allowed to serve both an IPT iPhone and a RAS Android initiator. So I combined them into a single firmware image: it advertises the Ranging Service for Android and the Inline PCT pairing service for iPhone, holds a bond for each phone at the same time, and runs Channel Sounding with both from one Tag. That is the interoperability story: one coin-cell Tag that pairs and exchanges Channel Sounding with a Pixel and an iPhone off a single build. The Android side is accurate today; the iPhone side, as noted above, returns results but is still rough in this beta. One note on antennas: the iPhone negotiates a single antenna path, so the combined image runs single-antenna. The dual-antenna advantage from earlier still applies on the Android RAS path, where the initiator can take both paths. ## Setting up Channel Sounding on iOS If you want to range against the Tag from your own iOS app, the NearbyInteraction path is compact. Here are the pieces that matter. First, confirm the device can do Channel Sounding. It needs an iPhone 17 (N1) on iOS 27: ```swift let caps = NISession.deviceCapabilities guard caps.supportsBluetoothChannelSounding else { // No N1 / not on iOS 27: Channel Sounding is unavailable. return } ``` Next, pair with the Tag using AccessorySetupKit, which presents the system pairing sheet and discovers the reflector by the service UUID it advertises: ```swift let descriptor = ASDiscoveryDescriptor() descriptor.bluetoothServiceUUID = CBUUID(string: reflectorServiceUUID) descriptor.supportedOptions = [.bluetoothPairingLE] // pair and bond over Bluetooth LE let item = ASPickerDisplayItem(name: "Nordic CS Tag", productImage: image, descriptor: descriptor) session.showPicker(for: [item]) { error in // handle picker errors } ``` The bond itself is triggered when iOS reads an encryption-protected characteristic on the Tag, which is why the reflector firmware exposes a tiny characteristic that requires encryption to read. That read is what makes iOS start Bluetooth LE Secure Connections pairing. With the Tag paired, create a NearbyInteraction session configured for Channel Sounding. The key is `NINearbyAccessoryConfiguration(bluetoothChannelSoundingIdentifier:)`, which takes the paired peripheral’s identifier: ```swift let config = NINearbyAccessoryConfiguration( bluetoothChannelSoundingIdentifier: peripheralID, previousBluetoothIdentifier: nil) let session = NISession() session.delegate = self session.run(config) ``` Finally, the distance arrives in the session delegate on each update: ```swift func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject]) { for obj in nearbyObjects { if let meters = obj.distance { // meters is the live Channel Sounding distance to the Tag. } } } ``` From there, the NearbyInteraction session delivers distance updates to your delegate as the devices move, and you surface them in the UI. ## Wrapping up In this post, we covered a lot of ground with a very small board. We: - Unboxed the nRF54L15 Tag and toured everything packed onto its 33 mm body - Framed where the Tag fits: prototyping trackers, asset tags, and other compact battery-powered products - Looked at why its two antennas matter for robust Channel Sounding when line-of-sight isn’t guaranteed - Flashed it as a Channel Sounding Reflector and ranged against it from a Pixel over the Ranging Service - Combined the RAS and Inline PCT paths into one firmware image so the same Tag also pairs with an iPhone 17 on iOS 27 beta and returns ranging results through a small NearbyInteraction app (iPhone-side accuracy still maturing) - Walked through the other Find My, edge AI, and Matter samples you can build with it With this, you should have a clear picture of where the Tag fits: it’s a compact, battery-powered platform for prototyping multi-antenna Channel Sounding trackers, with accurate ranging from an Android phone today and an early iPhone path opening up on iOS 27. If you end up building something with it, I’d genuinely like to hear what you make. ## Resources - [nRF54L15 Tag product page](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-Tag?ref=novelbits.io) - [nRF54L15 Tag hardware design files: schematics, layout, BoM](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-Tag/Downloads?lang=en&ref=novelbits.io#infotabs) - [nRF54L15 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK?ref=novelbits.io) - [Bluetooth LE Channel Sounding Reflector with Ranging Responder sample](https://nrfconnectdocs.nordicsemi.com/ncs/latest/nrf/samples/bluetooth/channel%5Fsounding/ras%5Freflector/README.html?ref=novelbits.io) - [Nordic Channel Sounding solutions](https://www.nordicsemi.com/Products/Wireless/Bluetooth-Low-Energy/Channel-Sounding?ref=novelbits.io) ### Nordic Axon NPU Development Guide: Edge AI and Bluetooth LE on the nRF54LM20B URL: https://novelbits.io/nordic-axon-voice-workout-tracker/ Last updated: 2026-08-07T02:04:15.000Z *Sponsored by* [*Nordic Semiconductor*](https://www.nordicsemi.com/?ref=novelbits.io)*.* You walk up to your bench with both hands full, look at a small Nordic Development Kit on the table, and say, *“Okay Nordic, Go.”* A second later your phone fires a notification: your workout has started. You do your set, say *“Okay Nordic, Stop,”* then *“Yes,”* and the phone confirms the workout was saved. No taps, no cloud, no internet. That’s what we’re going to build in this post: a hands-free voice-controlled workout tracker running entirely on a Nordic **nRF54LM20 Development Kit**, talking to a phone over [Bluetooth LE](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/). The brain of the demo is Nordic’s [**Axon NPU**](https://www.nordicsemi.com/Products/Technologies/Edge-AI/Axon-NPU?ref=novelbits.io) (Neural Processing Unit), a hardware accelerator on the **nRF54LM20B** SoC that brings always-on short-vocabulary speech recognition into the sub-1-mA range. The wakeword model and the 10-keyword spotter we use are both pre-trained and pre-compiled by Nordic, so we’ll spend our time on the firmware that sits on top: a small [Bluetooth LE GATT service](https://novelbits.io/bluetooth-gatt-services-characteristics/) driving a workout state machine that pushes notifications to the phone in real time. In this post we’ll cover what the Axon NPU is and how it differs from Nordic’s Neuton framework, the hardware and toolchain you need, the Voice Workout demo end-to-end (state machine, three Bluetooth LE notify characteristics), the firmware sitting on top of Nordic’s bundled wakeword + KWS sample, a measured power profile of the listening loop on real hardware, and where to go next with Nordic’s Edge AI Lab. By the end, you should be able to take the companion code, flash it to your own DK, connect from the nRF Connect Mobile app, and have the demo working in front of you in roughly fifteen minutes. 🎬**Prefer to watch?** [Jump to the \~7-minute video walkthrough](#demo-video) in Section 3 — hardware setup, pairing, and three live demo scenarios. Keep reading for the firmware design, GATT service implementation, and the measured power profile. The category this fits into is **Edge AI**: running machine learning algorithms directly on embedded devices like microcontrollers and low-power SoCs, rather than calling out to a cloud service. Per Nordic’s framing, running models on-device lets you: - **Reduce cloud connectivity and latency** by making real-time decisions locally. - **Improve privacy and reliability** by keeping raw sensor data on the device. - **Reduce operational cost and power usage** by transmitting only compact results or events. The Voice Workout demo hits all three: the wakeword and KWS networks run on the Axon NPU (no cloud, no internet), the only thing leaving the device is a few bytes of Bluetooth LE notifications per detection, and Section 7 measures what the SoC’s listening loop costs end-to-end (\~971 µA average). ## 1\. Axon vs. Neuton: What’s the Difference? The **Axon NPU** is a hardware neural processing unit built into the **nRF54LM20B** SoC that runs short-vocabulary machine learning models up to 15× faster than the Cortex-M33 CPU. It enables always-on speech recognition, gesture recognition, and anomaly detection in the sub-1-mA range, making it well-suited for battery-powered edge AI applications. If you’ve been following Nordic’s Edge AI announcements, you may have come across two names: **Axon** and **Neuton**. Both fall under Nordic’s Edge AI umbrella, and the shared branding has caused real confusion in the developer community. The short version: **Axon is a hardware NPU built into the nRF54LM20B; Neuton is a software ML framework that runs on the Cortex-M33 CPU.** They’re complementary, not competing. ![Block diagram showing Axon NPU and Neuton on the nRF54LM20B.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/axon-vs-neuton-block-1.png) Where each one lives on the nRF54LM20B: Axon is a dedicated hardware NPU peripheral on the SoC; Neuton is a software framework that runs on the Cortex-M33 CPU. Your application code can call either one (or both). A model trained for one won’t run on the other; the toolchains and model formats are entirely separate. Let’s see how the Axon NPU and Neuton framework compare side by side: | | Axon | Neuton | | -------------------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | **Type** | Hardware NPU peripheral | Software framework (runs on CPU) | | **Model format** | TensorFlow Lite (compiled for Axon) | Proprietary Neuton format | | **Architectures** | CNN, TCN, fully connected (int8) | Varies (handled by the framework) | | **Power efficiency** | Up to 15x faster than CPU inference | Depends on model complexity and CPU load | | **Hardware required** | nRF54LM20B (with NPU) | Any nRF54L series (CPU only) | | **Can run simultaneously** | Yes (NPU + CPU) | Yes (CPU) | | **Ideal use-case** | Always-on speech recognition, gesture recognition, anomaly detection on audio or motion streams | Lightweight time-series anomaly detection, simple classification on accelerometer or sensor streams (no NPU required) | For example, the always-on speech recognition we’re building in this post is a natural Axon job, while a small accelerometer-based anomaly detector running on the Cortex-M33 alone is a natural Neuton fit. Per [Nordic’s product page](https://www.nordicsemi.com/Products/Technologies/Edge-AI/Axon-NPU?ref=novelbits.io), the Axon NPU **runs machine learning models up to 15x faster than the Cortex-M33 CPU**, and it operates as a hardware peripheral that runs in parallel with the CPU. That means the Bluetooth LE radio and your application logic keep running unblocked while the NPU runs the model. We use Axon for this post because the Voice Workout demo runs Nordic’s bundled wakeword and 10-keyword KWS networks (both pre-compiled and shipped with the [**Edge AI Add-on**](https://www.nordicsemi.com/Products/Technologies/Edge-AI/Software?ref=novelbits.io)) as-is, and layers a Bluetooth LE GATT service on top. ## 2\. The nRF54LM20B and Toolchain Overview Let’s start with the hardware. The [**nRF54LM20B**](https://www.nordicsemi.com/Products/nRF54LM20B?ref=novelbits.io)is the SoC we’re building on: ARM Cortex-M33 at 128 MHz, Bluetooth LE radio, and the Axon NPU in one package. The **nRF54LM20 Development Kit (DK)** is the board we use throughout. There’s only one DK version, the Axon NPU is unlocked on all units, the build target is `nrf54lm20dk/nrf54lm20b/cpuapp`, and the expansion headers expose **P1.04** and **P1.05** for our PDM microphone with no solder-bridge changes needed. ![The nRF54LM20 Development Kit with the P14 current-measurement pins and the 2x20-pin expansion headers labeled.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/nRF54LM20DK-info-image.jpg) The nRF54LM20 Development Kit. The current-measurement pins (P14) are what we tap into for the power profile in Section 7; the nRF54LM20B SoC sits to the right of center. The 2x20-pin expansion headers along the top expose P1.04 and P1.05 for the PDM microphone. ### The Toolchain Pipeline You don’t run model training or compilation yourself: the wakeword and KWS networks ship pre-trained and pre-compiled inside the **Edge AI Add-on**. Three steps: **1\. Install** the [**nRF Connect for VS Code extension**](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/installation.html?ref=novelbits.io), which pulls in NCS v3.3.0 and the Edge AI Add-on automatically. **2\. Build:** ```bash west build -b nrf54lm20dk/nrf54lm20b/cpuapp applications/ww_kws \ -- -DCONFIG_APP_MODE_WW_GATED_KWS=y ``` **3\. Flash:** ```bash west flash --dev-id ``` To swap in your own model later (custom wakeword, different keyword set, anomaly detector), the longer path adds a training step ([**Nordic Edge AI Lab**](https://ai.lab.nordicsemi.com/?ref=novelbits.io) for no-code custom wakewords) and an Axon Compiler step before the build. ### What you’ll need - [**nRF Connect SDK v3.3.0**](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/installation.html?ref=novelbits.io) \+ the latest [**Edge AI Add-on**](https://docs.nordicsemi.com/bundle/addon-edge-ai%5Flatest/page/index.html?ref=novelbits.io), plus **nRF Connect for Mobile** on a phone for inspection. - The **Axon NPU enabled in your project’s Device Tree Source (DTS) overlay**, since it’s not on by default. The matching `prj.conf` flags and the full overlay are below. Here’s the full DTS overlay we use (`applications/ww_kws/boards/nrf54lm20dk_nrf54lm20b_cpuapp.overlay`): ```dts / { chosen { /* uart20 is the one bridged to the VCOM on this DK, so control_output * messages land on the J-Link USB serial port. */ ncs,control-output-uart = &uart20; }; }; &pinctrl { pdm20_default_alt: pdm20_default_alt { group1 { psels = , ; }; }; }; dmic_dev: &pdm20 { status = "okay"; pinctrl-0 = <&pdm20_default_alt>; pinctrl-names = "default"; clock-source = "PCLK32M"; }; &axon { status = "okay"; }; ``` And the relevant `prj.conf` additions (full file in the companion repo): ```kconfig # nRF Edge AI + Axon NPU CONFIG_NRF_EDGEAI=y CONFIG_NRF_AXON=y CONFIG_NEWLIB_LIBC=y CONFIG_FPU=y # Axon model buffer sizes (sized for the bundled wakeword + KWS models) CONFIG_NRF_AXON_INTERLAYER_BUFFER_SIZE=6656 CONFIG_NRF_AXON_PSUM_BUFFER_SIZE=0 # PDM microphone capture CONFIG_GPIO=y CONFIG_AUDIO=y CONFIG_AUDIO_DMIC=y # Bluetooth LE Voice Workout GATT service CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DEVICE_NAME="Voice Workout" CONFIG_BT_DEVICE_APPEARANCE=833 CONFIG_BT_MAX_CONN=1 CONFIG_BT_MAX_PAIRED=1 CONFIG_HEAP_MEM_POOL_SIZE=4096 # Extend the post-wakeword KWS window from upstream's 3 s default so the # workout flow (Go -> reps -> Stop -> Yes/No) doesn't force a re-wakeword # between commands. CONFIG_KWS_PERIOD_MS=10000 ``` ## 3\. The Demo: What We’re Building Let’s walk through what the demo actually does. The goal is a hands-free Voice Workout tracker running entirely on a Nordic DK, talking to a phone over Bluetooth LE, updating in real time as you speak. User flow: - “Okay Nordic, **Go**” → device transitions to **ACTIVE** (workout in progress) - Do your set, then “Okay Nordic, **Stop**” → device moves to **AWAITING\_CONFIRM** - “Okay Nordic, **Yes**” → saves the workout. The device briefly shows **SAVED** and auto-returns to **IDLE** two seconds later. - “Okay Nordic, **No**” → discards. Passes through **DISCARDED**, then back to IDLE. The phone sees three Bluetooth LE notifications update live at every step: **Workout State**, **Last Command**, and **Confidence**. ### Hardware Bill of Materials - [**nRF54LM20 DK**](https://www.nordicsemi.com/Products/Development-hardware/nRF54LM20-DK?ref=novelbits.io) (Nordic Semiconductor) - [**Adafruit 3492 PDM MEMS Microphone Breakout**](https://www.adafruit.com/product/3492?ref=novelbits.io), a common PDM MEMS breakout that drops onto the same CLK/DAT pins (P1.04/P1.05) Nordic’s KWS sample expects - A USB-C cable - A phone running **nRF Connect Mobile** - Optional: [**Power Profiler Kit II (PPK2)**](https://www.nordicsemi.com/Products/Development-hardware/Power-Profiler-Kit-2?ref=novelbits.io) for the Section 7 power measurements ### Wiring the Microphone Four pins from the Adafruit 3492 connect to the DK’s expansion header: **CLK** → **P1.04**, **DAT** → **P1.05**, **3V** → **VDD:IO** (the Adafruit 3492 accepts 1.8-3.3 V; the DK’s default works), **GND** → **GND**. ![Wiring diagram for the Adafruit 3492 PDM mic to the nRF54LM20 DK expansion header.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/mic-to-dk-wiring-1.png) Wiring the Adafruit 3492 PDM mic to the nRF54LM20 DK: CLK to P1.04, DAT to P1.05, 3V to VDD:IO, GND to GND. ![Adafruit 3492 PDM mic on a breadboard wired to the nRF54LM20 DK's expansion header with four jumpers: 3V (red), GND (black), CLK (yellow) to P1.04, DAT (green) to P1.05.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/mic-wiring-closeup.jpg) Mic-to-DK wiring on the bench. Four jumpers from the Adafruit 3492 breakout to the DK’s expansion header: 3V to VDD:IO, GND to GND, CLK to P1.04, DAT to P1.05\. These pin assignments match Nordic’s own KWS sample, so you have a known-good reference to cross-check against if anything misbehaves. ⚠️ **Before you plug in: two quick checks.** Verify the **P14 jumper** is installed. Without it, every debug-port operation fails with confusing errors. For the mic supply: the Adafruit 3492 accepts **1.8 V to 3.3 V** on its VDD line, which covers the DK’s full programmable VDD:nRF range, so the DK’s default works regardless of how it was previously configured. ### End-to-End Architecture ![Voice Workout signal chain on the Axon NPU: PDM mic, wakeword model, KWS model, state machine, Bluetooth LE notifications.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/cascade-500.png) Signal chain: microphone → wakeword (Axon) → KWS (Axon) → state machine → Bluetooth LE notifications. The microphone captures sound as a PDM bitstream that the nRF54LM20B’s PDM peripheral decimates into 16-bit PCM at 16 kHz. The wakeword model runs continuously over those samples (always-on, on the Axon NPU). When it detects “Okay Nordic,” it opens a 10-second window during which the **Keyword Spotting (KWS) model** runs (also on the Axon NPU) and classifies each frame into one of ten short commands. The recognized command feeds the **workout state machine**, which either drives a state transition (Go, Stop, Yes, No) or reports through (Up, Down, On, Right, Left, Off). On every detection, three Bluetooth LE notifications go out: Workout State, Last Command, and Confidence. ## 4\. Nordic’s Bundled Wakeword and Keyword-Spotting Models Both networks ship pre-trained and pre-compiled with the Edge AI Add-on. The smaller **wakeword model** (\~25 KB int8 weights, 12 layers, with 6 recurrent state buffers that carry context across audio frames) runs continuously and sets the always-on listening floor we measure in Section 7\. The larger **KWS model**only runs inside the 10-second window after a wakeword detection, classifying each frame into one of ten short commands: `Go`, `Stop`, `Yes`, `No`, `Up`, `Down`, `On`, `Off`, `Right`, `Left`. Both are stored as C headers compiled by the **Axon Compiler** and included directly by `ww_kws`. To swap in your own model later (a custom wakeword from [Nordic Edge AI Lab](https://ai.lab.nordicsemi.com/?ref=novelbits.io), or your own TF Lite model through the Axon Compiler), this is a clean baseline to extend. ## 5\. Firmware Walkthrough Let’s open up the firmware. I kept the diff against Nordic upstream as small as possible: three small hooks in `main.c` plus one new sibling directory, so the demo survives Edge AI Add-on upgrades cleanly. We layer a small Voice Workout GATT service on top of Nordic’s bundled [applications/ww\_kws](https://docs.nordicsemi.com/bundle/addon-edge-ai%5Flatest/page/applications/ww%5Fkws/README.html?ref=novelbits.io)sample, which already does the hard parts: PDM capture, wakeword and KWS model loading, the wakeword-gated state machine, and the main loop. Our additions land in one new sibling subdirectory plus a few small edits in two host files: ``` applications/ww_kws/ ├── src/ │ ├── main.c ← three small additions (hooks for our service) │ ├── voice_workout/ ← NEW: our GATT service │ │ ├── voice_workout.c │ │ └── voice_workout.h │ └── ... ← Nordic upstream (unchanged) ├── prj.conf ← three Bluetooth LE additions + KWS_PERIOD_MS └── ... ``` This shape keeps the diff against Nordic upstream small (and survives Edge AI Add-on upgrades cleanly). Full source is in the [companion repo](https://github.com/NovelBits/nordic-axon-voice-workout-tracker?ref=novelbits.io); the rest of this section walks through the design decisions rather than the line-by-line code. ### The Voice Workout GATT Service A single primary [GATT service with three notify characteristics](https://novelbits.io/design-bluetooth-low-energy-gatt-server-database/). Each carries an ASCII payload, so values render as human-readable text in nRF Connect Mobile’s UTF-8 view with no client-side decoding: | Characteristic | UUID suffix | Sample payload | What it tells you | | ----------------- | ----------- | ----------------------------------------------------------- | --------------------------------------- | | **Workout State** | 7c000002… | "IDLE", "ACTIVE", "AWAITING\_CONFIRM", "SAVED", "DISCARDED" | Where the state machine is right now | | **Last Command** | 7c000003… | "Go", "Stop", "Yes", "No", "Up", … | The most recent keyword the KWS spotted | | **Confidence** | 7c000004… | "94%" | Smoothed classification probability | The service base UUID is `7c00000X-c0ff-ee00-0001-1e2b3c4d5e6f`, with the leading 32 bits incrementing per characteristic. Each characteristic is `READ | NOTIFY` with a `BT_GATT_CCC()` descriptor so the central can subscribe; the CCC change callback lets our code skip the notify when no one is listening. Here’s the service definition from `voice_workout.c`: ```c BT_GATT_SERVICE_DEFINE(voice_workout_svc, BT_GATT_PRIMARY_SERVICE(VW_SERVICE_UUID), BT_GATT_CHARACTERISTIC(VW_STATE_CHRC_UUID, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, read_state, NULL, NULL), BT_GATT_CCC(state_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), BT_GATT_CHARACTERISTIC(VW_LAST_CMD_CHRC_UUID, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, read_last_cmd, NULL, NULL), BT_GATT_CCC(last_cmd_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), BT_GATT_CHARACTERISTIC(VW_CONFIDENCE_CHRC_UUID, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, read_confidence, NULL, NULL), BT_GATT_CCC(confidence_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), ); ``` ### The Workout State Machine Five states, four user-driven transitions, and a 2-second timer that auto-returns from `SAVED` and `DISCARDED` back to `IDLE`: ![Voice Workout state machine on the nRF54LM20B: IDLE, ACTIVE, AWAITING_CONFIRM, SAVED, DISCARDED states with four wakeword-gated transitions.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/wsm-650.png) Workout state machine: IDLE → ACTIVE → AWAITING\_CONFIRM → SAVED or DISCARDED → IDLE, with the four keyword transitions and the 2-second auto-return on the terminal states. Three implementation details not visible in the figure: - **Every keyword input is gated by an “Okay Nordic” wakeword detection.** The KWS spotter only runs inside the 10-second window opened by a successful wakeword. Outside that window the spotter literally cannot fire (privacy-friendly by construction). - **The KWS model recognizes ten keywords.** Four (`Go`, `Stop`, `Yes`, `No`) drive the state machine; the other six (`Up`, `Down`, `On`, `Right`, `Left`, `Off`) update Last Command and Confidence but don’t change State. `**Off**` also closes the active listening window early (think “Alexa, stop”), via a single `if (strcmp(name, "Off") == 0) { spotting_timeout = 0; }`. - **Invalid transitions are no-ops.** Saying “Yes” while in `IDLE` leaves State unchanged but still updates Last Command. ### KWS window, DT overlay, Kconfig, and `main.c` hooks The `ww_kws` sample exposes the KWS active window as `CONFIG_KWS_PERIOD_MS`, defaulting to 3 seconds upstream, too tight for a workout flow where you do reps between commands. Our `prj.conf` overrides it to `10000` (10 s). Each detection inside the window resets the timer, so an active conversation stays active for as long as you keep talking. Section 7 shows how this knob shapes the power profile. Our DT overlay enables `&pdm20` (the LM20B’s PDM peripheral, **not `pdm0`** as in older Nordic samples; biggest porting trip-up) on P1.04/P1.05, and sets `&axon` to `okay`. Our `prj.conf`adds three Bluetooth LE Kconfigs (`CONFIG_BT=y`, `CONFIG_BT_PERIPHERAL=y`, `CONFIG_BT_DEVICE_NAME="Voice Workout"`) plus the `KWS_PERIOD_MS` override. One PDM gotcha worth flagging even though the code is in the repo: **don’t set `clock-frequency` on the PDM node**. The binding doesn’t accept it. Use `clock-source = "PCLK32M"`and configure the sample rate at runtime through the DMIC API. Our additions to `main.c` are well under 30 lines, organized as three hooks: (1) `voice_workout_init()` at startup, which registers the GATT service and starts advertising; (2) `voice_workout_handle_result(name, avg_probability)` inside the KWS loop, called once per keyword detection to update the three characteristics and run the state machine; and (3) the `Off`early-exit that sets `spotting_timeout = 0`. Hook (1), the startup call, sits in `main()` right after the wakeword and KWS init: ```c err = voice_workout_init(); if (err) { return err; } LOG_INF("Initialization completed"); ``` Hooks (2) and (3) live inside the KWS loop, right after a valid keyword detection: ```c if (prediction.valid) { leds_blink_led1(); spotting_timeout = k_uptime_get_32() + CONFIG_KWS_PERIOD_MS; print_control_output( (struct control_message){.type = CONTROL_MESSAGE_KW_SPOTTED, .kw_class = prediction.class, .name = prediction.name}); voice_workout_handle_result(prediction.name, prediction.avg_probability); /* "Off" closes the active KWS window early and returns the device * to wakeword-only listening. Pure listening-window control: the * workout state machine is untouched. */ if (strcmp(prediction.name, "Off") == 0) { LOG_INF("Listening window closed by 'Off' keyword"); spotting_timeout = 0; } } ``` And the keyword-to-state-transition cascade inside `voice_workout_handle_result()`, which is the heart of the state machine: ```c if (strcmp(name, "Go") == 0 && current_state == WORKOUT_STATE_IDLE) { state_change_to(WORKOUT_STATE_ACTIVE); } else if (strcmp(name, "Stop") == 0 && current_state == WORKOUT_STATE_ACTIVE) { state_change_to(WORKOUT_STATE_AWAITING_CONFIRM); } else if (strcmp(name, "Yes") == 0 && current_state == WORKOUT_STATE_AWAITING_CONFIRM) { state_change_to(WORKOUT_STATE_SAVED); } else if (strcmp(name, "No") == 0 && current_state == WORKOUT_STATE_AWAITING_CONFIRM) { state_change_to(WORKOUT_STATE_DISCARDED); } ``` `state_change_to()` updates `current_state`, writes the new state name into the GATT characteristic buffer, and calls `bt_gatt_notify()` only if the central has subscribed (the `state_ccc_enabled` flag). One race-condition gotcha worth knowing: when a connected central drops the link, **don’t call `bt_le_adv_start()`directly from the `disconnected` callback**. It can race with the Bluetooth LE host’s connection-teardown bookkeeping and return `-ENOMEM`. Schedule a system workqueue item with a 100 ms delay instead. The pattern in `voice_workout.c`: ```c static void disconnected(struct bt_conn *conn, uint8_t reason) { LOG_INF("Central disconnected (reason %u)", reason); ble_connected = false; state_ccc_enabled = false; last_cmd_ccc_enabled = false; confidence_ccc_enabled = false; if (current_conn) { bt_conn_unref(current_conn); current_conn = NULL; } /* Defer through the system workqueue: bt_le_adv_start() can race * with the Bluetooth LE host's connection-teardown bookkeeping if * called directly from this callback. */ k_work_schedule(&adv_restart_work, K_MSEC(100)); } ``` ## 6\. Running the Demo From a flashed DK and a phone with **nRF Connect Mobile** installed, you should be at a working demo in a few minutes. **1\. Sanity-check the stock sample first.** I recommend this even if you’re confident in your wiring, since it catches mic-clock or P14 issues in under a minute. Build and flash the upstream `applications/ww_kws` sample (without our `voice_workout/` directory) using the same `west build` / `west flash` commands. With a UART terminal open, say “Okay Nordic, Go”. The firmware should log a wakeword detection followed by a `Go` keyword detection. If it doesn’t, debug the baseline first (most likely the mic wiring or the P14 jumper). **2\. Build and flash the demo** from your Edge AI Add-on workspace root, with our `voice_workout/` directory copied into `applications/ww_kws/src/`: ```bash west build -b nrf54lm20dk/nrf54lm20b/cpuapp edge-ai/applications/ww_kws \ -- -DCONFIG_APP_MODE_WW_GATED_KWS=y west flash --dev-id ``` **3\. Watch the boot log** at 115200 baud. The two lines you’re looking for: ``` Bluetooth initialized Advertising as 'Voice Workout' ``` **4\. Connect from the phone.** In **nRF Connect Mobile**, tap **Scan**, find **Voice Workout**, **Connect**, then expand the service whose UUID base starts with `7c000001-c0ff-ee00-...`. **5\. Subscribe to the three notifications.** Tap the triple-down-arrow on each characteristic (`...0002` State, `...0003` Last Command, `...0004` Confidence). The UART log prints `State notifications enabled` (and the equivalents) once each subscription lands. **6\. Run a Save cycle.** Speak the four commands one at a time, with a short pause after each to watch the phone: - “Okay Nordic, Go” → State `ACTIVE`, Last Command `Go`, Confidence \~94% - “Stop” → State `AWAITING_CONFIRM` - “Yes” → State `SAVED`, then auto-returns to `IDLE` after 2 seconds If all four notifications fire in order, the demo is working end to end. Common bring-up snags (no advertising message, wakeword detects but State doesn’t change, mic wiring debugging) are documented in the [companion repo’s troubleshooting guide](https://github.com/NovelBits/nordic-axon-voice-workout-tracker?ref=novelbits.io). ## 7\. Power Profile Let’s measure what this listening loop actually costs. I’d recommend starting with Nordic’s `axon_low_power` sample before measuring the full firmware: it isolates the NPU on its own, and the numbers it produces line up directly with what Nordic publishes for the Axon. Once that baseline is in hand, the full-firmware measurement is much easier to interpret. The remaining technical question is where the current goes once the firmware is running, so I put the firmware on a Power Profiler Kit II (PPK2) in **source measure mode at 3.0 V** ([Nordic’s MLPerf Tiny operating point](https://www.nordicsemi.com/Products/Technologies/Edge-AI/Axon-NPU?ref=novelbits.io)), wired into the DK’s **P14** SoC current-measurement header. P14 isolates the **VDDM rail of the nRF54LM20B SoC itself**, which excludes the J-Link debugger, the on-board PMIC, and the external microphone (the mic sits on VDD:IO, a voltage follower of VDD:nRF designed specifically to keep external loads off the SoC measurement). ![Nordic Power Profiler Kit II wired to the nRF54LM20 DK via the P14 4-pin jumper harness. USB-C plugged into the DK's J-Link port.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/ppk2-measurement-setup.jpg) PPK2 measurement setup: Source-Measure-mode harness from the PPK2 to the DK’s P14 header, with USB-C powering the J-Link interface. ### The full listening loop We captured a full Save cycle: 113 seconds with three commands (“Go”, “Stop”, “Yes”) and a phone subscribed to the three notify characteristics. Four phases stand out across the trace: - **Wakeword-listening baseline** at roughly **831 µA average** when the phone is connected (PDM streaming continuously, wakeword network running every \~30 ms, [Bluetooth LE connection events](https://novelbits.io/ble-connection-intervals/) on top). - **KWS shelves** that lift the running average by \~125 µA whenever the wakeword fires and the larger KWS network runs alongside it for the 10-second window (subtle on the trace because PDM dominates the y-axis, but measurable: the 10-second active window averages \~955 µA against the \~831 µA quiet baseline). - **Notification bursts** of up to three taller spikes per detection (Workout State, Last Command, Confidence). - **KWS timeout** that drops the device back to wakeword-only when the window expires (or `Off` closes it early). Here’s one of those events up close. The 955 µA WINDOW in this slice covers the full event (baseline + KWS shelf + three notification spikes), which is why it’s higher than the quiet baseline: ![1.6 s zoom of the "Okay Nordic, Go" event: wakeword baseline, KWS shelf rising on detection, then three notification spikes in tight succession.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/A-okay-nordic-go.png) Source: Nordic Power Profiler Kit II, Voice Workout firmware (`ww_kws` \+ `WW_GATED_KWS=y`). The “Stop” and “Yes” events show the same triplet pattern. The quiet baseline itself, measured on a separate per-segment capture of steady-state connected listening with no commands, averages **\~831 µA**: ![18-second per-segment capture of steady-state connected listening. WINDOW average: 830.78 µA. Dense ~3.5 mA band from continuous PDM streaming, with taller 6-8 mA spikes that are Bluetooth LE connection events.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/B-connected.png) Source: Voice Workout firmware, per-segment shot of the connected steady-state (no active commands). ### Disconnecting the phone increases current (the counter-intuitive part) The first time I ran this measurement, I expected disconnecting the phone to drop the current. It doesn’t: ![36.6-second capture spanning a connected period followed by a forced disconnect. WINDOW average across the full capture: 887.02 µA.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/traceB-overview-1.png) Source: Voice Workout firmware on the same DK; Y-axis autoscaled to 20 mA. The 887 µA shown in the WINDOW is the average over the whole capture. Sliced into per-segment WINDOWs, the connected half averages \~**831 µA** (the `B-connected.ppk2` figure shown earlier) and the disconnected half averages \~**971 µA**, a \~140 µA delta: ![14-second per-segment capture of the disconnected portion (advertising, no central connected). WINDOW average: 971.04 µA, ~140 µA higher than the connected baseline.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/B-disconnected.png) Source: Voice Workout firmware, per-segment shot of the disconnected period (advertising only, no central connected). **Disconnecting the phone increases listening current by roughly 140 µA.** The reason: our firmware advertises with [**FAST\_1**](https://novelbits.io/bluetooth-low-energy-advertisements-part-2/)parameters (Zephyr’s `BT_LE_ADV_CONN_FAST_1`, mapping to the Core Spec’s `Advertising_Interval_Min/Max` set to a fast cadence), which transmits short bursts on the three primary advertising channels (37, 38, 39) per event. When a central is connected, the radio runs scheduled connection events at the negotiated interval instead, and because our characteristics carry only a few bytes per notification, most of those events ship empty Data PDUs. **On a per-second basis the radio spends less air time servicing empty connection events than firing repeated FAST\_1 advertising on three channels.** ### Decomposing the 971 µA listening floor The headline number is **971 µA** for the disconnected listening floor. To attribute where that current goes, we built a stripped variant with the entire audio path wrapped in `#if 0` (PDM init, wakeword and KWS init, audio loop) and an early `return 0` after `voice_workout_init()`. The kernel keeps running and Bluetooth LE keeps advertising, but the PDM peripheral never enables (FLASH usage drops by roughly 22 percentage points, from \~31.5% to \~7.0%, confirming the audio path is fully excluded). ![Bluetooth LE-only baseline on the nRF54LM20B: 209-second PPK2 capture with PDM and inference disabled, averaging 224 µA on FAST_1 advertising across channels 37, 38, and 39.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/D-advertising-full.png) Source: Stripped variant, same DK and PPK2 setup. That **\~224 µA** is the directly-measured cost of the Bluetooth LE peripheral with FAST\_1 advertising and nothing else. With the per-inference cost of the wakeword network independently measurable on Nordic’s `axon_low_power` sample (next subsection), the residual is everything else, dominated by PDM: | Component | Average current | How it was attributed | | -------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | Bluetooth LE peripheral, FAST\_1 advertising | **\~224 µA** | Measured directly via the stripped variant | | PDM streaming and audio plumbing | **\~655 µA** | Residual: 971 − 224 − 92 | | Axon wakeword inference cadence | **\~92 µA** | From axon\_low\_power per-inference data: 2.77 µC per inference at the firmware’s \~30 ms wakeword stride (2.77 µC / 30 ms ≈ 92 µA averaged) | | **Total** | **\~971 µA** | Matches measured 971 µA | The takeaway: **PDM streaming dominates the listening floor**, not the NPU and not the radio. The path to dropping the floor below \~700 µA on this SoC class is to break the always-on PDM assumption (button press, motion sensor, low-power voice-activity detector), not to optimize the wakeword network or the radio further. ### The NPU itself, in isolation Where does the **\~92 µA** Axon figure come from? Nordic ships an [**axon\_low\_power**](https://docs.nordicsemi.com/bundle/addon-edge-ai%5Flatest/page/samples/axon/axon%5Flow%5Fpower/README.html?ref=novelbits.io)measurement-reference build that runs the same `okay_nordic`wakeword model our demo uses, with no live mic, no Bluetooth LE, and no UART, with the CPU sleeping between sweeps: ![Nordic axon_low_power sample on the nRF54LM20B: 2-second view of two Axon NPU inference sweeps at 3 mA peak with deep-sleep idle between, averaging 282 µA.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/C-low-power-2sec.png) Source: Nordic `axon_low_power` sample, same DK and PPK2 setup. The figure averages **282.84 µA** over 2 seconds because the trace is mostly deep-sleep idle (visibly near zero between sweeps) punctuated by two brief inference sweeps. Each sweep contains 100 back-to-back inferences peaking at **\~3 mA** (the figure’s `max = 3.035 mA`) for **\~1.3 ms** per inference (\~8.3 µJ each, from each sweep’s \~278 µC charge ÷ 100 inferences ÷ 3 V). For context, [Nordic’s published Axon MLPerf Tiny figure](https://www.nordicsemi.com/Products/Technologies/Edge-AI/Axon-NPU?ref=novelbits.io) shows the heavier MLPerf KWS reference model averaging **3.0 mA during a 4.5 ms inference** (40.5 µJ). Our `okay_nordic` wakeword is a lighter model, so its inference is faster and the per-inference energy is lower. Drag a WINDOW across a between-sweeps quiet region and it averages **\~6 µA** (Nordic publishes `<10 µA`), orders of magnitude lower than the 971 µA full-firmware floor. Even at the wakeword cadence, the NPU’s time-averaged cost is \~92 µA, under a tenth of the listening floor. ### Axon vs. CPU, and what’s not in the measurement Nordic’s Embedded World 2026 video on the LM20B [(YouTube)](https://www.youtube.com/watch?v=Us4RqWi1uTI&ref=novelbits.io)compares the same `okay_nordic` pipeline on the Axon NPU versus the Cortex-M33 CPU, framing the Axon as [**“up to 15x faster, 15x more energy-efficient”**](https://www.nordicsemi.com/Products/Technologies/Edge-AI/Axon-NPU?ref=novelbits.io) for short-vocabulary speech recognition. If you imagine swapping Axon for CPU in this firmware, the \~92 µA inference component scales by roughly 9–15× (to roughly 0.8–1.4 mA averaged) and pushes the total floor well above 1.5 mA. **The Axon NPU is what keeps the always-on floor under 1 mA on this SoC.** Two caveats before you take these numbers anywhere else. First, **the microphone is on VDD:IO, not VDDM.** The Adafruit 3492 mic sits on the GPIO header’s VDD:IO rail, a voltage follower of VDD:nRF (we have VDD:nRF set to 1.8 V via Board Configurator) that keeps external loads off the SoC measurement. The mic itself draws around 500–600 µA, so a realistic **system total** for always-listening is closer to **\~1.5 mA**, not 971 µA. (The J-Link and PMIC are on USB 5 V; a battery-powered product would remove the J-Link entirely.) Second, **PPK2 range-switching artifacts** produce 1–4 sample-wide transient spikes at internal range boundaries. The matplotlib renders above apply a 9-sample median despike that preserves real signals (Bluetooth LE TX events span 25+ samples, Axon sweeps 130+) while filtering the artifacts. Averages are unaffected. This firmware fits an ultra-low-power always-on voice budget on this SoC: sub-1-mA SoC-only, \~1.5 mA system with the mic. The path to multi-week or multi-month battery life on a small primary cell is to break the always-on PDM assumption (button, motion sensor, low-power voice-activity detector), as the decomposition above makes clear. ## 8\. When This Fits, and What to Build Next Let’s step back. When do you reach for the Axon NPU, and when does it not fit? **Reach for the Axon NPU** when you need always-on speech recognition on a microcontroller running on a battery, or frequent on-device inference where the model is short-vocabulary classification or anomaly detection (compact CNN or TCN, int8-quantizable), and a sub-1-mA always-on floor matters. **Reach for Neuton** when you don’t have ML expertise and the model is small enough to run on the M33 CPU within budget. **Reach for a more powerful SoC or cloud inference** when the vocabulary is large, you need natural-language understanding, or model size/latency exceeds what the Axon NPU supports. The architecture here (PDM capture → wakeword-gated KWS on Axon → small state machine → Bluetooth LE notifications) is a starting point, not a finished product. For example, swap the workout state machine for “Light On / Off / Brighter / Dimmer” and you have hands-free smart-home control; swap it for a short safety vocabulary and you have hands-free industrial PPE. The model and vocabulary change; the firmware wiring stays the same. Nordic’s **Edge AI Lab** is an automated no-code platform for building compact models and embedding them across all of Nordic’s wireless SoCs. Its [**Use Cases**](https://app.lab.nordicsemi.com/?ref=novelbits.io#/cases)page (free Nordic Edge AI Lab sign-in required) has a curated set of pre-built demos (gesture-based smartwatch and remote control, daily activity recognition, handwashing and toothbrushing tracking, smart-ring control, on-device package tracking, accessibility-focused activity recognition, etc.), fast ways to see what else the Axon NPU can do without training a model yourself. ![The Edge AI Lab "Demo Use Cases" gallery (sign-in required). Each tile is a pre-built demo with a model, dataset, and sample firmware you can flash to a Nordic DK.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/edge-ai-lab-cases.png) The link above lands on the Edge AI Lab web app, which requires a free Nordic Edge AI Lab sign-in to view. The login is free; the screenshot above is what you’ll see once you’re in. To swap “Okay Nordic” for your own wakeword in this firmware, the Edge AI Lab’s no-code **My Solutions** workflow trains a custom phrase and produces a compiled header that drops into the same slot the bundled wakeword sits in. The companion code (DT overlay, `prj.conf`, Voice Workout source files, and a troubleshooting guide) is at [**https://github.com/NovelBits/nordic-axon-voice-workout-tracker**](https://github.com/NovelBits/nordic-axon-voice-workout-tracker?ref=novelbits.io). From a flashed DK and a phone with nRF Connect Mobile, you should be at a working hands-free voice-controlled Bluetooth LE device on your bench within fifteen minutes. ## 9\. Conclusion In this post we covered: - The **Axon NPU** and how it differs from **Neuton** (hardware NPU vs. software framework on the Cortex-M33). - The **nRF54LM20 DK** and toolchain setup, plus the Adafruit PDM mic wiring. - The **Voice Workout demo** end to end: state machine, three Bluetooth LE notify characteristics, GATT service. - The small Bluetooth LE layer we add on top of Nordic’s bundled `ww_kws` sample. - A measured power profile that decomposes the 971 µA SoC-only listening floor into \~224 µA Bluetooth LE + \~655 µA PDM + \~92 µA Axon. **Bottom line:** the Axon NPU contributes under 10% of the listening floor. PDM streaming dominates always-on voice on this SoC, and without the Axon’s hardware acceleration that floor would be well above 1 mA. You should now be able to flash the companion code, connect from nRF Connect Mobile, and have a hands-free voice-controlled Bluetooth LE device working on your bench within fifteen minutes. From here, swap the keywords or the state machine and you’re 80% of the way to a different product running on the same battery. ### Why I Couldn't Use J-Link RTT Viewer (And Built My Own) URL: https://novelbits.io/why-i-couldnt-use-jlink-rtt-viewer/ Last updated: 2026-05-17T17:20:44.000Z For over ten years, I’ve wanted a better embedded log viewer, specifically for Bluetooth LE work. That’s a long time, especially for a Bluetooth LE engineer staring at HCI hex dumps in a tool that hasn’t really changed since the 90s. Every Bluetooth LE debug session goes the same way: plain text scrolling by, no filtering, no structure, no way to see what your firmware is actually doing without piecing it together across [SEGGER J-Link RTT Viewer](https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/?ref=novelbits.io) (for the live log), a serial terminal (for the UART side), and Wireshark (for the HCI capture you exported five minutes ago). If you’ve ever spent an afternoon alt-tabbing between three windows trying to correlate a pairing failure with a hard fault in your application logs, you know exactly the workflow I’m talking about. In March 2026, I finally built the tool I wished existed. It’s called **LogScope**, it’s free, it’s open source, and it lives inside VS Code. In this post, let’s walk through: - Why J-Link RTT Viewer never quite worked for my workflow - What changed in 2026 that made building a replacement realistic - How LogScope went from blank repo to a working extension in about six hours - Why I think the real differentiator just shifted, now that AI coding agents have collapsed the activation energy - What the launch on LinkedIn showed me about who else felt the same itch - Where LogScope is now, and what’s coming next If you’ve ever wished your embedded debugging tools were a little less stuck in 1998, this should resonate. ## Where J-Link RTT Viewer falls short for me Let’s be fair to SEGGER first. **J-Link RTT Viewer** is a genuinely good tool. It’s reliable. It works with any J-Link probe (which is most of the Nordic, ST, Silicon Labs, Infineon, and NXP ecosystem). It handles the transport layer cleanly. For a lot of bring-up work, it’s the right tool. The problem isn’t that it’s bad. The problem is that it’s narrow. Here’s what bothered me as a Bluetooth LE engineer for years: **Everything lives outside the editor.** J-Link RTT Viewer is a standalone desktop application. Every debug session means alt-tabbing between VS Code (where my firmware code lives), RTT Viewer (where the logs scroll by), a serial terminal (for the UART side of things), and Wireshark (for HCI captures). That’s four windows for one workflow. ![Feature comparison table: J-Link RTT Viewer versus LogScope across nine debug-workflow capabilities. Both tools provide live RTT log streaming and work with any J-Link probe. LogScope adds: lives inside VS Code, Bluetooth LE HCI decoded inline, auto-detect severity and module filtering, fault auto-detect with auto-pause, mid-session reset recovery, one-click Wireshark btsnoop export, and auto-reconnect after flashing. J-Link RTT Viewer can display ANSI-colored text if the firmware emits it, and supports manual reconnect after a mid-session reset.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/logscope-feature-comparison-v2.png) Feature-by-feature comparison: J-Link RTT Viewer versus LogScope across the debug-workflow capabilities that matter for Bluetooth LE work. **The output is plain text.** A modern log line in a structured RTOS like [Zephyr](https://zephyrproject.org/?ref=novelbits.io) or nRF Connect SDK carries severity, module name, timestamp, and the actual message, all parseable. RTT Viewer shows you the raw text stream. You write the parsing in your head, every line, every session. For example, a Zephyr log entry that prints `[00:00:01.234,000] sensor_drv: temp=22.5C`should at minimum show up with the severity color-coded, the module name in its own column, and the timestamp in a sortable format. In RTT Viewer, it’s just text. **Mid-session resets disrupt the connection.** This is the issue that bothered me most as I built more complex Bluetooth LE work. If your firmware does a soft reset (which, on a peripheral, can happen often during pairing failures and connection drops), RTT Viewer typically loses sync with the RTT control block and you have to manually reconnect to resume the log stream. For a tool designed to follow what your firmware is doing, that’s a brutal limitation. **There’s no Bluetooth LE awareness.** This is the one that drove me to actually start building, and it’s the heart of the whole story. A Bluetooth LE engineer staring at HCI packet bytes (or worse, raw ACL bytes) is doing protocol decoding by hand, which is exactly the kind of mechanical work software should do for us. Every byte of an HCI command has a meaning defined in the [Bluetooth Core Specification](https://www.bluetooth.com/specifications/specs/core-specification/?ref=novelbits.io). Every ATT operation has a structured field layout. Why am I reading hex dumps when the spec tells us exactly what each byte is? For example, an `HCI LE Connection Complete`event carries the connection status, handle, role, peer address (with type), [connection interval](https://novelbits.io/ble-connection-intervals/), peripheral latency, supervision timeout, and central clock accuracy. That’s eight pieces of information a Bluetooth LE engineer cares about, every connection, every session. Surfacing them inline as decoded text is not a nice-to-have. It’s the table-stakes feature that the rest of the tooling industry never built. For a long time, the answer to “why don’t you just build something better” was: because building something better takes months, I have a day job (Novel Bits and the Bluetooth Developer Academy), and the activation energy is too high. That changed in 2026. ## What changed in 2026 The honest answer is: AI coding agents got good enough to ship real tools. Let’s be specific about what that means, because there’s a lot of noise in this space. I’m a Bluetooth LE engineer. I’ve been doing this work for over a decade. I know the Core Specification well enough that I built the bluetooth-spec MCP server (a retrieval system over the spec, used by my other tools too). What I’m not is a TypeScript expert who lives inside the VS Code extension API. I don’t write Astro plugins for breakfast. I haven’t internalized every corner of the J-Link DLL or the SEGGER RTT control-block format. For years, that gap between “domain knowledge” and “tooling knowledge” was where my better-log-viewer idea died. The mechanical work of building a VS Code extension (wiring up activation events, managing the webview lifecycle, designing the message-passing protocol, scaffolding a parser pipeline) would have taken me weeks of part-time work just to reach the point where I could start solving the actual Bluetooth LE problems. With [Claude Code](https://www.anthropic.com/claude-code?ref=novelbits.io)(the AI coding agent I used to build LogScope), the math is different. I supply the judgment: what to parse, what to surface, what HCI fields a Bluetooth LE engineer actually needs to see, how the connection-parameter visualization should work. Claude handles the mechanics: the VS Code extension API, the TypeScript types, the parser scaffolding, the webview rendering. This is the “build in public with AI” angle of the LogScope story, and I think it’s worth being explicit about it. The interesting part isn’t that AI wrote code. The interesting part is that for the first time, a domain expert without deep tooling-internals expertise can ship serious developer tools in their niche. For Bluetooth LE specifically, that’s me. For other niches, it’ll be other people, and that’s good for everyone. ## From blank repo to working extension in six hours Let’s walk through the actual timeline, because the contrast with where I started matters. On 2026-03-17 at 15:22 (a Sunday afternoon, for context), I made the initial commit: just an MIT license file and a README. Six hours later, at 21:02 the same day, the next commit was the “thin slice”: a working VS Code extension that connected to a J-Link probe via RTT, parsed Zephyr log output, and rendered the results in a filterable webview. Four-layer architecture (transport, parser, model, UI), 33 passing tests, packaged as a VSIX ready to install. A few minutes after midnight on March 18, I added auto-J-Link integration so the extension would spawn JLinkExe automatically on connect (zero-config RTT setup for the user). Then I added a demo firmware app for the nRF54L15 DK so I could test it against real hardware. I renamed the project from “Devscope” to “DevScope”, and then a few commits later, again to “LogScope”, because both earlier names were too close to existing projects. The rest of March 18 went into HCI decoding. By the end of that day, the extension could capture Bluetooth LE HCI packets from Zephyr’s `btmonitor` channel, decode them inline (commands, events, ACL data, ATT operations), and let you click any row to expand the decoded fields. Crash and fault detection landed in the same window. On March 19, I shipped v0.1.0 (well, technically v0.1.7 by then; there were a few publishing iterations) to the VS Code Marketplace and posted on LinkedIn. ![LogScope build timeline showing six milestones from initial commit on March 17 at 15:22 through the v0.1.0 ship and LinkedIn launch on March 19](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/logscope-build-timeline-v4.png) Build timeline: from blank repo to v0.1.0 shipped, plus the LinkedIn launch, in about 36 hours. That’s about 36 hours from “I should just build this” to “anyone can install it from the Marketplace.” I’m not claiming I understood every J-Link DLL behavior the first day. I didn’t, and that knowledge has come in painful pieces over the months since, especially around the mid-session reset bug that took two weeks to actually fix later. What I’m saying is the *activation energy* is now low enough that domain experts can ship. For example, when I needed to handle the SEGGER RTT control-block format, I didn’t have to read the SEGGER spec first. Claude already knew the pattern (the magic string, the up-buffer / down-buffer layout, the descriptor structure). I just had to confirm it produced output that matched what real Nordic firmware emits, which I could verify against a real nRF54L15 DK on my desk. The Bluetooth LE side, by contrast, was all me. Which HCI events matter most to surface? Which ATT operations need decoded fields versus a hex dump fallback? How should connection parameters render so they’re actually useful (interval, latency, supervision timeout, all in the units engineers actually think in)? Those decisions came from more than a decade of staring at Bluetooth LE traces. ## The differentiator just shifted I want to pause here for a second, because this is the part of the story I think matters most. It’s also why I’m building LogScope in public rather than treating it as a quiet side project. For decades, the bottleneck for shipping software was writing it. If you wanted a tool that didn’t exist, you either built it yourself (slowly), waited for someone with the time and skill to build it, or paid a company to build it for you. “Can they write the code” was a real filter, and it kept a lot of would-be tools from ever existing. In 2026, that filter is collapsing. Domain experts, indie hackers, and product people are shipping real software with AI coding agents, often at a speed that would have looked impossible two years ago. The bottleneck isn’t writing code anymore. It’s everything else. What does “everything else” mean in practice? For LogScope specifically, it’s decisions like these: - Which seven HCI fields actually matter when an engineer is debugging a Bluetooth LE connection drop? That answer comes from doing the work for over a decade, not from reading the spec. - What does the connection-parameter visualization need to show at a glance, and what can wait until the user clicks to expand a row? You learn that by watching your own eyes flick across logs in real debug sessions. - When the chip resets mid-session, what should the UI do in the half-second before logs resume? You learn that by losing your session a hundred times in J-Link RTT Viewer. - Should the auto-detect feature surface the chip name, the J-Link device name, both, or just “connected”? You learn that by talking to embedded engineers about how they actually think about their boards. None of those are coding problems. They’re judgment problems, born from doing the work. So my honest take is that the next several years of indie tool-building belong to people who combine deep domain experience with a real sense of how products feel to use. The code is the easy part now. The hard part, and the differentiator, is knowing which problems are actually worth solving and what “actually solved” looks like for the user. Design intuition, workflow empathy, and the patience to ship something that’s *good* and not just *working* are about to matter more than ever. LogScope is my bet on that thesis. ## The launch moment Let’s talk about what happened next, because the response taught me as much as the build did. I posted the [founding announcement on LinkedIn](https://www.linkedin.com/feed/update/urn:li:ugcPost:7440416291292798976/?ref=novelbits.io) the morning of March 19, 2026\. Short video demo of the extension in action, the same “for over ten years I’ve wanted to build this” framing, the Marketplace link in the first comment. The post has reached 17,947 impressions, 256 reactions, 22 comments, and 10 reposts. That’s by far the largest reach I’ve had on any LogScope-related post since. What that response told me was that the itch wasn’t just mine. A lot of embedded engineers have the same alt-tab-between-three-windows debugging workflow, and they recognized it the second they saw the video. The most common comment was a variant of: “I’ve been wanting exactly this.” A few people asked for nRF5 SDK parser support immediately (which shipped in v0.3.0 two weeks later). A couple asked for non-Nordic chip support (working on it). One Nordic engineer reached out separately to say it was useful for their internal work. ## Where LogScope is now Let’s look at where LogScope stands today, two months after the founding post. The current version is **v0.6.5** (May 2026). Shipping cadence has been one to three releases per month. Before the feature list, the positioning matters: **LogScope is built by a Bluetooth LE engineer for Bluetooth LE engineers first.** It works for any J-Link-based embedded project (Nordic, ST, Silicon Labs, NXP, Infineon, generic Cortex-M targets), and a lot of the value (live log streaming, severity filtering, Wireshark export, fault auto-detection) serves general embedded work just fine. But the features that genuinely distinguish LogScope from any other RTT viewer are all things only someone deep in Bluetooth LE would think to build: the inline HCI decoding, the upcoming Bluetooth Core Spec hyperlinks, the connection-parameter visualization, the fault detection tuned for Zephyr Bluetooth stack failures, and the btsnoop export pipeline. If you do general embedded work, LogScope serves you well. If you do Bluetooth LE work, it serves you better. The major moves since v0.1.0: - **Bluetooth LE HCI decoding inline** with 14+ packet decoders (HCI commands and events, ACL/ATT/GATT operations, expandable detail views) - **Direct-memory RTT recovery** (v0.6.0), which solved the mid-session reset bug that broke J-Link RTT Viewer in the same scenarios - **Fault auto-detect** for hard faults, bus faults, Zephyr fatal errors, assertions, stack overflows, and watchdog resets - **Wireshark btsnoop export** so HCI captures hand off cleanly to deeper protocol analysis - **Multi-parser support** (Zephyr, nRF5 SDK, raw mode) so non-Zephyr firmware works too ![LogScope connected to an nRF54L15 DK, showing live RTT logs with Bluetooth LE HCI commands decoded inline. The sidebar shows Channel 0 Terminal and Channel 1 btmonitor; the log panel shows HCI EVT and CMD rows alongside application logs, with fault highlights on red ERR rows.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/connected.png) LogScope in action: a live RTT stream from an nRF54L15 DK, with Bluetooth LE HCI commands decoded inline (LE Set Advertising Parameters, LE Set Scan Response Data) alongside Zephyr application logs and fault highlights. The current focus (v0.7) is full [ATT and GATT](https://novelbits.io/bluetooth-le-att-gatt-explained-connection-oriented-communication/) protocol decoding with inline Bluetooth Core Specification hyperlinks. Click any HCI event, ATT error, or SMP failure code and jump straight to the section in the Core Spec that defines it. That’s a moat that no horizontal AI-for-embedded tool can replicate without building a Bluetooth Core Spec retrieval system of their own, and we already have one. Every release ships with a dedicated page in the [LogScope releases archive](https://docs.novelbits.io/logscope/releases/?ref=novelbits.io), auto-generated from the changelog, so you can see what changed and when. In this post, we covered: - Why J-Link RTT Viewer’s plain-text, outside-the-editor, no-Bluetooth-LE-awareness workflow stopped working for me - How AI coding agents in 2026 dropped the activation energy for shipping niche developer tools - The six-hour build that took LogScope from blank repo to working extension - Why I think the real differentiator just shifted from coding skill to domain experience and product judgment - What the LinkedIn launch showed me about how many engineers had the same itch - Where LogScope is now (v0.6.5, with v0.7 ATT/GATT decode in flight) You should now have a clear sense of what LogScope is and why it exists. If you want to try it, it’s a free install on the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=novelbits.novelbits-logscope&ref=novelbits.io). If you want to follow along, the [GitHub repo](https://github.com/NovelBits/logscope?ref=novelbits.io) is public and the issue tracker is open. 💡 **Insider Tip:** Want to go deeper into Bluetooth LE protocol work, the kind of debugging this whole tool was built around? Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) for in-depth courses on HCI, GATT, SMP, advertising, and connection parameters. ### Bluetooth LE Audio and Auracast: The Profile Stack Explained (BAP, PBP, CAP, TMAP, HAP, GMAP) URL: https://novelbits.io/bluetooth-le-audio-auracast-profiles/ Last updated: 2026-05-17T11:33:17.000Z If you’ve been following Bluetooth audio over the last few years, you’ve probably noticed two names showing up everywhere: **Bluetooth LE Audio** and **Auracast**. They’re often used interchangeably, and that’s the first thing worth straightening out, because they’re not the same thing. LE Audio is the entire next-generation Bluetooth audio platform. It’s the replacement story for A2DP, the stereo audio profile that’s powered Bluetooth headphones since the early 2000s. Auracast is one *feature* inside LE Audio, specifically the broadcast audio feature, where a single transmitter can send audio to an unlimited number of receivers without any pairing. The relationship is something like: **LE Audio is the road, Auracast is one (very interesting) car on that road.** In this post, we’ll cover: - What Bluetooth LE Audio actually is, and the three building blocks underneath it - What Auracast is, how it works end-to-end, and how it differs from A2DP - The six LE Audio profiles you’ll keep seeing referenced (BAP, PBP, CAP, TMAP, HAP, GMAP) and what each one is responsible for - What the LE Audio software situation looks like from a developer’s perspective today - A short FAQ at the bottom covering the questions I get asked most 💡 **Insider Tip:** Want to go deeper into LE Audio implementation, codec configurations, and hands-on Auracast development? The [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) has full courses on the Bluetooth LE protocol stack and the LE Audio profiles covered below. ## Key takeaways - **LE Audio** is the umbrella name for the new Bluetooth audio stack built on Bluetooth LE (not Classic). Its three foundational building blocks are the **LC3 codec**, **isochronous channels** (CIS and BIS, introduced in Bluetooth 5.2), and **multi-stream audio**. - **Auracast** is one feature within LE Audio: one-to-many broadcast audio over Broadcast Isochronous Streams (BIS), with no pairing required between source and receiver. - The LE Audio profile suite (BAP, PBP, CAP, TMAP, HAP) was published in mid-2022\. The Gaming Audio Profile (GMAP) was added later. - The three Auracast use cases worth knowing: **public venues** (airports, gyms, gate announcements), **assistive listening** (hearing aids in public spaces, a huge accessibility story), and **personal audio sharing** (one phone driving multiple sets of headphones). - Six LE Audio profiles cover the layered stack: **BAP**(foundation), **PBP** (public Auracast streams), **CAP** (coordination across devices), **TMAP** (telephony and media), **HAP**(hearing aids), **GMAP** (low-latency gaming). ## What is Bluetooth LE Audio? LE Audio is the rebuild of Bluetooth audio on top of Bluetooth Low Energy. That’s worth pausing on. For two decades, all the Bluetooth audio you’ve ever heard (headphones, speakers, hands-free in your car) ran on **Bluetooth Classic**, also called BR/EDR (Basic Rate / Enhanced Data Rate). LE Audio moves the entire audio stack over to Bluetooth LE, which is the lower-power radio that’s been used mostly for sensors, beacons, and notifications until now. Let’s look at the three things that make LE Audio possible: **1\. The LC3 codec.** LC3 stands for Low Complexity Communication Codec. It replaces the SBC codec that’s been mandatory for A2DP. LC3 delivers better audio quality at lower bitrates than SBC, which is the whole reason LE Audio can match or beat Classic audio quality while using less radio time and less battery. That last point matters a lot for earbuds, where every milliwatt saved is more battery life. **2\. Isochronous channels.** Introduced in **Bluetooth Core Specification version 5.2**, isochronous channels are the time-synchronized transport that audio needs to work over Bluetooth LE. They come in two flavors: - **CIS (Connected Isochronous Stream):** unicast, one-to-one. Used for things like a phone streaming music to a single pair of earbuds. - **BIS (Broadcast Isochronous Stream):** broadcast, one-to-many. This is the foundation Auracast is built on. **3\. Multi-stream audio.** LE Audio is natively multi-stream from the bottom up. A pair of true wireless earbuds can each receive their own independent, synchronized stream from the phone (a real left and a real right channel), instead of the awkward Classic-Bluetooth workaround where one bud forwards audio to the other. The LE Audio profile suite (the upper-layer specifications that define how all of this gets used in real products) was rolled out by the Bluetooth SIG between late 2021 and mid-2022\. **Basic Audio Profile v1.0 was adopted 2021-09-14, with v1.0.1 following on 2022-06-21\. Common Audio Profile v1.0 landed 2022-03-22, Hearing Access Profile v1.0 on 2022-06-07, Telephony and Media Audio Profile v1.0 on 2022-06-11, and Public Broadcast Profile v1.0 on 2022-07-05**(per the spec front matter on each profile’s Bluetooth SIG specification page). If you want a deeper look at the spec-mechanics layer (LC3 frame structure, presentation delay, EATT, LE Power Control), we have a [separate post on Bluetooth 5.2 features](https://novelbits.io/bluetooth-version-5-2-le-audio/) that goes into those details. This post stays focused on Auracast and the profile stack. ## What is Auracast? Let’s start with the short definition. Auracast is the Bluetooth SIG’s brand name for **broadcast audio built on top of Broadcast Isochronous Streams**. Functionally, an Auracast transmitter advertises one or more audio streams over BIS, and any nearby receiver can discover and join those streams without pairing, without prior knowledge of the transmitter, and without limit on how many receivers can listen at once. Let’s walk through what that actually looks like end-to-end: 1. The **transmitter** (say, a TV at the airport gate, or a microphone at a yoga class) configures one or more **Broadcast Isochronous Groups (BIGs)**, each containing one or more BIS. Each BIS carries an LC3-encoded audio stream. 2. Alongside the audio data, the transmitter sends out **Extended Advertisements** containing a **Broadcast Audio Announcement** (defined in the Basic Audio Profile, Service UUID 0x1852) and, if it claims Auracast compliance, a **Public Broadcast Announcement** (defined in the Public Broadcast Profile, Service UUID 0x1856). A third element, the **Basic Audio Announcement** (BAP, Service UUID 0x1851), travels in the *periodic* advertising train and carries the Broadcast Audio Source Endpoint (BASE) structure that describes the actual audio stream configuration. Together, these three tell a receiver what’s available, at what quality, and how to decode it. 3. A **receiver** (your earbuds, your hearing aid, your phone) scans for those advertisements, picks a stream that matches its capabilities, and synchronizes to the BIG to start decoding audio. 4. Optionally, an **Auracast Assistant** (typically your phone) can scan on behalf of a constrained device (like a hearing aid that doesn’t have a great UI), find the right stream, and tell the receiver which BIG to lock onto. The Assistant is what makes “tap the airport gate sign with your phone, your hearing aids start playing the announcement” actually work. Three use-case archetypes are worth keeping in your head, because they map directly onto how Bluetooth SIG positions Auracast publicly (“Share your audio,” “Unmute your world,” “Hear your best”): - **Public venues.** Airports, gyms, train stations, conference rooms, museum exhibits, gate announcements. Anywhere there’s a TV on mute or a sound system that would benefit from a wireless overlay. - **Assistive listening.** Hearing aid users in public spaces. This is the *huge* one for accessibility (no more dragging hearing-loop wiring around historic buildings). - **Personal audio sharing.** One phone, multiple listeners, each on their own headphones. You and a friend on a plane watching the same movie, each with your own earbuds. ![Sequence diagram of Auracast end-to-end roles: the Source configures and advertises a Broadcast Isochronous Group, the Assistant scans on behalf of the Sink and transfers SyncInfo via PAST, and the Sink synchronizes to the BIG and decodes the LC3 audio stream.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/auracast-end-to-end-roles.png) *Figure 1: Auracast end-to-end. The Source advertises the broadcast (extended adv and periodic adv). The Assistant helps a constrained Sink find the right stream by transferring SyncInfo via the BASS / Scan Delegator path. The Sink synchronizes to the BIG and decodes the LC3 audio.* ### How is this different from A2DP? A2DP (Advanced Audio Distribution Profile) is the legacy stereo audio profile that’s powered Bluetooth headphones since the early 2000s. A reasonable comparison: | Dimension | A2DP | Auracast | | ------------------- | -------------------------------------- | --------------------------------------------------------- | | Transport | Bluetooth Classic (BR/EDR) | Bluetooth LE (BIS, introduced in 5.2) | | Topology | Unicast, one-to-one | Broadcast, one-to-unlimited | | Mandatory codec | SBC (with AAC, aptX, LDAC as optional) | LC3 | | Pairing required? | Yes | No | | Native multi-stream | No (TWS hacks around it) | Yes | | Encryption | Per-connection (paired) | Optional, via 16-octet Broadcast\_Code shared out-of-band | Auracast is also explicitly designed to be **discoverable without bonding**. A2DP requires a pairing dance up front. Auracast receivers just listen for advertisements and join. That changes the user experience pretty fundamentally: you don’t “pair with an airport,” you just walk up and tune in. One nuance worth knowing: Auracast streams *can* be encrypted. The transmitter optionally sets a 16-octet **Broadcast\_Code** that receivers need in order to decrypt the BIS payload (defined in the Core Specification v6.3 §4.4.6.10). For public Auracast streams this is usually disabled (you want the airport announcement to reach everyone), but for private personal Auracast (you sharing your music with one specific friend) you can lock it with a code distributed via a QR code or the Auracast Assistant flow. Extended Advertising Train carried in AUX\_ADV\_IND PDUs on the secondary advertising channels - Broadcast Audio Announcement, Service UUID `0x1852`, defined by BAP - Public Broadcast Announcement, Service UUID `0x1856`, defined by PBP - Broadcast\_Name (human-readable identifier of the broadcast) ↓ Periodic Advertising Train sent on the periodic advertising sync that the extended train points to - Basic Audio Announcement, Service UUID `0x1851`, defined by BAP - BASE: codec configuration, audio channel allocation, presentation delay, metadata - BIGInfo: BIS scheduling parameters and encryption status ↓ BIS: Broadcast Isochronous Stream LC3-encoded audio data, optionally encrypted with the 16-octet Broadcast\_Code *Figure 2: The three advertising elements an Auracast transmitter sends. The Extended Advertising train carries the Broadcast Audio Announcement (0x1852, BAP) and the Public Broadcast Announcement (0x1856, PBP), the Periodic Advertising train carries the Basic Audio Announcement (0x1851, BAP) and the BASE plus BIGInfo, and the actual audio rides on the Broadcast Isochronous Stream (BIS).* ## The LE Audio profile stack Let’s now step back and look at the LE Audio profile stack as a whole. LE Audio is intentionally layered: each profile builds on the ones below it, and devices can implement just the layers they need. Let’s walk through all six, because while it can feel like a lot of acronyms, the layering actually makes a lot of sense once you see it. ![Layered architecture diagram of the LE Audio profile stack: Core Bluetooth LE foundations (LC3 codec and Isochronous Channels introduced in Bluetooth 5.2) at the base, BAP (Basic Audio Profile) as the foundation profile, PBP (Public Broadcast Profile) and CAP (Common Audio Profile) on top of BAP, and TMAP, HAP, and GMAP on top of CAP.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/05/le-audio-profile-stack.png) *Figure 3: The LE Audio profile stack. BAP is the foundation every device implements. PBP adds the Auracast public-broadcast rules on top of BAP. CAP adds the coordination layer used by the consumer-product profiles (TMAP for media + telephony, HAP for hearing aids, GMAP for gaming).* ### BAP: Basic Audio Profile BAP is the foundation. Everything else in the LE Audio stack depends on it. BAP defines **six profile roles** (per BAP v1.0.2 §2.2): - **Unicast Server** (a device that exposes audio capabilities and receives a unicast stream, e.g. an earbud) - **Unicast Client** (a device that initiates unicast streams, e.g. a phone) - **Broadcast Source** (a transmitter of broadcast audio, e.g. an Auracast TV) - **Broadcast Sink** (a receiver of broadcast audio, e.g. an Auracast-compatible earbud) - **Broadcast Assistant** (a helper device that scans on behalf of a constrained receiver, e.g. your phone helping your hearing aid find a stream) - **Scan Delegator** (the constrained device’s side of the Assistant relationship) BAP also defines the **codec configurations** every LE Audio device must support, plus the **Quality of Service (QoS) configurations** for unicast audio (retransmission counts, transport latency, presentation delay, framing). Those QoS configurations are what let a chipset claim “compatible with LE Audio” with confidence. If you implement nothing else, you implement BAP. Everything from a $20 earbud to a public Auracast loudspeaker speaks BAP underneath. ### PBP: Public Broadcast Profile PBP is the profile that defines what Auracast actually *looks like* over the air for public-venue broadcasts. It’s a thin layer on top of BAP that adds two important things. First, it defines two stream **quality tiers**: - **Standard Quality (SQ):** 16 kHz or 24 kHz sample rate with 10 ms frames. PBP-compliant (Auracast) receivers are required to support SQ, which means *every* Auracast receiver is guaranteed to be able to play it. - **High Quality (HQ):** 48 kHz sample rate with 10 ms frames. Optional. Lets premium devices stream higher-fidelity audio when the receiver can handle it. Second, PBP defines the **Public Broadcast Announcement** (Service UUID 0x1856), which is the data element a transmitter includes in its Extended Advertisements to tell receivers “this is an Auracast-compliant public broadcast, and here’s whether I’m transmitting at SQ, HQ, or both.” Public Auracast transmitters are required to make at least one SQ stream available, so a hearing aid that can only decode SQ never gets shut out of an airport announcement. The Auracast Transmitter Recommendations document spells out the rules for public transmitters specifically: you must transmit at least one SQ stream, you must publish the Public Broadcast Announcement, and you should usually leave the stream unencrypted (so receivers can join without a code). ### CAP: Common Audio Profile CAP is the coordination layer. Where BAP defines how a single device participates in audio streaming, CAP defines how *multiple*devices stay in sync, particularly when they belong to a **Coordinated Set** (the canonical example: a left earbud and a right earbud that act as one logical device). CAP defines three roles (per CAP v1.0.1 §2.1): - **Acceptor** (a peripheral that renders or transmits audio, e.g. an earbud or hearing aid) - **Initiator** (a central that starts and controls audio streams, e.g. a phone or laptop) - **Commander** (a controller that orchestrates a Coordinated Set’s behavior, e.g. a hearing aid remote that adjusts both ears simultaneously, or a phone’s volume slider that needs to set the same level on both earbuds at once) Underneath, CAP uses the **Coordinated Set Identification Service (CSIS)** so that set members can find each other and recognize that they belong together. CAP procedures cover **synchronized volume control**, **synchronized mute**, **microphone control**, **content control**, and the audio-stream transitions between unicast and broadcast (the famous “your earbuds switch from listening to your phone’s music to listening to the gym TV’s Auracast and back again” handoff). CAP is one of those profiles you don’t see, but you feel. Without it, your two earbuds would slowly drift on volume, and switching between music and Auracast would feel clunky. ### TMAP: Telephony and Media Audio Profile TMAP is the **consumer-product profile**. It sits on top of CAP and defines the roles and requirements for the two use cases most people actually use audio for: media playback and phone calls. For our purposes, the two TMAP roles you’ll see referenced most often are **Broadcast Media Sender** and **Broadcast Media Receiver** (defined in TMAP §3.5.2). The Auracast Transmitter Recommendations document explicitly maps “Auracast transmitter” and “Auracast receiver” to these TMAP roles, which is how TMAP shows up in the Auracast story. TMAP also defines unicast roles for telephony (call gateway and call terminal), so a hands-free LE Audio earbud + phone pair speaks TMAP for both the music-streaming and phone-call directions. **If you’re building a consumer earbud or headphone with LE Audio, TMAP is the profile your product will most likely claim conformance with.** ### HAP: Hearing Access Profile HAP is the hearing-aid-specific profile, and it’s one of the most genuinely consequential parts of the LE Audio rollout for end users. HAP defines four roles (per HAP v1.0.1 §2.1): - **HA (Hearing Aid).** Implemented on the hearing aid itself. Can be a single Monaural Hearing Aid, a Banded Hearing Aid (one device with separate left/right outputs), or a member of a Binaural Hearing Aid Set (matched left + right pair). - **HAUC (Hearing Aid Unicast Client).** A device that sends unicast audio to the hearing aid, typically a smartphone, tablet, or laptop. - **HARC (Hearing Aid Remote Controller).** A device (e.g. a dedicated remote, or your phone in remote-controller mode) that adjusts hearing-aid volume, mute, and **presets** (named hearing-aid configurations like “quiet room,” “restaurant,” “outdoor”). - **IAC (Immediate Alert Client).** A device that can grab the HA wearer’s attention (think: a doorbell triggering an alert through the hearing aid). The preset system is one of HAP’s defining features. The Hearing Access Service exposes a list of named preset records (in UTF-8, localized to the wearer’s language), and a controller can switch between them via the Preset Control Point characteristic. So a hearing aid wearer with a “noisy restaurant” preset can hit one button on a remote and the hearing aid adjusts every parameter to match. HAP requires **Bluetooth Core Specification 5.2 or later** for the HA, HAUC, and HARC roles (because isochronous channels are required). The simpler IAC role can run on Core 4.2. ### GMAP: Gaming Audio Profile GMAP is the most recent addition to the LE Audio profile family. It’s optimized for the one use case the original LE Audio profile set didn’t tune for: **low-latency gaming**. GMAP defines four roles (per GMAP v1.0.1 §2.2): - **UGG (Unicast Game Gateway):** smartphones, gaming devices, laptops, tablets, PCs (the source of game audio) - **UGT (Unicast Game Terminal):** gaming headphones, earbuds, wireless microphones (the rendering side) - **BGS (Broadcast Game Sender):** broadcast game audio source - **BGR (Broadcast Game Receiver):** broadcast game audio sink What makes GMAP “low latency” is its set of mandatory codec configurations and the corresponding QoS constraints. GMAP devices target end-to-end audio latency in the 20-30 ms range with various reliability/latency trade-offs the controller can pick from (per GMAP v1.0.1 §3.5.2.3 Table 3.22). For comparison, the LE Audio default media QoS settings target higher transport latency for better reliability, which is fine for music but noticeable in gaming. If you’ve ever fired a gun in a competitive shooter and heard the muzzle flash three frames before the sound, you understand why GMAP exists. ## Getting started as a developer Let’s bring this down to ground level. Here’s the honest 2026 picture of where LE Audio is on the silicon and SDK side. **Nordic Semiconductor** is the most LE Audio-ready of the silicon vendors I track. Their flagship LE Audio chip is the **nRF5340**, a dual-core SoC explicitly architected for LE Audio: the 128 MHz application core handles LC3 encode/decode and your application, and the 64 MHz network core runs a dedicated LE Audio Bluetooth controller (per the [nRF5340 Audio DK product page](https://www.nordicsemi.com/Products/Development-hardware/nRF5340-Audio-DK?ref=novelbits.io)). The newer **nRF54H20** is also positioned for LE Audio applications. nRF Connect SDK ships the full stack: LE Audio Controller, Zephyr-based Bluetooth Host, the licensed LC3 codec library, the LE Audio profiles from Zephyr, and a complete reference application at `applications/nrf5340_audio` that you can build as a USB dongle, TWS earbud, headset, or broadcast receiver. NCS v2.0.0 introduced experimental LE Audio support; v2.6.0 promoted isochronous channels to “supported” maturity; v2.8.0 added the `nRF Auraconfig` sample, which can act as an Auracast broadcaster with configurable presets. Beyond Nordic, two other vendors have shipping LE Audio support today worth knowing about. **NXP’s IW612** connectivity SoC brings BIS and CIS to MCUXpresso, and **STMicroelectronics’ STM32WBA** family (Bluetooth 5.4) provides LE Audio through STM32CubeWBA. Coverage on both is less mature than Nordic’s flagship LE Audio platform, so the safest move is to confirm the specific profiles you need (BAP, PBP, CAP, TMAP, HAP, GMAP) with the vendor’s FAE before committing. Several other Bluetooth LE silicon vendors don’t yet ship LE Audio in their public SDKs as of mid-2026, so plan around current shipping reality if you’re evaluating options outside the three above. For learning the stack itself, the Bluetooth SIG publishes all six profile specifications (BAP, PBP, CAP, TMAP, HAP, GMAP) as free downloads on [bluetooth.com](https://www.bluetooth.com/specifications/specs/?ref=novelbits.io). The two Auracast guideline documents (Auracast Transmitter Recommendations, and the Auracast Receiver and Assistant how-to papers) are also worth reading early because they’re written for implementers, not spec lawyers. 💡 **Insider Tip:** The fastest way to get hands-on with LE Audio is to grab the [nRF5340 Audio DK](https://www.nordicsemi.com/Products/Development-hardware/nRF5340-Audio-DK?ref=novelbits.io) and walk through the nRF5340 Audio application in nRF Connect SDK. If you want a guided path through the Bluetooth LE stack first (so the profiles above actually make sense in context), the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io)covers it end-to-end. ## Frequently asked questions ### Is Auracast the same as LE Audio? No. LE Audio is the entire next-generation Bluetooth audio platform (built on Bluetooth LE, using the LC3 codec and isochronous channels). Auracast is one feature within LE Audio: the broadcast-audio feature, built on Broadcast Isochronous Streams (BIS). Every Auracast device is an LE Audio device, but not every LE Audio device implements Auracast. ### Do I need a special chipset to support Auracast? Yes. You need a Bluetooth chipset whose controller supports **isochronous channels**, which were introduced in **Bluetooth Core Specification 5.2**. Most pre-2022 Bluetooth LE silicon doesn’t support BIS, so you can’t add Auracast in software alone. Nordic’s nRF5340 is the canonical Auracast-capable chip today; NXP’s IW612 and STMicroelectronics’ STM32WBA also ship the foundation in their respective SDKs. ### Does Auracast replace A2DP? Over time, yes, but not overnight. A2DP and Bluetooth Classic audio aren’t being deprecated; they’ll coexist with LE Audio for years, especially in cars and legacy hardware. The long-term direction is that new audio products move to LE Audio, and Auracast handles the broadcast use cases (public venues, assistive listening, personal sharing) that A2DP literally cannot. ### Can Auracast actually be used for hearing aids? Yes, and that’s one of its most important use cases. The Hearing Access Profile (HAP) maps a hearing aid to the BAP **Broadcast Sink** role, so a HAP-compliant hearing aid can directly receive a public Auracast broadcast (an airport announcement, a movie theater’s audio feed, a church’s sermon). The user experience is typically “tap the QR code at the venue with your phone, your hearing aids join the broadcast,” with the phone acting as the Auracast Assistant. ### What Bluetooth version do I need for Auracast? Bluetooth Core Specification **5.2 or later** for the controller-level isochronous channel support that Auracast requires. The profile specifications themselves (BAP, PBP, CAP, etc.) were published as standalone documents in 2022 and reference Core 5.2 features. ### Is Auracast encrypted? Optionally. The Core Specification defines BIG-level encryption using a 16-octet **Broadcast\_Code** that the transmitter sets and that receivers must obtain (typically via a QR code, a tap-to-share mechanism, or the Auracast Assistant). Public Auracast transmitters at venues usually leave streams unencrypted (the goal is universal access), while personal-sharing scenarios commonly enable the Broadcast\_Code to keep the audio private. ### When will Auracast be everywhere? Honestly, I’d rather not put a date on it. The chipset support is here, the profile stack is published, and the first wave of Auracast-capable phones, hearing aids, and venue installations is shipping. Mainstream rollout in public venues (airports, gyms, transit) is the gating factor and that’s an infrastructure-replacement timeline, which historically takes years for any new audio standard. I’d plan around 2027-2028 for “broadly noticeable in public” and treat anything sooner as a bonus. ## Wrapping up In this post, we covered: - What Bluetooth LE Audio is (the umbrella stack on Bluetooth LE) and the three building blocks underneath it: LC3, isochronous channels, and multi-stream audio - What Auracast is (broadcast audio over BIS, no pairing) and how it compares to A2DP across transport, topology, codec, and discovery - The six LE Audio profiles (BAP as foundation, PBP for public Auracast, CAP for coordination, TMAP for consumer media + telephony, HAP for hearing aids, GMAP for low-latency gaming) and the role each one plays - Where the developer-side reality stands in 2026, and which vendors are ready today You should now be able to read any LE Audio or Auracast announcement and place it correctly in the stack (is this a BAP-level change, a CAP coordination feature, a HAP preset update?). You should also have a clear answer to the most common confusion in this space: **LE Audio and Auracast aren’t the same thing**. Auracast is one feature within LE Audio. 💡 **Insider Tip:** Want a deeper, structured path through Bluetooth LE (the protocol stack underneath all of this) and the LE Audio profiles in detail? The [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io)has full courses with sample code, captures, and projects so you can build real LE Audio products end-to-end. ### How Much Signal Do Building Materials Block? Real Bluetooth LE Measurements URL: https://novelbits.io/rf-chamber-episode-1-material-attenuation-public/ Last updated: 2026-07-28T15:19:25.000Z Every Bluetooth Low Energy (Bluetooth LE) product has to work through enclosures and building materials. But how much signal do they actually block? If you’re designing a sensor inside a plastic enclosure or a tracker behind a metal panel, you need real numbers, not guesses. I’ve seen plenty of generic “RF attenuation” charts online, but most cite vague ranges without specifying the frequency or test methodology. For Bluetooth LE developers working at 2.4 GHz, that’s not good enough. So I decided to measure it myself, inside a calibrated RF shielded chamber, with a repeatable test setup. Let’s take a look at what the data shows. In this post, we’ll cover: - Why material attenuation matters for Bluetooth LE product design - The test setup: how we measured signal loss through real materials inside a $4,000 RF chamber - Two measured results: ABS plastic and aluminum foil, the extremes of the spectrum - What surprised us in the middle ground (and why the full Academy analysis matters) 💡 **Insider Tip:** Want to see the full material comparison and the surprising antenna detuning discovery? Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io)for the complete Episode 1 analysis with all configurations tested. ## Why Material Attenuation Matters If you’ve ever deployed a Bluetooth LE device in the real world, you know that the range you measured on your desk rarely matches what you get in the field. A big part of that gap comes down to what’s between the transmitter and receiver, and I don’t just mean distance. Building materials absorb and reflect RF energy at 2.4 GHz. The amount varies dramatically depending on the material. Most developers don’t have hard numbers for these materials at Bluetooth LE frequencies, so they end up over-engineering (cranking TX power to maximum “just in case”) or under-engineering (discovering range problems after deployment). Let’s step back and look at why having real attenuation data changes how you approach product design: - **Enclosure material selection**: If you’re choosing between ABS plastic and an aluminum housing for your Bluetooth LE sensor, the RF attenuation difference could mean reliable connectivity versus a device that can’t even establish a connection. Knowing the actual impact lets you make an informed decision before you commit to a Bill of Materials (BOM). - **Link budget calculations**: A proper link budget accounts for every source of signal loss: TX power, antenna gain, free-space path loss, and material attenuation. For example, if your link budget has 5 dB of margin and the enclosure material attenuates 8 dB, you have a problem. But you won’t know that until you measure. - **Installation planning**: If you’re deploying sensors in a building, knowing exactly how much each material attenuates helps you plan repeater placement and estimate coverage. The difference between “some loss” and “total blockage” is the difference between a working deployment and a support nightmare. ## The Test Setup Let’s walk through the test setup. For this experiment, I used the Ramsey STE3000M RF shielded chamber (a $4,000 professional-grade enclosure) that we verified in [Episode 0](https://novelbits.io/rf-chamber-episode-0-shielded-enclosure-bluetooth-le/). The chamber demonstrated over 85 dB of shielding effectiveness at 2.4 GHz, giving us a controlled, interference-free environment where the only variable is the material we place between the transmitter and receiver. ![Overview of the test setup inside the RF shielded chamber](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/04/01-baseline-air-topdown.jpg) Overview of the test setup inside the RF shielded chamber Here’s the equipment and configuration: - **Transmitter**: Nordic Semiconductor nRF54L15 DK, transmitting at 0 dBm on LE 1M PHY - **Separation**: 4 inches between transmitter and receiver antennas - **Measurement**: Received Signal Strength Indicator (RSSI) and Packet Error Rate (PER) monitored on the receiver - **Protocol**: Bluetooth LE connection established, then material samples inserted between devices - **Chamber**: Ramsey STE3000M with absorber foam to minimize reflections The basic approach: establish a baseline measurement with nothing between the transmitter and receiver, then insert a material sample, measure again, and compare. With the devices only 4 inches apart and the transmitter set to 0 dBm, we had plenty of signal margin to detect even small changes in attenuation. Our baseline measurement came in at **\-26 dBm RSSI with 0% Packet Error Rate (PER)**. This is the reference point: the signal strength with a clear line of sight between the two devices, no material in the way. Let’s look at what we found. ## The Results: Two Extremes We tested multiple materials and configurations in total. For this public post, let’s dive into the two results that define the boundaries of what’s possible. They sit at opposite ends of the attenuation spectrum, and they tell you a lot about what to expect from your own designs. ### ABS Plastic: Completely Transparent ABS (Acrylonitrile Butadiene Styrene) is one of the most common enclosure materials for consumer electronics. It’s what most Bluetooth LE sensor housings, smart home devices, and wearable casings are made from. If you’ve 3D-printed a prototype enclosure, there’s a good chance it was ABS. ![ABS plastic sample positioned between the transmitter and receiver](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/04/03-abs-plastic-setup.jpg) ABS plastic sample positioned between the transmitter and receiver The result? ABS plastic is completely transparent to Bluetooth LE signals at 2.4 GHz. With the ABS sample in place, we measured **\-26 dBm RSSI and 0% PER**, identical to our baseline. That’s **0 dB of attenuation**. The signal passed through the plastic as if it wasn’t there. For practical purposes, an ABS enclosure adds zero measurable signal loss to your link budget. If you’re seeing range problems with a device in an ABS housing, the enclosure is not your problem. Look at your antenna design, TX power configuration, or the RF environment instead. This is good news for the vast majority of consumer Bluetooth LE products. Your plastic enclosure is not degrading your RF performance. ### Aluminum Foil Wrap: Total Blockage Now let’s look at the other extreme. We wrapped one of the devices completely in aluminum foil (with no cable passthrough) to simulate a fully enclosed metal housing. The kind of scenario you’d encounter with a sealed metal enclosure, an equipment rack, or a foil-backed insulation panel. ![Device fully wrapped in aluminum foil to simulate a sealed metal enclosure](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/04/21-foil-wrap-sealed.jpg) Device fully wrapped in aluminum foil to simulate a sealed metal enclosure The result was decisive: **the devices could not even establish a Bluetooth LE connection**. Total blockage. Not degraded performance, not higher packet loss, simply no communication whatsoever. This has real implications. If your device sits inside a metal enclosure (industrial sensors, equipment monitoring, automotive applications), you cannot rely on the signal radiating through the housing. You will need an external antenna, an RF window made from a non-metallic material, or a deliberate gap in the shielding. I’ve seen developers discover this the hard way: prototype with a 3D-printed plastic case, everything works beautifully, then move to the production metal enclosure and the device goes completely silent. Having the data upfront prevents that expensive surprise. ## The Surprising Middle Ground Those two extremes are useful anchors: plastic is invisible, metal is an impenetrable wall. But the really interesting results live in between. We tested ceramic tile, multiple aluminum configurations (not just the full wrap), and discovered something genuinely unexpected about what happens when metal is near an antenna without fully enclosing it. I’ll say this much: the relationship between metal proximity and signal degradation is not what most developers assume. The data revealed a phenomenon that goes beyond simple attenuation, and it has direct implications for how you position antennas relative to metal surfaces in your product designs. ![Material attenuation comparison: from ABS plastic (0 dB) to sealed aluminum (total block), with Academy-only configurations in between.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/04/results-chart-teaser-2.png) The full spectrum: from completely transparent to total blockage. What happens in between is available in the Academy. The full Academy lesson for Episode 1 covers: - **All materials and configurations tested** with exact RSSI values, PER numbers, and attenuation calculations - **A detailed comparison table** showing how each configuration stacks up - **The antenna detuning discovery** that changed how I think about metal near Bluetooth LE antennas - **Multiple aluminum configurations compared** revealing that how you use metal matters as much as whether you use it - **Practical design guidelines** for enclosure selection, antenna placement, and deployment strategy ## Why Controlled Measurements Matter You might be wondering: couldn’t I just test this at my desk? Set up two dev boards, put a piece of material between them, and compare the RSSI readings? You could, but the results would be unreliable. In an open environment, the signal goes around the material, bounces off walls, and gets influenced by whatever Wi-Fi traffic happens to be present. Your “material attenuation” measurement would actually be a mixture of direct-path attenuation, multipath reflections, diffraction, and ambient interference. The shielded chamber eliminates those confounding variables. The absorber foam minimizes internal reflections, the shielding blocks external interference, and fixed device positions ensure repeatable geometry. When we measure a difference with a material in place, we know it’s from the material, not from someone’s microwave oven turning on next door. That’s the value of a $4,000 chamber. It turns “I think plastic is fine” into “I measured 0 dB attenuation through ABS at 2.4 GHz with 0% packet error rate.” One is a guess. The other is engineering. ## Wrapping Up In this post, we covered why material attenuation matters for Bluetooth LE product design, walked through the test setup inside the RF shielded chamber, and looked at two measured results that define the extremes: ABS plastic (completely transparent, 0 dB attenuation) and aluminum foil wrapping (total blockage, connection impossible). Here are the key takeaways: - **Material attenuation at 2.4 GHz varies from zero to total blockage** depending on the material, making it one of the most important variables in your link budget - **ABS plastic enclosures** are completely transparent to Bluetooth LE signals (0 dB measured attenuation, 0% PER), so if you’re seeing range problems with a plastic-housed device, look elsewhere - **Metal enclosures** can completely block Bluetooth LE signals to the point where a connection cannot even be established. Plan for external antennas or non-metallic RF windows - **Controlled measurements** in a shielded chamber isolate the material’s effect from multipath, diffraction, and interference - **The middle ground between plastic and metal** is where the most actionable (and surprising) data lives You should now have a clearer picture of how materials at opposite ends of the spectrum affect Bluetooth LE signals, and why having real measured numbers matters for your product design decisions. 💡 **Insider Tip:** Want the complete material comparison with all configurations, the antenna detuning analysis, and practical design guidelines? The [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) has the full Episode 1 analysis, including results that will change how you think about metal near Bluetooth LE antennas. Stay tuned for the next episode, where we’ll continue testing more materials and configurations inside the chamber. ### Meet the Nordic nRF54LS05: The Cost-Optimized Entry Point to the nRF54L Series URL: https://novelbits.io/nordic-nrf54ls05-introduction/ Last updated: 2026-04-08T17:57:56.000Z *This post is sponsored by* [*Nordic Semiconductor*](https://www.nordicsemi.com/?ref=novelbits.io)*.* Not every connected product needs a powerhouse SoC. In fact, a huge portion of Bluetooth Low Energy (Bluetooth LE) devices out there are doing relatively straightforward things — reading a temperature sensor, broadcasting a beacon signal, or forwarding button presses from a remote control. For these kinds of applications, loading up on memory and peripherals you’ll never use just drives up cost and complexity without adding real value. Nordic Semiconductor clearly understands this. After expanding the nRF54L Series with the feature-packed nRF54LM20A (which I covered in a [previous post](https://novelbits.io/nordic-nrf54lm20a-introduction/)), they’ve now introduced the nRF54LS05A and nRF54LS05B — entry-level, ultra-low-power Bluetooth LE SoCs built specifically for simple, cost-sensitive wireless applications. **Note:** The nRF54LS05A/B datasheet is currently preliminary (v0.6), and all specifications listed in this post are estimated values that may change in subsequent updates. Nordic is running a project-based early access program — customers can apply to be enrolled and receive SoC samples and development kits. Think of them as the “right-sized” members of the nRF54L family. They inherit the same 22nm architecture and power efficiency improvements that define the series, but with a memory and peripheral set that’s specifically sized to keep costs low and design complexity to a minimum. ![nRF54LS05A QFN48 SoC perspective view](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/03/nRF54LS05A_QFN48_Perspective-1.png) The nRF54LS05A in its QFN48 package (6x6 mm) — *Source: Nordic Semiconductor* In this post, we’ll cover: - Where the nRF54LS05A and nRF54LS05B fit within the nRF54L Series lineup - The key technical features and specifications of these new SoCs - The difference between the LS05A and LS05B variants - Power consumption highlights from the preliminary datasheet - Real-world applications they’re well suited for - How nRF Connect SDK Bare Metal simplifies development and migration from the nRF5 SDK ## The nRF54L Series: A Complete Portfolio If you’ve been following Nordic’s product evolution, you’ll know that the nRF54L Series represents a significant step forward from the widely adopted nRF52 generation. Built on a 22nm low-leakage process (compared to the previous-generation process used in the nRF52), the series delivers roughly 2x the processing power and 3x the processing efficiency, with an Arm Cortex-M33 running at 128 MHz. Nordic has stated that these improvements, combined with a ultra-low-power radio, result in an average 30%–50% lower system power consumption for common Bluetooth LE use cases. But here’s what makes the nRF54L Series particularly interesting from a product planning perspective: it’s not just one chip. It’s a family of SoCs spanning a wide range of capabilities — from entry-level to premium — with aligned pinouts across multiple variants in the series to streamline hardware migration. Let’s take a quick look at how the lineup breaks down: - **nRF54LS05A/B** — Entry-level. 508 KB NVM, 64–96 KB RAM. Optimized for cost-sensitive, simple Bluetooth LE applications. - **nRF54L05** — Entry-level tier with 500 KB NVM and 96 KB RAM, but includes a RISC-V coprocessor and a broader peripheral set (I2S, PDM, NFC) compared to the LS05 variants. - **nRF54L10** — Mid-range option with 1 MB NVM and 192 KB RAM. - **nRF54L15** — The established workhorse of the series, with 1.5 MB NVM, 256 KB RAM, and a RISC-V coprocessor. - **nRF54LM20A** — The most feature-rich option in the series, with 2 MB NVM, 512 KB RAM, up to 66 GPIOs, high-speed USB, and comprehensive multi-protocol support. The nRF54LS05A and nRF54LS05B are **drop-in pin-to-pin compatible** with each other. For migration to other variants in the series (such as the nRF54L05, nRF54L10, or nRF54L15), the pinouts are the same for the overlapping set of features — which streamlines hardware migration, though some board-level changes may be needed depending on the specific features used. For example, the nRF54LS05A/B feature 37 GPIOs on the QFN48 package, while the nRF54L05 features 31 GPIOs on the same package. That kind of design flexibility is a big deal in product development, especially when you’re managing multiple SKUs or planning for future variants. ## Key Highlights: What the nRF54LS05A/B Bring to the Table Let’s dive into the technical details. Despite being the entry-level option, these SoCs pack a solid set of features for their target applications. ### 128 MHz Arm Cortex-M33 The nRF54LS05A and nRF54LS05B run the same Arm Cortex-M33 processor at 128 MHz as the rest of the nRF54L Series. This is a meaningful upgrade from the Arm Cortex-M4 in the nRF52 generation — you get improved power efficiency per instruction. Note that unlike the higher-end nRF54L variants, the LS05 does not include DSP or FPU capabilities. The preliminary datasheet lists a CoreMark score of 500 at 3.90 CoreMark/MHz, which is roughly 2.4x the nRF52840’s score of 212 — meaning significantly more processing headroom while consuming less power per operation (2.0 mA during CoreMark execution from RRAM with cache). Note that while the Cortex-M33 architecture supports TrustZone, it is not available on the nRF54LS05 variants due to memory constraints. Even for “simple” applications, having a capable processor means your firmware runs faster and returns to sleep sooner, which directly translates to longer battery life. ### Right-Sized Memory Both variants come with 508 KB of Non-Volatile Memory (NVM), which is plenty for a Bluetooth LE application stack plus your application firmware. Where they differ is in RAM: - **nRF54LS05A**: 508 KB NVM + 64 KB RAM - **nRF54LS05B**: 508 KB NVM + 96 KB RAM For context, these memory sizes are comparable to the popular nRF52832 (512 KB Flash, 64 KB RAM), making the LS05 a natural upgrade path for many existing nRF52-based designs. 64 KB of RAM is sufficient for many straightforward Bluetooth LE applications — a sensor that advertises data, a beacon, or a simple peripheral. The 96 KB option (nRF54LS05B) gives you extra headroom if your application needs to handle more simultaneous connections, larger data buffers, or more complex protocol handling. I’d recommend the nRF54LS05B if you’re not tightly cost-constrained and want a comfortable margin for firmware growth. Either way, both variants should serve most simple Bluetooth LE applications well. ### 2.4 GHz Radio The nRF54LS05A/B feature Nordic’s ultra-low-power 2.4 GHz radio supporting both Bluetooth LE (LE 1M and LE 2M) and proprietary 2.4 GHz GFSK modes at data rates up to 4 Mbps. TX power is configurable from -10 dBm to +4 dBm in 1 dBm steps, with an RX sensitivity of -96 dBm at 1 Mbps Bluetooth LE. However, unlike the higher-end nRF54L Series SoCs, the LS05 variants don’t support 802.15.4-based protocols — so no Thread, Zigbee, or Matter. For the cost-optimized applications these chips target, the Bluetooth LE and proprietary 2.4 GHz combination covers the vast majority of use cases. One thing to note: the nRF54LS05 also does not support Bluetooth Channel Sounding. If your application requires high-accuracy distance measurement via Channel Sounding, you’ll want to look at the nRF54L05 or higher. ### Essential Peripherals The nRF54LS05A/B include the peripherals you’d expect for their target applications: - **Three serial interfaces** (SPI, TWI/I2C, UART) — enough for communicating with external sensors, displays, or host MCUs. SPI runs up to 8 MHz, TWI up to 400 kHz (I2C compatible), and UART up to 1 Mbps. - **SAADC** (Successive Approximation ADC) — four channels with up to 14-bit resolution (oversampled at 31.25 ksps), 12-bit at 125 ksps, or 10-bit at up to 1 Msps. More than sufficient for reading analog sensor data directly. - **PWM** (Pulse Width Modulation) — a four-channel modulator with autonomous waveform generation, useful for controlling LEDs, motor speed, or generating audio tones - **QDEC** (Quadrature Decoder) — handy for rotary encoder inputs on remote controls or user interfaces - **Global RTC** (Real-Time Counter) — notably available even in System OFF mode, which is important for timed wakeups with minimal power draw - **Three 32-bit timers** with counter mode, a watchdog timer, and a built-in temperature sensor round out the peripheral set This is what I’d call a “no-waste” peripheral set. You get what you need for the target applications without paying for extras you won’t use. ### Baseline Security The nRF54LS05A/B include a baseline security configuration designed to support compliance with existing and upcoming regulations for Bluetooth LE products. Specifically, the datasheet lists: - **Secure boot** — ensuring only authenticated firmware runs on the device - **Tamper detectors** (TAMPC) — physical protection against hardware-level attacks - **Hardware-accelerated Bluetooth LE encryption** — a 128-bit AES/ECB/CCM/AAR coprocessor handles cryptographic operations without burdening the CPU As connected device regulations continue to tighten globally (the EU Cyber Resilience Act, for example), having built-in security features — even at the entry level — is increasingly important. For example, if you’re building a sensor that receives over-the-air firmware updates, secure boot ensures that only authenticated images can run on the device. This gives you a foundation for secure firmware updates and other security requirements without needing to implement everything from scratch. ### Pin-to-Pin Compatibility The nRF54LS05A/B are available in a **QFN48** (6x6 mm) package with **37 GPIO pins**. As mentioned earlier, the nRF54LS05A and nRF54LS05B are drop-in pin-to-pin compatible with each other. For migration to other nRF54L Series variants, the pinouts are aligned for the overlapping set of features, which simplifies hardware migration — though some board-level adjustments may be needed depending on the target SoC and features used. ## LS05A vs. LS05B: Which One Should You Choose? Let’s keep this simple, because the difference really is straightforward. Both chips are identical except for the amount of RAM: | Feature | nRF54LS05A | nRF54LS05B | | ----------- | ------------------------------------ | ------------------------------------ | | Processor | Arm Cortex-M33 @ 128 MHz | Arm Cortex-M33 @ 128 MHz | | NVM | 508 KB | 508 KB | | **RAM** | **64 KB** | **96 KB** | | Radio | Bluetooth LE + proprietary 2.4 GHz | Bluetooth LE + proprietary 2.4 GHz | | Peripherals | SPI, TWI, UART, ADC, PWM, QDEC, GRTC | SPI, TWI, UART, ADC, PWM, QDEC, GRTC | | Security | Baseline | Baseline | When does the extra 32 KB of RAM matter? Here are a few scenarios where the nRF54LS05B makes more sense: - You’re running the Bluetooth LE stack with multiple simultaneous connections - Your application involves larger data buffers (for example, buffering sensor data before transmitting) - You want extra headroom for future firmware features without worrying about running out of RAM - You’re processing data locally before transmitting (filtering, averaging, simple algorithms) For the simplest use cases — a beacon, a basic sensor, or a remote with a handful of buttons — the nRF54LS05A with 64 KB RAM should be more than enough. ## Power Efficiency: The Numbers Let’s look at the preliminary power consumption figures from Nordic’s datasheet. The nRF54LS05A/B operate on a 1.7–3.6V supply with a single-inductor DC/DC converter, and the operating temperature range is -40°C to +85°C. These are estimated values at 3.0V: ### Active with Radio | Mode | Current (Estimated) | | --------------------------------- | ------------------- | | Bluetooth LE TX, 1 Mbps at 0 dBm | 4.8 mA | | Bluetooth LE TX, 1 Mbps at +4 dBm | 6.6 mA | | Bluetooth LE RX, 1 Mbps | 3.4 mA | ### Active with Processing | Mode | Current (Estimated) | | --------------------------------- | ------------------- | | CPU CoreMark from RRAM with cache | 2.0 mA | ### Sleep Modes | Mode | Current (Estimated) | | --------------------------------------------- | ------------------- | | System ON IDLE with GRTC (XOSC) and 96 KB RAM | 1.2 µA | | System OFF with GRTC wakeup | 0.7 µA | | System OFF | 0.6 µA | The sleep numbers are where things get really interesting for battery-powered devices. At 0.6 µA in System OFF, a standard CR2032 coin cell battery (with roughly 220 mAh of capacity) could keep the device in deep sleep for over 40 years — obviously, the practical limit is the battery’s own shelf life. Even with the Global RTC (GRTC) running for timed wakeups, the current only increases to 0.7 µA. This means you can maintain periodic timekeeping (for example, waking up every 10 seconds to take a sensor reading) with negligible impact on battery life. ## Real-World Applications The nRF54LS05A/B are designed for applications where simplicity, low cost, and long battery life are the primary requirements. Let’s look at some specific use cases: **Environmental Sensors**: Temperature, humidity, air quality, and other sensors that periodically wake up, take a reading, advertise or transmit the data over Bluetooth LE, and go back to sleep. The low sleep current (0.6 µA in System OFF) makes these SoCs well suited for years-long battery life on a coin cell. **Asset Tags and Beacons**: Bluetooth LE beacons for indoor positioning, asset tracking tags for warehouses, or proximity-based triggers. These applications typically need minimal processing power but demand extremely low power consumption and small physical size. **Remote Controls**: Simple wireless remote controls for consumer electronics, smart home devices, or industrial equipment. The QDEC peripheral is particularly useful here for handling rotary encoder inputs. **PC Peripherals**: Wireless mice, keyboards, and other input devices where cost and power efficiency are critical. The proprietary 2.4 GHz mode (up to 4 Mbps) is particularly useful here for low-latency communication, while Bluetooth LE can be used for pairing and smartphone connectivity. **Bluetooth Companion Devices**: One use case that’s easy to overlook — the nRF54LS05A/B can serve as a Bluetooth companion chip in a larger system. For example, if you have a product built around a more powerful (but non-wireless) MCU, you can add Bluetooth LE connectivity by pairing it with an nRF54LS05 over SPI or UART. This is a cost-effective way to add wireless capability to existing designs without replacing the main processor. ## Getting Started: nRF Connect SDK Bare Metal ![nRF54LS05 Development Kit](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/03/nRF54LS05-DK-Info-Image-web-1.jpg) The nRF54LS05 Development Kit — *Source: Nordic Semiconductor* One aspect of the nRF54LS05A/B that I think deserves special attention is the nRF Connect SDK Bare Metal support. If you’re coming from the nRF5 SDK (and many developers are), you’ll appreciate having a familiar programming model on the newer hardware. The nRF54L Series — including the LS05 variants — supports nRF Connect SDK Bare Metal alongside the full Zephyr-based stack. nRF Connect SDK Bare Metal gives you a single-threaded, event-driven programming model without the overhead of an RTOS. For the kinds of simple applications the nRF54LS05 targets — sensors, beacons, remotes — this is often all you need. It’s a smoother migration path from the nRF5 SDK, especially if your team is more comfortable with bare-metal programming. I’ve written a [comprehensive guide to nRF Connect SDK Bare Metal](https://novelbits.io/nrf-connect-sdk-bare-metal-guide/) that covers this in detail, including the architecture differences between bare-metal and Zephyr-based development, migration strategies from the nRF5 SDK, and practical use cases. I recommend checking it out if this approach interests you. ## When to Choose the nRF54LS05: A Decision Guide Let’s step back and look at the big picture. With several SoCs in the nRF54L Series, how do you decide which one is right for your project? ### Choose the nRF54LS05A/B when: - **Cost is a primary concern** — your application is simple and every cent matters at scale - **You’re building simple Bluetooth LE devices** — sensors, tags, beacons, remotes, or basic peripherals - **You don’t need large memory** — 508 KB NVM and 64–96 KB RAM are sufficient for your firmware - **You want a Bluetooth companion chip** — adding wireless capability to an existing design alongside a host MCU - **nRF Connect SDK Bare Metal is preferred** — you want a simpler programming model without RTOS overhead ### Consider the nRF54L15 or nRF54LM20A when: - **You need more memory** — applications requiring >508 KB NVM or >96 KB RAM - **Multi-protocol support is required** — simultaneously running Bluetooth LE, Matter, Thread, or Zigbee - **You need a RISC-V coprocessor** — for time-critical tasks or offloading workloads (available on L15 and LM20A) - **Your design needs more GPIOs** — the LS05 has fewer GPIO pins than the L15 or LM20A - **High-speed USB is needed** — only available on the nRF54LM20A Here’s a quick comparison of the key specs across the lineup: | Feature | nRF54LS05A | nRF54LS05B | nRF54L15 | nRF54LM20A | | --------- | -------------------------- | -------------------------- | ------------------------------------ | ------------------------------------ | | NVM | 508 KB | 508 KB | 1.5 MB | 2 MB | | RAM | 64 KB | 96 KB | 256 KB | 512 KB | | Processor | Cortex-M33 | Cortex-M33 | Cortex-M33 + RISC-V | Cortex-M33 + RISC-V | | USB | No | No | No | High-speed USB | | Protocols | Bluetooth LE + proprietary | Bluetooth LE + proprietary | Bluetooth LE, Thread, Zigbee, Matter | Bluetooth LE, Thread, Zigbee, Matter | | Target | Simple, cost-sensitive | Simple, cost-sensitive | General-purpose | Advanced/premium | What I like about the nRF54L Series is that you don’t have to make this decision permanently — the aligned pinouts across the series give you room to scale up as your product requirements evolve. ## Conclusion In this post, we covered Nordic Semiconductor’s latest additions to the nRF54L Series — the nRF54LS05A and nRF54LS05B. These entry-level, ultra-low-power Bluetooth LE SoCs fill an important gap in the lineup for developers building simple, cost-sensitive wireless products. Here are the key takeaways: - The nRF54LS05A/B are **entry-level Bluetooth LE SoCs**optimized for sensors, tags, beacons, remotes, and PC peripherals - They feature a **128 MHz Arm Cortex-M33** processor with **508 KB NVM** and either **64 KB RAM**(LS05A) or **96 KB RAM** (LS05B) - The **22nm low-leakage process** delivers impressive sleep currents — as low as **0.6 µA** in System OFF - **Drop-in pin-to-pin compatibility** between the LS05A and LS05B, with aligned pinouts across the broader nRF54L Series to simplify hardware migration - **nRF Connect SDK Bare Metal** provides a smoother migration path from the nRF5 SDK - **Baseline security** helps meet current and upcoming regulatory requirements You should now be able to evaluate whether the nRF54LS05A or nRF54LS05B is the right fit for your next project. For simple, battery-powered Bluetooth LE applications where cost matters, these SoCs give you access to the nRF54L Series’ power efficiency and modern architecture without paying for features you don’t need. ## References & Resources - [nRF54LM20A Introduction Post](https://novelbits.io/nordic-nrf54lm20a-introduction/) - [nRF Connect SDK Bare Metal Guide](https://novelbits.io/nrf-connect-sdk-bare-metal-guide/) - [nRF54L15 First Impressions](https://novelbits.io/nrf54l15-unboxing-first-impressions/) - [nRF54L Series Express Course](https://academy.nordicsemi.com/courses/nrf54l-series-express-course/?ref=novelbits.io) - [nRF54L15 Product Page](https://www.nordicsemi.com/Products/nRF54L15?ref=novelbits.io) - [nRF54LM20A Product Page](https://www.nordicsemi.com/Products/nRF54LM20A?ref=novelbits.io) ### Integrate Hubble Network on your nRF54L15 for Global Connectivity URL: https://novelbits.io/hubble-network-nrf54l15-tutorial/ Last updated: 2026-05-05T00:57:50.000Z Integrate Hubble Network on your nRF54L15 for Global Connectivity *This post is sponsored by* [*Hubble Network*](https://www.hubblenetwork.com/?ref=novelbits.io)*.* What if your Bluetooth LE device could communicate beyond the range of traditional gateways—even from remote locations without cellular coverage? Hubble Network makes this possible. They've built a global infrastructure for delivering device data to the cloud, using over 90 million terrestrial gateways that receive standard Bluetooth LE advertisements (available now) and a direct-to-satellite network with its own transmission protocol (currently in beta with select customers, with general availability expected later in 2026). In this tutorial, we'll walk through setting up a Hubble Network demo on Nordic's [**nRF54L15 DK**](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK?ref=novelbits.io) using [**nRF Connect SDK**](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK?ref=novelbits.io) and VS Code. We'll use Hubble's [reference app](https://github.com/HubbleNetwork/hubble-reference-zephyr-simple?ref=novelbits.io) as our starting point, with a small tweak to how the device key is loaded—making the provisioning workflow simple and IDE-friendly. By the end, you'll have a working beacon that transmits encrypted data to Hubble's terrestrial network, and you'll see that data appear in their cloud dashboard—accessible via their open API for easy integration into downstream applications. I've found this to be one of the most straightforward ways to explore satellite/terrestrial IoT connectivity without needing specialized hardware or setting up my own scanning infrastructure. **In this tutorial, we'll cover:** - What Hubble Network is and how their terrestrial network works - Setting up the development environment with nRF Connect for VS Code - Provisioning our device with an encryption key - Building and flashing the Bluetooth LE beacon application - Verifying communication with the Hubble cloud 💡 **Prefer video?** I recorded a full walkthrough of this tutorial using the nRF54L15 DK and the Hubble Connect mobile app. [Jump to the video demo](#video-demo) to see the entire process in action—from provisioning to seeing our device data in the Hubble dashboard. ## What is Hubble Network? Hubble Network is building global IoT connectivity infrastructure that works with standard, off-the-shelf Bluetooth LE chips. Unlike traditional IoT solutions that require cellular modems, LoRa radios, or proprietary hardware, Hubble works with the standard Bluetooth LE radio that's already in most devices. Founded in 2021 by Alex Haro (co-founder of Life360) and Ben Wild, the company has raised [$100M in funding](https://spacenews.com/hubble-network-raises-70-million-to-accelerate-60-satellite-bluetooth-constellation/?ref=novelbits.io) and achieved a major milestone in 2024: the [first-ever Bluetooth-to-satellite connection](https://techcrunch.com/2024/05/02/hubble-network-connects-a-bluetooth-chip-to-a-satellite-for-the-first-time/?ref=novelbits.io). Let's take a closer look at how this works. ### How It Works Our device broadcasts a standard Bluetooth LE advertisement containing an encrypted payload. Hubble's infrastructure—either terrestrial gateways or satellites—receives these advertisements and forwards the data to their cloud. From there, we can access our device data via API or dashboard. The Hubble SDK handles all the complexity. For example, here's what happens under the hood when our device broadcasts: - **Encryption**: Each device has a unique AES-256 key that encrypts the payload (AES-128 is also available for constrained devices) - **Device Identity**: The encrypted payload contains a derived device ID (not transmitted in plain text) - **Replay Protection**: A rolling counter prevents packet replay attacks - **Privacy**: The device uses a Non-Resolvable Private Address (NRPA) that changes periodically The following diagram shows the complete data flow from device to cloud: ![Hubble Network data flow diagram showing nRF54L15 device connecting via Bluetooth LE to smartphone gateway or satellite, then to Hubble Cloud and dashboard](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hubble-dataflow-v3-2.png) *Data flow: nRF54L15 broadcasts via Bluetooth LE to terrestrial gateways or satellites, which forward to Hubble Cloud* ### How Hubble Compares to Amazon Sidewalk If you're familiar with the IoT connectivity space, you might be wondering how Hubble compares to Amazon Sidewalk—another network that uses existing infrastructure for low-power device connectivity. While both aim to solve the "last mile" connectivity problem for IoT devices, there are some key differences: | Feature | Hubble Network | Amazon Sidewalk | | ------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | **Terrestrial Coverage** | [90M+ smartphones](https://network.hubble.com/?ref=novelbits.io) (dedicated, always-on) | Consumer Echo/Ring devices (users may opt out) | | **Global Reach** | Satellite constellation (coming later 2026) | [US only](https://docs.silabs.com/amazon-sidewalk/latest/sidewalk-demo/network-availability?ref=novelbits.io), no satellite component | | **Coverage Consistency** | Purpose-built network with high engagement users | Depends on Amazon device density and opt-in rates | | **Chip Support** | Nordic, TI, Silicon Labs (any standard Bluetooth LE) | Amazon-certified devices only | | **Enterprise Focus** | Built for commercial IoT with REST API and webhooks | Primarily consumer-oriented | The key advantage of Hubble over something like Amazon Sidewalk is the **satellite component**—once operational, our devices will have connectivity anywhere on Earth, not just in neighborhoods with Amazon devices. For applications like stolen vehicle recovery, fleet tracking, or remote asset monitoring, you really need global coverage. You can't rely on thieves driving through areas with good Sidewalk coverage. 😄 ### Terrestrial and Satellite Networks Hubble has two networks: | Network | Status | Coverage | Use Case | | --------------- | ------------------------------------------------------ | ---------------------------------------- | ---------------------------------------------------------------------------------------- | | **Terrestrial** | Available now | Urban/suburban via 90M+ smartphones | Asset tracking, fleet/vehicle tracking, stolen vehicle recovery, dense urban deployments | | **Satellite** | Beta testing with select customers (coming later 2026) | Global including oceans and remote areas | Asset tracking, agriculture, maritime, wilderness | For this tutorial, we'll focus on the terrestrial network. The satellite network has its own SDK library (`CONFIG_HUBBLE_SAT_NETWORK`) with a different transmission protocol, but it shares the same provisioning keys and cloud backend—so the foundation we build here transfers directly. ### The Advertisement Format When our device broadcasts, the Bluetooth LE advertisement contains 18-31 bytes of Hubble-specific data depending on whether we include custom payload (the complete Bluetooth LE packet includes additional headers and addressing). The following table shows the packet structure, using standard [Bluetooth AD types](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/CSS%5Fv11/out/en/supplement-to-the-bluetooth-core-specification/data-types-specification.html?ref=novelbits.io): | Hubble Bluetooth LE Advertisement (18-31 bytes) | | | | | ----------------------------------------------- | ------------------ | ----------------------------------------------------------------- | ------------------ | | AD Structure | Field | Value | Description | | **UUID List**(4 bytes) | Length | 0x03 | 3 bytes follow | | Type | 0x03 | Complete List of 16-bit UUIDs | | | UUID | 0xFCA6 | Hubble Network Service | | | **Service Data**(14-27 bytes) | Length | 0x0D \- 0x1A | 13-26 bytes follow | | Type | 0x16 | Service Data - 16-bit UUID | | | UUID + Hubble Payload | 0xFCA6 \+ 10 bytes | Encrypted: Protocol version, sequence number, device ID, auth tag | | | Custom Payload (optional) | 0-13 bytes | Encrypted application data (telemetry, sensor readings) | | The base 10-byte Hubble payload (generated by the SDK) contains: - **Protocol Version**: Hubble Terrestrial Network version - **Sequence Number**: Rolling counter for replay protection - **Ephemeral Device ID**: Derived from master key (not transmitted in plain text) - **Authentication Tag**: Integrity verification You can optionally add up to **13 bytes of custom payload** for application-specific data—for example, temperature readings, motion events, or diagnostic information. See Hubble's [Custom Payload guide](https://docs.hubble.com/docs/guides/use-case/custom-payload?ref=novelbits.io) for encoding examples. This custom data is encrypted alongside the Hubble fields using our device's master key. When a Hubble gateway receives this advertisement, it adds its own GPS location and forwards everything to the cloud. The backend decrypts the payload using our device's key and associates the data with our account. ### Supported Chip Platforms The Hubble Device SDK is compatible with any Bluetooth LE-capable chip. The examples below are platforms Hubble has tested and provides additional resources for (like [reference apps](https://docs.hubble.com/docs/guides/device-integration/reference-apps?ref=novelbits.io)): | Platform | Supported Chips | Notes | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Nordic Semiconductor** | nRF52, nRF53, nRF54 series | Official support via nRF Connect SDK (Zephyr-based) | | **Zephyr RTOS** | Any Zephyr-compatible Bluetooth LE chip | Official support via Zephyr SDK module | | **Espressif** | ESP32 family | Official support via ESP-IDF | | **Texas Instruments** | CC23xx family (e.g., CC2340R5) | Official support via FreeRTOS ([TI partnership](https://www.prnewswire.com/news-releases/hubble-network-announces-collaboration-with-texas-instruments-to-expand-global-bluetooth-connectivity-302653623.html?ref=novelbits.io)) | | **Silicon Labs** | [EFR32MG24](https://www.silabs.com/applications/case-studies/hubble-network-utilizes-silicon-labs-mg24-in-its-global-bluetooth-le-network?ref=novelbits.io) and Series 2 SoCs | Includes Secure Vault integration | This tutorial uses the **nRF54L15 DK**, but the same principles apply to any supported platform. The Hubble SDK integrates as a Zephyr module, making it compatible with any Zephyr-based build system. ## Development Environment Setup Let's get our development environment ready. We'll be using nRF Connect for VS Code, which is what I use for all my NCS projects. If you're already familiar with this toolchain, skip ahead to Step 2 where we clone the Hubble SDK. ### Prerequisites Before we begin, make sure you have: **Software**: - Visual Studio Code - nRF Connect for VS Code extension pack - nRF Connect SDK (tested with v3.2.0 for this tutorial) - **Account**: Hubble Network developer account (sign up at [dash.hubble.com](https://dash.hubble.com/?ref=novelbits.io)) ### What to Expect: Sandbox vs. Live Access When you sign up at [dash.hubble.com](https://dash.hubble.com/?ref=novelbits.io), you'll receive **Sandbox access** by default. Here's what that means: | Access Level | What You Get | How to Test | | ------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | **Sandbox** (self-signup) | Local testing only | Use the [Hubble Connect mobile app](https://apps.apple.com/us/app/hubble-connect/id6751236191?ref=novelbits.io) as a local gateway | | **Live** | Full Terrestrial Network access via 90M+ gateways | Contact Hubble Sales | With Sandbox access, the production Terrestrial Network still detects our device's packets and shows aggregate statistics in our dashboard, but the actual packet data is only delivered when captured locally using the Hubble Connect mobile app on our phone. That works fine for development and testing—we can verify our implementation before deploying to production. For production deployments with full Terrestrial Network connectivity, you'll need to contact Hubble's sales team. **For this tutorial, Sandbox access is all you need.** We'll use the Hubble Connect app to verify our beacon is working correctly. ### Step 1: Install nRF Connect for VS Code If you haven't already set up nRF Connect for VS Code: 1. Download and install [Visual Studio Code](https://code.visualstudio.com/?ref=novelbits.io) 2. Open VS Code and go to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X) 3. Search for "[nRF Connect for VS Code](https://marketplace.visualstudio.com/items?itemName=nordic-semiconductor.nrf-connect-extension-pack&ref=novelbits.io)" and install the extension pack 4. Click the nRF Connect icon in the sidebar to open the extension panel 5. Under **Manage Toolchains**, install the latest toolchain 6. Under **Manage SDKs**, install nRF Connect SDK (v3.2.0 was used for this tutorial) The SDK installation takes a few minutes as it downloads the full nRF Connect SDK (including Zephyr RTOS and all dependencies). ### Step 2: Clone the Hubble Network SDK The [Hubble Device SDK](https://github.com/HubbleNetwork/hubble-device-sdk?ref=novelbits.io) is available on GitHub. Clone it to a convenient location: ```bash mkdir hubble-demo && cd hubble-demo git clone https://github.com/HubbleNetwork/hubble-device-sdk.git hubblenetwork-sdk ``` This gives you the following structure: ```plaintext hubble-demo/ └── hubblenetwork-sdk/ ├── samples/ │ ├── zephyr/ │ │ ├── ble-beacon/ # Terrestrial beacon │ │ └── ble-network/ # Combined terrestrial + satellite │ ├── esp-idf/ble-beacon/ # ESP32 sample │ └── freertos/ti/ble-beacon/ # TI FreeRTOS sample ├── port/ │ ├── zephyr/ # Zephyr/NCS integration layer │ ├── esp-idf/ # ESP-IDF integration layer │ └── freertos/ # FreeRTOS integration layer ├── include/hubble/ # SDK headers ├── tools/ # Provisioning scripts └── zephyr/module.yml # Module registration for Zephyr ``` ### Step 3: Set Up the Reference App Hubble provides a [reference app](https://github.com/HubbleNetwork/hubble-reference-zephyr-simple?ref=novelbits.io) that streamlines the development workflow. It handles key loading and computes the UTC timestamp automatically at build time—no extra steps before each build. Clone the reference app into your project directory: ```bash git clone https://github.com/HubbleNetwork/hubble-reference-zephyr-simple.git ble-beacon-refapp ``` Our project structure should now look like: ```plaintext hubble-demo/ ├── hubblenetwork-sdk/ # SDK (keep clean, can git pull updates) └── ble-beacon-refapp/ # Our reference app project ├── src/ │ ├── main.c # Application code │ ├── b64.c # Base64 decoder (for runtime key decode) │ └── b64.h ├── prj.conf └── CMakeLists.txt # Key loading + UTC timestamp at build time ``` The key part is `CMakeLists.txt`. The stock reference app reads the device key from a `HUBBLE_DEVICE_KEY` environment variable—which works fine when building from the command line, but can be unreliable in VS Code since the IDE doesn't always inherit your shell environment. We've made a small modification to read the key from a file instead (`hubble-device-b64.key` in the parent directory), which works reliably regardless of how you trigger the build. It also computes the UTC timestamp automatically at build time—so we just need to save our key to a file before building: ```cmake # Device key from file (our modification — stock app uses environment variable) set(_keyfile "${CMAKE_CURRENT_SOURCE_DIR}/../hubble-device-b64.key") if(EXISTS "${_keyfile}") file(READ "${_keyfile}" HUBBLE_DEVICE_KEY) string(STRIP "${HUBBLE_DEVICE_KEY}" HUBBLE_DEVICE_KEY) else() set(HUBBLE_DEVICE_KEY "1111111111111111111111111111111111111111111=") endif() # UTC timestamp computed automatically at build time string(TIMESTAMP EPOCH_S "%s" UTC) math(EXPR TIME_MS "${EPOCH_S} * 1000") target_compile_definitions(app PRIVATE HUBBLE_KEY="${HUBBLE_DEVICE_KEY}") target_compile_definitions(app PRIVATE TIME=${TIME_MS}) ``` The app decodes the Base64 key at runtime using a bundled `b64.c` decoder, so the raw key bytes are available to the Hubble SDK at initialization. ### Step 4: Create the Build Configuration Now let's set up the build configuration in VS Code: Configure the following settings: - **Application**: Browse to `hubble-demo/ble-beacon-refapp` (our reference app project) - **Board**: Select `nrf54l15dk/nrf54l15/cpuapp` - **SDK**: Select your installed nRF Connect SDK (e.g., v3.2.0) Expand **Extra CMake arguments** and add: ```plaintext -DEXTRA_ZEPHYR_MODULES=/absolute/path/to/hubble-demo/hubblenetwork-sdk ``` That's all you need—no extra Kconfig fragments required. The reference app has `CONFIG_LOG_BACKEND_UART=y` in `prj.conf`, so serial logging is ready to go. - (Replace with the actual absolute path to your SDK folder) - Click **Build Configuration** to create the configuration The `EXTRA_ZEPHYR_MODULES` argument tells the build system to include the Hubble SDK as an external Zephyr module, making its Kconfig options (like `CONFIG_HUBBLE_BLE_NETWORK`) and source files available to your project. If you've worked with Zephyr modules before, this should look familiar. ### Step 5: Enable Debug Logging The reference app registers its log module with `CONFIG_APP_LOG_LEVEL`, which defaults to `CONFIG_LOG_DEFAULT_LEVEL` (info). For development, I recommend overriding this to `LOG_LEVEL_DBG` directly in `main.c` so we can see all the diagnostic output—decoded key bytes, advertisement details, and payload contents: ```c LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); ``` This enables debug logging for our application module only, without flooding the console with debug messages from every Zephyr subsystem (which is what happens if you set `CONFIG_LOG_DEFAULT_LEVEL=4` globally). You'll see the key decode, temperature, and advertisement messages while keeping the OS-level noise at info level. ## Device Provisioning Before you can build and run the application, we need to provision our device with an encryption key. This key is used to encrypt the Bluetooth LE advertisements so that only Hubble's backend can decrypt and identify our device. ### Step 1: Register Your Device with Hubble First, we need to register a device in the Hubble dashboard to obtain an encryption key. You'll need an API Token to access the API—see [how to create one here](https://docs.hubble.com/docs/api-specification/hubble-platform-api?ref=novelbits.io#api-access). You can also [import the API spec](https://docs.hubble.com/docs/api-specification/hubble-platform-api?ref=novelbits.io#import-api-definition) into your preferred developer environment (Postman, Insomnia, etc.). Go to the [Register New Devices](https://docs.hubble.com/docs/api-specification/register-new-devices?ref=novelbits.io) page in the Hubble Cloud API documentation, which provides an interactive form for registering devices directly from the browser. In the interactive panel on the right, fill in: - **org\_id**: Your Organization ID (required path parameter) In the **Body** section, configure: - **n\_devices**: Number of devices to provision (1-1000) - **encryption**: Select "AES-256-CTR" (required) - **names**: Array of device names (e.g., \["nrf54l15\_demo"\]) - **tags**: Optional array of tag objects - Click **SEND API REQUEST** - Copy the Base64-encoded `key` from the response—you'll need it for provisioning ![Hubble Cloud API Register New Devices interface](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/hubble-register-devices-api.png) **The Cloud API documentation provides an interactive form for registering devices* 💡 **Tip:** If you prefer to automate device registration, you can also use `curl` or any HTTP client to call the same API endpoint directly. See Hubble's [API documentation](https://docs.hubble.com/docs/api-specification/register-new-devices?ref=novelbits.io) for the request format. ⚠️ **Important:** Each device needs a unique key. If you're testing with multiple development boards, register a separate device for each one. Hubble's backend uses rolling counters for replay protection, and if two devices share the same key, the backend may filter out packets that appear to be replay attacks. For development, I recommend naming your devices descriptively—for example, `nrf54l15_dk_01` and `nrf54l15_dk_02`—so you can easily identify them in the dashboard. ### Step 2: Set the Device Key With our modified `CMakeLists.txt`, we read the device key from a file called `hubble-device-b64.key` in the parent directory (i.e., the `hubble-demo/` folder). Save your key to this file: ```bash echo "YOUR_BASE64_KEY_HERE" > hubble-demo/hubble-device-b64.key ``` Replace `YOUR_BASE64_KEY_HERE` with the Base64-encoded key you received from the API in Step 1\. The build system reads this file automatically—no environment variables to manage. 💡 **Tip:** If you're working with multiple devices, just swap the contents of `hubble-device-b64.key` when switching between devices—no need to manage environment variables or restart your IDE. 📝 **Note:** The stock reference app uses the environment variable approach (`export HUBBLE_DEVICE_KEY=...`), which is what Hubble's documentation shows. That works well when building with `west build` directly from the command line. However, when using VS Code with the nRF Connect extension, environment variables set in your shell profile (e.g., `~/.zshrc`) aren't automatically inherited by the IDE's build process. That's why we modified `CMakeLists.txt` to read from a file instead—it works reliably regardless of how you trigger the build. ### Fresh Timestamp on Every Build The UTC timestamp is computed fresh by CMake on every build, so you can just rebuild and flash at any time. The timestamp is always current. **The Terrestrial Network supports ±24 hours of clock precision.** Since the reference app generates a fresh timestamp on every pristine build, you'll always be within that window as long as you do a pristine build before flashing. For production devices, Hubble recommends at least 500PPM clock accuracy to control drift over time. If your device will run for extended periods, consider implementing a time synchronization protocol—the Terrestrial Network gateways do not manage or refresh device time. 📝 **Note:** Make sure the `hubble-device-b64.key` file contains your actual device key before building. If the file is missing or contains the default test key, your device won't appear under "My Devices" in the Hubble dashboard. The reference app initializes the Bluetooth LE stack and the Hubble SDK, then calls `hubble_ble_advertise_get()` in a loop to generate fresh encrypted payloads. That single SDK function handles all the cryptography (key derivation, nonce generation, AES-256 encryption) internally, so we don't have to deal with any of that. We also add temperature sensor reading as a custom payload—see [Adding Custom Sensor Data](#sending-custom-sensor-data) below for details on how the encoding works. ## Building and Flashing Now that our device key is in place, let's build and flash the application. ### Build the Application 1. Open the nRF Connect extension panel in VS Code 2. Find your build configuration under **Applications** 3. Click the **Build** button (hammer icon) The build should complete without errors. You'll verify the key was loaded correctly in the serial output after flashing. ### Flash to the nRF54L15 DK 1. Connect your nRF54L15 DK to your computer via USB 2. In the nRF Connect panel, click the **Flash** button 3. Wait for the flashing process to complete ### Verify with Serial Output Open a serial terminal (115200 baud) to see the application output: 1. In VS Code, open the nRF Terminal (View > Terminal, then select nRF Terminal) 2. Or use your preferred serial terminal application We should see output similar to: ```plaintext *** Booting nRF Connect SDK v3.2.0 *** [00:00:00.022,411] main: main: Hubble Network BLE Beacon Reference App started [00:00:00.022,439] main: Temperature sensor initialized [00:00:00.024,124] bt_hci_core: Identity: D1:11:FE:93:26:44 (random) [00:00:00.024,184] main: decode_master_key: Decoded key: bc 6b 26 5f c1 b4 ad 00 ... [00:00:00.024,200] main: decode_master_key: TIME = 1738000000000 [00:00:00.024,213] hubblenetwork: Hubble Network SDK initialized [00:00:00.028,996] main: Temperature: 28.50 C | Base64: CyI= [00:00:00.031,137] main: main: Number of bytes in advertisement: 14 ``` The output confirms several things: our key was decoded correctly (the `Decoded key:` line logs the first bytes of the decoded key so you can confirm the right key was loaded), the temperature sensor we added is reading (28.50°C), and the advertisement includes 14 bytes of service data content (2-byte UUID + 10-byte Hubble payload + 2 bytes of our temperature data). The device broadcasts at a 2-second advertising interval, refreshing the encrypted payload—including a new temperature reading—every 5 minutes. 💡 **Verifying the key:** Want to double-check that the decoded bytes match your key? Run this in your terminal: `cat hubble-device-b64.key | base64 -d | xxd -p -c 8 | head -1` The output should match the hex bytes shown in the `Decoded key:` line. Our device is now broadcasting Hubble advertisements! ## Testing and Verification Let's verify that our device is communicating with the Hubble network. With Sandbox access, we'll use the **Hubble Connect** mobile app as a local gateway to receive our device's Bluetooth LE advertisements and forward them to the cloud. ### Testing with the Hubble Connect App The [Hubble Connect](https://docs.hubble.com/docs/guides/hubble-connect?ref=novelbits.io) app (available on [iOS](https://apps.apple.com/us/app/hubble-connect/id6751236191?ref=novelbits.io) and [Android](https://play.google.com/store/apps/details?id=com.hubble.connect&ref=novelbits.io)) turns our smartphone into a local Hubble gateway for development and testing: 1. Download **Hubble Connect** from the [App Store](https://apps.apple.com/us/app/hubble-connect/id6751236191?ref=novelbits.io) 2. Log in with your Hubble developer account (the same one you used at [dash.hubble.com](https://dash.hubble.com/?ref=novelbits.io)) 3. Grant Bluetooth and location permissions when prompted 4. The app will start scanning for nearby Hubble devices 5. Our registered device should appear in the **My Devices** tab ![Hubble Connect mobile app My Nearby Devices screen showing nrf54l15_dk device with UUID and Live tag](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hubble-connect-my-devices.png) *The Hubble Connect app detecting our nRF54L15 beacon in the My Nearby Devices list* The app scans for nearby devices broadcasting on the Hubble protocol and registered with our organization. When it receives our device's advertisement, it forwards the encrypted payload to Hubble's cloud. 📝 **Note:** With Sandbox access, the production Terrestrial Network (90M+ smartphones) will still detect our device's packets and show aggregate statistics in the dashboard. However, the actual packet data is only delivered when captured locally through the Hubble Connect app. For full Terrestrial Network data delivery, contact Hubble's sales team for Live access. ### Check the Hubble Dashboard 1. Open [dash.hubble.com](https://dash.hubble.com/?ref=novelbits.io) and log in 2. Navigate to our devices list 3. Find our registered device (e.g., "nrf54l15\_demo") 4. Click to view device details ![Hubble cloud dashboard showing nrf54l15_dk device with network traffic graph, recent packet data including payload CyI=, RSSI, and gateway location](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hubble-dashboard-device-detail.png) *The Hubble dashboard showing our device's network traffic and recent packet data* With the Hubble Connect app running nearby, we should see recent data including: - **Location**: GPS coordinates of the receiving gateway - **RSSI**: Signal strength at the gateway - **Timestamp**: When the packet was received - **Counter**: Rolling counter value (for replay protection) ### Understanding the Data When we view a device packet in the dashboard, we'll see something like: ```json { "location": { "timestamp": 1769703217.7, "latitude": 39.76493314820157, "longitude": -86.16218773415692, "altitude": 219.84721038564210, "horizontal_accuracy": 4.67592332215799, "vertical_accuracy": 30 }, "device": { "id": "826b4243-1c0b-41c4-8555-dfcc723c36a1", "name": "nrf54l15_dk", "tags": { "_env": "production" }, "payload": "CyI=", "sequence_number": 3, "counter": 20481, "rssi": -51, "timestamp": 1769703220.007 }, "network_type": "TERRESTRIAL" } ``` The location comes from the **gateway**, not your device. This is how Hubble provides location context—the gateway knows where it is and tags the received packets with that information. ## Adding Custom Sensor Data To demonstrate end-to-end data flow, we add temperature sensor reading to the reference app. This is a small modification—we read the nRF54L15's on-chip die temperature sensor every advertising cycle and include it as a 2-byte custom payload in the Hubble advertisement. I find that sending a known sensor value and comparing the Base64 output on the serial console with what appears on the dashboard is the quickest way to verify end-to-end data flow—from the device, through the gateway, to the cloud. ### How the Payload Works The temperature is packed as a big-endian `int16` in 0.01°C units (so 28.50°C becomes the integer 2850, or `0x0B22`). Our app logs both the human-readable temperature and its Base64 encoding for easy comparison with the dashboard: ```plaintext [00:00:00.028,996] main: Temperature: 28.50 C | Base64: CyI= ``` The 2 bytes of temperature data are passed to `hubble_ble_advertise_get()` as the custom payload, encrypted alongside the Hubble protocol fields, and transmitted in the advertisement. That's well within the 13-byte maximum—you still have 11 bytes left over if you want to pack in additional readings or device state down the road. ### Configuration For the temperature sensor and Base64 debug logging, we add these Kconfig options to `prj.conf`: ```ini # Sensor subsystem (for on-chip temperature) CONFIG_SENSOR=y # Base64 encoding (for debug payload logging) CONFIG_BASE64=y ``` ### Verifying the Payload End-to-End Now let's verify that our data made it through. The serial console shows each temperature reading along with its base64 encoding: ![Serial console output from nRF54L15 showing Hubble beacon startup, decoded key, temperature reading of 28.50 C, and Base64-encoded payload CyI=](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hubble-refapp-serial-output.png) *The serial console shows the temperature reading (28.50 C) and its Base64 encoding (CyI=)—we'll match this on the dashboard* And on the Hubble Connect app (or the web dashboard), the same base64 string appears in the `payload` field: ![Hubble Connect mobile app showing received packet from nrf54l15_dk device with payload CyI= matching the serial console output](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hubble-connect-app-payload-redact.jpg) *The Hubble Connect app shows "payload": "CyI="—matching the serial output, confirming end-to-end delivery* The payloads match. For example, a reading of 28.50°C gets packed as `0x0B22` (2850 in 0.01°C units), which base64-encodes to `CyI=`. That value was encrypted by the SDK, transmitted via Bluetooth LE, received by a terrestrial gateway, decrypted in the cloud, and delivered to our dashboard—all verifiable with a quick glance at both screens. This is the core workflow for any custom payload application. Whether it's sensor readings, device diagnostics, or application state—the pattern is the same: pack your data into a byte array (up to 13 bytes), pass it to `hubble_ble_advertise_get()`, and retrieve it from the dashboard or via Hubble's API. At this point, you should be able to send any custom data through the Hubble network and verify it arrives intact. ## Video Demo Want to see the entire process in action? In this video, I walk through the complete tutorial—from provisioning the nRF54L15 DK to building and flashing the firmware, then verifying the device using the Hubble Connect mobile app and the cloud dashboard. ## Real-World Applications Hubble's technology enables applications that were previously impractical with standard Bluetooth LE. Two use cases that make the most sense here: ### Stolen Vehicle Recovery Traditional GPS tracking modules and cellular modems are bulky, predictably placed (usually under the dashboard or in the engine compartment), and therefore quickly disabled by criminals who know exactly where to look. With Hubble, there's no telltale antenna or obvious hardware to rip out. A tiny Bluetooth LE beacon can be hidden virtually anywhere in a vehicle—for example, inside a door panel, within the seat cushion, or embedded in a non-obvious location. Since the beacon doesn't need a cellular signal or large GPS antenna, thieves have no easy way to locate and disable it. This same principle applies broadly to **stolen asset recovery**—think high-value equipment, construction machinery, boats, trailers, or even expensive bicycles. Any asset that's at risk of theft can benefit from a tracking solution that's small, inconspicuous, and doesn't rely on easily-disabled cellular infrastructure. ### Fleet Tracking For logistics and transportation companies, tracking vehicles and cargo across vast distances (including areas with spotty cellular coverage) has traditionally required expensive satellite communicators or accepting gaps in visibility. Hubble enables continuous fleet tracking using inexpensive Bluetooth LE beacons, with the upcoming satellite network ensuring coverage even through remote highways, rural areas, and international routes. ### Other Applications Beyond vehicle and fleet tracking, you can think of any scenario where you need to know where something is (or that it's still there) without relying on cellular—agriculture sensors in remote fields, wildlife trackers, pipeline monitoring, shipping containers on ocean crossings. Hubble delivers not only better satellite connectivity but also lower power requirements than traditional cellular IoT solutions, which works well for battery-constrained deployments. ## Next Steps That's it—we now have a working Hubble Network beacon on the nRF54L15 DK, complete with custom sensor data. Here are some ways to extend this further: - **Expand your payload**: We used 2 bytes for temperature, but you have up to 13 bytes available. Consider adding battery voltage, accelerometer data, or device status flags. See Hubble's [Custom Payload guide](https://docs.hubble.com/docs/guides/use-case/custom-payload?ref=novelbits.io) for encoding examples. - **Optimize power consumption**: For battery-powered deployments, tune the advertising interval and transmit power (dBm) for your battery budget. Higher output power means better range and reliability, but draws more current. Early Hubble customers report achieving 1+ year battery life on a coin cell with the right tuning. The nRF54L15 is designed for ultra-low-power operation—see the [BlueJoule project](https://novelbits.io/bluejoule) for standardized power consumption benchmarks across Bluetooth LE chips. - **Prepare for satellite connectivity**: Hubble's satellite constellation is in beta testing and expected to launch more broadly later this year. Devices will use a separate satellite protocol in the SDK for global coverage—oceans, deserts, anywhere. ## Conclusion In this tutorial, we covered a lot! We went from zero to a working Hubble beacon. We set up the nRF Connect SDK toolchain, cloned the Hubble SDK and reference app, provisioned our device key, and added temperature sensor reading as a custom payload. We then verified the whole thing end-to-end through the Hubble Connect app and cloud dashboard. Here's what we covered: - How Hubble's terrestrial network uses 90M+ smartphone gateways to receive standard Bluetooth LE advertisements - Setting up the reference app with nRF Connect for VS Code and the Hubble SDK as an external Zephyr module - Provisioning a device key via a key file - Building, flashing, and verifying serial output on the nRF54L15 DK - End-to-end verification of custom temperature payload from device to cloud dashboard At this point you should be comfortable integrating the Hubble SDK into your own nRF Connect SDK projects, provisioning devices, and deploying Bluetooth LE beacons with custom payload data that talk to Hubble's infrastructure. The nRF54L15 paired with Hubble's network is a solid combination for IoT applications that need connectivity beyond cellular or WiFi. And once the satellite constellation goes live, your Bluetooth LE devices will be able to communicate from anywhere on Earth—no gateways required. 🚀 **Try it yourself:** The Hubble SDK works with standard Bluetooth LE chipsets—we used the nRF54L15 DK here, but you can use any supported platform. Head over to [dash.hubble.com](https://dash.hubble.com/?ref=novelbits.io), sign up for a free Sandbox account, and start building. ### Inside the RF Chamber — Episode 0: Can an RF Shielded Enclosure Really Block Bluetooth LE Signals? URL: https://novelbits.io/rf-chamber-episode-0-shielded-enclosure-bluetooth-le/ Last updated: 2026-08-19T17:39:43.000Z *Disclosure: Novel Bits is a US distributor of the BleuIO dongles featured in this post.* If you've ever tried to test a Bluetooth Low Energy (Bluetooth LE) device at your desk, you know the frustration. Your phone is advertising. Your neighbor's smartwatch is broadcasting. The office Wi-Fi access point is stomping all over the 2.4 GHz band. And somehow, your test results look different every time you run them. The root problem is straightforward: **ambient RF interference can make certain Bluetooth LE tests unreliable** in an uncontrolled environment. If you're measuring received signal strength, characterizing advertising behavior, or validating a scanning implementation, the wireless noise floor in a typical office or home lab can shift your results by 10–20 dB from one run to the next. Not every test requires isolation — but some scenarios absolutely do. So I decided to do something about it. I picked up a [Ramsey STE3000M](https://ramseytest.com/product/ste3000m/?ref=novelbits.io) RF shielded test enclosure — a benchtop Faraday cage designed to isolate your Device Under Test (DUT) from the outside world. And in this first episode, I wanted to answer one straightforward question: *does it actually work?* Let's find out. In this post, we'll cover: - What an RF shielded enclosure is and why it matters for Bluetooth LE development - A simple experiment: scanning for Bluetooth LE devices from inside the chamber with the door open vs. closed - The results (spoiler: they're dramatic) - Why this matters for your own Bluetooth LE testing workflow - What's coming next in the "Inside the RF Chamber" series 💡 **Insider Tip:** Want to go deeper on Bluetooth LE development with hands-on courses covering the protocol stack, firmware implementation, and RF testing? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## What Is an RF Shielded Enclosure? An RF shielded enclosure (sometimes called a Faraday cage or RF test chamber) is essentially a metal box designed to block electromagnetic signals from passing through its walls. Let's go over how this works. The concept goes back to Michael Faraday in the 1830s — a continuous conductive shell prevents external electric fields from reaching the interior. The Ramsey STE3000M I'm using is a benchtop model with an interior of 17.2" W x 10.2" D x 8.6" H — large enough for a few development boards, a dongle or two, and some cabling. It's rated for **greater than 85 dB of shielding at 2.4 GHz**, which is the frequency band Bluetooth LE operates in. To put that in perspective, 85 dB of attenuation means an outside signal is reduced to roughly **0.000003%** of its original power by the time it reaches the inside of the chamber. The enclosure also has a viewing window (RF-shielded, of course), RF-shielded gloves for manipulating devices inside without opening the door, and connector feedthroughs for USB and other cables. That last part is key — it lets you control a device inside the chamber from your laptop sitting comfortably outside. ![Ramsey STE3000M RF shielded test enclosure on workbench, door closed](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/01-chamber-exterior-closed.jpg) The Ramsey STE3000M on the workbench — door closed, latches engaged. ![Interior of the Ramsey STE3000M with door open showing absorber foam, gloves, and warning labels](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/03-chamber-interior-door-open.jpg) Door open — RF absorber foam lines all interior surfaces. The RF-shielded gloves and I/O panel are visible. ## The Test: Scanning from Inside the Chamber For this experiment, I wanted to keep things as simple as possible. Let's take a look at the setup. I used a [BleuIO](https://novelbits.io/bleuio/) dongle — a USB Bluetooth LE dongle that you can control entirely through AT commands from a serial terminal. No SDK, no firmware flashing, no IDE. Just plug it in, open a terminal, and type commands. I recommend these for quick Bluetooth LE experiments because they remove all the setup friction. You can [pick one up from our shop](https://novelbits.io/bleuio/) — the Standard is $29 and the Pro is $45. Here's what I did: 1. Connected the BleuIO dongle to my laptop via the chamber's USB feedthrough (the dongle sits inside the chamber, the laptop stays outside) 2. Set the dongle to central role with `AT+CENTRAL` 3. Ran `AT+GAPSCAN=5` to scan for nearby Bluetooth LE devices for 5 seconds — **with the chamber door open** 4. Recorded the results 5. **Closed the chamber door** (both latches engaged) 6. Ran the exact same `AT+GAPSCAN=5` scan again 7. Recorded the results 8. Opened the door and scanned one final time to confirm everything came back ![Close-up of the Ramsey STE3000M left I/O panel showing USB feedthrough, SMA connectors, and banana jacks](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/06-io-panel-detail.jpg) The left I/O panel — USB feedthrough, SMA connectors, and banana jacks for routing signals in and out of the chamber. ![Close-up of the Ramsey STE3000M right I/O panel showing two USB pass-through modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/04-io-panel-right.jpg) The right I/O panel — two additional USB pass-throughs. Let's walk through what happened. ## The Results ### Door Open: Full Visibility With the chamber door open, the BleuIO dongle had a clear view of the RF environment in my lab. The scan picked up **43 devices** in 5 seconds — my phone, nearby headphones, smartwatches, Ruuvi beacons, and a handful of other Bluetooth LE peripherals I didn't even realize were broadcasting. The Received Signal Strength Indicator (RSSI) values ranged from **\-45 dBm** (strongest nearby device) down to **\-96 dBm** (weakest). A typical office or home environment will usually show somewhere between 5 and 20+ devices depending on how many Bluetooth LE gadgets are in range. ![Terminal output showing AT+GAPSCAN=5 results with 43 Bluetooth LE devices discovered, RSSI values from -45 to -96 dBm](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/11-terminal-scan-door-open.png) Door open: 43 devices discovered in a 5-second scan. ### Door Closed: Radio Silence Then I closed the door. Let's just say the difference was not subtle. The same 5-second scan returned **zero devices**. Not one. Not even a faint signal from my phone sitting right next to the chamber. I ran the scan twice to make sure — both times, the dongle reported nothing but silence. ![Terminal output showing two AT+GAPSCAN=5 scans with zero devices found inside sealed RF chamber](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/12-terminal-scan-door-closed.png) Door closed: Two consecutive scans, zero devices. Complete RF isolation. ### Door Reopened: Everything Returns Opening the door and scanning again brought all the devices right back — but here's the interesting part. I started the scan while I was still releasing the second latch, and devices were already appearing before the door was fully open. The RF seal breaks as soon as the latches begin to disengage, which tells you just how critical that mechanical seal is to the chamber's shielding performance. Once fully open, the RSSI values essentially matched the first scan, confirming that the chamber — and nothing else — was the variable. ## Why This Matters for Bluetooth LE Developers You might be thinking, "Okay, it blocks signals. So what?" Let's step back and talk about why this matters in practice. If you're developing Bluetooth LE firmware or applications, there are several scenarios where ambient interference can ruin your day: - **RSSI-based distance estimation** — If you're building anything that relies on signal strength (asset tracking, proximity detection, indoor positioning), you need a known-good baseline before you can trust your field data. A shielded enclosure lets you verify your device's RF output and measure received power at known TX levels — without a stray Wi-Fi router or someone's smartwatch shifting your numbers. - **Advertising and scanning behavior** — When you're verifying that your device advertises at the correct interval, with the correct data, on the correct channels (37, 38, and 39 for primary advertising), you don't want to sift through dozens of unrelated advertisement packets to find yours. - **Connection parameter testing** — Testing connection intervals, slave latency, and supervision timeouts is much more reliable when you eliminate the possibility of external devices causing interference or collisions on the same channels (especially in the crowded 2.4 GHz ISM band). For example, if you're trying to measure how a specific connection interval affects throughput, you need to know that any packet loss is due to your parameters — not a Wi-Fi access point blasting on an overlapping channel. - **Compliance and pre-certification** — While a benchtop enclosure isn't a substitute for a proper anechoic chamber, it's an excellent tool for pre-screening your device's RF behavior before you send it off for formal testing. For example, you can verify that your device's TX power output is within spec before spending thousands on a formal test lab. If you're trying to verify that your device's TX power output matches what you configured in firmware, doing that in an open office means fighting a noise floor that shifts with every passing phone. Inside a shielded enclosure, you remove that variable. ## What's Coming Next This was Episode 0, just a proof that the chamber works and a taste of what's possible. The "Inside the RF Chamber" series goes much deeper from here: - **[Episode 1: How Much Signal Do Common Materials Block?](https://novelbits.io/rf-chamber-episode-1-material-attenuation-public/)** (published): measured attenuation for ABS plastic, ceramic tile and aluminum, with drywall and insulation to follow Each episode will include hands-on procedures you can follow in your own lab, along with the actual data and analysis from my tests. ## Wrapping Up In this post, we covered what an RF shielded enclosure is, why ambient interference is a real problem for Bluetooth LE developers, and ran a simple but effective experiment: scanning for Bluetooth LE devices from inside the Ramsey STE3000M with the door open versus closed. Here are the key takeaways: - **Ambient RF interference** makes repeatable Bluetooth LE testing difficult in uncontrolled environments - **The Ramsey STE3000M** provides over 85 dB of shielding at 2.4 GHz — enough to eliminate virtually all outside Bluetooth LE signals - **A simple scan test** confirmed the chamber's effectiveness: 43 devices with the door open, zero with it closed - **Controlled RF environments** are essential for baseline RF verification, advertising validation, connection testing, and pre-certification work You should now be able to evaluate whether an RF shielded enclosure would improve your own Bluetooth LE testing workflow — and have a clear picture of what this series will deliver. If you've been struggling with inconsistent test results in your Bluetooth LE projects, this is the kind of tooling that can make a real difference. 💡 **Insider Tip:** Want to go deeper on RF testing, antenna design, and Bluetooth LE protocol internals? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. Next up is [Episode 1](https://novelbits.io/rf-chamber-episode-1-material-attenuation-public/), where we measure how much signal common building materials actually block at 2.4 GHz. ### Bluetooth Channel Sounding: Proximity Unlock Demo with Pixel Watch URL: https://novelbits.io/bluetooth-channel-sounding-proximity-unlock-demo/ Last updated: 2026-05-05T00:55:49.000Z *This post is sponsored by [Silicon Labs](https://www.silabs.com/?ref=novelbits.io).* Imagine walking up to your Mac and having it unlock automatically—no password, no Touch ID, just your presence. Then, when you walk away, it locks itself. This isn't science fiction; it's **Bluetooth Channel Sounding** in action. If you've ever tried to build proximity-based features using RSSI (Received Signal Strength Indicator), you know the frustration. Signal strength fluctuates wildly based on obstacles, interference, and even how you're holding your phone. Trying to determine if someone is 1 meter away versus 3 meters away with RSSI is, frankly, a guessing game. Channel Sounding changes that. **Channel Sounding** is a Bluetooth Low Energy feature introduced in **Bluetooth Core Specification 6.0** (September 2024) that measures distance between devices with sub-meter accuracy using Phase-Based Ranging (PBR). Unlike RSSI methods that estimate distance from signal strength, Channel Sounding measures the phase shift of radio signals across multiple frequencies to calculate the actual physical distance between devices. In this post, I'll walk you through a complete working demo I built: a proximity-based Mac unlock system using a Pixel Watch 4, a Silicon Labs development kit, and a Python script. When I'm nearby, my Mac unlocks. When I walk away, it locks. The demo does require an external development kit for now—but think of it as a prototype for what could eventually be built into laptops natively. Unlike UWB, which requires proprietary hardware, Channel Sounding is a standard Bluetooth feature. The same radio that connects your wireless headphones could, in principle, handle secure ranging. Let's take a closer look at how it all works. We'll cover: - The roles involved: Bluetooth LE Central/Peripheral and CS Initiator/Reflector - The architecture of all three components: Watch app, SoC firmware, and Mac script - How GATT and the Ranging Service (RAS) fit into the picture - A live demo of the complete system All the source code for this demo—the [Wear OS app](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FRangingWatchApp.zip?ref=novelbits.io) (plus a pre-built APK), the [Python unlock script](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FProximity%5FUnlock.zip?ref=novelbits.io), and the Silicon Labs SoC configuration—is available for free download so you can build and test this yourself. 🎬 **Video Demo Included:** This post includes a [full video demo](#live-demo) of the proximity unlock system in action—watch the Mac lock and unlock automatically as I walk toward and away from it. ## What We're Building Before we dive into the details, let's step back and look at the complete system. The demo consists of three components that work together to create a proximity-based unlock experience: ![Channel Sounding system architecture: Pixel Watch 4 connects to Silicon Labs xG24-DK2606A development kit via Bluetooth LE, which sends distance measurements to MacBook via USB serial for lock/unlock control](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/architecture-detailed-updated.png) *System architecture: Watch connects to SoC via Bluetooth LE + Channel Sounding, SoC calculates distance and sends to Mac for lock/unlock control* I'm providing all the source code for free—you can download the [watch app](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FRangingWatchApp.zip?ref=novelbits.io) (source code plus a pre-built APK if you just want to install and go), the [Mac script](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FProximity%5FUnlock.zip?ref=novelbits.io), and get the [SoC firmware from Silicon Labs](https://github.com/SiliconLabs/bluetooth%5Fstack%5Ffeatures/tree/master/channel%5Fsounding/initiator%5Fas%5Fperipheral%5Freflector%5Fas%5Fcentral?ref=novelbits.io) to build this exact demo yourself. ### 1\. Pixel Watch 4 (Wear OS) The watch runs a custom Android app that acts as the **Bluetooth LE Central** (it initiates the connection) and the **CS Reflector** (it responds to ranging requests). The app is intentionally minimal—around 300 lines of Java—because the watch's job is simply to establish and maintain the Bluetooth LE connection. All the ranging calculations happen on the other device. I didn't fully realize this until I pulled out my Bluetooth sniffer: the watch doesn't actually see any distance values. It participates in the Channel Sounding procedure by responding to radio signals, but the Initiator (the SoC in our case) performs all the distance calculations. There's also a practical advantage to using a watch for proximity applications: a watch worn on your wrist is almost always in clear line of sight when you're walking toward something. Compare that to a phone that might be in your pocket or bag, where your body can obstruct the signal path. For ranging accuracy, that visibility matters. ### 2\. [Silicon Labs xG24-DK2606A](https://www.silabs.com/development-tools/wireless/efr32xg24-channel-sounding-dev-kit?ref=novelbits.io) (Channel Sounding Dev Kit) The Silicon Labs SoC acts as the **Bluetooth LE Peripheral** (it advertises and waits for connections) and the **CS Initiator** (it controls ranging procedures and calculates distance). This might seem like an unusual pairing—we'll explore [why these roles can be mixed](#why-these-roles-can-be-mixed) in the roles section below. The SoC is responsible for the ranging logic. It: - Advertises for Bluetooth LE connections - Schedules Channel Sounding procedures (as the Initiator) - Processes the phase measurements to calculate distance - Outputs distance values over USB serial ### 3\. MacBook with Python Script A Python script running on the Mac reads distance measurements from the SoC's serial output. The script applies smoothing and hysteresis to handle the natural variation in ranging measurements, then locks or unlocks the Mac based on configurable thresholds (80 cm to unlock, 200 cm to lock in my setup). ### How It All Connects The data flows in one direction: 1. **Watch ↔ SoC:** Bluetooth LE connection carries Channel Sounding procedures. The devices exchange radio signals across multiple frequencies, and the phase shifts of these signals reveal the distance. 2. **SoC → Mac:** The SoC calculates distance and sends measurements over USB serial (simple ASCII text, one measurement per line). 3. **Mac → Lock/Unlock:** The Python script parses measurements and uses macOS APIs to control the screen lock. What I like about this architecture is that each component does one thing well. The watch maintains the wireless link. The SoC handles the ranging math. The Mac makes the unlock decision. If you wanted to swap out the unlock behavior (say, for a smart door lock), you'd only need to replace the Mac component. ## Understanding Channel Sounding Roles One of the concepts that confused me early on was the relationship between traditional Bluetooth LE roles and Channel Sounding roles. Let's break this down because understanding these roles is essential for designing your own Channel Sounding applications. ### Bluetooth LE Roles: Central and Peripheral These are the standard Bluetooth LE connection roles you're probably familiar with: - **Central:** Scans for devices, initiates connections, and controls connection timing. Typically the more powerful device (phone, laptop, gateway). - **Peripheral:** Advertises its presence and waits for connection requests. Typically the low-power device (sensor, beacon, accessory). For example, in a traditional setup, your phone (Central) connects to your fitness tracker (Peripheral). The Central controls when data exchanges happen by managing the connection parameters. ### Channel Sounding Roles: Initiator and Reflector Channel Sounding introduces a separate pair of roles that operate independently from the Bluetooth LE connection roles: - **Initiator:** Controls the ranging procedure—schedules when ranging happens, collects phase data from both devices, and performs the distance calculation. The Initiator is the device that knows how far away the other device is. - **Reflector:** Responds to ranging requests by transmitting and receiving signals at precise times. The Reflector participates in the ranging procedure but doesn't calculate the distance itself. The key insight: **the Reflector never sees the distance value.** In our demo, the watch acts as the Reflector, which means the watch app has no idea how far away it is from the SoC. All it does is maintain the Bluetooth LE connection and let the Bluetooth stack handle the Channel Sounding procedure. The SoC (Initiator) performs all the math and outputs the distance. ### Why These Roles Can Be Mixed What surprised me when learning about Channel Sounding was that Bluetooth LE roles and CS roles are completely independent. According to the Bluetooth Core Specification, both Central and Peripheral devices can act as either Initiator or Reflector. This means you can have: - **Central + Initiator:** The device that controls the Bluetooth LE connection also controls ranging. For example, your phone acts as Central to connect to your car, and as Initiator to measure distance for passive entry. - **Central + Reflector:** The device that controls the Bluetooth LE connection lets the other device handle ranging (our demo). - **Peripheral + Initiator:** The accessory controls ranging even though it's the peripheral (useful when the accessory needs the distance)—this is what our demo uses. - **Peripheral + Reflector:** The accessory responds to ranging requests (traditional sensor model). ![Diagram showing how Bluetooth LE roles (Central/Peripheral) and Channel Sounding roles (Initiator/Reflector) can be combined independently. In our demo, the Watch is Central + Reflector while the SoC is Peripheral + Initiator.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/role-combinations.png) *Bluetooth LE and Channel Sounding roles are independent—any combination is valid* In our demo, we chose Watch as Central + Reflector and SoC as Peripheral + Initiator. Why? A few reasons: 1. **Simplicity:** The watch app only needs to establish a connection—no ranging APIs required since the Android Ranging API doesn't provide callbacks when an external device initiates CS procedures. 2. **Algorithm control:** Having the SoC as the Initiator gives us direct access to the ranging calculations and lets us customize how distance is computed. 3. **Existing code:** Silicon Labs had already developed and tested the Peripheral + Initiator configuration on their SoC. 4. **Flexibility demonstration:** This unusual role combination shows that Channel Sounding truly allows mixing roles based on your application needs. The roles you choose depend on your specific use case. Consider questions like: Which device needs to know the distance? Which device has better processing power for the ranging calculations? Which device should control when ranging happens? Do you need more control over the distance measurement algorithm? ## The Silicon Labs SoC: Peripheral + Initiator Let's look at what the SoC does in this system. The xG24-DK2606A runs a Channel Sounding Initiator application that handles all the ranging logic. As the **Bluetooth LE Peripheral**, it advertises and waits for connections. As the **CS Initiator**, it controls when ranging procedures happen and performs all the distance calculations. At a high level, the SoC is responsible for: - **Advertising:** Broadcasting its presence so the watch can find and connect to it - **Accepting connections:** Handling pairing and encryption when the watch connects - **Channel Sounding procedures:** Scheduling and executing the ranging measurements - **Distance calculation:** Processing the raw phase data to produce distance values - **Output:** Sending distance measurements to the Mac via USB serial The firmware uses Silicon Labs' Channel Sounding sample application as a foundation. For this demo, the key configuration choices were antenna selection and pairing behavior—but the ranging logic itself comes from Silicon Labs' well-tested implementation. ### The GATT Ranging Service (RAS) Let's dig into one aspect of the architecture that isn't immediately obvious: the role of GATT (Generic Attribute Profile) in Channel Sounding applications. In two-way ranging, both devices take measurements during the CS procedure. The Reflector then sends its measurements to the Initiator via the **GATT Ranging Service (RAS)**, and the Initiator combines both sets of data to calculate the final distance. The Ranging Service (UUID 0x185B) is defined in the Bluetooth specification and includes several characteristics: - **Real-time Ranging Data (UUID 0x2C15):** Streams ranging measurements as they're captured - **On-demand Data (UUID 0x2C16):** Allows requesting specific ranging data - **RAS Control Point (UUID 0x2C17):** Controls ranging behavior and configuration In our demo, the watch (Reflector) sends its measured phase data to the SoC (Initiator) via RAS. The Android Bluetooth stack handles this RAS communication automatically—the watch app doesn't need to explicitly manage the GATT characteristics. The SoC receives the Reflector's measurements, combines them with its own, and calculates the distance. This layered architecture is worth understanding: Channel Sounding operates at the link layer (handled by the Bluetooth controller), while the RAS service provides the application-layer mechanism for exchanging ranging data between devices. The Initiator needs data from both sides to perform accurate distance calculations. ### Antenna Configuration and Diversity The demo uses an asymmetric antenna setup that affects ranging accuracy: - **Pixel Watch 4:** Single antenna - **Silicon Labs xG24-DK2606A:** Two antennas with antenna diversity This creates a **2-antenna path** for Channel Sounding measurements. The SoC can switch between antennas during the ranging procedure (and does so in this demo), which helps mitigate multipath interference and improves accuracy in real-world environments. Antenna diversity is particularly valuable for Channel Sounding because: - Different antenna positions capture different signal paths - Reduces the impact of signal reflections and obstacles For this demo, the key configuration choices were antenna selection timing and pairing behavior—but the ranging logic itself comes from Silicon Labs' well-tested implementation. ## The Watch App: Central + Reflector The Wear OS app is intentionally minimal. Since the watch acts as the **Reflector**, it doesn't need to do any ranging calculations—its entire job is to establish and maintain a Bluetooth LE connection to the SoC. The Bluetooth stack handles the Channel Sounding procedure at the link layer without any app involvement. This is a key architectural insight: the app doesn't call any Channel Sounding APIs. It simply creates a standard Bluetooth LE connection, and the underlying Bluetooth controller handles the ranging procedures automatically when the Initiator (SoC) requests them. ### Connection Flow The app follows a straightforward connection flow: ![Watch app state machine: IDLE transitions to SCANNING on tap, then to CONNECTING when device found, then to CONNECTED when paired, and back to IDLE on disconnect](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/statemachine-watch-3.png) *Watch app connection flow: scan for device, connect, pair, then maintain the link* 1. **Idle:** Waiting for user interaction (tap to start in this demo) 2. **Scanning:** Looking for the SoC by its advertised name 3. **Connecting:** Establishing the Bluetooth LE connection and handling pairing 4. **Connected:** Link established—Channel Sounding procedures now run automatically at the link layer The app also handles error states like Bluetooth being disabled, connection failures, and pairing issues. These are important for user experience but don't affect the core ranging functionality. ![Watch app UI across all connection states: idle, scanning, connecting, connected, disconnected, Bluetooth off, and pairing failed](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/watch-app-all-states.png) *The watch app's UI across all connection states* ### Why the Watch Doesn't See Distance Values One thing worth emphasizing: the watch app has no idea how far away it is from the SoC. As the Reflector, it participates in the ranging procedure by responding to radio signals at precise times, but all the distance calculations happen on the Initiator side. If the watch needed to know the distance (for example, to display it on screen), it would need to either become the Initiator itself, or the SoC would need to send the calculated distance back over GATT. In our architecture, neither is necessary—the Mac receives the distance directly from the SoC over USB. ### Background Behavior An important characteristic of this architecture: the Bluetooth LE connection persists even when the watch app goes to the background. Channel Sounding procedures continue running at the link layer because they're managed by the Bluetooth controller, not the application. You can switch to a different watch face and the proximity demo keeps working. The tap-to-start behavior is purely for the demo—it gives a clear trigger point for the video. In a production application, you'd want the connection to happen automatically when the watch comes within range, using background scanning and automatic reconnection. ## The Mac Unlock Script: Distance Processing and Control The final piece is a Python script running on the Mac that reads distance measurements from the SoC and controls the screen lock. The script bridges the gap between raw ranging data and meaningful actions. ⚠️ **Security & Liability Disclaimer** This script is provided for **demonstration and educational purposes only**. What you should understand about how it works: **Password storage:** Your Mac password is stored in macOS Keychain (encrypted), not in plain text. **Password entry:** The script types your password programmatically using macOS APIs. While safety checks verify the lock screen is active before typing, this approach has inherent security implications compared to Apple's native unlock mechanisms. **Not production-ready:** This is a proof-of-concept to demonstrate Channel Sounding capabilities—it is not a secure authentication system. **USE AT YOUR OWN RISK.** The author and Novel Bits assume no liability for any security issues, data loss, or other damages resulting from using this code. By downloading and running this script, you accept full responsibility for any consequences. For production security applications, use proper authentication frameworks and security audits. ### What the Script Does The script has three core responsibilities: 1. **Receive measurements:** Read distance data from the SoC via USB serial 2. **Process the data:** Apply smoothing and thresholds to make reliable decisions 3. **Control the Mac:** Lock or unlock the screen based on processed distance Each measurement from the SoC includes the distance (in millimeters), a confidence score, and velocity. The script monitors for both measurement data and connection events—when a device disconnects, the script automatically locks the screen as a safety measure. ### Why Signal Processing Matters Raw distance measurements can vary between readings, even under ideal conditions. A single outlier could trigger an unwanted lock or unlock. The script addresses this with two techniques: - **Moving average:** Instead of reacting to individual measurements, the script maintains a rolling window of recent readings and uses their average. For example, if five readings come in as 75 cm, 82 cm, 68 cm, 79 cm, and 76 cm, the averaged value of 76 cm gives a more stable picture than any single reading. - **Consecutive reading requirement:** Before triggering an action, the script requires multiple consecutive readings past the threshold. This prevents brief fluctuations from causing false triggers. ### Proximity Zones and Hysteresis ![Proximity zones diagram showing Near Zone (under 80 cm, triggers unlock), Dead Zone (80 cm to 200 cm, no action), and Far Zone (over 200 cm, triggers lock)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/proximity-zones-h-2.png) *Three proximity zones with hysteresis to prevent oscillation* Let's look at how the script decides when to act. It defines three proximity zones: - **Near zone:** Close enough to unlock (configurable, around 80 cm in my setup) - **Dead zone:** Between near and far—no action taken - **Far zone:** Far enough to lock (configurable, around 200 cm in my setup) The gap between unlock and lock thresholds (the "dead zone") is intentional. It prevents oscillation when you're at the edge of a threshold—you have to move decisively closer or further away to trigger an action. For example, if you're sitting at 1.5 meters (between the 80 cm unlock and 200 cm lock thresholds), the system stays in its current state rather than rapidly toggling. This is a classic hysteresis pattern used in many control systems. The script also includes safety checks that verify the lock screen is active before attempting to unlock. This prevents the password from being typed into the wrong application if something unexpected happens with macOS window focus. ![Terminal showing Screen Unlocked status at 0.34m distance in the near zone (green)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/terminal-unlocked.png) *Terminal output showing "Screen Unlocked" when in the near zone (< 80 cm)* ![Terminal showing Screen Locked status at 2.90m distance in the far zone (red)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/terminal-locked.png) *Terminal output showing "Screen Locked" when in the far zone (> 200 cm). Screenshot captured after manually unlocking to show the terminal state.* ## Live Demo Now let's see everything working together. In this video, I walk through the hardware setup, explain the threshold distances, show the raw serial output from the SoC, and then run a live test with a measuring tape to demonstrate the lock and unlock behavior at precise distances. ### What to Watch For In the video, here are the key moments to watch for: 1. **Hardware and setup:** I walk through the three components—the Pixel Watch 4 (Reflector), the Silicon Labs xG24 dev kit with dual antennas (Initiator), and the Python script reading distance measurements from the SoC's serial port. 2. **Raw serial output:** Before running the Python script, I show what the firmware outputs directly to the serial port—this gives you a sense of the raw data the script works with. 3. **Initial pairing:** When I tap the watch screen, it scans for the SoC, pairs, and establishes the Bluetooth LE connection. The Python script immediately starts displaying live distance measurements. 4. **Walking to the two-meter mark:** With a measuring tape on the ground, I walk back to exactly two meters. You can see the distance readings climbing in the terminal, and when I hit the threshold, the Mac locks. 5. **The dead zone:** As I walk back toward the Mac, I pause around 1.1–1.2 meters—right in the dead zone between the lock and unlock thresholds. Nothing happens, which is exactly what the hysteresis is designed to do. 6. **Walking to 0.8 meters:** When I step closer to the 0.8-meter mark, the Mac automatically unlocks. No button press, no Touch ID—just my presence. The key thing to notice is how accurate the distance readings are compared to the actual measuring tape on the ground. Channel Sounding provides readings at a high rate, and with the smoothing and hysteresis I've configured, the lock/unlock actions feel responsive without being twitchy. ### What This Demo Shows (and What It Doesn't) This is a demo, not a production application. A few things to keep in mind: - **Tap-to-start is for demo purposes.** In a real product, you'd want the watch to automatically scan and connect in the background when you're near your Mac. - **The password typing approach is for demo purposes.** Production applications would use macOS APIs for seamless unlock without needing to store a password. - **Line of sight matters.** Channel Sounding works best with clear line of sight. Obstacles between the watch and SoC can affect accuracy, though it's still much better than RSSI. What this demo does show is the potential. Bluetooth Channel Sounding provides the accuracy needed for true proximity-based access control. Whether it's your Mac, your car, or your front door, the technology enables knowing not just "is this device nearby" but "is this device within arm's reach." In a production implementation, the experience would be completely passive—you'd simply walk toward your Mac and it unlocks, walk away and it locks, with no user interaction required. That's the real promise of Channel Sounding: security that works in the background without demanding your attention. Want to try this yourself? Grab the [watch app](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FRangingWatchApp.zip?ref=novelbits.io) and the [Mac script](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FProximity%5FUnlock.zip?ref=novelbits.io)—you can have this running in an afternoon. ## What's Next ### Beyond Proximity Unlock The proximity unlock demo is just one application. Channel Sounding enables many other use cases: - **Digital car keys:** Unlock your car as you approach, with the precision to know whether you're at the driver door or the trunk. - **Smart door locks:** Hands-free home access that actually works reliably, not just "sometimes when you're holding your phone the right way." - **Asset tracking:** Find tagged items with sub-meter precision—useful in warehouses, hospitals, and large facilities. - **Industrial access control:** Secure zones that respond to exactly where a worker is standing, not just "somewhere in the building." - **Retail and hospitality:** Personalized experiences triggered by precise customer location, not broad proximity. ### Beyond the Development Kit You might be wondering why this demo needs an external development kit at all. The answer is timing—Channel Sounding was only added to the Bluetooth specification in September 2024, and laptop manufacturers haven't shipped Bluetooth chips with this capability yet. But what makes this interesting: Channel Sounding doesn't require new hardware categories. Unlike UWB, which needs dedicated chips (Apple's U1/U2, for example), Channel Sounding is an extension of standard Bluetooth. The same radio that pairs your AirPods could, in principle, handle secure ranging. What we're building with a dev kit today is really a prototype for functionality that could ship natively in your next MacBook or PC. Intel, Qualcomm, and Apple all make Bluetooth silicon—once they add Channel Sounding support, this kind of proximity unlock could work out of the box. No dongle, no extra hardware, just your laptop and your watch. ## Summary In this post, we covered: - What Channel Sounding is and why it's fundamentally different from RSSI-based approaches (introduced in Bluetooth Core Specification 6.0) - The difference between Bluetooth LE roles (Central/Peripheral) and CS roles (Initiator/Reflector)—and why they can be mixed independently - The three-component architecture: Watch (Central + Reflector), SoC (Peripheral + Initiator), and Mac (distance processing and control) - How the GATT Ranging Service (RAS) provides an application-layer interface to ranging data - Signal processing concepts like smoothing, hysteresis, and proximity zones for reliable decision-making - A complete working demo of proximity-based access control You should now be able to understand how Channel Sounding works at a conceptual level, why it's fundamentally different from RSSI-based approaches, and how the various roles and layers fit together in a real system. No more guessing games with signal strength—Channel Sounding gives you the precision to know exactly where devices are. Whether you're building digital keys, smart locks, or other proximity-based applications, this technology provides the accuracy foundation you need. ## Resources ### Get the Code [ ⌚ Watch App Wear OS source + APK Download ZIP ](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FRangingWatchApp.zip?ref=novelbits.io) [ 💻 Mac Script Python unlock script Download ZIP ](https://downloads.novelbits.io/downloads/posts/bluetooth-channel-sounding-proximity-unlock-demo/CS%5FProximity%5FUnlock.zip?ref=novelbits.io) [ 🔧 SoC Firmware Silicon Labs xG24 View on GitHub ](https://github.com/SiliconLabs/bluetooth%5Fstack%5Ffeatures/tree/master/channel%5Fsounding/initiator%5Fas%5Fperipheral%5Freflector%5Fas%5Fcentral?ref=novelbits.io) ### Documentation & References - [Silicon Labs xG24-DK2606A Channel Sounding Dev Kit](https://www.silabs.com/development-tools/wireless/efr32xg24-channel-sounding-dev-kit?ref=novelbits.io) - [Silicon Labs Channel Sounding Documentation](https://docs.silabs.com/rtl-lib/latest/rtl-lib-channel-sounding-fundamentals/?ref=novelbits.io) - [Bluetooth Core Specification 6.0](https://www.bluetooth.com/specifications/specs/core-specification-6-0/?ref=novelbits.io) - [Bluetooth SIG Channel Sounding Overview](https://www.bluetooth.com/channel-sounding-tech-overview/?ref=novelbits.io) 💡 **Free Course:** Ready to build your own Channel Sounding applications? Check out the [free Channel Sounding course](https://academy.novelbits.io/register/free-course-bluetooth-channel-sounding-silicon-labs/?ref=novelbits.io) I created with Silicon Labs—it covers the theory, tools, and implementation details you need to get started! ### BLE Sniffer Basics + Comparison Guide (Updated 2026) URL: https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/ Last updated: 2026-08-19T17:39:48.000Z *Disclosure: Novel Bits is a US distributor of the BleuIO dongles featured in this post.* ## Introduction A BLE sniffer is one of the most crucial tools that every Bluetooth developer should have on hand. There are many cases where the two communicating BLE devices seem to be doing everything right, but things are just not working right.. 😖 In these circumstances, a *BLE sniffer* can come in pretty handy! So, what does a BLE sniffer do? How can it be helpful? What are the different options for BLE sniffers? Those are the exact questions we'll be addressing in this article. ## What is a BLE sniffer? What does a BLE sniffer do? A BLE sniffer (aka Bluetooth protocol analyzer) acts as a **passive listening device** that captures BLE packets sent over the air from various devices within the direct radio range. Why do we call it "passive"? Because it does not interact with the BLE devices around it and instead simply captures the packets, meaning other BLE devices are unaware of its existence. This can be very helpful, especially when you're interested in debugging communication between devices and without interfering and affecting the communication between these devices. For example, when two Bluetooth LE devices connect to each other and something is not working correctly, you wouldn't want to interfere with the communication. Instead, passively capturing the packets exchanged between the devices will give you a better insight into the issues going on with the communication. ## A BLE sniffer is helpful, not just for debugging! Another important reason for getting familiar with and using a BLE sniffer is that it can help tremendously in learning how BLE works. This is especially useful for new features that have just been released in recent versions of the Bluetooth specification. ## How does a BLE sniffer work? In general, a BLE sniffer captures packets in two main scenarios: - **Advertising mode**: it captures advertising packets (mainly on the primary advertising channels 37, 38, and 39) - **Connection mode**: it captures raw packet data exchanged between two Bluetooth LE devices during a connection (the remaining 37 channels: 0 through 36) The way the sniffer accomplishes this primarily depends on its hardware implementation. There are two main types of sniffers: ### 1\. **Low-Cost Sniffers (Dev-Kit Based)** #### Advertising Capture - Can only capture packets on **one RF channel at a time** - Continuously switches between the three primary advertising channels (37, 38, and 39) to capture as many advertising packets as possible - Will inevitably miss some packets, but the probability of capturing missed packets increases the longer the sniffer runs #### Connection Capture - Usually only capable of **sniffing one connection** at a given time - Sniffs a connection by listening on the exact RF channel where the two communicating BLE devices exchange packets - Connected BLE devices use **frequency hopping** — they exchange packets on a specific RF channel during a “connection event,” then switch to a different channel based on a pre-determined pattern #### Hardware & Software - Based on existing **development kits** from chip vendors (Nordic, TI, etc.), with sniffer firmware provided separately - Usually do not support the latest Bluetooth spec updates — sniffing is secondary functionality for these kits - Typically use **Wireshark** (open-source) for viewing captured packets #### Cost - Very affordable — usually **≤ $100**. Typically just the hardware cost (development kit), and the sniffer firmware is provided for free ### 2\. **Professional Sniffers (SDR-Based)** - Typically **Software Defined Radio (SDR)** based — can capture the entire 2.4 GHz radio spectrum - Purpose-built devices, much more capable than dev-kit based sniffers - Can capture **all types of BLE packets** on all 40 channels (advertising and connection) - Can sniff **multiple connections simultaneously** - Can capture all advertising packets in the area without needing to hop between advertising channels - Vendors are committed to supporting the **latest Bluetooth standard** - PC software is typically custom-developed by the vendor (rather than relying on open-source software) - Significantly more expensive — reflects the engineering costs of developing and maintaining dedicated hardware and software *Be sure to check out my *related blog post* covering the differences between a professional Bluetooth sniffer and a low-cost one and why a professional is worth the investment*: [**7 Reasons a Professional BLE Sniffer is Better Than a Low-cost Sniffer for Debugging**](https://novelbits.io/professional-ble-sniffer-vs-low-cost-sniffer-debugging/) ## Can Wireshark sniff BLE? As mentioned above, the type of software needed to interface with the BLE sniffer hardware/device depends on the type of sniffer. For development kit based and some of the mid-range sniffers, Wireshark is usually the officially supported software used to interface with the sniffer. The main advantage here is that it's open-source, which means it's free and well-maintained, and updated with new features and bug fixes. Keep in mind some of the new fields introduced in new versions of the Bluetooth specification may depend on support to be added to Wireshark for these packet types and fields (or added by the sniffer vendor). For dedicated sniffers, the most common solution provided is the use of proprietary software provided by the vendor. The software is typically offered for free to accompany the sniffer device. The main advantage here is that the vendor controls both the PC-based software and sniffer firmware, so they can provide a much better and more seamless user experience. They're also better at providing support for the latest features of the Bluetooth standard. Let's go over a comparison of the most popular BLE sniffers in the market. | Sniffer | Price | Type | Channels | Software | | ------------------------- | --------- | ------------ | -------------- | ----------------------- | | Nordic nRF52840 | \~$10 | Dev-Kit | 1 at a time | nRF Connect for Desktop | | Adafruit Bluefruit | \~$30 | Dev-Kit | 1 at a time | nRF Connect for Desktop | | TI CC2540 | \~$50 | Dev-Kit | 1 at a time | Proprietary (TI) | | Nordic nRF51 | \~$50 | Dev-Kit | 1 at a time | Wireshark | | Ubertooth One | $125–$150 | Dev-Kit | 1 at a time | Open-source tools | | mini-moreph (Recommended) | \~$18K+ | Wideband SDR | All 40 | blueSPY | | moreph30 | \~$23K+ | Wideband SDR | All 40 | blueSPY | | Frontline ComProbe | $1,295 | Dedicated | 3 adv + 1 conn | Frontline Software | | PANalyzr | $9,495 | SDR | All 40 | Wireshark | | Ellisys Tracker | \~$25K | SDR | All 40 | Ellisys Analyzer | | Frontline X240 | $30K+ | SDR | All 40 | Frontline Software | | Ellisys Explorer | $30K+ | SDR | All 40 | Ellisys Analyzer | | Frontline X500 | $45K+ | SDR | All 40 | Frontline Software | | Ellisys Vanguard | $50K+ | SDR | All 40 | Ellisys Analyzer | Sorted by price within each tier. Scroll right on mobile to see all columns. ## BLE Sniffer Comparison ### **1\.** [RFcreations mini-moreph (Novel Bits #1 Recommended)](https://novelbits.io/rfcreations) ***Disclaimer: Novel Bits is the exclusive distributor for RFcreations in North America***. ![RFcreations mini-moreph](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-1.png) - The world’s smallest USB-powered wideband Protocol Analyzer. - **Price:** starts at around $18,000 and goes up depending on added features. - **Pros:** - Very compact and portable (90 × 78 × 20 mm, only 110 g). - SDR-based — supports BR/EDR, BLE, LE Audio, IEEE 802.15.4, and more. - Supports the latest Bluetooth features, including **Channel Sounding**, **T0 Timing for LE Audio**, and **LC3 Autodetect**. - Up to **16-channel logic analysis** with configurable voltage threshold (blueSPY PRO option). - True WiFi packet timing — monitors all 13 WiFi channels simultaneously for co-existence debugging. - Autonomous captures via a connected Android phone app. - Native cross-platform software (macOS, Linux, and Windows). - **Cons:** Not affordable for many. ![RFcreations audiopod](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-2.png) **Works with audiopod™** — an industry-first audio measurement tool for LE Audio and Auracast™ products: - Measure audio latency end-to-end, between channels, relative to on-air packets, and presentation delay. - Current measurement with 8µs resolution and 13-bit precision. ### **2\.** [RFcreations moreph30](https://novelbits.io/rfcreations) ![RFcreations moreph30](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rfcreations-moreph30.jpg) - Wideband 2.4 GHz signal analyzer and generator designed for PHY layer testing. - **Price:** starts at around $23,000. - **Pros:** - SDR-based — supports BR/EDR, BLE, LE Audio, Channel Sounding, IEEE 802.15.4, and more. - Supports all Bluetooth 6.0 RF-PHY test cases with no additional test equipment required. - Built-in 6 GHz CW signal generator and ultra-linear RX/TX chain. - USB + Ethernet interfaces for flexible connectivity. - Expandable with morephE (RF record/playback) and CS-PHY Tester accessories. - Native cross-platform software via blueSPY (macOS, Linux, and Windows). - **Cons:** Larger and more expensive than mini-moreph; designed more for lab/PHY testing than portable field debugging. ### 3\. [**Ellisys Bluetooth Tracker**](https://www.ellisys.com/products/btr1/index.php?ref=novelbits.io) ![Ellisys Bluetooth Tracker BTR1](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/btr1_unit.png) - **Price**: around $25,000. - **Pros**: - Very compact and portable - SDR-based and supports the latest released version of Bluetooth Low Energy spec (BLE-only). - Supports Wi-Fi and 802.15.4 technologies. - Lower cost than other commercial sniffers. - Easy-to-use PC Software - **Cons**: - Not affordable for many - Does not support Classic or dual mode - The software is Windows only (macOS available, but **not** a native app) ### **4\.** [**Texas Instruments BLE Sniffer (CC2540EMK-USB dongle)**](https://www.ti.com/tool/CC2540EMK-USB?ref=novelbits.io) ![Texas Instruments CC2540EMK-USB Bluetooth LE sniffer dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/cc2540emk-usb_cc2540emk-usb_web.jpg) - **Price**: around $50. - **Pros**: Relatively easy to use, reasonable cost, minimal setup required. - **Cons**: can listen on only one advertising channel at a time (hardware limitation), uses proprietary analysis application, challenging to export captured data (need to develop/ or use a tool that parses the exported data), drops packets occasionally, crashes occasionally, **only supports up to Bluetooth version 4.2**. ### **5\.** [**Nordic nRF Sniffer (nRF51 PCA10031 USB dongle)**](https://www.nordicsemi.com/Products/Development-hardware/nrf51-dongle?ref=novelbits.io) ![Nordic Semiconductor nRF51 PCA10031 USB dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nrf51-dongle.png) - **Price**: around $50. - **Pros**: reasonable cost, integrates with Wireshark (Windows only) through the use of Nordic nRF Sniffer software (command line utility). - **Cons**: can listen on only one advertising channel at a time (hardware limitation), requires a bit of setup, occasionally drops packets, and has no support for Bluetooth 5.0 and later versions. ### **6\.** [**Nordic nRF Sniffer (nRF52 PCA10059 USB dongle)**](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle?ref=novelbits.io) ![Nordic Semiconductor nRF52840 PCA10059 USB dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nrf52840-dongle-rev2-prod-page.webp) - **Price**: around $10. - **Pros**: very low cost, fully supports Bluetooth 5 as a development kit, integrates with a full suite of applications from Nordic, the nRF Connect for desktop. - **Cons**: can listen on only one advertising channel at a time (hardware limitation), requires a bit of setup, occasionally drops packets, and usually lags behind in terms of support for the latest Bluetooth Low Energy features. - *Here’s a Getting Started tutorial for this USB dongle: [The nRF52840 USB Dongle Tutorial (Part 1)](https://novelbits.io/nrf52840-usb-dongle-tutorial-1/)* ### **7\.** [**Adafruit Bluefruit LE Sniffer**](https://www.adafruit.com/product/2269?ref=novelbits.io) *(pretty much the same as the nRF51 sniffer – based on the same chipset)* ![Adafruit Bluefruit LE Sniffer](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/adafruit-ble-sniffer-jpeg.jpg) - **Price**: around $30. - **Pros**: low cost, integrates with a full suite of applications from Nordic, the [nRF Connect for Desktop](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF-Connect-for-Desktop?ref=novelbits.io). - **Cons**: Does not support Bluetooth 5.0 and later, can listen on only one advertising channel at a time (hardware limitation), a bit of setup required, drops packets occasionally. ### 8\. [**Ubertooth One**](https://ubertooth.readthedocs.io/en/latest/ubertooth%5Fone.html?ref=novelbits.io) ![Ubertooth One Bluetooth sniffer](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ubertooth-one-jpeg.jpg) - **Price**: $125-$150. - **Pros**: open-source software and hardware. - **Cons**: can listen on only one advertising channel at a time (hardware limitation); difficult to get set up on Mac OS X or Windows (much simpler on Linux). Lags behind in terms of support for the latest Bluetooth spec versions. ### 9\. [**Frontline (Teledyne Lecroy) ComProbe BPA low energy**](https://www.teledynelecroy.com/protocolanalyzer/frontline-bpa-le?ref=novelbits.io) (deprecated) ![Frontline ComProbe BPA Low Energy Bluetooth analyzer](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bpalowenergy-fingers.jpg) - **Price**: [$1,295](https://shop-fte-com.3dcartstores.com/Frontline-BPA-low-energy-Bluetooth-Protocol-Analyzer%5Fp%5F65.html?ref=novelbits.io). - **Pros**: can listen in on all three advertising channels simultaneously, compact design, powerful PC software (almost overwhelmingly powerful). - **Cons**: relatively pricey, Windows only, cumbersome UI (too many bells and whistles), minimal tutorials available, support for Bluetooth version 4.2 (BLE-only, no support for later versions). - **Note:** this sniffer is a bit unique compared to the other sniffers in the list. It utilizes *four* BLE chipsets, *three* of them used to scan each of the primary advertising channels simultaneously (37, 38, and 39), and the *fourth* is used to follow a specific connection between two Bluetooth Low Energy devices. ### 10\. [**Frontline X500**](https://www.teledynelecroy.com/protocolanalyzer/frontline-x500.aspx?ref=novelbits.io)[**TM**](https://www.teledynelecroy.com/protocolanalyzer/frontline-x500.aspx?ref=novelbits.io)[ **Wireless Protocol Analyzer**](https://www.teledynelecroy.com/protocolanalyzer/frontline-x500.aspx?ref=novelbits.io) ![Frontline X500 Wireless Protocol Analyzer](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/x500.jpg) - **Price**: $45,000+ - **Pros**: - Employs Software Defined Radio (SDR), meaning the device’s firmware can be updated to support any future version of the Bluetooth spec. - Captures Bluetooth (BR/EDR and Low Energy), Wi-Fi (Wi-Fi 5, 6, and 6e - including 6 GHz ISM band), and 802.15.4 technologies. - Allows capturing data with a push of a button on the device without being connected to a PC - **Cons**: very expensive, bulky, software is Windows-only. ### 11\. [**Frontline X240**](https://www.teledynelecroy.com/protocolanalyzer/frontline-x240?ref=novelbits.io)[**TM**](https://www.teledynelecroy.com/protocolanalyzer/frontline-x240?ref=novelbits.io)[ **Wireless Wideband Analyzer**](https://www.teledynelecroy.com/protocolanalyzer/frontline-x240?ref=novelbits.io) ![Frontline X240](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/x240_left.png) - **Price**: $30,000+ - **Pros**: - Employs Software Defined Radio (SDR), meaning the device’s firmware can be updated to support any future version of the Bluetooth spec. - Captures Bluetooth (BR/EDR and Classic), Wi-Fi (2.4 GHz only), and 802.15.4 technologies. - Small footprint than similar offerings, lightweight. - Allows capturing data with a push of a button on the device without being connected to a PC - **Cons**: expensive, software is Windows-only. ### 12\. [**Ellisys Bluetooth Explorer**](http://www.ellisys.com/products/bex400/?ref=novelbits.io) ![Ellisys Bluetooth Explorer 400](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bex400_unit.png) - **Price**: $30,000+. - **Pros**: - Employs Software Defined Radio (SDR), meaning the device’s firmware can be updated to support any future version of Bluetooth (BR/EDR and Low Energy). - Captures Bluetooth (BR/EDR and Low Energy), Wi-Fi (2.4 GHz only), and 802.15.4 technologies. - Easy-to-use PC Software. - **Cons**: very expensive, bulky, software is Windows-only. ### 13\. [**Ellisys Bluetooth Vanguard**](https://www.ellisys.com/products/bv1/index.php?ref=novelbits.io) ![Ellisys Bluetooth Vanguard](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bv1_unit.png) - **Price**: $50,000+ - **Pros**: - Employs Software Defined Radio (SDR), meaning the device’s firmware can be updated to support any future version of Bluetooth (BR/EDR and Low Energy). - Captures Bluetooth (BR/EDR and Low Energy), Wi-Fi (2.4 GHz only), and 802.15.4 technologies. - Easy-to-use PC Software. - Supports connection through Ethernet in addition to USB (allowing interfacing remotely). - **Cons**: very expensive, bulky, software is Windows-only. ### 14\. [**Spanalytics PANalyzr**](https://www.spanalytics.com/panalyzr?ref=novelbits.io) ![Spanalytics PANalyzr](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/panalyzer.jpg) - Mid-tier Bluetooth protocol analyzer by [**Spanalytics**](https://www.spanalytics.com/?ref=novelbits.io). - **Price:** $9,495 - **Pros:** - Small form factor. - Bluetooth (BR/EDR + BLE), Wi-Fi & 802.15.4 support. - Optional Wireless Intrusion Detection System (WIDS) module. - Integrates with Wireshark. - Continuous updates for latest Bluetooth versions. - Credit card payment option — no POs or invoicing needed. - **Cons:** May not be affordable for some. Development Companion BleuIO: A Developer-Friendly Bluetooth LE USB Dongle While a sniffer passively listens, BleuIO lets you actively control Bluetooth LE from your computer via simple AT commands. Generate test advertising traffic, scan for nearby devices, establish connections, and read GATT services — all from a terminal or script. A great companion to any sniffer setup. [Learn More About BleuIO →](https://novelbits.io/bleuio/) ## Conclusion & Recommendations I hope that after reading this article, you've learned a lot about BLE sniffers (protocol analyzers) and that you now have a better understanding of how they work. As you can see, the pricing of the different sniffers ranges dramatically between them. Here are a few recommendations depending on your budget and needs: 1. The best sniffer in the list is the RFcreations mini-moreph 2. Obviously, if you're just getting started with BLE development or you're on a budget, then you will have a limited number of options. In that scenario, I highly recommend the [**nRF52840 USB Dongle**](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle?ref=novelbits.io) **\+** [**nRF Sniffer**](https://www.nordicsemi.com/Products/Development-tools/nrf-sniffer-for-bluetooth-le?ref=novelbits.io) option. 3. If you are looking for a capable sniffer that can handle some of what the high-end sniffers (RFcreations, Ellisys, Frontline/Teledyne Lecroy) offer at a lower price, I recommend checking out the **Spanalytics PANalyzr**. Keep an eye out for upcoming posts covering more on BLE sniffers, and be sure to subscribe to the newsletter to be notified when a new post gets published! ## Frequently Asked Questions What is the best Bluetooth LE sniffer for beginners? The Nordic Semiconductor nRF52840 USB Dongle ($10) with nRF Sniffer software and Wireshark is the best starting point. It is inexpensive, portable, supports Bluetooth 5, and integrates with the industry-standard Wireshark packet analyzer. It does have limitations (single-channel sniffing, can miss packets), but it covers most learning and debugging scenarios. Can a Bluetooth LE sniffer capture encrypted data? A sniffer can capture encrypted packets, but decrypting them requires knowing the encryption keys. For development-kit-based sniffers like the nRF52840, you can input keys (LTK, IRK) in the Wireshark toolbar if you have them. Dedicated sniffers from vendors like Ellisys support capturing the pairing process to derive keys automatically. What is the difference between a sniffer and a protocol analyzer? The terms are often used interchangeably. Technically, a "sniffer" refers to the hardware that captures raw radio packets, while a "protocol analyzer" includes the software that decodes and presents the data. In practice, dedicated products (Ellisys, Frontline) bundle both into an integrated solution, while dev-kit solutions pair hardware (nRF52840) with separate software (Wireshark). How many Bluetooth LE channels can a sniffer listen on at once? Development-kit-based sniffers (nRF52840, CC2540) have a single radio and can only listen on one channel at a time — they hop between channels to approximate full coverage. Dedicated SDR-based sniffers (Ellisys, Teledyne, Frontline) can monitor all 40 channels simultaneously, capturing every packet without gaps. Free Download BLE Sniffer Decision Matrix Get our free PDF comparing 14 Bluetooth LE sniffers side by side — budget, professional, and enterprise tiers with prices, features, and recommendations. Send Me the PDF Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ## Ready to Elevate Your Bluetooth Debugging? If you are stuck on a problem you cannot see, I can put a professional sniffer in your hands, shipped within the United States, and help you work out what to capture next. If you would rather own one outright, I distribute them too. [I'm Stuck on a Problem](https://calendly.com/novelbits/bluetooth-le-debugging-scoping-call?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=sniffer-tutorial) [See a Sniffer Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) [Contact Us](https://novelbits.io/contact/) [See what a Debug Block includes, and what it costs →](https://novelbits.io/consulting/?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=sniffer-tutorial) ### Why I Built My New Bluetooth LE Course with BleuIO and AT Commands URL: https://novelbits.io/why-i-built-my-bluetooth-le-course-with-bleuio/ Last updated: 2026-08-19T17:39:34.000Z *Disclosure: Novel Bits is a US distributor of the BleuIO dongles featured in this post.* For the past decade, I've been teaching Bluetooth LE to engineers, developers, and hobbyists. I've used Nordic dev kits, Silicon Labs boards, ESP32 modules, and half a dozen different IDEs. I've written courses that start with toolchain setup, SDK installation, and the inevitable "blinky" example before anyone writes a single line of wireless code. It works. People learn. But I've always felt like there was friction in the process—friction that had nothing to do with Bluetooth LE itself. When I started designing my new course, [**Bluetooth LE Unplugged**](https://novelbits.io/ble-unplugged-course/), I wanted to remove that friction entirely. That decision led me to BleuIO, and it fundamentally changed how I think about teaching wireless protocols. In this post, I'll share why I made this choice, what I discovered along the way, and why I think this approach might work better for certain types of learners. ## The Problem I Kept Running Into Here's a pattern I noticed over years of training: A developer signs up to learn Bluetooth LE. They're motivated. Maybe they're building a mobile app that connects to a sensor, or prototyping a wearable, or evaluating wireless options for their company's next product. Day one looks like this: 1. Download an IDE (often several gigabytes) 2. Install the SDK and toolchain 3. Configure environment variables, paths, and board definitions 4. Debug why the "hello world" example won't compile 5. Flash the board, troubleshoot the debugger connection 6. Finally—maybe—see an LED blink And we haven't touched Bluetooth LE yet. For experienced embedded engineers, this setup is routine. Annoying, maybe, but familiar. But for developers coming from web, mobile, or application backgrounds? It's a wall. And that wall has nothing to do with understanding advertising packets, connection intervals, or GATT services. I found myself spending entire training sessions on toolchain issues instead of the protocol I was supposed to be teaching. ## What I Was Looking For When I started planning Bluetooth LE Unplugged, I had a few requirements: - **Immediate wireless interaction.** Learners should be able to send and receive Bluetooth LE packets within minutes, not hours. - **No SDK installation.** The learning environment should work out of the box, on any operating system, without downloading gigabytes of toolchains. - **See both sides.** One of the hardest concepts in Bluetooth LE is understanding how Central and Peripheral roles work together. I wanted learners to control *both* sides of a connection simultaneously. - **Focus on concepts, not syntax.** The commands should be readable and self-explanatory, not buried in vendor-specific APIs. I evaluated several options: HCI-level tools, Python libraries, various USB dongles, and even browser-based Web Bluetooth approaches. Each had tradeoffs. Then I found [BleuIO](https://novelbits.io/bleuio/). ## Why BleuIO Clicked BleuIO is a USB dongle that speaks Bluetooth LE through simple AT commands over a serial port. You plug it in, open a terminal, type `AT+CENTRAL`, and you're a Central device. Type `AT+PERIPHERAL`, and you're a Peripheral. No drivers on most systems. No SDK. No compilation. And while the simplicity makes it ideal for learning, BleuIO is also deployed in commercial and enterprise environments—industrial gateways, testing infrastructure, and rapid prototyping workflows. Here's what scanning for nearby devices looks like: ```bash AT+CENTRAL AT+GAPSCAN=3 ``` That's it. Two commands, and you're seeing every Bluetooth LE device advertising around you. What struck me wasn't just the simplicity—it was the *readability*. When a student types `AT+GAPSCAN`, they're literally invoking a GAP (Generic Access Profile) scan. The command names map directly to Bluetooth LE concepts. There's no abstraction layer hiding what's actually happening. With AT commands, the abstraction is almost zero. You type a command, you see the result. Cause and effect are immediate and visible. Compare that to any SDK, where you're dealing with initialization structures, callback functions, error handling, and vendor-specific APIs—all before you've even started scanning. ## The Dual-Dongle Insight Here's where things got interesting. BleuIO dongles are inexpensive enough that I could include *two* in the course kit. One acts as a Central, one as a Peripheral. You open two terminal windows side by side, and suddenly you're watching a Bluetooth LE conversation from both perspectives. Let me show you what I mean. In one terminal (the Peripheral): ```bash AT+PERIPHERAL AT+ADVSTART ``` In the other terminal (the Central): ```bash AT+CENTRAL AT+GAPSCAN=3 AT+GAPCONNECT=[address from scan] ``` And just like that, you've established a Bluetooth LE connection—and you can see exactly what happened on both sides. This was the moment I knew I had found the right approach. One of the most common points of confusion in Bluetooth LE is understanding the asymmetry between Central and Peripheral roles. Who initiates the connection? Who advertises? Who scans? Why does the Peripheral set the advertising interval but the Central set the connection parameters? When you're staring at two terminals and watching the handshake happen in real time, these questions answer themselves. ## What This Means for Learners The BleuIO approach isn't right for every *application*. If you're building a battery-powered wearable, a compact sensor node, or any product where size, power consumption, and cost-per-unit matter, you'll need custom firmware on dedicated hardware. There's no escaping that. But many Bluetooth LE applications don't have those constraints. If you're building a desktop tool, a test fixture, an industrial gateway, or a prototype that runs from USB power, BleuIO can take you all the way to production. And even if you *do* need custom firmware eventually, here's what I've found: **learning the protocol first makes the SDK easier later**. When you already understand how advertising and scanning work, how connections are established, and how GATT operations flow between Central and Peripheral—when you've *controlled* both sides of these interactions yourself—the SDK code starts to make sense. You're not learning the protocol and the implementation simultaneously. You're mapping familiar concepts onto new syntax. The BleuIO approach works particularly well for: - **Mobile and web developers** who want to understand what's happening on the other side of their Bluetooth LE stack - **Product managers and architects** who need protocol literacy without becoming firmware engineers - **Embedded developers new to wireless** who want to understand Bluetooth LE concepts before diving into vendor-specific SDKs - **Anyone who's tried the SDK-first approach and bounced off** ## The Tradeoffs I want to be honest about the limitations, because I think that matters. BleuIO's AT command interface doesn't expose everything. The underlying hardware doesn't support LE Coded PHY for long-range applications, and some advanced features like channel-specific scanning or Direct Test Mode aren't accessible via AT commands. For battery-operated products, compact form factors, or high-volume manufacturing where every cent and milliamp matters, you'll still need traditional embedded development with custom firmware. But those constraints help focus attention on what matters most when learning: the protocol fundamentals. Advertising, scanning, connections, GATT services and characteristics, reading, writing, notifications—these concepts are the same whether you're working with AT commands or an SDK, whether you're prototyping or deploying in the field. The difference is that with BleuIO, you can master those concepts in hours instead of days, and the knowledge transfers directly to whatever platform you use next. ## What I Built Bluetooth LE Unplugged is the course I wish I'd had when I started learning wireless protocols. It ships with two BleuIO dongles, and the entire curriculum is designed around the dual-terminal approach I described above. You'll go from unboxing to your first Bluetooth LE connection in about ten minutes. No SDK installation. No toolchain configuration. Just plug in, open a terminal, and start sending commands. From there, we build up systematically: - How advertising and scanning actually work (and why the timing matters) - Connection establishment from both Central and Peripheral perspectives - GATT services, characteristics, and descriptors—what they are and how to interact with them - Reading, writing, and notifications in practice - Bonding and security basics By the end, you'll have a working mental model of Bluetooth LE that will serve you whether you're writing Swift for iOS, Kotlin for Android, or C for embedded systems. 💡 **Insider Tip:** The course is currently in pre-sale with a 25% discount (ends April 20th, 2026). If you've been wanting to understand Bluetooth LE without fighting toolchains first, this might be a good fit. [Learn more about Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/). ## Final Thoughts I'm not abandoning SDK-based training. For developers building battery-powered devices, compact wearables, or high-volume products, custom firmware is still the right path—and I have [courses in the Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) that cover exactly that. But I've come to believe that the protocol and the implementation are two different things—and that learning them separately, in the right order, makes both easier. And for many applications, the AT command approach isn't just a stepping stone; it's a viable production solution. BleuIO gave me a way to teach the protocol first, with tools that scale from learning to deployment. Bluetooth LE Unplugged is the result. If you've struggled with Bluetooth LE in the past, or if you've been putting off learning it because the SDK setup felt overwhelming, I'd encourage you to try a different approach. Sometimes the fastest path forward is the one with the fewest obstacles at the start. ### Introducing BleuIO Explorer: A Free Web-Based Bluetooth LE Debugging Tool URL: https://novelbits.io/bleuio-explorer-free-bluetooth-le-debugging-tool/ Last updated: 2026-08-19T17:39:17.000Z *Disclosure: Novel Bits is a US distributor of the BleuIO dongles featured in this post.* If you've ever spent hours wrestling with native Bluetooth LE debugging tools, dealing with complex setup procedures, or waiting for app store approvals just to test a simple characteristic read, you're going to appreciate what I'm about to share with you. I've been working on a tool that I believe will significantly improve the Bluetooth LE development and debugging workflow for many of you. It's called [**BleuIO Explorer**](https://novelbits.io/bleuio-explorer), and it runs entirely in your web browser. In this post, we'll cover: - What BleuIO Explorer is and why I built it - The four main capabilities: scanning, connections, GATT exploration, and advertising - How to get started in under a minute - Real-world use cases where this tool shines 💡 **New to Bluetooth LE?** If terms like GATT, characteristics, and notifications are unfamiliar, the [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course) course covers all the fundamentals you need to make the most of debugging tools like this one. ## The Problem with Existing Bluetooth LE Tools Before we dive into the solution, let's take a step back and acknowledge the pain points that many Bluetooth LE developers face daily. Most Bluetooth LE debugging tools fall into one of these categories: - **Mobile apps** (like nRF Connect or LightBlue) - Great for quick checks, but limited screen real estate, difficult to copy/paste data, and you're constantly switching between your phone and computer - **Desktop applications** \- Often require specific hardware, complex installation procedures, or platform-specific builds - **Command-line tools** \- Powerful but not exactly user-friendly for rapid prototyping What if you could have a debugging tool that combines the convenience of a web app with the power of a dedicated desktop application? That's exactly what BleuIO Explorer aims to deliver. ## What is BleuIO Explorer? BleuIO Explorer is a **free, browser-based Bluetooth LE debugging and prototyping tool** that works with the BleuIO USB dongle. It leverages the Web Serial API (available in Chrome, Edge, and Opera) to communicate directly with the dongle from your browser - no installation required. ![BleuIO Explorer interface showing the Scanner tab with discovered devices and dongle information](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/bleuio-explorer-scanner-overview.png) The BleuIO Explorer interface - clean, intuitive, and runs right in your browser Let's walk through the four main capabilities that make this tool useful for everyday Bluetooth LE development. ## 1\. Device Scanning The Scanner tab is where most debugging sessions begin. With BleuIO Explorer, you can discover nearby Bluetooth LE devices with several filtering options to help you find exactly what you're looking for. **Key scanning features include:** - **Adjustable scan duration** \- Set anywhere from 1 to 30 seconds depending on your needs - **Device name filtering** \- Quickly find devices by typing part of their name (case-insensitive) - **RSSI threshold** \- Filter out distant devices to focus on nearby ones - **Hide unknown devices** \- Remove unnamed devices from the list to reduce clutter For each discovered device, you'll see: - Device name (with smart emoji icons based on device type - heart monitors get ❤️, headphones get 🎧, and so on) - MAC address - Real-time RSSI signal strength with a visual indicator - Whether the device is connectable or a beacon ![BleuIO Explorer scan results showing multiple discovered Bluetooth LE devices with RSSI values](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/bleuio-explorer-scan-results.png) Scan results showing nearby devices with names, MAC addresses, and signal strength indicators For example, if you're debugging a heart rate monitor and there are dozens of devices nearby, you can simply type "heart" in the filter field, and the list will instantly narrow down to matching devices. ## 2\. Connection Management Once you've found the device you want to debug, connecting is straightforward. Click the "Connect" button on any connectable device, and BleuIO Explorer handles the rest. The Connections tab provides: - **Real-time connection status** \- Watch the connection progress through each step (opening port, verifying dongle, configuring, ready) - **Active connection list** \- See all currently connected devices at a glance - **Quick GATT access** \- Jump directly to exploring a device's services and characteristics - **Unexpected disconnection alerts** \- Get notified immediately if a device disconnects One feature I'm particularly pleased with is the **auto-reconnect option**. If you enable "Reconnect on refresh," the tool will automatically reconnect to your BleuIO dongle when you reload the page - a small convenience that saves time during iterative development. ![BleuIO Explorer Connections tab showing a connected device with Explore GATT and Disconnect options](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/bleuio-explorer-connections.png) The Connections tab shows active device connections with quick access to GATT exploration ## 3\. GATT Explorer This is where BleuIO Explorer really shines for debugging purposes. The GATT Explorer tab provides a hierarchical view of all services and characteristics on a connected device. **For each characteristic, you can:** - **Read values** \- Fetch the current value with a single click - **Write values** \- Send data in either HEX or text format - **Write without response** \- For characteristics that support this faster write mode - **Subscribe to notifications** \- Real-time updates when values change - **Subscribe to indications** \- For characteristics that require acknowledgment The interface clearly shows which operations are available for each characteristic through property badges (Read, Write, Write No Response, Notify, Indicate). This means you won't waste time trying to write to a read-only characteristic. For example, if you're testing a custom sensor that sends temperature readings via notifications, you can subscribe to the temperature characteristic and watch the values update in real-time as the sensor takes measurements. The value display supports both HEX and interpreted ASCII modes, so you can toggle between raw bytes and human-readable text. ![BleuIO Explorer GATT Explorer tab showing services and characteristics with Read and Subscribe buttons](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/bleuio-explorer-gatt.png) The GATT Explorer provides full read/write/subscribe capabilities for all characteristics 💡 **Want to understand GATT at a deeper level?** The [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course) course includes dedicated modules on GATT architecture, service design, and characteristic properties - essential knowledge for building robust Bluetooth LE applications. ## 4\. Advertiser The Advertiser tab lets you configure and broadcast custom Bluetooth LE advertisements - turning your computer (via the BleuIO dongle) into a BLE peripheral. This is incredibly useful for: - Testing how your mobile app discovers and filters devices - Prototyping beacon configurations - Simulating a peripheral before the hardware is ready - Teaching and demonstrating BLE concepts **Advertisement configuration options include:** - **Advertisement type** \- Connectable, Non-Connectable (beacon), or Scannable - **Device name** \- Set the Complete Local Name that scanners will see - **Service UUIDs** \- Advertise specific services (with autocomplete for standard UUIDs) - **Manufacturer data** \- Include custom manufacturer-specific data with company ID lookup - **Advertising interval** \- Control how frequently advertisements are broadcast - **Raw data mode** \- For advanced users who need precise control over the advertisement payload The tool includes a **real-time packet size indicator** that shows how much of the available advertisement space you're using. This helps you stay within the 31-byte limit (or 28 bytes for connectable advertisements that include flags). For example, if you're building an app that needs to discover devices advertising a specific service UUID, you can use BleuIO Explorer to broadcast that exact advertisement and verify your app's filtering logic works correctly. ## Getting Started Getting up and running with BleuIO Explorer takes less than a minute: 1. **Get a BleuIO dongle** \- If you don't already have one, you can [order from our shop](https://novelbits.io/bleuio) 2. **Plug it in** \- Connect the dongle to any USB port on your computer 3. **Open the tool** \- Navigate to [BleuIO Explorer](https://novelbits.io/bleuio-explorer) in Chrome, Edge, or Opera 4. **Connect** \- Click "Connect Dongle" and select the BleuIO from the port picker That's it. No drivers to install, no software to download, no accounts to create. You're ready to start scanning, connecting, and debugging. ## Real-World Use Cases Let me share a few scenarios where BleuIO Explorer has proven particularly valuable: ### Debugging Connection Issues When a mobile app fails to connect to a Bluetooth LE device, it's often unclear whether the problem is with the app, the device, or the connection parameters. With BleuIO Explorer, you can quickly verify that the device is advertising correctly, that it's connectable, and that its GATT services are accessible. If BleuIO Explorer can connect and read characteristics successfully, you know the issue is likely in your app code. ### Verifying Firmware Updates After flashing new firmware to a BLE device, you want to verify that the GATT structure is correct and that characteristics behave as expected. BleuIO Explorer lets you rapidly test read/write operations without writing any code. ### Teaching and Demonstrations If you're teaching Bluetooth LE concepts, having a visual tool that runs in a browser makes demonstrations much more accessible. Students can follow along on their own computers without complex setup procedures. ### Quick Prototyping Before writing mobile app code to interact with a BLE device, you can use BleuIO Explorer to understand the device's GATT structure, test different write commands, and observe notification patterns. This exploration phase often reveals important details that inform your app's architecture. ## Browser Compatibility BleuIO Explorer requires a browser that supports the Web Serial API: - **Chrome 89+** (recommended) - **Edge 89+** - **Opera 75+** Unfortunately, Safari and Firefox don't currently support Web Serial API, so they won't work with this tool. If you're primarily a Safari user, Chrome can be used just for this purpose. ## What's Next BleuIO Explorer is currently in beta, and I'm actively working on improvements based on user feedback. Some features on the roadmap include: - Saving and loading device profiles - Exporting scan results and GATT data - Improved dark mode support - Additional advertisement data type builders If you have feature requests or encounter any issues, I'd love to hear from you. ## Try It Now BleuIO Explorer is available now at [**novelbits.io/bleuio-explorer**](https://novelbits.io/bleuio-explorer). If you have a BleuIO dongle, give it a try and let me know what you think. If you don't have a dongle yet but want to see the interface, you can still open the tool - it will show a placeholder prompting you to connect a dongle, but you'll get a sense of the layout and capabilities. 💡 **Want to dive deeper into Bluetooth LE development?** Check out the [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course) course - a comprehensive video course that takes you from the fundamentals to building real-world Bluetooth LE applications. Perfect for developers who want to master Bluetooth LE development! ## Summary In this post, we introduced BleuIO Explorer, a free browser-based Bluetooth LE debugging tool. Here's what we covered: - **Scanner** \- Discover and filter nearby BLE devices with real-time RSSI visualization - **Connections** \- Manage device connections with auto-reconnect support - **GATT Explorer** \- Read, write, and subscribe to characteristics with full property support - **Advertiser** \- Configure and broadcast custom BLE advertisements You should now be able to use BleuIO Explorer to debug BLE devices, verify GATT implementations, and prototype advertising configurations - all without leaving your browser. [Launch BleuIO Explorer →](https://novelbits.io/bleuio-explorer) ### Getting Started with BleuIO: Your First Bluetooth LE Commands in 10 Minutes URL: https://novelbits.io/bleuio-getting-started-guide/ Last updated: 2026-04-08T18:05:13.000Z ## Getting Started with BleuIO: Your First Bluetooth LE Commands in 10 Minutes If you've ever tried to learn Bluetooth Low Energy (Bluetooth LE), you know the frustration. Download a vendor SDK, configure toolchains, write embedded C, flash firmware—and maybe, after a full day, you'll see your first advertising packet. The tooling gets in the way of the learning. That's exactly why I chose BleuIO for my new hands-on course, **[Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/)**. It strips away all that complexity and lets you focus on what actually matters: understanding the protocol. In this post, I'll walk you through everything you need to get started with BleuIO—from unboxing to running your first Bluetooth LE commands. By the end, you'll have scanned for nearby devices, understood what the results mean, and made your own dongle visible to the world. Here's what we'll cover: - What BleuIO is and why it's different from traditional development kits - The hidden superpower: bypassing your computer's Bluetooth stack entirely - Real-world applications (production testing, industrial IoT, automation) - Setting up your hardware and software - Your first AT commands (and what they do) - Scanning for nearby Bluetooth LE devices - Understanding scan results (MAC addresses, RSSI, advertising data) - Making your dongle visible with custom advertising - The two-dongle advantage for complete visibility - Troubleshooting common setup issues Let's get started. --- ## What is BleuIO? BleuIO is a Bluetooth LE USB dongle that you control through simple text commands—no embedded C, no SDK, no compilation required. Here's why that matters: traditional Bluetooth LE development requires you to learn a vendor's SDK (often thousands of files), set up a specific toolchain, write firmware in C, and flash it to a development board. That's a lot of friction when you just want to understand how advertising works. BleuIO uses **AT commands**—the same command style used in modems for decades. If you can type text into a terminal, you can control BleuIO. For example, to start advertising: ```plaintext AT+ADVSTART ``` That's it. Your dongle is now broadcasting Bluetooth LE packets. ### Key Specifications Let's look at what you're working with: - **Bluetooth Version**: Bluetooth LE 5.0 (5.2 on Pro model) - **Connections**: Up to 8 simultaneous connections per dongle - **Roles**: Central, Peripheral, or both simultaneously - **Interface**: USB virtual serial port (no special drivers on most systems) - **Libraries**: Python ([pip install bleuio](https://pypi.org/project/bleuio/?ref=novelbits.io)) and JavaScript available - **Chipset**: Renesas DA14683 (Standard version) and DA14695 (Pro version) SoC (same chip used in commercial products) - **Price**: $29-45 USD ([available from our US store](https://novelbits.io/bleuio/) with fast domestic shipping) I recommend BleuIO specifically because you're not learning on a toy—you're working with production-grade hardware that's used in real commercial products. ### The Hidden Superpower: No Host Bluetooth Stack Required Here's something most people don't realize until they've struggled with it: **BleuIO has its own complete Bluetooth LE stack built into the dongle**. You're not using your computer's Bluetooth at all. Why does this matter? Let me explain. If you've ever tried to build a Bluetooth LE application using your computer's native Bluetooth, you've likely encountered these frustrations: - **Windows**: The Bluetooth stack is locked down. Accessing raw advertising data or controlling low-level parameters requires complex WinRT APIs, and many operations simply aren't exposed. - **macOS**: Apple restricts Bluetooth LE access significantly. You need to use CoreBluetooth, which abstracts away protocol details and limits what you can do programmatically. - **Linux**: BlueZ is powerful but notoriously complex. Configuration varies between distributions, and getting consistent behavior across systems is a challenge. With BleuIO, you bypass all of this. The dongle appears as a simple serial port—something every operating system handles identically. Your Python script, Node.js application, or shell command works exactly the same on Windows, macOS, and Linux. No platform-specific APIs, no permission issues, no driver headaches. For example, this Python code runs identically on any operating system: ```python import serial dongle = serial.Serial('/dev/ttyUSB0', 57600) # or 'COM3' on Windows dongle.write(b'AT+GAPSCAN=5\r') print(dongle.read_until(b'SCAN COMPLETE')) ``` This portability opens up powerful possibilities that aren't practical with native Bluetooth stacks. ### Real-World Applications BleuIO's architecture makes it ideal for scenarios where reliability, portability, and automation matter: **Production Line Testing** Manufacturing facilities need to test Bluetooth LE devices as they come off the assembly line. With BleuIO, you can build test stations that: - Connect to devices and verify GATT services - Measure signal strength for antenna validation - Run automated test sequences across hundreds of units per day - Work on whatever operating system the factory already uses I've seen teams save hundreds of engineering hours by automating tests that previously required manual interaction with mobile apps. **Industrial IoT Gateways** In industrial settings, you often need to collect data from multiple Bluetooth LE sensors—temperature monitors, vibration sensors, environmental sensors. BleuIO can: - Connect to up to 8 sensors simultaneously per dongle - Run on industrial PCs, Raspberry Pi, or edge devices - Operate 24/7 without the stability issues that plague native Bluetooth stacks - Scale by adding more dongles (each appears as a separate serial port) **Automated QA and CI/CD Pipelines** Software teams building Bluetooth LE products can include hardware-in-the-loop testing in their continuous integration pipelines. BleuIO makes this practical because: - Tests run identically on developers' machines (any OS) and CI servers - No special Bluetooth permissions or VM configurations required - Scripts are simple serial communication—easy to maintain and debug **Kiosk and Retail Applications** Interactive kiosks that need to communicate with customer devices (for loyalty programs, proximity marketing, or check-in systems) benefit from BleuIO's reliability. The dongle handles the Bluetooth complexity while your application focuses on business logic. **Healthcare Device Development** Medical device manufacturers testing Bluetooth LE blood pressure monitors, glucose meters, or patient monitors can build consistent test environments that work across their engineering teams, regardless of what computers they use. **Multi-Device Orchestration** Need to control dozens of Bluetooth LE devices simultaneously? Connect multiple BleuIO dongles to a single computer. Each dongle supports 8 connections, so four dongles give you 32 simultaneous connections—something that's nearly impossible with native Bluetooth stacks. ### Why Portability Matters Let me share a concrete example. I've worked with teams where: - Developers use macOS - QA uses Windows - Production runs on Linux With native Bluetooth, they needed three different codebases, three sets of APIs, and constant cross-platform debugging. With BleuIO, they write one script that works everywhere. The dongle abstracts away the operating system entirely. This isn't just about convenience—it's about building applications that actually ship. When your Bluetooth LE code works identically on every platform, you eliminate an entire category of bugs and support issues. --- ## What You'll Need Before we dive in, let's make sure you have everything ready. ### Hardware **Required**: - 1× BleuIO USB dongle (Standard $29, Pro $45) - Computer with a USB port (Windows, macOS, or Linux) **Recommended** (for later in the series): - 2× BleuIO dongles (to see both sides of Bluetooth LE communication) - Smartphone with a Bluetooth LE scanner app ([nRF Connect for iOS](https://apps.apple.com/app/nrf-connect-for-mobile/id1054362403?ref=novelbits.io) or [Android](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&ref=novelbits.io), LightBlue, or BLE Scanner) **Where to Buy**: Novel Bits is an official US distributor for BleuIO. [Get yours from our US store →](https://novelbits.io/bleuio/) with fast domestic shipping (typically 3-5 business days). You can also purchase directly from [bleuio.com](https://www.bleuio.com/?ref=novelbits.io) (ships from Sweden). ![Two BleuIO USB dongles - one blue and one red - showing the hardware you'll use throughout this series](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/Dual-Dongles---STD.png) BleuIO dongles come in different colors. Having two lets you simulate both sides of a Bluetooth LE connection. ### Software You'll need a way to send commands to the dongle. Choose one: **Option 1: BleuIO Web Terminal** (easiest) - No installation required - Works in Chrome, Edge, or any WebSerial-compatible browser - Visit: [bleuio.com/bleuioapp/](https://bleuio.com/bleuioapp/?ref=novelbits.io) **Option 2: Desktop Terminal Application** - **Windows**: PuTTY, RealTerm, or Tera Term - **macOS**: `screen` command or CoolTerm - **Linux**: `screen`, `minicom`, or `picocom` **Option 3: Python** (for automation later) - Python 3.8+ - BleuIO library: `pip install bleuio` For this tutorial, I recommend starting with the Web Terminal—it's the fastest way to get going. --- ## Setting Up Your BleuIO Let's get the dongle connected and verify it's working. ### Step 1: Plug In the Dongle Insert your BleuIO into any USB port. On most systems, it will appear as a virtual serial port automatically—no drivers needed. **What to expect**: - **Windows**: A new COM port appears (check Device Manager → Ports) - **macOS**: A device like `/dev/tty.usbmodem*` appears - **Linux**: A device like `/dev/ttyUSB0` or `/dev/ttyACM0` appears ### Step 2: Wait for the Bootloader When you plug in BleuIO, it enters a 10-second bootloader window (for firmware updates). Just wait for this to pass—you'll see the LED behavior change when it's ready for commands. ### Step 3: Connect Your Terminal **If using the Web Terminal**: 1. Go to [bleuio.com/bleuioapp/](https://bleuio.com/bleuioapp/?ref=novelbits.io) 2. Click "Connect" 3. Select your BleuIO device from the popup 4. You should see a terminal ready for input **If using a desktop terminal** (PuTTY, screen, etc.): Configure these serial settings: | Setting | Value | | ------------ | ----- | | Baud rate | 57600 | | Data bits | 8 | | Parity | None | | Stop bits | 1 | | Flow control | None | For example, on macOS or Linux: ```bash screen /dev/tty.usbmodem* 57600 ``` ### Step 4: Verify the Connection Type this command and press Enter: ```plaintext AT ``` You should see: ```plaintext OK ``` If you see `OK`, congratulations—your BleuIO is connected and ready! If not, check the troubleshooting section at the end of this post. --- ## Your First AT Commands Now that we're connected, let's explore a few basic commands to understand how BleuIO works. ### Command 1: AT - Connection Test ```plaintext AT ``` **Response**: `OK` This is the simplest command—it just confirms that communication is working. I recommend using this whenever you're unsure if the dongle is responding. ### Command 2: ATI - Device Information ```plaintext ATI ``` **Response**: ```plaintext Smart Sensor Devices DA14695 BleuIO Firmware Version:2.7.6 Peripheral role Not Connected Not Advertising ``` This tells you the manufacturer, chipset, firmware version, current role, and connection state. If you're following along with this series, I recommend having firmware v2.7.0 or later for all features to work correctly. ### Command 3: AT+GETMAC - Your MAC Address ```plaintext AT+GETMAC ``` **Response**: ```plaintext OK OWN MAC ADDRESS:40:48:FD:EB:AC:12 ``` This is your dongle's Bluetooth MAC address—its unique identifier on the network. You'll see this address when scanning from other devices. Your MAC address will be different from this example. ### Command 4: AT+GAPSTATUS - Current State ```plaintext AT+GAPSTATUS ``` **Response**: ```plaintext Dual role Not Connected Not Advertising ``` This shows what your dongle is currently doing: its role (Central, Peripheral, or Dual), connection status, and whether it's advertising. Right now, it's not advertising or connected to anything. --- ## Discovering Nearby Devices Here's where it gets interesting. Let's scan for every Bluetooth LE device in range. ### Start a Scan Type this command to scan for 10 seconds: ```plaintext AT+GAPSCAN=10 ``` **What happens**: Your dongle listens on the three advertising channels (37, 38, and 39) and reports every Bluetooth LE device it hears. ### Understanding the Output You'll see something like this: ```plaintext SCANNING... [01] Device: [1]30:63:C5:D0:B1:DE RSSI: -38 [02] Device: [0]D0:76:50:80:0A:98 RSSI: -75 [03] Device: [1]27:5D:B8:2E:96:B0 RSSI: -51 [04] Device: [1]5E:CE:CF:C5:20:BB RSSI: -84 SCAN COMPLETE ``` Let's break down what each part means: ```plaintext [01] Device: [1]30:63:C5:D0:B1:DE RSSI: -38 │ │ │ │ │ │ │ └── Signal strength in dBm │ │ └───────────────────────── MAC address │ └──────────────────────────── Address type: [0]=Public, [1]=Random └──────────────────────────────────────── Device index ``` ### Address Types The number in brackets indicates the address type: - **\[0\] Public address**: Permanent, factory-assigned MAC address (like traditional Ethernet MACs) - **\[1\] Random address**: Generated address, often used for privacy (many smartphones use these) For example, Apple devices typically use random addresses that change periodically to prevent tracking. ### RSSI (Signal Strength) The negative number (like `-65`) is the **Received Signal Strength Indicator (RSSI)** in dBm—a measure of how strong the signal is from that device: ![RSSI Signal Strength Guide showing signal quality ranges from Excellent (-30 to -50 dBm) to Weak (-85 to -100 dBm)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/rssi-guide-minimal.png) RSSI signal strength ranges and their approximate meanings. ### Advertising Data The basic scan shows addresses and signal strength, but Bluetooth LE devices also broadcast an **advertising payload**—up to 31 bytes of useful data. To see this data, use the `AT+FINDSCANDATA` command: ```plaintext AT+FINDSCANDATA ``` This shows the raw advertising data in hex format: ```plaintext [D0:76:50:80:0A:98] Device Data [ADV]: 02010609094D79426561636F6E ``` The advertising payload is encoded in LTV (Length-Type-Value) format. Let me decode this example: | Bytes | Meaning | | ----------------------------- | ------------------------------------------------------------------------------------ | | 02 01 06 | Length=2, Type=0x01 (Flags), Value=0x06 (General Discoverable, BR/EDR Not Supported) | | 09 09 4D 79 42 65 61 63 6F 6E | Length=9, Type=0x09 (Complete Local Name), Value="MyBeacon" (ASCII) | Common advertising data types you'll see: - **0x01** \- Flags (discoverability, BR/EDR support) - **0x02/0x03** \- 16-bit Service UUIDs (incomplete/complete) - **0x06/0x07** \- 128-bit Service UUIDs (incomplete/complete) - **0x08/0x09** \- Device Name (shortened/complete) - **0xFF** \- Manufacturer Specific Data (company ID + custom data) ![Advertising Data Decoder infographic showing how to parse LTV (Length-Type-Value) format in Bluetooth LE advertising packets](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/advertising-data-decoder-3.png) Visual breakdown of advertising data LTV format—each field is Length + Type + Value. ### What Devices Will You Find? When you scan, you'll likely discover: - **Smartphones** (often with random addresses, minimal advertising data) - **Smart TVs** (many advertise for remote pairing) - **Wireless earbuds** (usually when in pairing mode) - **Fitness trackers and smartwatches** - **Smart home devices** (thermostats, locks, sensors) - **Bluetooth beacons** (retail, navigation, asset tracking) - **Other BleuIO dongles** (if you have more than one) For example, if you see advertising data starting with `4C:00`, that's Apple's company ID—you've found an iPhone, iPad, AirPods, or other Apple device. --- ## Making Yourself Visible Now let's flip the script—instead of scanning, let's make your dongle visible to the world. ### Set Your Device Name First, let's give your dongle a recognizable name: ```plaintext AT+DEVICENAME=MyFirstBeacon ``` **Response**: `OK` This name will appear when other devices scan for you. ### Start Advertising Now, start broadcasting: ```plaintext AT+ADVSTART ``` **Response**: `OK` Your dongle is now advertising! It's sending packets on channels 37, 38, and 39, announcing its presence to the world. ### Verify with Your Phone Open a Bluetooth LE scanner app on your smartphone (nRF Connect is my favorite). You should see "MyFirstBeacon" in the list of nearby devices. Try walking around while watching the RSSI value change—you'll see the signal strength decrease as you move away from your dongle. ### Stop Advertising When you're done: ```plaintext AT+ADVSTOP ``` **Response**: `OK` ### Experiment: Change the Advertising Interval By default, BleuIO advertises every 30 milliseconds. You can change this to see the tradeoff between discoverability and power consumption: ```plaintext AT+ADVSTART=1000 ``` This advertises every 1000ms (1 second). Now scan from your phone—you'll notice it takes longer to discover the device because it's broadcasting less frequently. For battery-powered beacons, longer intervals save power. For devices that need quick discovery, shorter intervals (20-100ms) are better. --- ## The Two-Dongle Advantage Here's where BleuIO really shines for learning. With two dongles connected to your computer, you can see both sides of Bluetooth LE communication simultaneously. ![Two BleuIO dongles connected to a computer - one acting as Central (scanner) and one as Peripheral (advertiser)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/11/Dual-Dongles---STD.png) With two dongles, one becomes your "Central" (scanner/connector) and one becomes your "Peripheral" (advertiser)—giving you complete visibility into both sides of the Bluetooth LE protocol. ### Why This Matters In Bluetooth LE, there are two fundamental roles: - **Central**: The device that scans and initiates connections (like your phone) - **Peripheral**: The device that advertises and accepts connections (like a heart rate monitor) ![BleuIO sequence diagram showing Bluetooth LE peripheral and central communication flow including advertising, scanning, and connection establishment](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/bleuio-sequence.png) With one dongle, you only experience one side. You can advertise, but you need your phone to scan. You can scan, but you need some external device to advertise. With two dongles, you control everything. Let's try it. If you only have one dongle, consider picking up a second one from [our US store](https://novelbits.io/bleuio/)—the [Pro 2-Pack](https://novelbits.io/bleuio/) is the most cost-effective way to get started with two-dongle development. ### Two-Dongle Experiment Open two terminal windows, one connected to each dongle. **Terminal 1 (Peripheral)**: ```plaintext AT+PERIPHERAL AT+DEVICENAME=Sensor1 AT+ADVSTART ``` **Terminal 2 (Central)**: ```plaintext AT+CENTRAL AT+GAPSCAN=5 ``` In Terminal 2, you'll see "Sensor1" appear in the scan results—your second dongle discovered the first one. Now take it further and connect: **Terminal 2**: ```plaintext AT+GAPCONNECT=[0]XX:XX:XX:XX:XX:XX ``` (Replace `XX:XX:XX:XX:XX:XX` with the MAC address from Terminal 1's `AT+GETMAC`. The `[0]` indicates a public address; use `[1]` for private/random addresses.) You now have a live Bluetooth LE connection between two devices you fully control. You can watch the connection establishment from both perspectives—something that's incredibly valuable for understanding the protocol. ![Two BleuIO Web Terminal windows showing a successful connection: the peripheral (left) advertising as SENSOR1 and the central (right) scanning, connecting, and discovering GATT services](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/two-dongle-connection-1.png) Two dongles connected: the peripheral (left) advertises while the central (right) scans, connects, and discovers services. I'll cover connections and data exchange in depth in the next posts, but this gives you a taste of what's possible. --- ## Troubleshooting Common Issues Let me share some issues I've seen developers encounter and how to fix them. ### "Dongle Not Recognized" **Symptoms**: No COM port appears, or the device isn't listed in the Web Terminal. **Solutions**: 1. **Try a different USB port** \- Some USB hubs have compatibility issues 2. **Wait for the bootloader** \- BleuIO has a 10-second bootloader window on startup; wait for it to pass 3. **Check for driver issues** (Windows) - Open Device Manager and look for unknown devices; you may need to install the CP210x USB driver 4. **Try a different cable** \- Some USB cables are charge-only and don't support data ### "No Response to AT Commands" **Symptoms**: You type `AT` but nothing happens. **Solutions**: 1. **Check baud rate** \- Must be 57600 2. **Check line ending** \- Some terminals need CR+LF, others just CR 3. **Wait for bootloader to finish** \- Try again after 15 seconds 4. **Reset the dongle** \- Unplug, wait 5 seconds, replug 5. **Check terminal connection** \- Make sure you're connected to the right port ### "Scan Shows Nothing" **Symptoms**: `AT+GAPSCAN` returns no devices. **Solutions**: 1. **Scan longer** \- Try `AT+GAPSCAN=30` for 30 seconds 2. **Move to a different location** \- Some environments have fewer Bluetooth LE devices 3. **Use your phone as a test target** \- Open Bluetooth settings on your phone to make sure at least one device is advertising 4. **Check you're in Central mode** \- Run `AT+CENTRAL` first ### "Error: Already Advertising/Connected" **Symptoms**: Commands fail with error messages. **Solutions**: 1. **Stop advertising first**: `AT+ADVSTOP` 2. **Disconnect first**: `AT+GAPDISCONNECT` 3. **Reset to clean state**: `ATR` (soft reset) --- ## Quick Command Reference Here's a summary of the commands we covered. For the complete list of AT commands, see the [BleuIO AT Commands Reference](https://www.bleuio.com/getting%5Fstarted/docs/commands/?ref=novelbits.io). ![BleuIO AT Command Quick Reference card showing essential commands for Basic, Role, Scanning, and Advertising operations](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/at-command-reference.png) Save this quick reference for your BleuIO command cheat sheet. --- ## What's Next In this post, we covered the fundamentals: setting up BleuIO, scanning for devices, understanding scan results, and making your dongle visible. You should now be comfortable with basic AT commands and have a mental model of how Bluetooth LE advertising works. In the next post, we'll go deeper into advertising—you'll learn how to create custom advertising packets, build an iBeacon, and understand the 31-byte advertising payload format in detail. Here's what's coming in this series: - **Advertising Deep Dive**: Custom packets, iBeacons, and scan response data - **Connections**: Establishing links, connection parameters, and GATT discovery - **Reading and Writing Data**: GATT operations, characteristics, and notifications - **Python Automation**: Scripting your Bluetooth LE workflows - **Common Mistakes**: Pitfalls I've seen trip up hundreds of engineers - **Testing and Debugging**: Automated validation and troubleshooting techniques --- ## Summary In this post, we covered: - **What BleuIO is**: A Bluetooth LE USB dongle controlled through simple AT commands—no SDK, no embedded C, no compilation - **The portability advantage**: BleuIO has its own Bluetooth stack, so you bypass Windows/macOS/Linux Bluetooth entirely—your code works identically on any operating system - **Real-world applications**: Production line testing, industrial IoT gateways, automated QA, healthcare device development, and multi-device orchestration - **Setup process**: Plug in, connect terminal, verify with `AT` → `OK` - **Basic commands**: `ATI` for info, `AT+GETMAC` for address, `AT+GAPSTATUS` for state - **Scanning**: `AT+GAPSCAN=10` discovers nearby devices and shows MAC, RSSI, and advertising data - **Understanding results**: Address types (\[0\]=public, \[1\]=random), RSSI as signal strength, advertising data in LTV format - **Advertising**: `AT+DEVICENAME` and `AT+ADVSTART` make your dongle visible - **Two-dongle advantage**: Control both Central and Peripheral for complete visibility You should now be able to connect a BleuIO dongle, scan for nearby Bluetooth LE devices, interpret the results, and advertise your own device. More importantly, you understand why BleuIO's architecture makes it ideal for building portable, production-ready Bluetooth LE applications. --- 💡 **Insider Tip:** Want to take your Bluetooth LE skills to the next level? I'm building a comprehensive hands-on course called **[Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/)** that includes two BleuIO dongles shipped directly to you. You'll master everything from fundamentals to advanced topics like security, Python automation, and packet analysis—with real hardware in your hands. [Learn more about Bluetooth LE Unplugged →](https://novelbits.io/ble-unplugged-course/) 🛒 **Just need the hardware?** If you already know Bluetooth LE and just want the dongles, grab them from our [US store](https://novelbits.io/bleuio/). We're an official BleuIO distributor with fast domestic shipping. [Shop BleuIO dongles →](https://novelbits.io/bleuio/) ### Bluetooth LE Shorter Connection Intervals: A Hands-On Guide with the nRF54L15 URL: https://novelbits.io/ble-shorter-connection-intervals-hands-on-nrf54l15/ Last updated: 2026-04-26T17:48:49.000Z *Sponsored by* [*Nordic Semiconductor*](https://www.nordicsemi.com/?ref=novelbits.io) If you've ever used a Bluetooth LE gaming mouse or VR controller, you've probably noticed something: there's a slight delay between your input and the response on screen. For casual use, it's barely noticeable. But for competitive gaming or immersive VR experiences, that delay can be the difference between a headshot and a miss—or the difference between presence and motion sickness. The culprit? Latency, and more specifically for Bluetooth LE: connection intervals. Until now, Bluetooth LE connections have been limited to a minimum interval of 7.5 milliseconds. That might not sound like much, but for applications where every millisecond counts, it's a real bottleneck. Bluetooth Core v6.2 changes everything with **Shorter Connection Intervals (SCI)**—a feature that reduces the minimum interval all the way down to 375 microseconds. That's a 20x improvement over the previous limit, enabling sub-millisecond communication cycles for the first time in Bluetooth LE's history. In this post, we'll explore what Shorter Connection Intervals bring to the table and why they matter for your next product. We'll also walk through a hands-on demo using Nordic's nRF54L15 Development Kit to see SCI in action. Here's what we'll cover: - What Shorter Connection Intervals are and why they matter - The technical changes in Bluetooth Core v6.2 that enable SCI - The dependencies you need to know about (Connection Subrating and Frame Space Update) - Practical limits and what's achievable today - A hands-on demo with the nRF54L15 Development Kit - Key considerations for your design Let's dive in. ## The Latency Problem Before we get into the specifics of Shorter Connection Intervals, let's step back and understand why connection intervals matter in the first place. In a Bluetooth LE connection, the Central and Peripheral don't communicate continuously. Instead, they wake up at regular intervals to exchange data, then go back to sleep to conserve power. This interval—the **connection interval**—determines how often these exchanges happen. Prior to Bluetooth Core v6.2, the minimum connection interval was 7.5 ms with a resolution of 1.25 ms. For many applications (fitness trackers, smart home sensors, medical devices), this is perfectly adequate. But for latency-sensitive use cases, 7.5 ms can feel like an eternity: - **Gaming peripherals**: A gaming mouse with a 7.5 ms connection interval translates to roughly 133 Hz polling rate. Competitive gamers expect 1000 Hz or higher. - **AR/VR controllers**: Immersive experiences require tight synchronization between your hand movements and what you see. Even small delays break the illusion. - **Real-time industrial sensors**: Factory automation and robotics demand predictable, low-latency data delivery. - **Pen tablets and styluses**: Artists and designers need responsive input that feels like pen on paper, not pen on molasses. The gaming peripheral market, in particular, has been stuck in a frustrating situation. Proprietary 2.4 GHz protocols can achieve sub-millisecond latency, but they require dedicated dongles and sacrifice the interoperability benefits of Bluetooth. Until now, developers had to choose between low latency and universal compatibility. Shorter Connection Intervals finally closes that gap. ## What's New in Bluetooth Core v6.2 Let's take a closer look at what the Bluetooth Core v6.2 specification actually changes to enable Shorter Connection Intervals. ### The New Limits The headline numbers are impressive: | Parameter | Before Bluetooth Core v6.2 | With Bluetooth Core v6.2 | | ---------------- | -------------------------- | ------------------------ | | Minimum interval | 7.5 ms | 375 µs | | Resolution | 1.25 ms | 125 µs | | Improvement | — | 20x shorter, 10x finer | This means connection intervals can now be configured in 125 µs increments, all the way down to 375 µs (0.375 ms). For a gaming mouse, that translates to a theoretical polling rate of over 2,600 Hz—well beyond what even the most demanding competitive gamers need. ### Three Connection Interval Value Types To maintain backward compatibility while enabling these new capabilities, Bluetooth Core v6.2 introduces three categories of connection interval values: | Type | Name | Range | Resolution | When Used | | ---- | ----------------------------------- | -------- | ---------- | ---------------------------------------- | | BCV | Baseline Connection Interval Values | ≥7.5 ms | 1.25 ms | Mandatory when SCI is supported | | RCV | Rounded Connection Interval Values | ≥1.25 ms | 1.25 ms | Mandatory when SCI supported | | ECV | Extended Connection Interval Values | ≥375 µs | 125 µs | Optional extension for ultra-low latency | Here's how to think about these: - **BCV (Baseline)** ensures backward compatibility. Devices that don't support SCI continue to work exactly as before. - **RCV (Rounded)** is the new mandatory baseline for SCI-capable devices. If your Controller supports SCI, it *must* support all RCV values (1.25 ms and above). - **ECV (Extended)** unlocks the full potential of SCI. These values go below 1.25 ms and provide the finest granularity (125 µs steps). Support for ECV is optional, so you'll want to verify your specific platform's capabilities. When a new connection is formed, it always starts with an interval in the BCV range (7.5 ms or higher). The devices can then negotiate shorter intervals using the new procedures we'll discuss next. ### New Link Layer PDUs The legacy `LL_CONNECTION_UPDATE_IND` PDU wasn't flexible enough for the new requirements, so Bluetooth Core v6.2 introduces two new Link Layer control PDUs for connection rate negotiation: - **`LL_CONNECTION_RATE_REQ`** — Sent by the Peripheral to propose new timing parameters. This PDU includes the acceptable interval range, subrate factors, latency, continuation number, timeout, preferred periodicity, and up to four candidate anchor offsets. - **`LL_CONNECTION_RATE_IND`** — Sent by the Central to confirm and enforce the final parameters. This PDU specifies the exact interval, window offset, and the instant (event count) at which the new parameters take effect. The key difference from the legacy approach is flexibility. The Peripheral can now propose a *range* of acceptable intervals, and the Central chooses the final value within that range. This negotiation happens at the Link Layer, keeping the process efficient and deterministic. ### ACL Flush Mechanism Here's a subtle but important addition: at shorter connection intervals, stale data becomes a real problem. Imagine a gaming mouse sending position updates every 750 µs. If one packet gets delayed due to interference and requires retransmission, the packets behind it start to pile up. By the time the retransmission succeeds, you might have several "old" position updates waiting in the queue. Transmitting all of them would add latency and waste airtime—but in a traditional Bluetooth LE connection, you have no choice. Bluetooth Core v6.2 introduces **LE Flushable ACL Data** to solve this. The Host can now mark certain packets as "flushable" and specify a flush timeout. If a packet sits in the queue longer than the timeout before its first transmission attempt, the Controller discards it. This keeps the data stream fresh and responsive. I recommend using flushable data for any application where freshness matters more than guaranteed delivery—gaming inputs, real-time sensor readings, and similar use cases. ## SCI Dependencies Shorter Connection Intervals (SCI) doesn't exist in isolation. To fully support SCI, your Controller needs to support features introduced in Bluetooth Core v5.3 and v6.0\. Let's walk through what you need to know. ### Connection Subrating (Bluetooth Core v5.3) — Mandatory If your Controller supports SCI, it **must** also support Connection Subrating. This isn't optional—it's a hard requirement in the specification. According to the Bluetooth Core Specification: > "Connection subrating is a means of quickly modifying the effective connection interval of an existing LE ACL connection. It is accomplished by the Central and Peripheral skipping most of the underlying connection events; for example, if the subrating factor is set to 7 then only every 7th connection event is used." > > *— Bluetooth Core v6.2, p. 313* Connection Subrating, introduced in Bluetooth Core v5.3, allows devices to skip connection events to save power while maintaining the connection. When connection subrating is applied to an existing connection, the active duty cycle may be quickly reduced—saving power—but the original connection interval can be quickly restored for improved throughput when needed. Why does SCI depend on it? The new `LL_CONNECTION_RATE_REQ` PDU includes subrate factor parameters as part of the negotiation. The subrate factor and latency are negotiated alongside the connection interval itself, with a specific constraint: SubrateFactorMax × (Max\_Latency + 1) ≤ 500 ```text SubrateFactorMax × (Max_Latency + 1) ≤ 500 ``` This integration makes sense when you think about it: shorter connection intervals mean more frequent wake-ups, which could dramatically increase power consumption. Connection Subrating provides a mechanism to balance latency and power by allowing devices to skip events when they don't have data to send. ### Frame Space Update (Bluetooth Core v6.0) — Recommended While not strictly mandatory, **Frame Space Update (FSU)** is highly recommended if you want to fully utilize Shorter Connection Intervals. In traditional Bluetooth LE, there's a fixed 150 µs gap (called T\_IFS, or Inter Frame Space) between adjacent packet transmissions within a connection event. This timing was baked into the specification and couldn't be changed. According to the Bluetooth Core Specification: > "A Controller that supports the Frame Space Update feature shall support a minimum frame space value that is less than or equal to 145 µs or support a maximum frame space value that is greater than or equal to 155 µs (or both)" > > *— Bluetooth Core v6.2, p. 3188* Frame Space Update, introduced in Bluetooth Core v6.0, makes T\_IFS negotiable. Devices can agree on values shorter *or* longer than 150 µs, depending on their capabilities and requirements. The negotiation uses two new Link Layer PDUs: - **`LL_FRAME_SPACE_REQ`** (Section 2.4.2.54) — Initiates the negotiation - **`LL_FRAME_SPACE_RSP`** (Section 2.4.2.55) — Responds with agreed parameters Why does this matter for SCI? When your connection interval is only 750 µs, every microsecond counts. If you're stuck with a fixed 150 µs gap between packets, that's a significant portion of your available time. FSU allows tighter packet spacing, making shorter intervals more practical and efficient. ### Dependency Summary | Feature | Spec Version | Required for SCI? | Purpose | | --------------------- | ------------------- | ----------------- | ----------------------------------------- | | Connection Subrating | Bluetooth Core v5.3 | **Mandatory** | Power optimization through event skipping | | Frame Space Update | Bluetooth Core v6.0 | Recommended | T\_IFS negotiation below 150 µs | | LE Flushable ACL Data | Bluetooth Core v6.2 | Optional | Prevents stale data buildup | - When evaluating platforms for SCI support, make sure to verify support for Connection Subrating at a minimum. - FSU support will give you the best performance, especially at the shortest intervals. ## Practical Limits — Theory vs. Reality The specification allows connection intervals as short as 375 µs, but what can you actually achieve in practice? Here's the reality: reaching the theoretical minimum is extremely difficult due to Bluetooth stack overhead. Processing packets, running the protocol state machine, and handling application logic all take time. Most implementations today can't get all the way down to 375 µs. Nordic's current support looks like this: | Platform | Minimum Supported Interval | | ----------------------------------------- | -------------------------- | | nRF54L Series | 750 µs | | nRF52 Series, nRF53 Series, nRF54H Series | 875 µs | These numbers may improve with future SDK optimizations, but they represent what's achievable today with the nRF Connect SDK. Now, before you get disappointed, let's put this in perspective: - **750 µs is still a 10x improvement** over the previous 7.5 ms minimum - **Both values are sub-1ms**, which is the "magical limit" for high-performance HID devices - A 750 µs interval translates to roughly **1,333 Hz polling rate**—well above the 1,000 Hz that competitive gamers consider the gold standard In other words, even without hitting the theoretical minimum, SCI delivers the performance that gaming peripherals and other latency-sensitive applications have been waiting for. ## Exploring Nordic's Stock SCI Sample If you want to dive deeper into how SCI works at the protocol level, Nordic provides a comprehensive `shorter_conn_intervals` sample in the nRF Connect SDK. This sample is perfect for understanding the underlying mechanics and for analyzing the connection with a Bluetooth protocol sniffer. Let's walk through how this sample works and what you'll see when you capture the traffic. ### What the Sample Does The stock sample demonstrates the complete SCI negotiation flow: 1. **Establishes a connection** between two nRF54L15 development kits 2. **Enables encryption** using Just Works pairing 3. **Updates PHY to LE 2M** (required for shortest intervals) 4. **Negotiates Frame Space Update** to reduce inter-frame spacing 5. **Cycles through connection intervals** every 3 seconds: 750 µs → 1 ms → 1.25 ms → 2 ms → 4 ms 6. **Measures transmission latency** using a custom GATT Latency service The sample continuously performs GATT write operations and measures round-trip time, providing real-time latency data at each interval. ### Key Code Components Here are the critical functions that make SCI work: #### 1\. Setting Connection Rate Defaults Before any connection rate updates can happen, the sample configures the default parameters: ```c static int set_conn_rate_defaults(uint32_t interval_min_us, uint32_t interval_max_us) { const struct bt_conn_le_conn_rate_param params = { .interval_min_125us = interval_min_us / 125, .interval_max_125us = interval_max_us / 125, .subrate_min = 1, .subrate_max = 1, .max_latency = 5, .continuation_number = 0, .supervision_timeout_10ms = 400, .min_ce_len_125us = BT_HCI_LE_SCI_CE_LEN_MIN_125US, .max_ce_len_125us = BT_HCI_LE_SCI_CE_LEN_MAX_125US, }; int err = bt_conn_le_conn_rate_set_defaults(¶ms); if (err) { LOG_WRN("Set default rate parameters failed (err %d)", err); return err; } LOG_INF("SCI default connection rate parameters set (min=%u μs, max=%u μs)", interval_min_us, interval_max_us); return 0; } ``` The `BT_CONN_INTERVAL_TO_ECV()` macro converts microseconds to the Extended Connection Interval Value format used by the Bluetooth stack. #### 2\. Frame Space Update To achieve the shortest intervals, the sample negotiates reduced inter-frame spacing: ```c static int select_lowest_frame_space(void) { const struct bt_conn_le_frame_space_update_param params = { .phys = BT_HCI_LE_FRAME_SPACE_UPDATE_PHY_2M_MASK, .spacing_types = BT_CONN_LE_FRAME_SPACE_TYPES_MASK_ACL_IFS, .frame_space_min = 0, .frame_space_max = 150, }; int err = bt_conn_le_frame_space_update(default_conn, ¶ms); if (err) { LOG_WRN("Frame space update request failed (err %d)", err); return err; } /* Wait for frame space update to complete */ k_sem_take(&frame_space_updated_sem, K_FOREVER); return 0; } ``` On the nRF54L15, this typically results in a frame space of approximately 63 µs—less than half the traditional 150 µs T\_IFS. #### 3\. Connection Rate Request When cycling through intervals, the sample uses the Connection Rate Request procedure: ```c static int conn_rate_request(uint32_t interval_min_us, uint32_t interval_max_us) { const struct bt_conn_le_conn_rate_param params = { .interval_min_125us = interval_min_us / 125, .interval_max_125us = interval_max_us / 125, .subrate_min = 1, .subrate_max = 1, .max_latency = 0, .continuation_number = 0, .supervision_timeout_10ms = 400, .min_ce_len_125us = BT_HCI_LE_SCI_CE_LEN_MIN_125US, .max_ce_len_125us = BT_HCI_LE_SCI_CE_LEN_MAX_125US, }; int err = bt_conn_le_conn_rate_request(default_conn, ¶ms); if (err) { LOG_WRN("Connection rate request failed (err %d)", err); return err; } return 0; } ``` ### Running the Sample To build and run the stock sample: 1. **Locate the sample** in your nRF Connect SDK installation 2. **Build for nRF54L15** using VS Code 3. **Flash both development kits** 4. **Open serial terminals** for both devices (115200 baud) 5. **Configure the devices**: - Device 1: Type `y` (initiator), then `c` (Central) - Device 2: Type `n` (follower), then `p` (Peripheral) You'll see the connection form and watch as the interval cycles every 3 seconds, with latency measurements at each step (watch the video demo below). ## Hands-On Demo with the nRF54L15 ## Key Considerations for Your Design Before you rush to implement Shorter Connection Intervals in your product, there are a few important considerations to keep in mind. ### Power Consumption Trade-offs Shorter intervals mean more frequent radio activity, which means higher power consumption. There's no way around this fundamental trade-off. SCI is best suited for: - **Devices with larger batteries** (gaming mice, VR controllers), where battery life is measured in days or weeks, not months or years - **Use cases where latency is more critical than long battery life** (competitive gaming, real-time control) - **Burst activity patterns** where you need low latency during active use but can relax intervals during idle periods (this is where Connection Subrating helps) For always-on sensors or devices powered by coin cells, SCI probably isn't the right choice. Stick with longer intervals and optimize for battery life instead. ### Device Support and Compatibility SCI requires support on *both* ends of the connection. Your Peripheral might support 750 µs intervals, but if the Central (phone, PC, gaming dongle) doesn't support SCI, you'll be limited to the legacy 7.5 ms minimum. As of this writing, smartphone support for SCI is still emerging. For now, SCI is best suited for applications with dedicated central hardware: - Gaming dongles (USB receivers) - VR/AR headsets - Custom Central devices you control As Android and iOS (*hopefully*!) add SCI support in future releases, the ecosystem will open up. But for production designs shipping today, plan for dedicated host hardware if you need guaranteed SCI support. ### What About Throughput? You might be wondering whether shorter connection intervals translate to higher throughput. The answer is nuanced: **SCI is optimized for latency, not throughput**. Here's why: at very short intervals like 750 µs, connection events are so brief that you can only fit one small packet per event. The packet transmission time itself (a 251-byte packet at 2M PHY takes \~1 ms) exceeds the connection interval! So you're limited to smaller payloads. With longer intervals, such as 7.5 ms, you can pack multiple full-size packets into each connection event, which is more efficient for bulk data transfer. The math works out to roughly similar peak throughput (\~1.5 Mbps) for both approaches, but with very different characteristics: - **SCI (750 µs)**: Small packets arriving very frequently—ideal for real-time control data - **Legacy (7.5 ms)**: Larger bursts less frequently—better for file transfers or streaming If your application needs to move large amounts of data quickly, longer connection intervals with multiple packets per event will serve you better. SCI shines when you need each individual piece of data to arrive as fast as possible, even if that data is small. ### Ultra-Low Latency HID Profile You might have heard about the Bluetooth SIG's work on an Ultra-Low Latency (ULL) HID profile. This profile is designed to standardize low-latency HID applications, building on SCI as a foundation. As of the time of this writing (NovemberDecember 2025), the ULL HID profile isn't available yet. You can absolutely use SCI today—it's fully specified and implemented—but you'll be doing so outside the context of a standardized profile. This means more flexibility in your implementation, but also more work to ensure interoperability. When ULL HID does arrive, expect it to provide standardized service definitions, report formats, and best practices for latency-sensitive HID applications. ## Summary In this post, we covered a lot of ground: - **The latency problem**: Why 7.5 ms connection intervals were limiting for gaming, VR, and real-time applications - **What's new in Bluetooth Core v6.2**: The SCI feature, including BCV/RCV/ECV value types, new Link Layer PDUs, and the ACL flush mechanism - **Dependencies**: Connection Subrating (mandatory) and Frame Space Update (recommended) - **Practical limits**: 750 µs on nRF54L, 875 µs on nRF52—both sub-1ms and a huge improvement over the legacy minimum - **Hands-on demo**: How to test SCI using Nordic's sample application - **Design considerations**: Power trade-offs, host support, and the upcoming ULL profile You should now be able to test Shorter Connection Intervals on your own Nordic development kit and evaluate whether sub-millisecond latency is the right fit for your next product. For gaming peripherals, AR/VR controllers, and real-time sensing applications, SCI is a genuine game-changer. After years of proprietary 2.4 GHz protocols holding the performance crown, Bluetooth LE finally has the latency characteristics to compete—without sacrificing interoperability. --- ## References - [nRF54L15 Product Page](https://www.nordicsemi.com/Products/nRF54L15?ref=novelbits.io) - [Getting Started with the nRF54L15](https://novelbits.io/nrf54l15-unboxing-first-impressions/) - [Shorter Connection Intervals (SCI) nRF Connect SDK Sample](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/bluetooth/shorter%5Fconn%5Fintervals/README.html?ref=novelbits.io) - [Bluetooth Core Specification v6.2](https://www.bluetooth.com/specifications/specs/core-specification-6-2/?ref=novelbits.io) - [Bluetooth Core v6.2 Feature Overview](https://www.bluetooth.com/bluetooth-core-6-2-feature-overview/?ref=novelbits.io) - [Bluetooth Core v5.3 Feature Enhancements (Connection Subrating)](https://www.bluetooth.com/wp-content/uploads/2021/01/Bluetooth%5F5.3%5FFeature%5FEnhancements%5FUpdate.pdf?ref=novelbits.io) - [Nordic DevZone: What's New in Bluetooth Core 6.2](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/whats-new-in-bluetooth-core-6-2-an-overview?ref=novelbits.io) - [nRF Connect SDK Documentation](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/index.html?ref=novelbits.io) ### nRF Cloud, powered by Memfault: Production-Ready Device Management and Observability for Bluetooth LE URL: https://novelbits.io/nrf-cloud-memfault-bluetooth-le-device-management/ Last updated: 2026-04-26T17:49:17.000Z *Sponsored by* [*Nordic Semiconductor*](https://nordicsemi.com/?ref=novelbits.io) If you've ever tried debugging a Bluetooth Low Energy device that's failing in production—deployed to a customer, thousands of miles away, with no debugger attached—you know exactly how frustrating the process becomes. The customer reports "it stopped working," but you have no crash logs, no stack traces, and no way to see what actually happened at the moment of failure. You're left trying to reproduce an issue that might only occur with specific phone models, after hours of use, under conditions you can't replicate in your lab. For embedded developers building Bluetooth Low Energy products, this scenario is all too common. Once your devices ship, visibility often diminishes. Building the infrastructure to maintain that visibility—crash capture, fleet monitoring, safe OTA updates—means months of development work that takes you away from your core product features. And that's assuming you have the expertise to build device management and observability systems that work reliably at scale. Nordic Semiconductor customers building with the nRF52, nRF53, and nRF54 series have had access to various OTA tools and libraries, but many times you'd piece together different components, build much of the cloud infrastructure yourself, and still end up with gaps in observability. That's where the recent acquisition changes things. [Nordic Semiconductor acquired Memfault](https://www.nordicsemi.com/Nordic-news/2025/06/Nordic-Semiconductor-acquires-Memfault?ref=novelbits.io) and now offers it as "nRF Cloud powered by Memfault." This brings enterprise-grade device management and observability directly into the Nordic ecosystem with seamless nRF Connect SDK support and ready-to-use mobile apps (and reference code) for iOS and Android. **In this post, we'll cover:** - What Memfault brings to Nordic's Bluetooth Low Energy ecosystem - How the integration works architecturally with the nRF Connect SDK - The setup essentials and configuration requirements - Real-world impact, resource footprint, and when this solution makes sense 🎥 **See It In Action** Want to see how easy it is to integrate nRF Cloud into your Bluetooth LE application? [Jump to the hands-on video demo →](#video-demo) ## What Memfault Brings to nRF Cloud The nRF Cloud Memfault integration provides Device Management (progressive OTA rollouts) and Embedded Observability (crash dumps, fleet monitoring, analytics). Both work seamlessly with nRF52/nRF53/nRF54 series chipsets and the nRF Connect Device Manager mobile app. You get 10 devices completely free, with full-feature access for non-production use. Beyond that, pay-as-you-go pricing starts from $0.10 per device per month with usage-based charges for observability operations. *For up-to-date, detailed pricing, refer to the* [*nRF Cloud Pricing Page.*](https://nrfcloud.com/?ref=novelbits.io#/pricing) ### 1\. **Embedded Device Observability** Every crash—hard fault, assertion failure, watchdog reset—triggers automatic coredump capture stored in flash/NVM. This includes everything you'd see with a debugger: program counter, register states, stack trace, and variable values. Next, a Bluetooth Low Energy connection uploads the coredump in small chunks. The platform translates all this information using your uploaded ELF file and presents a fully analyzed crash report. Instead of "the device stopped working," you get: ... a crash at line 247 in `bluetooth_handler.c` in the `bt_conn_get_info()` function with null pointer dereference in register R0, complete call chain, variable states, and correlation with similar crashes across your fleet. Fleet health monitoring provides continuous visibility. Memfault automatically collects connectivity statistics, battery trends, stability metrics (reboot counts, crash frequency), and memory patterns—viewable per device or aggregated across your fleet, with filtering by firmware version or hardware revision. Product analytics tracks feature usage, measures how features impact performance (battery, memory, connection stability), and identifies which features deliver the most value. ### 2\. **Device and Fleet Management** Rather than deploying to all devices simultaneously, you create customized device groups controlling which devices receive updates and when. Deploy to a 10-device QA group and monitor for 24 hours. Then, expand to 10% of beta, monitor, and expand to 50%. Finally, deploy to full production over the next week. The dashboard shows exactly how many devices received the update, successfully applied it, and any failures. If crash rates spike, you can abort the rollout with a single button click—devices without updates will remain on their current firmware. The OTA integrates with the nRF Connect Device Manager mobile app. When users connect, it automatically checks nRF Cloud for updates. If available, the app downloads firmware and transfers it over Bluetooth Low Energy using the SMP protocol. The device receives chunks, writes to flash/NVM, verifies the signature (MCUboot), and reboots. The mobile app libraries are open source on GitHub ([iOS](https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager?ref=novelbits.io) and [Android](https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager?ref=novelbits.io)), so you can integrate this functionality into your own customer-facing application. ## How the Integration Works The integration follows a three-tier model: your nRF device, the Bluetooth Low Energy connectivity layer, and the nRF Cloud platform. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nrf-cloud-memfault-architecture-diagram.png) nRF Cloud Memfault Integration Architecture At the device level, you run application code on the nRF Connect SDK. You add the Memfault SDK—a lightweight library that adds around 5KB of flash/NVM usage and requires 1.5KB of RAM. This SDK handles crash capture, metric collection, and data packetization. The connectivity layer uses three key Bluetooth Low Energy GATT services: 1\. The Memfault Diagnostic Service (MDS) exposes observability data. 2\. The SMP (Simple Management Protocol) service from MCUmgr handles firmware updates. 3\. The Device Information Service (DIS) exposes the metadata and information about the hardware, software, etc. The nRF Connect Device Manager app reads from MDS to upload diagnostic data, uses DIS to identify the device, and uses SMP to transfer new firmware images for OTA device firmware updates (DFU) on the devices of interest. The cloud side processes everything. When crash dumps arrive, the platform symbolicates them (matching memory addresses to function names using uploaded ELF files), analyzes patterns across your fleet, and presents results in a dashboard. For OTA updates, it hosts firmware images, manages rollout rules, and tracks adoption. ### **Device-Side Components** The firmware requires several components: - MCUboot bootloader: verifies signatures, supports A/B partition swapping. - MCUmgr: implements SMP service for firmware transfers and OTA DFU. - Memfault SDK: handles crash capture, heartbeat metrics, and event logging. - Memfault Diagnostic Service (MDS): exposes observability data. - Device Information Service (DIS): provides device metadata for correlation with firmware builds. ### **From Crash to Root Cause Analysis** Your Bluetooth Low Energy fitness tracker crashes from a null pointer dereference during a GATT write response. Memfault's exception handler captures complete processor state—registers, stack contents, configured data regions—writes this compressed snapshot to flash/NVM, and the device reboots. Hours later, the user opens your app. It connects via Bluetooth Low Energy, and the device provides the crash dump in small chunks. The app uploads it to nRF Cloud, which symbolicates the crash—converting raw addresses like `0x00012A4C` into `bt_gatt_write_handler()` at line 342 in `gatt_operations.c`. You see the crash report with full stack trace, register dump, and analysis showing 47 occurrences across 12 devices in the past week—all firmware 1.3.2, same function. You immediately identify and fix the root cause without lab reproduction. ## Setting Up nRF Cloud with Your nRF Project #### 🎥 Companion Video Walkthrough I've created a hands-on video demonstrating the complete setup process using the `peripheral_mds` example from nRF Connect SDK. The video shows exactly how straightforward integration is—from enabling configuration flags to testing crash capture and OTA updates on real hardware. **Prefer visual learning?** [Watch the demo first →](#video-demo) then return here for the technical details. You'll primarily configure existing components rather than write extensive code. The setup involves enabling components already in the nRF Connect SDK, adding the Memfault SDK to your build, and configuring a few services. **Prerequisites:** nRF Connect SDK version 3.1.0 or later (earlier versions will likely require additional Kconfig configuration for OTA support), an nRF52/nRF53/nRF54 series development kit, an nRF Cloud account (starting with 10 free non-production devices), and the nRF Connect Device Manager app on iOS or Android. ### Step #1: **Configuring Your Firmware** For testing purposes, I recommend starting with the `peripheral_lbs` (LED Button Service) or `peripheral_mds` samples from the nRF Connect SDK, as they include many necessary configurations and provide good foundations for a quick test. The integration requires enabling several components in your project configuration (`prj.conf`). Here's what each does and why you need it: **Core Components:** ```makefile # Essential Memfault configuration CONFIG_MEMFAULT=y CONFIG_BT_MDS=y # SMP is a must CONFIG_BT_SMP=y # Enable OTA updates CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y # Memfault firmware identification CONFIG_MEMFAULT_NCS_FW_TYPE="main" CONFIG_MEMFAULT_NCS_FW_VERSION_STATIC=y CONFIG_MEMFAULT_NCS_DEVICE_ID="mfltqs1" # Testing shell (optional) CONFIG_SHELL=y CONFIG_MCUBOOT_SHELL=y ``` **Device Information Service Configuration:** The DIS provides critical metadata that both Memfault and OTA rely on for device identification and firmware correlation: ```makefile CONFIG_BT_DIS=y CONFIG_BT_DIS_SERIAL_NUMBER=y CONFIG_BT_DIS_SERIAL_NUMBER_STR="mfltqs1" CONFIG_BT_DIS_HW_REV=y CONFIG_BT_DIS_HW_REV_STR="nrf54l15dk" # Adjust for your board CONFIG_BT_DIS_SW_REV=y CONFIG_BT_DIS_SW_REV_STR="main" CONFIG_BT_DIS_FW_REV=y ``` **Firmware Version Configuration:** You will need to define three matching configurations for the firmware image version: ```makefile # MCUBoot image header version should match DIS and Memfault version CONFIG_BT_DIS_FW_REV_STR="0.0.1" CONFIG_MEMFAULT_NCS_FW_VERSION="0.0.1" CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="0.0.1" ``` **Critical Sysbuild Configuration:** When using sysbuild (required for bootloader integration), create a separate `sysbuild.conf` file alongside `prj.conf`: ```makefile SB_CONFIG_BOOTLOADER_MCUBOOT=y ``` Without this, your project compiles, but MCUboot won't be included, so you'll have no OTA capability. If using VS Code with the nRF Connect extension, check "Use sysbuild" in build configuration settings (this is also enabled by default in newer versions of the nRF Connect SDK for VS Code Extension). ### 2\. **Symbol File Upload and Project Keys** For crash symbolication to work, nRF Cloud needs the ELF symbol file from your build. This file contains mappings between memory addresses and function names, source line numbers, and variable names. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-2-scaled.png) **Build and Upload Workflow:** 1. Build your firmware ( via `west build -b `, or the VS Code Extension) 2. Find the ELF file (e.g., `build/peripheral_mds/zephyr/zephyr.elf`) 3. Upload to nRF Cloud via the web interface. The upload associates your symbol file with a GNU build ID—a unique hash embedded in both the firmware binary and ELF file. When devices send crash dumps, nRF Cloud uses this build ID to [automatically select the correct symbol file](https://interrupt.memfault.com/blog/gnu-build-id-for-firmware?ref=novelbits.io), even with multiple firmware versions deployed simultaneously. This means you never have to manually specify which symbol file corresponds to which crash. **Project Key Configuration:** Get your project key from the nRF Cloud dashboard and add it to `prj.conf`: ```makefile # ⚠️ Make sure to update this line with YOUR Project Key from https://mflt.io/project-key! CONFIG_MEMFAULT_NCS_PROJECT_KEY="YOUR_PROJECT_KEY" ``` This key routes diagnostic data to the correct dashboard and organization. ### 3\. **Verifying the Integration** After flashing your configured firmware to the device, verify the integration works: **1\. Bluetooth Low Energy Connection:** - Open the nRF Connect Device Manager app - Scan for your device - Select your device - Send a "Hello!" message to initiate a connection - Allow the pairing and bonding of the device to your smartphone - Confirm you see "Observability: Streaming" and "OTA: Supported" status indicators ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-3-scaled.png) **2\. Test Crash Capture:** If your firmware includes Memfault shell commands (available if you enabled the shell in `prj.conf`), trigger a test crash: ```bash uart:~$ mflt test assert ``` The device crashes, captures the coredump, and reboots. Reconnect with the app to upload the crash dump. Within minutes, you'll see the fully symbolicated crash report in your nRF Cloud dashboard showing the exact line in the Memfault test code where the assertion occurred. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-5-scaled.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-7-scaled.png) **3\. Test OTA Update:** To test OTA updates, perform the following steps: - Increment/increase your firmware version number for the following KConfig definitions: - `CONFIG_BT_DIS_FW_REV_STR` - `CONFIG_MEMFAULT_NCS_FW_VERSION` - `CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION` - Rebuild and upload both the new firmware binary and symbol file to nRF Cloud - Create a new release in the dashboard, then activate it for your device. - Connect with the mobile app—it will detect the update, download it, transfer it over Bluetooth Low Energy, and the device will reboot into the new firmware. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/IMG_3840-scaled.png) Image Tab / OTA Update Available / Performing OTA Update / OTA Update in progress ## nRF Cloud Hands-On Video Demo ## Practical Considerations ### **Resource Footprint and Performance Impact** The Memfault SDK is designed specifically for resource-constrained embedded devices, so the footprint is quite reasonable for most Bluetooth Low Energy applications. - Flash/NVM: Memfault SDK typically adds around 5 KB to your firmware image (exact size depends on enabled features and compiler optimization). MCUboot bootloader adds additional flash/NVM overhead (typically 16-32kB depending on enabled security features and target hardware), but this is necessary for secure OTA updates regardless of using Memfault. - RAM usage is approximately 1.5 KB for the default circular buffer configuration. This buffer stores heartbeat metrics and event data until cloud upload. You can tune buffer size based on device constraints—smaller buffers lose older data if devices don't connect frequently, while larger buffers provide more historical data at RAM cost. - Performance impact during normal operation is minimal. The SDK operates primarily in background contexts (collecting periodic metrics, logging events). The only real-time overhead comes from exception handlers executing during crashes—but at that point, the device is crashing anyway, so a small additional capture time doesn't affect user experience. During Bluetooth Low Energy transmission, you may notice negligible bandwidth and power consumption impacts, but the SDK transfers data in small chunks that fit within typical Bluetooth Low Energy MTU sizes, avoiding fragmentation or special handling. ### **Pricing and Cost Considerations** I recommend starting with the free tier (10 devices with full feature access for non-production use) during development and testing. Beyond that, the Pro tier uses pay-as-you-go pricing starting at $0.10 per device per month, with OTA updates included and usage-based charges for observability operations. Enterprise options with fixed annual pricing are also available for larger deployments. On all pricing plans, the cost per device discounts significantly as you grow, with total costs easily justified by reduced support costs and faster fix deployments. ### **When Using nRF Cloud Makes Sense** This integration is particularly well-suited for: - **Consumer devices with regular firmware updates** (fitness trackers, smart home devices, health monitors) that benefit from progressive rollouts and crash analysis - **Products requiring regulatory compliance** (EU Cyber Resilience Act, US Cyber Trust Mark), needing secure remote updates - **Complex applications** with sophisticated behavior (multiple sensors, state machines, varied phone compatibility), where field debugging without lab reproduction is critical - **Battery-powered devices** where product analytics identify unexpected power consumption patterns based on real-world usage - **Production deployments beyond 10-50 devices up to millions,** where automated rollout management, fleet-wide metrics, and centralized crash analysis become essential Integration effort takes minutes, not days, not weeks—primarily configuration-based, with a comprehensive quick start guide and active DevZone community support. ## Frequently Asked Questions **Q: Does nRF Cloud work with Nordic's nRF52, nRF53, and nRF54 series?** Yes. nRF Cloud, powered by Memfault, offers integration support for all nRF52, nRF53, and nRF54 series chipsets. The setup has been tested with nRF Connect SDK version 3.1.0\. Earlier SDK versions may work with additional Kconfig configuration adjustments, but v3.1.0 or later is recommended for the most straightforward integration. **Q: How much flash and RAM overhead does Memfault add?** The Memfault SDK adds around 5 KB of flash/NVM usage and approximately 1.5 KB of RAM. The MCUboot bootloader adds 16-32 KB to flash/NVM usage depending on enabled security features and target hardware, but is required for OTA regardless of Memfault. **Q: Can I use nRF Cloud in my own mobile app instead of nRF Connect Device Manager?** Yes. The nRF Connect Device Manager libraries are open source on GitHub for both iOS and Android. You can integrate the same OTA and observability functionality into your customer-facing application. **Q: How much does nRF Cloud powered by Memfault cost?** The free tier includes 10 devices with full feature access for non-production use. The Pro tier starts at $0.10 per device per month with pay-as-you-go pricing, OTA updates included, and usage-based charges for observability operations. Enterprise plans with fixed annual pricing are available for production deployments. Visit the [nRF Cloud Pricing Page](https://nrfcloud.com/?ref=novelbits.io#/pricing) for current details. **Q: What's the difference between MDS and DIS in Bluetooth Low Energy?** MDS (Memfault Diagnostic Service) is a Memfault-specific GATT service that handles observability data transfer (crash dumps, metrics, logs). DIS (Device Information Service) is a standard Bluetooth service providing static device metadata (firmware version, hardware revision, serial number). Both are required for the integration. **Q: How do I trigger a test crash to verify nRF Cloud is working?** Use the Memfault shell command: `mflt test assert`. The device will crash, capture the coredump, and reboot. Reconnect with the mobile app to upload the crash dump to nRF Cloud. **Q: Does nRF Cloud help with regulatory compliance like the EU Cyber Resilience Act or the US Cyber Trust Mark program?** Yes. nRF Cloud provides infrastructure to satisfy secure remote update capabilities and vulnerability management requirements for both the [EU Cyber Resilience Act](https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act?ref=novelbits.io) and the [US Cyber Trust Mark program](https://www.fcc.gov/cybersecurity-certification-mark?ref=novelbits.io) with minimal custom development: ## Summary Nordic Semiconductor's integration of Memfault into nRF Cloud brings enterprise-grade device management and observability to Bluetooth Low Energy developers. The platform addresses one of embedded development's most persistent challenges: gaining visibility into production device performance and safely deploying firmware updates at scale. **What is offered:** - Automatic crash capture with full symbolication—see exactly where crashes occur without lab reproduction - Fleet-wide health monitoring and product analytics across all your devices - Progressive OTA rollouts with abort capabilities—deploy safely with visibility at every stage - Around 5 KB flash/NVM overhead with seamless nRF Connect SDK integration - 10 free devices for non-production use, then pay-as-you-go starting at $0.10 per device per month With regulatory requirements (EU Cyber Resilience Act enforcement, US Cyber Trust Mark) and customer expectations for devices that improve over time, robust device management and observability are becoming more essential. The nRF Cloud integration provides a turnkey solution leveraging Nordic's existing development tools. **Resources:** - [**nRF Cloud Sign-up**](https://nrfcloud.com/?ref=novelbits.io) – Start with 10 free devices and full feature access - [**Memfault Quick Start Guide**](https://docs.memfault.com/docs/mcu/quickstart-nrf5x-ncs?ref=novelbits.io) – Step-by-step integration instructions for nRF Connect SDK - [**nRF Connect Device Manager on GitHub**](https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager?ref=novelbits.io) (iOS) - [**nRF Connect Device Manager on GitHub**](https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager?ref=novelbits.io) (Android) - [**Nordic DevZone**](https://devzone.nordicsemi.com/?ref=novelbits.io) – Community support, discussions, and technical resources ### Meet the Nordic nRF54LM20A: The Perfect Fit for Advanced Bluetooth LE Projects URL: https://novelbits.io/nordic-nrf54lm20a-introduction/ Last updated: 2026-04-26T17:49:14.000Z When Nordic Semiconductor launched the nRF54L Series in late 2024, it marked a significant evolution from the beloved nRF52 Series. As I shared in my [nRF54L15 first impressions post](https://novelbits.io/nrf54l15-unboxing-first-impressions/), this new generation brought impressive improvements in processing power, energy efficiency, and wireless capabilities. Now, Nordic has expanded their offering with the nRF54LM20A—the bigger sibling to the nRF54L15 that takes everything up a notch. Think of it as the "premium edition" of the lineup. While the nRF54L15 established Nordic's new direction with its 22nm process and higher power-efficiency design, the nRF54LM20A represents what happens when you remove the constraints and build for developers who need maximum capability. Why should you care about this new Nordic SoC? Because it addresses a fundamental challenge in modern IoT development: the growing complexity of connected products. Increasingly, today's smart devices aren't only sending simple sensor readings—they're also running sophisticated algorithms, processing multiple data streams, managing complex user interfaces, and coordinating multiple wireless protocols simultaneously. The nRF54LM20A is built for that reality, while still achieving longer battery life and robust RF performance. 🎥 **See It In Action** Check out the video unboxing and overview of the nRF54LM20A Development Kit [Jump to the hands-on unboxing video →](#video-demo) ## The nRF54L Series Story: Evolution from nRF52 The nRF54L Series represents Nordic's transition from the beloved nRF52 generation to address modern IoT demands. Built on a 22nm process (versus 90nm for the nRF52), the series introduces 2x processing power and 3x processing efficiency with an upgrade to Arm Cortex-M33 at 128MHz in a 22nm process. Nordic claims that this improvement, combined with 4th-generation ultra-low-power radio, results in an average 30%-50% lower system power consumption for common Bluetooth LE use cases. The nRF54L15, as I covered in my [previous post](https://novelbits.io/nrf54l15-unboxing-first-impressions/), established this foundation with 1.5 MB of non-volatile memory and Bluetooth LE Core v6.0 support. However, developers sometimes require more memory, additional GPIO pins, and enhanced connectivity options for complex applications. That's precisely where the nRF54LM20A comes in. It takes the proven foundation of the nRF54L architecture and scales it up for applications that need maximum capability without compromise. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nRF54LM20A-2-729x1024.png) *Figure 1: Evolution of Nordic's wireless SoCs showing the progression from nRF52 to nRF54L Series* ## Key Highlights: What Makes the nRF54LM20A Special ### Massive Memory for Complex Applications The nRF54LM20A's standout feature is its memory: 2MB non-volatile memory (NVM) and 512KB RAM (double the RAM of the nRF54L15). This enables: - **Matter devices** running multiple wireless protocol stacks simultaneously - **Industrial sensors** storing weeks of operational data locally - **Advanced wearables** processing sensor fusion algorithms with rich interfaces - **Medical devices** implementing complex signal processing with audit logs This memory capacity eliminates the need for external storage in most applications while supporting sophisticated real-time processing and multiple protocol stacks. ### 66 GPIO Pins: Designing Without Limits The nRF54LM20A provides up to 66 GPIO pins (package dependent), enabling complex single-chip designs that previously required external I/O expanders. This supports multiple sensor buses, user interfaces, relay controls, and debugging interfaces simultaneously—simplifying PCB design and improving reliability. ### High-Speed USB: Modern Connectivity High-speed USB support enables fast data transfer for firmware updates, data synchronization, and direct computer connectivity. This is particularly valuable for gaming peripherals, development tools, industrial devices, and medical equipment requiring rapid data transfer. ### Additional Processing Power - Design Made Simple ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/nRF54LM20A-Architecture-2026-02-01-041716.png) *Figure 2: nRF54LM20A: ARM Cortex-M33 and RISC-V FLPR Processor Architecture* The nRF54LM20A's RISC-V coprocessor is an additional processor optimized for performance, running at 128 MHz alongside the main ARM Cortex-M33\. Supervised by the main processor, it provides additional processing capacity and can handle time-critical tasks, offload workload from the main processor, or implement low-level custom protocols. It can also run SoftPeripherals—emulated peripherals that utilize hardware acceleration for I/O. Developers can choose from three usage modes for the RISC-V coprocessor, each optimized for different scenarios: **Coprocessor Mode**: Run a standalone custom application on the coprocessor while supervised by the main processor. This mode utilizes Zephyr RTOS, enabling access to the Zephyr ecosystem (drivers, samples, and more) with the same APIs and toolchain as the main processor. The coprocessor runs a separate instance of Zephyr RTOS, enabling efficient development. **SoftPeripherals**: Extend hardware capabilities with emulated peripherals that utilize hardware acceleration for I/O performance. Nordic provides these as part of the nRF Connect SDK with verified quality and straightforward usage. Access them through driver-level APIs just like conventional peripherals. **High-Performance Framework**: A low-level framework for developing custom high-speed or timing-critical protocols. This framework enables low-level implementation that directly accesses hardware peripherals, providing higher performance and more predictable timing, and allowing the development of customized protocols for specific and demanding use cases. ### Protocol Support: Future-Proofing Your Design The nRF54LM20A supports the complete modern wireless ecosystem: Bluetooth LE Core v6.0 with Channel Sounding, Matter, Thread, and Zigbee. Crucially, it can run multiple protocols simultaneously, enabling devices that serve as Bluetooth LE sensors, Matter endpoints, and Thread routers concurrently. ## Real-World Applications: Where the nRF54LM20A Shines The nRF54LM20A's enhanced capabilities make it ideal for: **Matter Devices**: Bridging multiple wireless technologies while processing automation rules locally and logging energy data. **Industrial IoT Sensors**: Process vibration patterns, store operational data during outages, implement predictive maintenance, and coordinate through mesh networks. **Advanced Wearables**: Handle sensor fusion algorithms, process sleep patterns, securely store health data, and support multiple connectivity options. **Medical Devices**: Store detailed historical data, maintain audit trails, and provide comprehensive logging for regulatory compliance. ## Power Efficiency in Context Overall, the nRF54L Series delivers significant power efficiency improvements versus nRF52 designs through advanced processing architecture and optimized power management. Practically, this translates to extended battery life across applications—Bluetooth LE beacons lasting over 6 years on a single CR2032 battery, connected devices operating for 5+ years between battery changes, and Matter over Thread devices running for 1 year and 7 months (4 months longer than the nRF52840). System-OFF mode with Global RTC wakeup consumes just 0.9µA while maintaining essential timekeeping functions—a capability unavailable in previous generations and 40% more efficient than comparable nRF52840 alternatives (System ON with RTC wakeup). The nRF54LM20A's power architecture features separate power domains, enabling ultra-low power operation. Peripheral and low-power domains can remain active while the ARM processor and radio are powered off, handling routine tasks autonomously. The DPPI (Distributed Programmable Peripheral Interconnect) can perform simple peripheral-related logic without waking the processor. Additionally, the increased processing power of both the ARM Cortex-M33 and RISC-V coprocessor shortens active time during computation, reducing overall energy consumption. Nordic's nRF54L Series Express Course is a great reference you can refer to for more details: [https://academy.nordicsemi.com/courses/nrf54l-series-express-course/lessons/lesson-1-architecture-overview/topic/processing-performance-and-power-consumption/](https://academy.nordicsemi.com/courses/nrf54l-series-express-course/lessons/lesson-1-architecture-overview/topic/processing-performance-and-power-consumption/?ref=novelbits.io) *(Above figures are primarily for the nRF54L15/10/05 SoCs. The numbers for the nRF54LM20A variant will be added soon.)* ## Getting Started with Development The nRF54LM20A is supported by Nordic's nRF Connect SDK (Zephyr-based), which includes comprehensive examples for all wireless protocols. The nRF54LM20 DK development kit is currently available only through Nordic's early access program, with production scheduled to start in Q1 2026\. Migration from nRF52 or nRF54L15 follows established patterns with SDK compatibility layers and extensive documentation support. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-scaled.png) Nordic Semiconductor nRF54LM20 DK ([Source](https://www.nordicsemi.com/Products/Development-hardware/nRF54LM20-DK?lang=en&ref=novelbits.io#infotabs)) ## When to Choose the nRF54LM20A: A Simple Decision Guide ### Choose the nRF54LM20A When You Need: - **Maximum memory**: Applications requiring >1.5MB flash or >256KB RAM - **Extensive connectivity**: Designs needing many GPIO pins or high-speed USB - **Multiple protocols**: Products that must simultaneously run Bluetooth LE, Matter, Thread, or Zigbee - **Complex processing**: Applications requiring sophisticated local algorithms or data processing - **Future-proofing**: Designs that may need to add features over their product lifetime ### Consider the nRF54L15/10/05 When: - **Cost optimization**: Simpler applications where the additional nRF54LM20A features aren't needed - **Size constraints**: Designs where every millimeter matters, and the nRF54L15's smaller packages are advantageous (this is applicable for the WLCSP form factor of the nRF54L15, but not for the L10 or L05 since they are not offered in WLCSP) - **Power optimization**: Battery-powered applications where even small power differences matter - **Faster availability**: Projects that can't wait for nRF54LM20A production ramp-up ## Module Options: Simplifying Your Hardware Design While modules specifically for the nRF54LM20A are not yet available, Nordic's module ecosystem for the nRF54L Series is worth understanding—especially if you're planning a product roadmap. ### Current Module Availability Modules are currently available for the nRF54L15, L10, and L05 variants. These pre-certified, ready-to-integrate solutions significantly reduce development complexity and time-to-market, particularly for teams without extensive RF expertise. ### Why Choose a Module? **Simplified PCB Design**: Modules eliminate the need for RF layout expertise. The antenna, matching network, and critical components are already integrated and tested, allowing your team to focus on the core functionality of your product rather than RF engineering challenges. **Pre-matched Antenna Options**: Many modules include optimized antenna solutions—either integrated chip antennas or connectors for external antennas. This removes the complex impedance matching work that can delay projects and require expensive RF testing iterations. **Streamlined Certification**: Perhaps the most significant advantage is the simplicity of certification. Modules typically come with pre-certified RF performance for FCC (United States), CE (Europe), and Bluetooth SIG compliance. This means: - Reduced certification costs (you inherit the module's certifications) - Faster time-to-market (weeks instead of months for RF certification) - Lower risk of certification failures requiring hardware redesigns ### Planning for nRF54LM20A Modules While nRF54LM20A-based modules aren't available during this early access period, they're likely to follow the same pattern as other nRF54L variants. For immediate projects requiring nRF54LM20A capabilities, you'll need to design with the bare SoC and handle RF layout and certification internally. For projects with flexibility, starting with an nRF54L15 module and planning for potential migration to the nRF54LM20A module could reduce risk while maintaining a path to enhanced capabilities. ## Video Unboxing ## Conclusion: The Premium Choice for Advanced Projects The Nordic nRF54LM20A represents the natural evolution of the nRF54L series—taking proven architecture and scaling it for applications that demand maximum capability. With its 2MB+ memory, 66 GPIO pins, high-speed USB, and comprehensive wireless protocol support, it removes the traditional constraints that force design compromises. Whether you're building sophisticated smart home hubs, advanced industrial sensors, or next-generation wearables, the nRF54LM20A provides the foundation for products that were previously difficult or impossible to implement in a single chip. The combination of processing power, memory capacity, and wireless capability opens up entirely new product categories while maintaining the power efficiency and developer-friendly ecosystem that made Nordic's previous generations so successful. For developers ready to build the next generation of connected products without compromising on capability, the nRF54LM20A deserves serious consideration. It's not just about having more memory or more pins—it's about having the freedom to innovate without architectural limitations. *Ready to explore the nRF54LM20A for your next project? Explore* [*Nordic's early access program*](https://www.nordicsemi.com/Products/nRF54LM20A?ref=novelbits.io#:~:text=Project%2Dbased%20sampling%20and%20product%20updates) *to request early sampling and begin prototyping today.* ## References & Resources - [nRF54LM20A Product Page](https://www.nordicsemi.com/Products/nRF54LM20A?ref=novelbits.io) - [nRF54L Series Express Course](https://academy.nordicsemi.com/courses/nrf54l-series-express-course/?ref=novelbits.io) - [nRF54L15 SoC](https://www.nordicsemi.com/Products/nRF54L15?ref=novelbits.io) - [Nordic's Early Access Program for nRF54LM20A sampling](https://www.nordicsemi.com/Products/nRF54LM20A?ref=novelbits.io#:~:text=Project%2Dbased%20sampling%20and%20product%20updates) ### Bluetooth Channel Sounding Applications: Beyond Distance Measurements with Nordic nRF54L15 URL: https://novelbits.io/bluetooth-channel-sounding-applications-nrf54l15/ Last updated: 2026-04-26T17:48:54.000Z Exploring the potential of Bluetooth Channel Sounding Applications? You’re in the right place. *Sponsored by* [*Nordic Semiconductor*](https://nordicsemi.com/?ref=novelbits.io) The introduction of [Bluetooth Channel Sounding](https://novelbits.io/introduction-to-channel-sounding/) in the Core v6.0 specification represents a paradigm shift in how devices can interact through precise distance measurement. While much of the industry discussion has focused on the technical implementation details, the real story lies in the transformative applications this technology enables. This article presents a demo application based on the Nordic Semiconductor nRF54L15 SoC DK, providing a compelling glimpse into the future by showcasing four distinct use cases that demonstrate how smartphones and embedded devices will work together to create smarter, more responsive environments. Channel Sounding fundamentally changes the relationship between devices by providing accurate distance measurements where traditional RSSI-based approaches fall short. Unlike signal strength indicators that can be influenced by interference, obstacles, and environmental conditions, Channel Sounding uses a combination of round-trip time (RTT) measurements and phase-based ranging (PBR) to deliver consistent and reliable/secure distance estimates. This reliability/security opens doors to applications that were previously impractical or unreliable with existing Bluetooth Low Energy implementations. The Nordic nRF54 demo serves as more than just a technical demonstration—it's a window into real-world applications that developers can implement today. By examining how the demo's four modes translate into practical use cases, we can understand the broader implications of Channel Sounding for automotive, industrial, healthcare, and smart home applications. Each mode represents a distinct interaction paradigm, ranging from gamified proximity detection to critical safety monitoring, highlighting the versatility of distance-aware Bluetooth applications. 🎥 **See It In Action** Want to see a showcase of four distinct Channel Sounding demos operating between a pair of nRF54L15 DKs? [Jump to our hands-on video demonstration →](#video-demo) ## Understanding the Channel Sounding Ecosystem Channel Sounding operates within a defined ecosystem where devices assume specific roles. The **Initiator** (typically smartphones) starts ranging procedures and calculates distances, while the **Reflector** (typically embedded devices) responds to ranging requests. This division creates a clear paradigm: smartphones handle complex processing while embedded devices focus on efficient signal reflection. The Nordic demo simulates this ecosystem by having one nRF54 device act as a smartphone mock-up (Initiator) while other devices serve as an embedded system representative (Reflector). This setup mirrors expected deployment patterns where a single smartphone ranges to multiple embedded devices in its vicinity. ![Channel Sounding Ecosystem - Initiator and Reflector roles](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-14-1024x707.png) ## The Nordic nRF54L15 DK-based Demo: Four Modes of Innovation The demo presents four distinct modes showcasing different distance-aware applications. Each represents a unique interaction paradigm, demonstrating how the same Channel Sounding technology can serve different industries. ### Hot/Cold Game Mode: Gamification and Proximity The Hot/Cold Game transforms distance into an interactive experience using temperature metaphors. As users approach targets, the display progresses through "COLD" (>6m), "COOL" (4-6m), "WARM" (2-4m), and "HOT" (<2m) with corresponding color changes. This gamification demonstrates applications in retail environments, museum exhibitions, and interactive installations where engagement drives customer behavior. ### Safety Zone Mode: Industrial Protection Safety Zone mode creates digital perimeters using binary feedback: "SAFE" (>2m) or "DANGER!" (<2m). This represents critical safety applications in manufacturing facilities, construction sites, and hazardous areas. Unlike infrared sensors affected by dust or steam, Channel Sounding maintains accuracy in harsh industrial environments, providing reliable worker protection and equipment monitoring. ### Access Control Mode: Secure Keyless Entry This mode demonstrates sophisticated keyless entry beyond simple presence detection. "ACCESS GRANTED" appears within 1m, "ACCESS DENIED" beyond. Channel Sounding's precision prevents false positives from keys detected through walls and ensures consistent operation regardless of interference—critical for automotive keyless entry and smart building access systems. ### Raw Distance Mode: Precision Measurement Raw Distance mode displays exact measurements, such as "Distance: 3.5 m," showcasing the precision that enables logistics, healthcare monitoring, and research applications. This foundation enables developers to create custom application logic for specialized use cases that require sub-meter-level accuracy. ## Nordic nRF54L15: Purpose-Built for Channel Sounding Reflectors The nRF54L15 represents a pivotal development engineered explicitly for the Reflector role that embedded devices will predominantly occupy. Understanding these optimizations reveals why it's architected for battery-powered, always-responsive implementations. ### Why nRF54L15 Excels as a Reflector **Power Efficiency Critical**: Reflectors must remain available for ranging while maximizing battery life. The nRF54L15 achieves fast wake-up times while preserving timing references, enabling multi-year battery life for asset tracking applications. **Scalable Product Series**: All nRF54L Series SoCs support Bluetooth Channel Sounding, which allows you to select the perfect match for your application in terms of features and memory options. **Processing Availability**: On the nRF54L Series, the Channel Sounding Reflector role runs efficiently, preserving substantial CPU headroom for application-specific workloads. This allows teams to position Channel Sounding as a value-add that enhances the overall user experience while keeping the product’s core differentiators front and center. ### Nordic SDK and Ecosystem Benefits Nordic's SDK provides comprehensive Channel Sounding support through: - High-level APIs abstracting complex timing and security - Pre-qualified Bluetooth stack reducing certification complexity - Example code demonstrating optimal implementation patterns (for both Initiator and Reflector devices) ## Real-World Industry Example Applications ### Automotive: Beyond Keyless Entry Channel Sounding transforms automotive applications through precise distance awareness. Advanced keyless entry eliminates false unlocks when owners are inside buildings. Driver identification enables automatic personalization of seats, mirrors, and climate. Car-sharing platforms leverage distance-guided vehicle location and automated access, eliminating the need for key exchanges. ### Industrial: Safety Through Proximity Manufacturing environments benefit from digital safety perimeters around machinery and hazardous zones. Channel Sounding maintains accuracy despite dust, steam, and interference common in industrial settings. Applications include worker safety monitoring, equipment collision prevention, and precise asset tracking for warehouse optimization. ### Healthcare: Patient Safety and Asset Management Healthcare facilities utilize Channel Sounding for fall detection through position monitoring, medical equipment tracking to minimize inventory requirements, and medication verification, ensuring accurate patient administration. The technology enables accurate contact tracing and social distancing monitoring critical for infection control. ### Smart Home: Intelligent Automation Smart homes achieve sophisticated automation through precise occupancy detection. Lighting follows users through spaces, HVAC systems focus on occupied areas, and security systems distinguish family members from intruders. Appliances prepare user-specific settings based on approach patterns, creating truly responsive environments. ## Channel Sounding vs. Existing Technologies Channel Sounding occupies a unique position in the distance measurement landscape: | Technology | Accuracy | Power | Infrastructure Required | Ecosystem | | ---------------- | -------- | ----------- | ----------------------- | --------- | | RSSI | ±5-10m | Very Low | None | Excellent | | Channel Sounding | ±0.1-1m | Low | None | Growing | | UWB | ±10cm | Medium-High | None | Limited | | Wi-Fi RTT | ±1-3m | High | Yes | Moderate | Unlike RSSI's environmental variability, Channel Sounding provides consistent measurements through time-of-flight rather than signal strength. Compared to UWB's complexity and limited ecosystem, Channel Sounding leverages existing Bluetooth infrastructure. Unlike Wi-Fi RTT's infrastructure dependencies, it enables device-to-device ranging anywhere. ## Implementation Considerations ### Hardware Requirements Channel Sounding demands precise timing capabilities beyond basic Bluetooth Low Energy: - Crystal oscillators with tight frequency tolerance - Stable RF performance across operating frequencies - Adequate processing power for real-time ranging - Sufficient memory for configuration and security keys ### Power Management Strategies Optimizing battery life requires balancing accuracy with consumption: - Adjust measurement frequency based on application needs - Coordinate ranging with existing BLE communications (e.g., connections) - Implement intelligent sleep scheduling, maintaining availability - Enable selective ranging only when distance data is needed ### Security Implementation Channel Sounding security ensures trusted distance measurements: - Secure key storage and management - Device authentication before ranging - Replay attack prevention through proper nonce handling - Application-specific security policies ## Video Demo ## The Future of Distance-Aware Interactions Channel Sounding represents the foundation for new smartphone-to-device interactions, enabling sophisticated spatial awareness. Success depends on ecosystem development across manufacturers, operating systems, and developers. Emerging applications include robotics, safety monitoring, and advanced healthcare tracking. Privacy considerations require careful implementation of consent mechanisms and data protection, while regulatory frameworks must evolve to address precise distance measurement implications. ## Conclusion Channel Sounding transforms simple device interactions into sophisticated, context-aware applications. The Nordic-based four demo modes—Hot/Cold Game, Safety Zone, Access Control, and Raw Distance—represent interaction paradigms developers can adapt to countless real-world applications. For embedded developers, Channel Sounding opens opportunities previously impossible with existing Bluetooth Low Energy capabilities. The smartphone-to-device model aligns with user expectations while providing embedded systems clear roles as efficient Reflectors. The nRF54L15's optimization for this role, combined with Nordic's ecosystem support, positions it as the definitive platform for building distance-aware embedded devices. The future of device interaction is distance-aware, and Channel Sounding provides the precise measurement capabilities needed to build that future. Whether implementing industrial safety systems, creating engaging retail experiences, or developing healthcare monitoring solutions, developers now have reliable distance measurement that transforms applications from simple connected devices into spatially intelligent systems. ## Resources and References - [nRF54L15 SoC](https://www.nordicsemi.com/Products/nRF54L15?ref=novelbits.io) - [nRF54L15 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK?ref=novelbits.io) - [Channel Sounding Solutions - Nordic Semiconductor](https://www.nordicsemi.com/Products/Wireless/Bluetooth-Low-Energy/Channel-Sounding?ref=novelbits.io) - [nRF Connect SDK Channel Sounding Initiator sample](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/bluetooth/channel%5Fsounding%5Fras%5Finitiator/README.html?ref=novelbits.io) - [nRF Connect SDK Channel Sounding Reflector sample](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/bluetooth/channel%5Fsounding%5Fras%5Freflector/README.html?ref=novelbits.io) ### Renesas Bluetooth LE Development Guide: Getting Started with the DA1453x SoC Family URL: https://novelbits.io/renesas-ble-development-da1453x/ Last updated: 2026-04-26T17:49:27.000Z *Sponsored by* [*Renesas Electronics Corporation*](https://renesas.com/?ref=novelbits.io) In 2021, Renesas Electronics, one of the world's largest semiconductor companies with dominant automotive and industrial positions, significantly strengthened its IoT capabilities by acquiring Dialog Semiconductor. Dialog had built deep expertise in ultra-low power wireless connectivity and power management through strategic acquisitions and the successful SmartBond™ [Bluetooth Low Energy](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) product line, including the DA1453x SoC family, which consistently redefined industry benchmarks for power consumption and size. This combination of Renesas' scale and manufacturing prowess with Dialog's wireless innovation creates comprehensive solutions spanning MCUs, wireless connectivity, and power management—positioning the merged entity as a formidable competitor in the rapidly expanding IoT market while maintaining Dialog's innovative edge in ultra-low power design. The Renesas DA1453x Bluetooth LE SoC family, led by the DA14531 "SmartBond TINY™", targets high-volume, cost-sensitive IoT applications through exceptional power efficiency and minimal system BOM. Built on Arm® Cortex-M0+ with dedicated hardware for BLE Link Layer and cryptographic functions, the DA14531 keeps the main CPU in deep sleep while its integrated PMU supports Buck, Boost, and Bypass modes for flexible battery options. Rather than competing on raw performance, it dominates where power, size, and cost matter most—highly constrained designs previously out of reach. The development ecosystem combines SDK6, Keil µVision IDE, IAR, e² studio, and SmartSnippets™ tools with an event-driven architecture that maximizes the hardware's low-power capabilities. ## **Key Value Propositions** **Ultra-Low Power in Minimal Form Factor:** The DA14531 measures just 1.7mm × 2.05mm (WLCSP) while achieving 240 nA hibernation current, enabling operation from tiny batteries, including silver oxide and zinc-air. This unlocks disposable and space-constrained IoT applications previously deemed unfeasible. **Development-to-Production Flexibility:** Start development with external Flash for over-the-air updates, then transition to cost-optimized OTP memory for production. This dual pathway supports both rapid prototyping and high-volume manufacturing economics, particularly valuable for disposable devices. **Renesas Ecosystem Integration:** Functions as a standalone solution or Bluetooth LE coprocessor with Renesas MCUs through dedicated RA, RL78, and RX frameworks. Pre-certified modules eliminate RF design complexity while preserving existing MCU investments and providing clear upgrade paths. 🎥 **See It In Action** Want to see the DA14531's ultra-low power performance and development workflow in practice? [Jump to our hands-on video demonstration →](#video-demo) ## **Core Design Philosophies** To achieve its market-enabling goals, Renesas built the DA1453x architecture upon three uncompromising design philosophies: extreme power efficiency, minimal system cost, and simplified integration. #### 1\. **Extreme Power Efficiency** The paramount design constraint for the Renesas DA1453x family is power consumption. The SoCs explicitly target disposable products and operate effectively from the tiniest, disposable batteries, including silver oxide, zinc-air, and even experimental printed batteries with high internal resistance. This focus is evident in industry-leading power efficiency, which ensures a long operating and shelf life, even with battery capacities below 30 mAh. The architecture's ability to limit inrush current is another critical feature that facilitates operation from these low-capacity power sources. #### 2\. **Minimal System Cost** The second pillar of the value proposition is an exceptionally low total system cost. A high degree of integration within the SoC itself achieves this. Developers can construct a complete and functional Bluetooth Low Energy system with the DA14531 and as few as six external passive components, a single 32 MHz crystal, and a power source. This minimalist approach drastically reduces the Bill of Materials (BOM) cost, a critical factor for the high-volume, low-margin products it targets. Furthermore, certain variants and configurations, such as the DA14530 or using the DA14531 in bypass mode, eliminate the need for an external DC/DC inductor, further trimming the BOM for applications where power efficiency is a secondary concern to absolute cost. #### 3\. **Ease of Use and Integration** Recognizing that many potential adopters in high-volume markets may lack deep RF engineering expertise, Renesas has made ease of integration a central part of the platform's strategy. The most prominent example of this is the DA14531MOD, a fully integrated and pre-certified module. This module incorporates the DA14531 SoC, all necessary passives, a crystal, external Flash memory, and an on-board antenna into a single, hand-solderable component. For product developers, this transforms the complex task of RF design, tuning, and regulatory certification into a "simple drop-in" solution, significantly reducing development costs, risk, and time-to-market. This approach effectively lowers the barrier to entry, making sophisticated Bluetooth LE technology accessible to a much broader range of manufacturers. **4\. System Integration Flexibility** The fourth cornerstone of the DA1453x architecture is its deployment versatility. The SoC family is engineered to excel in two distinct system configurations: as a standalone Bluetooth LE solution where the DA1453x handles all processing and connectivity functions, or as a dedicated Bluetooth LE coprocessor paired with a host MCU from Renesas's extensive microcontroller portfolio. This architectural flexibility allows developers to optimize their system design based on specific requirements. Standalone deployment maximizes simplicity and minimizes BOM count, while coprocessor configurations leverage the computational power and peripheral richness of Renesas MCUs while offloading Bluetooth LE complexity to the specialized DA1453x. This dual-capability approach reduces development risk by allowing designers to migrate between architectures as product requirements evolve, while strengthening the overall Renesas ecosystem value proposition. ## **Deployment Flexibility: Standalone or Coprocessor Configurations** The DA1453x family's architectural design enables two distinct deployment strategies, each optimized for different application requirements and development workflows. **Standalone Configuration: Maximum Simplicity** In standalone mode, the DA1453x operates as a complete Bluetooth LE system, executing application code directly from its internal memory architecture. This configuration requires minimal external components—as few as six passive components plus a crystal and power source—making it ideal for cost-sensitive, space-constrained applications where simplicity is a priority. The standalone approach is particularly well-suited for sensor nodes, beacons, simple HID devices, and disposable medical products where the application logic is relatively straightforward and the benefits of ultra-low power consumption and minimal BOM cost are critical. **Coprocessor Configuration: Leveraging the Renesas Ecosystem** Alternatively, the DA1453x can function as a dedicated Bluetooth LE coprocessor, connected to a host Renesas MCU via UART using the proprietary GTL (Generic Transport Layer) interface. In this configuration, the host MCU manages application logic, sensor interfacing, and complex processing, while the DA1453x handles all Bluetooth LE operations, including advertising, connection management, and data transmission. This approach unlocks the full potential of Renesas's comprehensive MCU portfolio—from the ultra-low-power RL78 family to the high-performance RA and RX series—while providing seamless integration through the FSP (Flexible Software Package) framework. The coprocessor model is ideal for applications requiring complex processing, extensive peripheral interfacing, or integration with existing Renesas-based designs. **Strategic Flexibility and Risk Mitigation** The ability to choose between these deployment models—or even migrate between them during product development—provides significant strategic advantages. Developers can begin with a coprocessor approach during prototyping to leverage familiar MCU development tools and extensive peripheral libraries, then potentially consolidate to a standalone configuration for cost optimization in production. Conversely, products initially designed around the standalone DA1453x can easily scale up to coprocessor configurations if requirements expand beyond the SoC's integrated capabilities. ## **Architectural Deep Dive: The DA14531 SoC** ![DA14531 SoC Architecture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image.png) *Source: [Renesas DA14531 Product Brief](https://www.renesas.com/en/document/prb/smartbond-tiny-da14531-product-brief?srsltid=AfmBOooqfLDE6alDP6y-ZnOBFNIOc2Lj14HDGCzCkErlZvTBAOLYtGNp&ref=novelbits.io)* The DA14531's architecture represents a carefully balanced system optimized for dual deployment scenarios: ultra-efficient standalone operation and seamless coprocessor integration within the broader Renesas ecosystem. Rather than a general-purpose microcontroller with attached radio, it is a specialized system engineered from the ground up for Bluetooth LE applications, whether operating independently or in partnership with a host MCU. This architectural specialization is evident throughout the design—from the processing core and memory subsystem to the power management unit—with each element optimized to excel in both standalone and coprocessor configurations while maintaining the platform's core strengths of minimal power consumption, small physical footprint, and exceptional cost efficiency. #### Did you know? The DA14531 measures just 1.7mm × 2.05mm—smaller than a grain of rice—making it perfect for wearables, smart sensors, and space-constrained IoT devices! ![DA14531 chip size comparison](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/SmallSize-Background-Removed.png) ### **Core Processing Unit: The Arm® Cortex-M0+** At the heart of the DA14531 is a 16 MHz 32-bit Arm® Cortex-M0+ processor. This core was selected for its exceptional energy efficiency and high code density rather than for raw computational power. It features a simple two-stage pipeline and implements the Thumb instruction set, achieving a performance metric of 0.9 DMIPS/MHz, which is more than sufficient for managing the Bluetooth LE stack and the simple sensor applications it targets. A key architectural choice that enables the use of such a modest CPU is the offloading of critical tasks to dedicated hardware. The efficiency of this holistic system design is quantified by its **EEMBC IoTMark™-Bluetooth LE score of 18300**, a standardized benchmark that validates its leadership in IoT connectivity performance per watt. ### **Memory Subsystem: OTP, RAM, and ROM** The memory architecture is carefully partitioned to strike a balance between cost, flexibility, and power consumption. - **32 kB One-Time-Programmable (OTP) Memory:** This non-volatile memory is used to store the final application code, custom Bluetooth LE profiles, system configuration parameters, and device-specific calibration data. As its name implies, it can only be programmed once, a crucial consideration for manufacturing and production workflows. - **48 kB Retainable System RAM:** This is the primary execution memory. During the boot process, the application code stored in OTP (or external Flash) is mirrored into this SRAM, from which the CPU executes it. It also serves as data RAM for application variables and protocol data structures. The "retainable" nature of this RAM is critical for low-power operation; its contents can be preserved during sleep modes, allowing the device to wake and resume operation almost instantly without needing to perform a full reboot. Unlike traditional MCUs with internal Flash, the DA1453x flash-less architecture reduces system cost, minimizes power consumption, and enables faster wake-up, while optional external Flash can be used for larger or updatable applications. - **144 kB ROM:** The SoC includes a significant amount of read-only memory that contains the immutable bootloader sequence and the core, qualified Bluetooth LE protocol stack. Placing the stack in ROM reduces the amount of OTP or external Flash memory required for the user's application, contributing to a lower overall system cost and smaller code footprint. ### **Peripherals and Interfaces** Despite its small size, the DA14531 integrates a comprehensive set of peripherals to support a wide range of applications. - **Digital Interfaces:** The number of available General Purpose I/O (GPIO) pins depends on the package: the ultra-small WLCSP17 package provides 6 GPIOs, while the larger FCGQFN24 package offers 12\. Standard serial communication is supported by two UARTs (one with hardware flow control), an SPI Master/Slave interface capable of operating at up to 32 MHz in master mode, and an I2C bus supporting speeds of 100 kHz and 400 kHz. - **Analog Interfaces:** The primary analog peripheral is a 4-channel 10-bit Analog-to-Digital Converter (ADC). It can be used to measure external analog sensors or internal signals, such as the battery voltage and the die temperature, providing essential system health monitoring capabilities. - **Timers and PWM:** The SoC features two general-purpose timers with capture and Pulse Width Modulation (PWM) capabilities, making them suitable for tasks such as driving LEDs or controlling small motors. ### **Power Management Unit (PMU) and Consumption** The integrated Power Management Unit is arguably the most critical component of the DA14531's architecture, directly enabling its ultra-low-power performance and operational flexibility. The PMU manages all internal power domains and supports three distinct operating configurations based on the input power source. - **Buck Mode:** Suitable for input voltages ranging from 1.8V to 3.6V, this mode utilizes a high-efficiency step-down DC/DC converter. This is the typical configuration for systems powered by lithium coin-cell or polymer batteries. - **Boost Mode:** For very low input voltages, from 1.1V to 1.65V, this mode uses a step-up DC/DC converter. This capability is essential for enabling operation from single-cell alkaline or silver-oxide batteries. - **Bypass Mode:** In this configuration, the DC/DC converter is disabled, and the system operates from an internal LDO. While less power-efficient, this mode offers the lowest BOM cost as it does not require an external inductor. This is a viable option for applications where cost is the absolute priority and battery life is less critical. The PMU also orchestrates several power modes, allowing the system to shed power aggressively when idle. The current consumption figures demonstrate the SoC's extreme efficiency: - **Active Mode (Tx/Rx):** 3.5 mA (transmitting at 0 dBm) and 2.2 mA (receiving). - **Extended Sleep Mode:** With all 48 kB of RAM retained, the system consumes approximately 1.6 µA, allowing for very fast wake-up times. - **Hibernation Mode:** In this clock-less state with no RAM retained, the SoC consumes a mere 240 nA to 270 nA, enabling multi-year shelf life on even the smallest batteries. ### **Radio Frequency (RF) Performance** The DA14531 features a fully integrated 2.4 GHz CMOS transceiver that is fully compliant with the Bluetooth 5.1 core specification. The design simplifies external circuitry by requiring only a single-wire antenna interface. Key RF performance metrics are highly competitive for their class: - **Receiver Sensitivity:** \-94 dBm, which allows for reliable communication over longer distances or in noisy environments. - **Transmit Output Power:** Programmable from a very low -19.5 dBm up to +2.5 dBm, giving developers the flexibility to trade range for power consumption based on the application's needs. ## Renesas **DA1453x Family Variants** The DA1453x is not a single device, but a family of SoCs and modules, each tailored with specific feature sets and cost structures to address different market segments. Understanding the nuanced differences between these variants is critical for selecting the optimal component for a given application. ### **1\. DA14531-00: The Baseline** - Full-featured device supporting both Central and Peripheral roles - Complete feature set as described in the architectural overview - Versatile choice for applications requiring connection initiation or discovery ### **2\. DA14531-01: The Peripheral-Optimized Variant** - Peripheral-only operation (no Central or Observer roles) - 25% more usable RAM compared to baseline - Ideal for beacons, sensors, and tags that don't initiate connections ### **3\. DA14530: The Cost-Optimized Variant** - Pin-compatible drop-in replacement for DA14531 in FCGQFN24 package - Internal LDO instead of Buck/Boost DC/DC converter - Eliminates the external inductor requirement for the lowest BOM cost - Trade-off: reduced power efficiency versus DA14531 ### **4\. DA14535: The Bluetooth LE 5.3 Upgrade** - Bluetooth 5.3 compliance with future-proofing - Increased system RAM (64 kB vs 48 kB) and higher transmit power (+4 dBm) - Extended temperature range to 105°C for industrial applications - Trade-offs: reduced OTP (12 kB vs 32 kB), no Link Layer Privacy ### **5\. DA14533: The Automotive & Industrial Variant** - Same enhanced specifications as DA14535 - AEC-Q100 Grade 2 compliance for automotive applications - 105°C operating temperature for harsh environments ### **DA1453x Family Comparative Specification Matrix** | Feature | DA14531-00 | DA14531-01 | DA14530 | DA14535 | DA14533 | | --------------------------------- | ----------------- | ----------------- | ------------ | --------------- | --------------- | | **Bluetooth Core Spec** | 5.1 | 5.1 | 5.1 | 5.3 | 5.3 | | **Bluetooth LE Central Support** | Yes | No | Yes | Yes | Yes | | **Bluetooth LE Observer Support** | Yes | No | Yes | Yes | Yes | | **LL Privacy** | Yes | No | Yes | No | No | | **System RAM** | 48 kB | 48 kB | 48 kB | 64 kB | 64 kB | | **OTP Memory** | 32 kB | 32 kB | 32 kB | 12 kB | 12 kB | | **ROM** | 144 kB | 144 kB | 144 kB | 160 kB | 160 kB | | **PMU** | Buck/Boost DCDC | Buck/Boost DCDC | LDO (Bypass) | Buck/Boost DCDC | Buck/Boost DCDC | | **Max Output Power** | +2.5 dBm | +2.5 dBm | +2.5 dBm | +4 dBm | +4 dBm | | **Temp Range (°C)** | \-40 to +85 | \-40 to +85 | \-40 to +85 | \-40 to +105 | \-40 to +105 | | **Package(s)** | FCGQFN24, WLCSP17 | FCGQFN24, WLCSP17 | FCGQFN24 | FCGQFN24 | FCGQFN24 | | **AEC-Q100** | No | No | No | No | Yes (Grade 2) | | **Module Available** | DA14531MOD | —— | —— | DA14535MOD | —— | ### **Choosing Your DA1453x Variant:** **For the simplest implementation and lowest BOM cost:** Choose DA14530 when external inductor elimination is a priority and moderate power efficiency is acceptable. **For ultra-low power sensors, beacons, and tags:** Choose DA14531-01 when devices only need to advertise or be connected to (not initiate connections), and maximum RAM is beneficial. **For versatile standalone applications:** Choose DA14531-00 when you need full Central/Peripheral capability and a proven, mature platform with maximum flexibility. **For future-proofed or industrial applications:** Choose DA14535 when Bluetooth 5.3 compliance, higher transmit power, or extended temperature operation is required, and a smaller OTP is acceptable. **For automotive applications:** Choose DA14533 when AEC-Q100 compliance and harsh environment operation are mandatory requirements. **Architecture Decision:** - **Standalone configuration:** Simple sensors, beacons, HID devices, or disposable products with straightforward application logic - **Coprocessor configuration:** Complex processing requirements, extensive peripheral interfacing, or integration with existing Renesas MCU-based designs ## **The Developer Experience: Ecosystem and Software Architecture** A successful SoC is defined not only by its hardware capabilities but also by the quality and accessibility of its software ecosystem. Renesas provides a comprehensive suite of tools and software for the Renesas DA1453x family, designed to support developers from initial prototyping through to mass production. ### **The Renesas SmartBond DK6** The foundation of software development for the Renesas DA1453x family is the SDK6, a comprehensive software development kit that includes the Bluetooth LE stack, peripheral drivers, and a rich set of example applications. A key architectural element of the SDK is its use of a small and efficient Real-Time Kernel (RTK). This is not a full-featured real-time operating system (RTOS), but rather a lightweight scheduler. The entire Bluetooth LE stack and the user application are structured as a series of independent tasks that communicate via messages and events handled by the kernel. This event-driven, message-passing architecture is a direct software reflection of the hardware's low-power design philosophy. The main application loop consists of the kernel's scheduler, which processes all pending events in its queues (such as incoming Bluetooth LE packets, timer expirations, or application messages). Once the queues are empty, there is no more work to be done, and the scheduler immediately allows the system to enter a low-power sleep mode. This tight coupling between the software paradigm and the hardware's capabilities is fundamental to achieving the ultra-low power performance that defines the platform. ### Renesas **SmartBond** SDK6 Unique Features The SDK6 also includes several high-level features to accelerate development. #### CodeLess AT Command Interface The **CodeLess AT command** **interface** is a ready-to-use firmware solution for the DA1453x family, providing a simple way to control the SoC via AT commands over serial interfaces and/or BLE. It abstracts away low-level Bluetooth LE programming, allowing system designers and application developers to quickly configure and operate the device without writing embedded code. This makes it particularly useful for rapid prototyping or for “Bluetooth LE pipe” applications where the DA1453x is paired with a host MCU. **When NOT to use Codeless** - Advanced or Custom BLE Features - High-Performance Applications with low latency; avoid AT command interpretation overhead - Memory-constrained application - Complex peripheral interfacing for efficient and real-time sensor data transmission ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-11.png) #### **Serial Port Service (SPS)** SPS (Serial Port Service) is a Bluetooth LE-based UART-to-serial bridge developed by Renesas Electronics. It allows wireless transmission of serial data over Bluetooth Low Energy, functioning similarly to a Classic serial (UART) connection but over Bluetooth LE. **When to use SPS** - When you need UART-to-Bluetooth LE functionality - For quick prototyping of serial data transfer - When monitoring throughput or testing a Bluetooth LE link performance - When replacing wired serial communication with Bluetooth LE **When NOT to use SPS** - While SPS is not only for monitoring throughput, it is mainly used for transparent serial data transmission rather than full-fledged Bluetooth LE application development. - If your application requires custom BLE services or complex logic - When optimizing low power (SPS may not be the most efficient) - If you need bidirectional control signals beyond just serial data #### Software Update Over-The-Air 1. The SDK also provides robust support for **Software Update Over-The-Air (SUOTA),** which is a critical feature for deploying firmware updates to devices in the field. This requires an external flash, which is used for storing the application image that gets executed from there or copied into system RAM for execution. In this scenario, the OTP could still be used for other important system data, such as configuration and/or calibration data. **References:** - CodeLess AT command interface: [https://www.renesas.com/en/software-tool/smartbond-codeless-commands](https://www.renesas.com/en/software-tool/smartbond-codeless-commands?utm%5Fsource=chatgpt.com) - SPS: [https://www.renesas.com/en/software-tool/serial-port-service-sps](https://www.renesas.com/en/software-tool/serial-port-service-sps?ref=novelbits.io) - Software Update Over-The-Air (SUOTA): [https://lpccs-docs.renesas.com/Tutorial\_SDK6/suota\_overview.html](https://lpccs-docs.renesas.com/Tutorial%5FSDK6/suota%5Foverview.html?utm%5Fsource=chatgpt.com) ### **The Development Tools Ecosystem** The development toolchain for the Renesas DA1453x provides comprehensive coverage through specialized tools, each serving distinct and complementary roles in the development workflow: - **e2 studio:** This is Renesas’s royalty-free, Eclipse-based IDE, providing a complete development environment with a project manager, editor, and debugger. The DA14531 SDK6 includes full support for e² studio and the LLVM compiler, offering enhanced development capabilities. e² studio is suitable for both evaluation and professional, long-term development, with no code-size limitations. - **SmartSnippets™ Toolbox** is a utility suite included with Renesas Bluetooth development kits, designed to simplify development and optimize applications for ultra-low-power performance. It provides full visibility into chip activity and leverages the motherboard’s features, eliminating the need for costly external equipment. Key tools include: - **Programmer:** A graphical tool for programming firmware into the SoC’s internal SRAM, OTP, or external SPI/I2C Flash memory. It is the primary tool for production programming. - **Power Profiler:** Interfaces with the development kit’s current measurement hardware to provide a real-time, high-resolution view of the SoC’s power consumption. Developers can see the impact of code changes instantly and optimize for maximum battery life. - **Keil® µVision:** This is the most common Integrated Development Environment (IDE) for getting started with the Renesas DA1453x. The vast majority of Renesas's official tutorials and example projects are provided as Keil µVision projects. A free version of the Keil MDK-ARM toolchain is sufficient for building and debugging these examples, making it an accessible entry point for new developers. ### Production Line Tool (PLT) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-10-1024x576.png) Renesas provides a production testing and programming solution that helps reduce costs and speed up production. The [Connectivity Production Line Tool (PLT)](https://www.renesas.com/en/design-resources/boards-kits/rtkrq00101s00000bj?ref=novelbits.io) is a flexible system that makes it easier to test and program devices built with Renesas DA1453x Connectivity ICs. The PLT can test, calibrate, and perform memory operations on several devices at the same time. For example, you can connect to four PLT boards, each with eight test sites, allowing up to 32 devices to be tested at once. This setup helps increase efficiency in high-volume production. ### **Development Hardware** Renesas provides a couple of hardware platforms to facilitate development with the Renesas DA1453x family. ![DA14531 Development Kit Pro](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/image-1-compressed.jpg) - [**DA14531 Development Kit Pro**](https://www.renesas.com/en/design-resources/boards-kits/da14531-00fxdevkt-p?ref=novelbits.io)**:** This is the primary development platform, offering maximum flexibility and functionality. It consists of a large motherboard and a small, interchangeable daughterboard that holds the specific DA1453x SoC variant. The motherboard includes an onboard Segger J-Link debugger, a USB-to-UART bridge, user-configurable buttons and LEDs, and, most importantly, dedicated circuitry for precise current measurement that integrates with the SmartSnippets™ Toolbox Power Profiler. ![DA14535 Development Kit Pro](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/image-8-compressed.jpg) - [**DA14535 Development Kit Pro**](https://www.renesas.com/en/design-resources/boards-kits/da14535-00fxdevkt-p?ref=novelbits.io): The DA14535-00FXDEVKT-P Bluetooth® Low Energy Development Kit Pro for the [DA14535](https://www.renesas.com/en/products/da14535?ref=novelbits.io) SmartBond TINY™ SoC includes a motherboard, daughterboard, and cables. This kit is primarily intended for software application development and power measurements. ![DA14535 Module](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-13.png) - [**DA14531 USB Development Kit**](https://www.renesas.com/en/design-resources/boards-kits/da14531-00fxdevkt-u?ref=novelbits.io)**:** This is a much smaller, self-contained "dongle" style board. It integrates the DA14531 SoC and a USB connector onto a single PCB, making it a convenient and low-cost option for simpler prototyping and software development where advanced power measurement is not required. ![DA14531 USB Development Kit](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/image-4-compressed.jpg) - [**DA14531 Module**](https://www.renesas.com/en/products/da14531mod?ref=novelbits.io): The DA14531 SmartBond TINY™ Module leverages the world's smallest, lowest-power Bluetooth 5.1 SoC in an integrated package. With regional certifications, an integrated antenna, and user-friendly software, it significantly reduces development costs and time-to-market. The module requires only a power supply and PCB to create Bluetooth applications, making BLE development more accessible for broad market deployment. ![DA14531 Module](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-5.png) - [**DA14535 Module**](https://www.renesas.com/en/products/da14535mod?ref=novelbits.io): The DA14535MOD is a globally certified, ultra-low-power Bluetooth® Low Energy v5.3 module designed for cost-effective wireless connectivity. Perfect for rapid product upgrades, it enables smartphone integration for commissioning, control, alerts, and data collection. As a pin-compatible alternative to the DA14531MOD, it features a Cortex-M0+ processor operating at 16MHz, integrated 1Mbit Flash, RAM/ROM/OTP memory, a 32MHz crystal, a power inductor, RF matching, and a printed antenna—all in a fully self-contained package. ### Mobile App Tools ![Renesas SmartBond mobile app](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/image-7.png) In addition to the PC-based software tools available (IDE, SmartSnippets™Toolbox, etc.), Renesas offers a Bluetooth Low Energy explorer application, available on both iOS and Android: ![](https://lpccs-docs.renesas.com/DA1453x-RL78_BLE_Framework/_images/apple-store-smartbond.svg) [Renesas Smartbond for iOS](https://apps.apple.com/app/renesas-smartbond/id1623197578?ref=novelbits.io) ![](https://lpccs-docs.renesas.com/DA1453x-RL78_BLE_Framework/_images/play-store-smartbond.svg) [Renesas Smartbond for Android](https://play.google.com/store/apps/details?id=com.renesas.smartbond&hl=en&gl=US&ref=novelbits.io) ### DA1453x SoC as a Network Coprocessor **Renesas Ecosystem Integration** The DA1453x family's coprocessor capability represents a strategic integration point within the broader Renesas semiconductor ecosystem, enabling customers to leverage decades of microcontroller expertise while adding best-in-class Bluetooth LE connectivity. **Architecture and Communication** In coprocessor mode, the DA1453x firmware is stored in the host MCU's flash memory and loaded into the DA1453x RAM at boot time. The two processors communicate via a 4-wire UART interface using Renesas's proprietary GTL (Generic Transport Layer) protocol, which provides native support for all Bluetooth LE operations, including advertising, connection management, security procedures, and data transfer. This architecture allows the host MCU to maintain complete control over Bluetooth LE functionality while offloading the complexity of RF management, protocol stack execution, and regulatory compliance to the specialized DA1453x hardware. **Renesas MCU Family Support** The coprocessor implementation is supported across Renesas's major MCU families through dedicated software frameworks: - **FSP (Flexible Software Package) Framework**: Comprehensive support for RA Arm Cortex-M MCUs with integrated Bluetooth LE APIs and example applications - **RL78 Framework**: Optimized integration for ultra-low-power RL78 applications where both processors can cooperate to minimize system power consumption - **RX Framework**: High-performance integration for applications requiring significant computational capabilities alongside Bluetooth LE connectivity **Strategic Advantages** This coprocessor approach delivers several key benefits: it preserves existing investments in Renesas MCU expertise and codebases, enables rapid integration of Bluetooth LE into established product lines, provides access to the extensive peripheral capabilities of Renesas MCUs, and creates clear upgrade paths as product requirements evolve. The unified Renesas ecosystem also simplifies supply chain management, technical support, and long-term roadmap alignment. For more information about this setup, refer to the following user guides: - [Getting Started with DA1453x and FSP Bluetooth Low Energy Framework on Renesas Microcontrollers](https://www.renesas.com/en/document/mat/getting-started-da1453x-and-fsp-bluetooth-low-energy-framework-renesas-microcontrollers?r=25467666&ref=novelbits.io) - [Getting Started with DA1453x and RL78 Bluetooth Low Energy Framework on Renesas Microcontrollers](https://www.renesas.com/en/document/mat/getting-started-da1453x-and-rl78-bluetooth-low-energy-framework-renesas-microcontrollers?r=25467666&ref=novelbits.io) - [Getting Started with DA1453x and RX Bluetooth Low Energy Framework on Renesas Microcontrollers](https://www.renesas.com/en/document/mat/getting-started-da1453x-and-rx-bluetooth-low-energy-framework-renesas-microcontrollers?r=25467666&ref=novelbits.io) ## Real-World Products Utilizing the DA1453x SoC Family The Renesas DA1453x family's specific focus on ultra-low power, minimal size, and low system cost has led to its adoption in a wide array of commercial products and reference designs. Here is a summary of products and companies that utilize this SoC family. ### Consumer and Smart Home Products The DA1453x family is frequently used in high-volume consumer electronics where long battery life and a small form factor are critical selling points. - **HyperSynes Smart BBQ Thermometers:** HyperSynes, a global leader in smart grilling technology, uses the Renesas DA14531 in its advanced smart meat probes and BBQ temperature controllers. The SoC's ultra-low power consumption and compact design were crucial for creating completely wireless, slim, and highly accurate food thermometers. According to HyperSynes, their products, powered by the DA14531, are used in 95% of the world's wireless food thermometers, sold under their own name and through private-label brands. - **Human Interface Devices (HID):** The SoC's efficiency makes it ideal for peripherals such as electronic styluses, wireless keyboards, computer mice, and remote controls that replace traditional infrared (IR) versions. - **General Consumer Goods:** The DA1453x is also found in products like smart toys, smart credit cards, and as a simple "Bluetooth LE pipe" to add connectivity to existing applications with a host microcontroller. ### Connected Medical and Health Devices The DA1453x family is explicitly optimized for the connected medical market, particularly for disposable or single-use products where cost and the ability to operate from small, non-rechargeable batteries are paramount. - **Disposable Medical Devices:** The SoC is designed to be integrated into products such as connected injectors, inhalers, glucose monitors, smart patches for vitals monitoring, blood pressure meters, and digital thermometers. Its ability to operate from specialized power sources, such as silver oxide, zinc-air, or even printed batteries, makes it uniquely suited for this category. ### Asset Tracking, Beacons, and Logistics The combination of low power for extended shelf life and small size for discreet placement makes the DA14531 a popular choice for tracking and proximity applications. - **Nodle N1 NanoComputer:** Nodle uses the DA14531 "SmartBond TINY™" as the core of its N1 NanoComputer, a device designed for its decentralized IoT network. This network is used in applications such as locating and recovering stolen vehicles for insurance companies. Nodle selected the DA14531 for its low-power operation, encryption capabilities, cost-effectiveness, and robust performance, which were essential for creating a programmable, low-power edge computing device. - **Feasycom Bluetooth Beacons:** Feasycom, a provider of IoT modules and solutions, partnered with Renesas to create a line of high-performance Bluetooth beacons based on the DA14531\. Feasycom chose the DA14531 over competing solutions because its power consumption is roughly half that of alternatives, effectively doubling the battery standby time. This advantage, combined with the SoC's small size and high return on investment, was critical for their product strategy. - **Renesas Smart Asset Tracking Label:** As part of its "Winning Combinations" portfolio, Renesas features a credit card-sized smart tracking label. This reference design uses the DA14531 SoC with Renesas humidity and temperature sensors to monitor environmental data. The design achieves a 2-3 month shelf life and around 30 days of active use from a small 25mAh printable battery. - **Hongjia Electronic Technology Modules**: Hongjia’s journey with Renesas began in 2014 when the company adopted the DA14580 System-on-Chip (SoC) to develop the HJ-580 series of modules. Building on this success, Hongjia continued to innovate with the introduction of the HJ-131IMH and HJ-531IMF Bluetooth® Low Energy (LE) modules in 2020, based on Renesas’ DA14531. - **DX Smart Technology**, a company specializing in wireless communication modules and solutions, joined forces with Renesas Electronics. By incorporating Renesas’ cutting-edge System-on-Chips (SoCs) into their products, DX Smart has not only streamlined its research and development but also provided unparalleled value to customers seeking competitive advantages through quick validation and reduced costs. ### Automotive and Industrial Applications While the family broadly targets consumer and medical markets, its reliability and efficiency also suit certain automotive and industrial use cases. - **Tire Pressure Monitoring Systems (TPMS):** The DA1453x family is frequently listed as a suitable component for TPMS applications, where low power consumption is necessary to maximize the battery life of sensors mounted inside tires. - **Low-Power Wireless Sensors:** The SoC is also used in various low-power wireless sensors for industrial monitoring applications. ## How to Get Started with Development for the DA14531 SoC ### Hardware Prerequisites - Computational workstation (for example, PC or Laptop) - 32-bit or 64-bit processor with 1 GHz processing speed - 1 GB RAM - 2 GB free disk space - [DA14531-00FXDEVKT-P](https://www.renesas.com/us/en/products/wireless-connectivity/bluetooth-low-energy/da14531-00fxdevkt-p-smartbond-tiny-da14531-bluetooth-low-energy-51-system-chip-development-kit-pro?ref=novelbits.io) as a motherboard - DA14531-0x daughterboard FCGQNFN 24 package (DA14531-00/DA14531-01- QFN daughterboard). - USB cable for power supply to the Pro Development kit and for on-board debugging ### Software Prerequisites To get started, download the following software packages: - [Software Development Kit (Renesas SmartBond SDK)](https://www.renesas.com/sdk6%5Flatest?ref=novelbits.io) - [e² studio](https://www.renesas.com/us/en/software-tool/e-studio/?ref=novelbits.io) (you can also use Keil) - [SmartSnippets™ Toolbox](https://www.renesas.com/eu/en/software-tool/smartbond-development-tools?ref=novelbits.io) - [Keil MDK ARM](https://developer.arm.com/Tools%20and%20Software/Keil%20MDK?ref=novelbits.io) (you can also use e² studio) - [FTDI Driver for Windows](https://ftdichip.com/drivers/vcp-drivers/?ref=novelbits.io) - [Segger J-Link SW driver](https://www.segger.com/downloads/jlink/?ref=novelbits.io) ## Video Tutorial/Demo ## Summary The Renesas DA1453x Bluetooth LE SoC family, led by the DA14531 "SmartBond TINY™", represents a breakthrough in ultra-low-power wireless connectivity for cost-sensitive IoT applications. Built on Arm® Cortex-M0+ architecture with dedicated BLE hardware, these SoCs achieve industry-leading hibernation currents as low as 240 nA while requiring just six external components for a complete system. The family's three core design philosophies—extreme power efficiency, minimal system cost, and simplified integration—enable operation from tiny batteries (including silver oxide and zinc-air) and make Bluetooth LE accessible for previously unfeasible applications. With variants optimized for different use cases (peripheral-only, cost-optimized, automotive-grade), comprehensive SDK6 development tools, and pre-certified modules, the platform has achieved widespread adoption in smart home devices, medical wearables, asset tracking, and automotive applications. This deep dive explored the architectural innovations, power management techniques, family variants, development ecosystem, and real-world implementations that position the DA1453x as the go-to solution for battery-powered IoT devices where every microamp and penny counts. ## Resources and Links **DA1453x SoCs** - Product Selector: [https://www.renesas.com/en/products/wireless-connectivity/bluetooth-low-energy/product-selector?product-id=da1453](https://www.renesas.com/en/products/wireless-connectivity/bluetooth-low-energy/product-selector?product-id=da1453&ref=novelbits.io) - DA14531 product page: [https://www.renesas.com/en/products/da14531](https://www.renesas.com/en/products/da14531?ref=novelbits.io) - DA14530 product page: [https://www.renesas.com/en/products/da14530](https://www.renesas.com/en/products/da14530?ref=novelbits.io) - DA14533 product page: [https://www.renesas.com/en/products/da14533](https://www.renesas.com/en/products/da14533?ref=novelbits.io) - DA14535 product page: [https://www.renesas.com/en/products/da14535](https://www.renesas.com/en/products/da14535?ref=novelbits.io) - DA14531 Datasheet: [https://www.renesas.com/en/document/dst/da14531-datasheet?r=1564826](https://www.renesas.com/en/document/dst/da14531-datasheet?r=1564826&ref=novelbits.io) **SDK6** - DA1453x/DA1458x Tutorial SDK6 Getting Started: [https://lpccs-docs.renesas.com/Tutorial\_SDK6/index.html](https://lpccs-docs.renesas.com/Tutorial%5FSDK6/index.html?ref=novelbits.io) - Download SDK6: [https://www.renesas.com/en/document/swo/sdk60241464-da1453x-da145856](https://www.renesas.com/en/document/swo/sdk60241464-da1453x-da145856?ref=novelbits.io) - SDK6 Examples: [https://github.com/renesas/ble-sdk6-examples](https://github.com/renesas/ble-sdk6-examples?ref=novelbits.io) **Development** - e2 studio: [https://lpccs-docs.renesas.com/e2\_studio\_sdk6\_getting\_started/index.html](https://lpccs-docs.renesas.com/e2%5Fstudio%5Fsdk6%5Fgetting%5Fstarted/index.html?utm%5Fsource=chatgpt.com) - Renesas DA Tutorials: [https://lpccs-docs.renesas.com/lpc\_docs\_index/DA145xx.html#tutorials](https://lpccs-docs.renesas.com/lpc%5Fdocs%5Findex/DA145xx.html?ref=novelbits.io#tutorials) - DA14531 Getting Started with the Pro-Development Kits: [https://lpccs-docs.renesas.com/UM-B-117-DA14531-Getting-Started-With-The-Pro-Development-Kit/index.html](https://lpccs-docs.renesas.com/UM-B-117-DA14531-Getting-Started-With-The-Pro-Development-Kit/index.html?ref=novelbits.io) **Bluetooth Low Energy Technical Support Community** - [Bluetooth Low Energy - Renesas Wireless Connectivity - Renesas Engineering Community](https://community.renesas.com/wireles-connectivity/f/bluetooth-low-energy?ref=novelbits.io) **End-product Example** - [Renesas Makes HyperSynes a Smart Outdoor Cooking ODM Game Changer](https://www.renesas.com/en/about/customer-success-stories/wireless-connectivity/renesas-makes-hypersynes-smart-outdoor-cooking-odm-game-changer?ref=novelbits.io) **Renesas Partner Program** - [Renesas Preferred Partners: Collaborating for Enhanced Solutions | Renesas](https://www.renesas.com/en/support/partners/preferred-partners?srsltid=AfmBOorrCxqebrLFfpvQdqk6jRMJQKghPEX0DBPq%5FYeXWJF3A54%5Fjl6z&ref=novelbits.io#find%5Fa%5Fpartner), [Wireless Communications Partners](https://www.renesas.com/en/products/wireless-connectivity/wireless-communications-partners?ref=novelbits.io) ### Automating Bluetooth LE Packet Analysis with RFcreations blueSPY URL: https://novelbits.io/bluetooth-le-packet-analysis-automation-bluespy-guide/ Last updated: 2026-02-19T06:13:28.000Z *Streamlining wireless debugging workflows with hardware-based sniffing and Python automation for automated Bluetooth LE packet analysis* ## Introduction: The Real Cost of Manual Debugging When developing Bluetooth LE products for production environments, every debugging session counts. Whether you're troubleshooting intermittent connection issues in medical devices, validating power consumption patterns in IoT sensors, or ensuring compliance with automotive standards, the traditional approach of manual packet analysis becomes a significant bottleneck in development workflows. Consider a typical debugging scenario: your team is investigating why Bluetooth LE devices randomly disconnect from mobile applications after 30-45 minutes of operation. Using manual debugging tools, an engineer might capture packets for hours, manually filter through thousands of entries, correlate timing relationships, and attempt to reproduce the issue multiple times. This process often takes days and requires deep expertise in Bluetooth protocols. The financial impact is substantial. Development teams can spend 30-40% of their time on wireless debugging activities. For a team of five engineers earning $150,000 annually, inefficient debugging processes cost organizations approximately $225,000 per year in lost productivity. More critically, delayed time-to-market in competitive industries like wearables or automotive can cost millions in lost revenue opportunities. [RFcreations' blueSPY (*the interface to RFcreations sniffers*)](https://novelbits.io/rfcreations) addresses these challenges through comprehensive automation capabilities. Unlike software-based sniffers that miss packets due to OS scheduling limitations, or basic hardware analyzers with limited scripting support, blueSPY combines professional-grade hardware with extensive Python and C APIs. This enables development teams to create sophisticated automated testing pipelines, continuous integration workflows, and comprehensive regression test suites. The system provides near-100% packet capture rates with nanosecond timing precision, supporting simultaneous capture of Bluetooth LE, Classic, 802.15.4, WiFi (timing-only), and proprietary protocols. Most importantly, its automation capabilities transform debugging from a manual, error-prone process into a systematic, repeatable engineering practice. Teams using blueSPY automation report a 60-70% reduction in debugging time and significantly improved product quality through comprehensive automated validation. ## Hardware vs Software Bluetooth Sniffers The choice between [hardware and software-based Bluetooth sniffers](https://novelbits.io/professional-ble-sniffer-vs-low-cost-sniffer-debugging/) fundamentally impacts debugging capabilities, especially for production-grade development. Understanding these differences is crucial for selecting the right toolchain for automated testing and continuous integration workflows. Software-based sniffers, including popular open-source solutions and mobile applications, operate by leveraging the host device's Bluetooth radio or are limited by operating on a single frequency within the Bluetooth LE spectrum. While convenient for basic protocol learning, these solutions face inherent limitations in production environments. The host operating system's scheduling priorities mean that critical timing information is lost, packets are dropped during high-traffic periods, and precise inter-frame spacing cannot be measured. Most critically, software sniffers cannot capture packets simultaneously on multiple advertising channels, missing crucial advertising and connection establishment sequences. These limitations become particularly problematic in automated testing scenarios. Software sniffers typically capture only 70-85% of actual air traffic, making them unsuitable for comprehensive protocol validation. They cannot reliably detect timing-sensitive issues, such as connection parameter violations, slave latency problems, or precise RSSI fluctuations that indicate RF performance issues. For teams implementing automated regression testing, these missing packets create false negatives that undermine confidence in test results. Hardware-based protocol analyzers address these fundamental limitations through dedicated RF circuitry and real-time processing capabilities. Professional systems like RFcreations' blueSPY employ purpose-built silicon designed specifically for protocol analysis. These systems achieve *near-*100% packet capture rates across all supported protocols, maintain nanosecond timing accuracy, and provide comprehensive visibility into RF characteristics, including RSSI, frequency errors, and spectrum occupancy. The automation advantages of hardware analyzers become evident in complex development scenarios. Consider validating Bluetooth LE Audio implementations where precise timing relationships between multiple audio streams are critical. Software sniffers cannot provide the timing accuracy needed to validate presentation delay requirements or detect subtle synchronization issues. Hardware analyzers like the RFcreations mini-moreph capture every packet with nanosecond precision, enabling automated validation of compliance with Bluetooth SIG specifications. Hardware analyzers also excel in multi-device testing scenarios. Production IoT deployments often involve dozens or hundreds of devices operating simultaneously. Software sniffers quickly become overwhelmed, dropping packets and losing critical protocol interactions. Hardware analyzers maintain full capture capability regardless of network density, enabling realistic production testing environments. The investment in hardware-based analysis tools pays dividends through reduced development cycles, improved product quality, and enhanced confidence in automated test results. While initial costs are higher than software alternatives, the productivity gains and reduced risk of field issues provide compelling return on investment for professional development teams. For organizations implementing DevOps practices in wireless development, hardware analyzers provide the reliability and comprehensiveness needed for continuous integration pipelines. Automated test suites can run overnight, validating protocol behavior across thousands of test scenarios with complete confidence that no critical issues are missed due to capture limitations. ## blueSPY Professional Capabilities and ROI RFcreations' blueSPY distinguishes itself in the professional protocol analyzer market through comprehensive automation APIs that transform debugging from reactive troubleshooting into proactive quality assurance. The system provides both Python and C APIs, enabling seamless integration into existing development toolchains and supporting diverse automation scenarios from simple capture scripts to sophisticated CI/CD pipelines. The Python API exposes blueSPY's full capture and analysis capabilities through intuitive interfaces. Development teams can create custom test frameworks that programmatically configure capture parameters, implement real-time packet filtering, extract protocol-specific metrics, and generate comprehensive test reports. This automation capability fundamentally changes how teams approach wireless debugging, shifting from manual investigation to systematic validation. Consider the power of automated regression testing: a single Python script can execute hundreds of test scenarios overnight, validating protocol compliance across different firmware versions, connection parameters, and RF environments. These automated tests catch regressions immediately, preventing bugs from reaching production, where they become exponentially more expensive to fix. Companies report finding 3-4x more bugs in development compared to manual testing approaches. The C API provides low-latency access for performance-critical applications, including real-time packet injection, custom protocol decoders, and integration with embedded test systems. This native performance enables sophisticated test scenarios like automated fuzzing, where millions of malformed packets test device robustness, or stress testing that validates behavior under extreme network conditions. The financial return on investment for blueSPY automation is compelling. Teams typically recoup hardware costs within 2-3 months through productivity gains alone. A comprehensive analysis of deployment metrics shows: - **Development Time Reduction**: 60-70% decrease in debugging cycles through automated capture and analysis - **Bug Detection Rate**: 3-4x more issues found in development vs. manual testing - **Field Issue Prevention**: 80% reduction in wireless-related customer complaints - **Time to Market**: 2-3 week acceleration in product release schedules - **Engineering Efficiency**: Single engineer can manage tests that previously required entire team Beyond direct cost savings, blueSPY automation enables new development practices impossible with manual approaches. Continuous wireless monitoring in production environments detects intermittent issues before customers report problems. Automated compliance validation ensures products meet certification requirements on first submission. Performance regression testing maintains quality across firmware updates without manual intervention. The comprehensive API documentation and example code library accelerate adoption. Teams can implement basic automation within days and sophisticated test frameworks within weeks. The active developer community shares scripts, best practices, and custom analysis tools, multiplying the value of the platform investment. For organizations serious about wireless product quality, blueSPY's automation capabilities represent a strategic advantage. The combination of hardware reliability, API comprehensiveness, and community support creates a platform that scales from prototype validation to production monitoring, providing consistent value throughout the product lifecycle. ## Hands-On Tutorial: Complete Code Walkthrough with `basic_capture.py` Let's dive into practical implementation with a complete Python automation example. This production-ready script demonstrates blueSPY's core capabilities while establishing patterns you can extend for your specific testing needs. ``` #!/usr/bin/env python3 """ blueSPY Basic Capture and Analysis Script Production-ready example demonstrating automated Bluetooth LE packet analysis """ import bluespy import time from datetime import datetime from collections import defaultdict def connect_to_bluespy(): """Establish connection to blueSPY hardware""" try: print("Connecting to blueSPY device...") bluespy.connect() # Auto-detects first available device print("✓ Connected to blueSPY") return True except bluespy.BluespyError as e: print(f"✗ Connection failed: {e}") return False ``` ### Initial Setup and Connection Management The connection phase uses blueSPY's auto-detection to find the first available device. The functional API approach provides simple, direct access to capture capabilities without unnecessary abstraction layers. The BluespyError exception handling ensures proper error reporting when hardware is unavailable or connection issues occur. ### Real-Time Capture and Analysis ``` def capture_and_analyze(duration_seconds=30, filename="capture_session.pcapng"): """Perform automated capture and post-analysis""" print(f"\n{'='*60}") print(f"Starting {duration_seconds}s capture at {datetime.now()}") print(f"Output file: {filename}") print(f"{'='*60}\n") try: # Start Bluetooth LE capture to file print("Starting capture...") bluespy.capture(filename, LE=True) # Capture for specified duration print(f"Capturing for {duration_seconds} seconds...") time.sleep(duration_seconds) # Stop capture bluespy.stop_capture() print(f"Capture complete. Total packets: {len(bluespy.packets)}") return True except bluespy.BluespyError as e: print(f"Capture error: {e}") return False ``` The capture workflow demonstrates blueSPY's file-based capture approach. Packets are captured to a pcapng file for comprehensive analysis, ensuring no data is lost during high-traffic periods. The LE=True parameter configures the hardware for Bluetooth LE capture across all advertising and data channels. The post-capture analysis provides complete visibility into all captured packets with nanosecond timing precision. ### Packet Type Distribution and Statistics ``` def analyze_packets(): """Analyze captured packets for statistics and patterns""" packet_types = defaultdict(int) rssi_values = [] channels_used = set() crc_failures = 0 device_addresses = set() for packet in bluespy.packets: # Extract packet type from summary if hasattr(packet, 'summary') and packet.summary: if "CRC fail" in packet.summary: crc_failures += 1 packet_type = "CRC_FAIL" else: packet_type = packet.summary.split()[0] packet_types[packet_type] += 1 # Collect RSSI values if hasattr(packet, 'rssi'): rssi_values.append(packet.rssi) # Track channels if hasattr(packet, 'channel'): channels_used.add(packet.channel) # Extract device addresses from summary if hasattr(packet, 'summary') and '(' in packet.summary and ')' in packet.summary: device_info = packet.summary.split('(')[1].split(')')[0] device_addresses.add(device_info) return packet_types, rssi_values, channels_used, crc_failures, device_addresses ``` Common Bluetooth LE packet types and their significance: | Packet Type | Description | Typical Frequency | Debugging Value | | ----------------- | ------------------------ | ----------------- | ----------------------- | | ADV\_IND | Connectable advertising | 20-100/sec | Device discovery issues | | ADV\_NONCONN\_IND | Non-connectable beacon | 1-10/sec | Beacon validation | | SCAN\_REQ/RSP | Active scanning | Variable | Scanner behavior | | CONNECT\_IND | Connection establishment | On connect | Connection parameters | | LL\_DATA\_PDU | Data transfer | 100-1000/sec | Throughput analysis | | LL\_CONTROL | Link control | 10-50/sec | Connection management | ### Generate Analysis Report ``` def generate_report(packet_types, rssi_values, channels_used, crc_failures, device_addresses): """Generate comprehensive analysis report""" total_packets = len(bluespy.packets) print(f"\n{'='*60}") print("CAPTURE ANALYSIS REPORT") print(f"{'='*60}") print(f"Total Packets: {total_packets:,}") print(f"CRC Errors: {crc_failures} ({crc_failures/total_packets*100:.2f}%)") # Packet type distribution print("\nPacket Type Distribution:") for ptype, count in sorted(packet_types.items(), key=lambda x: x[1], reverse=True)[:10]: percentage = (count / total_packets) * 100 print(f" {ptype:20} {count:8} ({percentage:5.1f}%)") # RSSI analysis if rssi_values: avg_rssi = sum(rssi_values) / len(rssi_values) print(f"\nRSSI Statistics:") print(f" Average: {avg_rssi:.1f} dBm") print(f" Min/Max: {min(rssi_values)}/{max(rssi_values)} dBm") print(f" Range: {max(rssi_values) - min(rssi_values)} dB") # Channel usage print(f"\nChannel Usage:") print(f" Channels used: {sorted(channels_used)}") print(f" Total unique channels: {len(channels_used)}") # Detected devices if device_addresses: print(f"\nDetected Devices/Manufacturers:") for device in sorted(device_addresses)[:10]: print(f" • {device}") ``` ### Complete Implementation Example ``` def main(): """Example usage demonstrating complete workflow""" try: # Connect to blueSPY if not connect_to_bluespy(): return # Perform capture duration = 30 filename = f"capture_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pcapng" if capture_and_analyze(duration, filename): # Analyze the captured packets packet_types, rssi_values, channels_used, crc_failures, device_addresses = analyze_packets() # Generate report generate_report(packet_types, rssi_values, channels_used, crc_failures, device_addresses) # Display first few packets as examples print(f"\n{'='*60}") print("SAMPLE PACKETS") print(f"{'='*60}") for i in range(min(5, len(bluespy.packets))): packet = bluespy.packets[i] print(f"\nPacket {i+1}: {packet.summary}") if hasattr(packet, 'rssi'): print(f" RSSI: {packet.rssi} dBm") if hasattr(packet, 'channel'): print(f" Channel: {packet.channel}") except bluespy.BluespyError as e: print(f"Error: {e}") finally: # Always cleanup bluespy.close_file() bluespy.disconnect() print("\nSession completed") if __name__ == "__main__": main() ``` This implementation demonstrates the actual blueSPY Python API, providing a solid foundation for automation. The functional design follows Python best practices, making it easy to integrate into larger test frameworks, CI/CD pipelines, or custom analysis tools. The file-based capture approach ensures reliable data collection even during high-traffic scenarios. ![](https://downloads.novelbits.io/media/posts/bluetooth-le-packet-analysis-automation-bluespy-guide/blueSPY_Basic_Capture_Demo-2.gif) **Demo: blueSPY Basic Capture for 10 seconds** ## Advanced Use Cases: CI/CD, Security, and Testing ### Continuous Integration and Deployment (CI/CD) Modern wireless development demands automated validation at every code commit. blueSPY integrates seamlessly into CI/CD pipelines, providing automated protocol compliance checking, regression testing, and performance validation. Jenkins, GitLab CI, and GitHub Actions can trigger blueSPY test suites, ensuring wireless functionality remains stable across firmware iterations. ### Security and Compliance Monitoring blueSPY's comprehensive packet capture enables automated security auditing and compliance validation. Organizations can continuously monitor for: - **Unencrypted data transmission** in production devices - **Weak pairing methods** that expose devices to MITM attacks - **Protocol violations** that could indicate security vulnerabilities - **Unauthorized device connections** in secure environments - **Compliance with GDPR** and data protection regulations Automated security scanning with blueSPY has identified critical vulnerabilities in production devices before public disclosure, preventing costly recalls and reputation damage. ### Performance Optimization Key performance metrics for automated monitoring: - **Connection interval optimization**: Validate power/latency tradeoffs - **Data throughput analysis**: Ensure maximum utilization of link capacity - **Latency profiling**: Measure end-to-end packet delivery times - **Power consumption correlation**: Link RF activity to current draw - **Interference detection**: Identify and mitigate RF environment issues ## Implementation Best Practices ### Error Handling and Recovery Production automation requires robust error handling. Common failure scenarios and recovery strategies: - **Hardware disconnection**: Implement automatic reconnection with exponential backoff - **Buffer overflow**: Monitor capture buffer utilization and implement flow control - **Corrupted packets**: Validate packet structure before processing - **Resource exhaustion**: Implement memory limits and cleanup routines ### Configuration Management Store test configurations in version-controlled YAML files for reproducibility: ``` capture_config: duration: 30 channels: [37, 38, 39] rssi_threshold: -80 filters: - type: address value: "AA:BB:CC:DD:EE:FF" - type: packet_type value: ["ADV_IND", "SCAN_REQ"] ``` ### Performance Considerations - **Batch processing**: Process packets in groups to reduce overhead - **Selective capture**: Use hardware filtering to reduce data volume - **Parallel analysis**: Utilize multiprocessing for CPU-intensive analysis - **Data compression**: Compress capture files for long-term storage - **Memory management**: Stream large captures to disk rather than memory ## Conclusion: Transforming Wireless Development Through Automation blueSPY automation fundamentally transforms how development teams approach Bluetooth LE debugging and validation. By replacing manual, error-prone processes with systematic, repeatable automation, teams achieve higher quality products, faster development cycles, and significant cost savings. The combination of professional-grade hardware capture capabilities and comprehensive automation APIs enables new development practices previously impossible with manual approaches. Continuous protocol monitoring, automated regression testing, and systematic security validation become routine rather than exceptional. Organizations implementing blueSPY automation report transformative results: 60-70% reduction in debugging time, 3-4x improvement in bug detection rates, and 80% fewer field issues. These metrics translate directly to competitive advantage in markets where wireless reliability determines product success. The future of wireless development lies in automation. As Bluetooth LE applications grow more complex, manual debugging becomes increasingly untenable. blueSPY provides the foundation for this transformation, offering professional teams the tools needed to deliver exceptional wireless products efficiently and reliably. 🛠️ **Ready to automate your Bluetooth LE debugging?** RFcreations' blueSPY and mini-moreph sniffers can reduce your debugging time by 60-70% with professional-grade packet capture and Python automation. [Learn more and book a demo](https://novelbits.io/rfcreations). ### Understanding nRF Connect SDK Bare Metal: A Comprehensive Guide to Lightweight Bluetooth Development URL: https://novelbits.io/nrf-connect-sdk-bare-metal-guide/ Last updated: 2026-04-08T17:50:55.000Z ## Introduction Picture this: you're designing a tiny Bluetooth temperature sensor that needs to run for years on a coin cell battery. You've got 256KB of RAM to work with, and every microamp of current draw matters. Do you really need a full Real-Time Operating System with thread scheduling, memory management, and all the bells and whistles? Or would you be better served by something leaner, meaner, and more predictable? This is the exact scenario that led Nordic Semiconductor to create the nRF Connect SDK Bare Metal—a streamlined alternative to their standard RTOS-based SDK. It's a recognition that sometimes, less really is more. In this comprehensive guide, we'll explore what makes bare metal development different, when it makes sense to choose it over a full RTOS, and how to make the most of this powerful approach to embedded development. Whether you're a battle-scarred veteran of the nRF5 SDK looking for a familiar programming model in the modern world, or a developer trying to squeeze every last drop of performance from your BLE application, this guide will help you understand if bare metal is the right choice for your next project. ## What is Bare Metal Programming? The term "bare metal" might conjure images of exposed circuit boards and manual bit manipulation, but the reality is both simpler and more nuanced. At its core, bare metal programming means writing code that runs directly on the hardware without an operating system acting as an intermediary. Your code is in direct conversation with the processor and peripherals, with nothing standing between your instructions and their execution. Think of it like the difference between driving an automatic and a manual transmission car. With an RTOS (the automatic), you tell the system what you want to do, and it handles the complexity of making it happen. With bare metal (the manual), you have direct control over every gear shift, every clutch engagement. This direct control can be more efficient and predictable, but it also means you're responsible for not stalling the engine. ### The Traditional Embedded Development Spectrum To understand where nRF Connect SDK Bare Metal fits in the embedded development landscape, imagine a spectrum of abstraction levels. At one end, you have full operating systems like Linux or Android, running on powerful processors with gigabytes of RAM. These systems provide rich functionality but come with significant overhead. Moving along the spectrum, you encounter Real-Time Operating Systems like FreeRTOS, Zephyr, or ThreadX. These are designed specifically for embedded systems, offering task scheduling and resource management while maintaining reasonable resource usage. They're the sweet spot for many complex embedded applications. Further along, we find bare metal programming with libraries—this is where nRF Connect SDK Bare Metal lives. You're working directly with the hardware, but you still have access to well-tested libraries for common tasks. It's like cooking from scratch but still using pre-made spice blends. At the far end of the spectrum is pure bare metal programming: direct register manipulation with no abstractions whatsoever. This approach is rarely necessary in modern development unless you're doing something truly exotic or working with bleeding-edge silicon. ### Why Bare Metal for Bluetooth LE? Here's where things get interesting. Bluetooth LE was designed from the ground up for low-power, simple devices. The protocol itself is event-driven: advertisements go out, connections come in, data gets exchanged, and then devices go back to sleep. This natural rhythm aligns perfectly with bare metal's event-driven programming model. Consider a typical BLE peripheral device like a heart rate monitor. Its life consists of long periods of sleep punctuated by brief moments of activity: read sensor, update characteristic value, notify connected device, go back to sleep. This pattern doesn't need complex thread scheduling or priority management. In fact, adding an RTOS to such a simple flow pattern is like using a sledgehammer to crack a nut—it works, but it's overkill. The advantages of bare metal for BLE applications go beyond just philosophical alignment. When you remove the RTOS layer, you eliminate kernel overhead, thread stacks, and scheduling delays. Memory that would have been consumed by OS structures becomes available for your application. Power consumption drops because there's no idle thread spinning in the background. Interrupt response times become more predictable because there's no scheduler deciding whether your interrupt handler should run now or after the current thread's time slice expires. ## The nRF Connect SDK Architecture To truly appreciate what makes the Bare Metal variant special, we need to understand how the standard nRF Connect SDK is structured. It's a bit like understanding the architecture of a modern apartment building before appreciating the elegance of a tiny house. ### Standard nRF Connect SDK The standard nRF Connect SDK is built on top of Zephyr RTOS, which is itself a fascinating piece of engineering. Zephyr is to embedded systems what a Swiss Army knife is to tools—incredibly versatile and packed with features. When you build an application with the standard SDK, you're getting a full technology stack that looks something like this: ![Standard nRF Connect SDK architecture stack](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/diagram-standard-sdk-1.png) Standard nRF Connect SDK Architecture This layered approach brings tremendous power to your fingertips. The Zephyr kernel provides preemptive multithreading, allowing you to structure your application as multiple independent tasks that appear to run simultaneously. Device drivers offer a unified API for hardware peripherals, meaning your GPIO code can work across different Nordic chips with minimal changes. The network stacks support not just Bluetooth, but also Thread, Zigbee, and other protocols. You even get file system support if you need to store configuration data or logs. All of this functionality is fantastic when you need it. But here's the thing—what if you don't? What if your application is a simple temperature sensor that wakes up every minute, takes a reading, and goes back to sleep? In that case, you're carrying around a lot of baggage you'll never use, and that baggage costs you in terms of RAM, flash, and power consumption. ### nRF Connect SDK Bare Metal This is where the Bare Metal variant comes in. Nordic's engineers asked themselves: what if we could keep all the good parts of the modern nRF Connect SDK—the build system, the hardware abstraction layer, the battle-tested Bluetooth stack—while stripping away the complexity of the RTOS? The result is an architecture that looks more like this: ![nRF Connect SDK Bare Metal architecture stack](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/diagram-bare-metal-1.png) nRF Connect SDK Bare Metal Architecture The magic happens with a simple configuration change: `CONFIG_KERNEL=n`. This single line transforms your Zephyr application into a bare-metal powerhouse, stripping away the RTOS kernel while keeping all the peripheral drivers and hardware abstraction layers you need. The SoftDevice deserves special mention here. It's Nordic's proprietary Bluetooth stack that has been refined over many years and millions of deployed devices. By using the SoftDevice in bare metal mode, you get all the benefits of a proven, certified Bluetooth implementation without the overhead of an RTOS. The SoftDevice handles all the complex timing requirements of the Bluetooth protocol, leaving your application code to focus on business logic. ## Deep Dive: Technical Differences Now let's roll up our sleeves and examine what really changes when you flip that CONFIG\_KERNEL switch. The differences go far deeper than just removing a few kilobytes of kernel code. ### Memory Management Memory is often the scarcest resource in embedded systems, and how you manage it can make or break your project. In the standard SDK, memory management follows a familiar pattern if you've worked with any RTOS. The kernel maintains its own data structures for managing threads, semaphores, mutexes, and other synchronization primitives. Each thread gets its own stack, sized according to its needs (or your best guess at its needs). The main thread might use 2KB, your Bluetooth handling thread another 4KB, and various system threads consume their own allocations. All told, before your application even starts doing useful work, you've committed somewhere around 40KB of RAM just to infrastructure. On a high-end nRF chip with megabytes of RAM, this might be a rounding error. But on a cost-optimized part with 256KB total, you've just spent 15% of your budget on overhead. The bare metal approach takes a radically different view. There's only one stack because there's only one thread of execution. The kernel data structures? Gone. Thread stacks? Not needed. Memory protection units? Optional, but usually disabled for simplicity. The result is dramatic: that same "hello world" BLE peripheral that needed 40-50KB in the standard SDK runs happily in 20-25KB with bare metal. But this efficiency comes with responsibility. In the RTOS world, if you overflow a thread's stack, the kernel might catch it (especially with MPU enabled). In bare metal, a stack overflow means you're writing into whatever happens to be next in memory, leading to mysterious crashes that only happen on Tuesdays when the moon is full. You need to be more careful about stack usage, more deliberate about memory allocation, and more paranoid about buffer overflows. ### Execution Model The execution model is where the philosophical differences between RTOS and bare metal become most apparent. In the standard SDK, you think in terms of tasks and threads. Your application might have a main thread handling user interface, a sensor thread periodically reading data, and a Bluetooth thread managing connections. Each thread has its own priority, its own stack, and its own illusion of running independently. ```c // Multiple threads with different priorities void main_thread(void) { while (1) { process_user_input(); k_sleep(K_MSEC(100)); } } void sensor_thread(void) { while (1) { read_sensor_data(); k_sem_give(&data_ready); k_sleep(K_SECONDS(1)); } } void ble_thread(void) { while (1) { k_sem_take(&data_ready, K_FOREVER); send_ble_notification(); } } ``` This multi-threaded approach is intuitive if you're coming from desktop or server programming. Each thread handles one concern, communication happens through well-defined mechanisms like semaphores, and the kernel ensures everyone gets their fair share of CPU time. It's elegant, it scales well to complex applications, and it's relatively easy to reason about—until it isn't. The bare metal approach throws all of this out the window in favor of a simpler model: one thread, one loop, handle events as they come. Your entire application becomes a state machine that responds to stimuli: ```c // Single execution context with event handling int main(void) { initialize_system(); while (1) { // Process any pending log messages LOG_PROCESS(); // Handle events if (sensor_data_ready) { process_sensor_data(); queue_ble_notification(); sensor_data_ready = false; } if (ble_event_pending) { handle_ble_event(); ble_event_pending = false; } // Sleep until next event __WFE(); } } ``` At first glance, this might seem primitive—and in a way, it is. But this simplicity brings powerful benefits. There's no context switching overhead because there's only one context. There are no priority inversions because there are no priorities. There's no risk of deadlock because there are no locks. The flow of execution is completely predictable: events happen, you handle them, you go to sleep. The \_\_WFE() instruction at the bottom of the loop is particularly important. This ARM instruction (Wait For Event) puts the processor into a low-power state until an interrupt occurs. Unlike a busy-wait loop that burns power checking flags, WFE allows the processor to essentially shut down until something interesting happens. This is the secret sauce that enables bare metal applications to achieve such impressive power consumption figures. ### Interrupt Handling Interrupt handling is where bare metal really shines—or where it can really bite you, depending on your perspective. In the standard SDK, interrupts travel through several layers of abstraction. When a GPIO pin changes state or a timer expires, the hardware generates an interrupt that's caught by Zephyr's interrupt handling framework. This framework does important bookkeeping: saving context, potentially waking threads, and deciding if a reschedule is needed. All of this takes time—typically 2-5 microseconds from interrupt assertion to your handler running. For many applications, a few microseconds of latency doesn't matter. But what if you're implementing a custom protocol that needs to respond within a microsecond? What if you're bit-banging a communication interface? What if you're building a motor controller where those extra microseconds mean the difference between smooth operation and jerky movement? Bare metal gives you direct access to the interrupt vectors. When you enable CONFIG\_ZERO\_LATENCY\_IRQS, your interrupt handlers run immediately, with no framework overhead. We're talking 12-20 CPU cycles from interrupt assertion to the first instruction of your handler—that's under 200 nanoseconds on a 64MHz processor. It's the difference between a sports car and a rocket ship. But with great power comes great responsibility. In the RTOS world, you can do quite a bit in an interrupt handler because the kernel will clean up after you. In bare metal, your interrupt handler needs to be lean and mean. Get in, do the absolute minimum necessary, set a flag for the main loop to handle the rest, and get out. Spending too long in an interrupt handler can cause you to miss other interrupts or interfere with the SoftDevice's critical timing. ### Bluetooth Implementation The approach to Bluetooth programming reveals another fundamental difference in philosophy between the two SDKs. The standard SDK uses Zephyr's Bluetooth API, which provides a high-level, portable interface to Bluetooth functionality. It's designed to work across different Bluetooth controllers and even different hardware platforms: ```c // Zephyr Bluetooth API static void connected(struct bt_conn *conn, uint8_t err) { if (err) { LOG_ERR("Connection failed (err 0x%02x)", err); } else { LOG_INF("Connected"); } } static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, }; int main(void) { bt_enable(NULL); bt_conn_cb_register(&conn_callbacks); bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); return 0; } ``` This code is clean, readable, and portable. The callback-based architecture is familiar to anyone who's done event-driven programming. The API abstracts away the details of how Bluetooth actually works, letting you focus on your application logic. The bare metal approach uses Nordic's SoftDevice API directly, which is more verbose but also more explicit about what's happening: ```c // SoftDevice event-driven API static void on_ble_evt(ble_evt_t const *p_ble_evt) { switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; LOG_INF("Connected"); break; case BLE_GAP_EVT_DISCONNECTED: m_conn_handle = BLE_CONN_HANDLE_INVALID; LOG_INF("Disconnected"); start_advertising(); break; default: break; } } int main(void) { softdevice_init(); ble_stack_init(); gap_params_init(); services_init(); advertising_init(); start_advertising(); while (true) { LOG_PROCESS(); softdevice_evt_get_and_dispatch(); power_manage(); } } ``` At first glance, this might seem like a step backward. The event handling is more manual, the initialization is more explicit, and you're dealing with lower-level concepts like connection handles. But this explicitness is actually a feature, not a bug. You know exactly when events are processed (when you call softdevice\_evt\_get\_and\_dispatch), you have direct control over power management, and there's no hidden magic happening behind the scenes. For developers coming from the nRF5 SDK, this pattern will feel like coming home. It's the same event-driven model they've been using for years, just with updated APIs for the newer chips. ## Real-World Use Cases and Examples Theory is all well and good, but let's talk about real devices that you might find in your pocket, on your wrist, or mounted on industrial equipment. Understanding these practical examples will help you recognize which approach fits your next project. ### Ideal Bare Metal Use Cases Let me paint you a picture of where bare metal truly excels. Imagine you're designing a temperature sensor for a cold chain logistics company. This sensor needs to sit in a shipping container for months, waking up every few minutes to check if the vaccines or food products are still at the right temperature. When it detects a problem, it needs to immediately broadcast an alert via BLE to any nearby smartphones or gateways. This is bare metal's sweet spot. The device spends 99.9% of its time sleeping, wakes up just long enough to read a sensor and make a decision, then goes back to sleep. There's no need for multiple threads because nothing happens concurrently. The entire application logic fits in a simple state machine: sleep, wake, measure, decide, potentially advertise, sleep again. With bare metal, this device might run for two years on a coin cell. With a full RTOS, you'd be lucky to get 18 months. Or consider the humble BLE beacon—those little devices that retailers use to send you coupons when you walk past the shoe department. A beacon does exactly one thing: broadcast a UUID at regular intervals. That's it. No connections, no data exchange, no complex logic. Implementing this with a full RTOS is like hiring a symphony orchestra to play "Happy Birthday"—technically correct but absurdly overwrought. Bare metal lets you implement a beacon in a few hundred lines of code that will run for years on a tiny battery. Fitness trackers represent another perfect use case. The basic ones that count steps and monitor heart rate follow a predictable pattern: sample accelerometer at 50Hz, run step detection algorithm, update count, occasionally sync with phone. The heart rate measurement happens on demand when the user checks their wrist. Everything is event-driven: accelerometer interrupt triggers step counting, button press triggers heart rate measurement, BLE connection event triggers data sync. The bare metal model maps perfectly to this flow. Industrial sensors often choose bare metal for a different reason: simplicity equals reliability. When you're monitoring vibration on a critical pump in a chemical plant, you don't want your sensor crashing because of a priority inversion or stack overflow in some auxiliary thread. You want dead-simple code that does one thing well and never fails. Bare metal's straightforward execution model makes it easier to analyze, test, and validate. ### When to Choose Standard nRF Connect SDK Now let's flip the script and talk about when you absolutely need the full power of the standard SDK. Consider an IoT gateway that bridges between BLE devices and the cloud. This device might be managing connections to dozens of BLE sensors while simultaneously maintaining a cellular or Wi-Fi connection to the internet. It needs to buffer data when the network is down, manage a local web server for configuration, and handle firmware updates for both itself and the connected sensors. This is where an RTOS shines. You've got genuinely concurrent activities that need different priorities and resources. The thread handling cellular communications can't block the thread processing BLE events. The web server needs to respond to requests while data logging continues in the background. Trying to implement this in a single event loop would be like juggling chainsaws—theoretically possible but practically inadvisable. Modern smartwatches push the envelope even further. They're running multiple sensors continuously: accelerometer for activity tracking, heart rate monitor for health metrics, GPS for run tracking, and maybe even an SpO2 sensor. They're displaying rich graphics on an OLED screen, handling touch input, managing music playback, and syncing with a phone. Oh, and users expect the battery to last at least a day or two. This level of complexity demands an RTOS. You need separate threads for sensor fusion, UI rendering, and communication. You need priority scheduling to ensure the UI stays responsive even when the GPS is working hard to get a fix. You need the sophisticated power management that comes with an RTOS to selectively shut down subsystems when they're not needed. Medical devices often require an RTOS not just for technical reasons but for regulatory ones. When you're building a continuous glucose monitor, you need to guarantee that critical alerts are delivered within a specific timeframe. You need extensive logging for FDA compliance. You need redundancy and error recovery mechanisms. The RTOS provides the infrastructure to build these safety-critical features with confidence. BLE Mesh networks represent another clear win for the full SDK. In a mesh network, your device isn't just a simple peripheral—it's a router, forwarding messages for other nodes. It needs to maintain routing tables, handle message queuing, and manage multiple simultaneous connections. The complexity ramps up quickly, and trying to handle it all in a single event loop would be a nightmare. ## Migration Strategies If you're reading this guide, chances are you're in one of two camps: either you're maintaining a product built with the legacy nRF5 SDK and wondering about the migration path, or you're starting a fresh project and trying to decide which approach to take. Let's address both scenarios. ### Migrating from nRF5 SDK to Bare Metal For those of you who've been in the Nordic ecosystem for a while, the nRF5 SDK feels like an old friend. You know its quirks, you've memorized its APIs, and you've probably got a collection of battle-tested code that's been shipping in products for years. The good news is that the Bare Metal variant of nRF Connect SDK was designed with you in mind. The programming model will feel instantly familiar. You've still got your main loop with event processing. The SoftDevice is still there, handling all the complex Bluetooth timing. You're still working directly with the hardware through Nordic's HAL. In many ways, it's like the nRF5 SDK grew up, went to college, and came back with some new ideas but the same fundamental personality. But there are differences, and pretending otherwise would be disingenuous. The biggest shock will be the build system. Gone are the days of Makefiles and sdk\_config.h. In their place, you'll find CMake and West (Zephyr's meta-tool for managing repositories) along with Kconfig for configuration and Devicetree for hardware description. If those terms make you nervous, take a deep breath—they're not as scary as they sound. Here's the migration path that's worked well for teams I've helped: First, get comfortable with the new build system. Don't try to port your entire application on day one. Instead, create a simple "hello world" BLE peripheral using the bare metal SDK. Get it building, get it running on your development board, and get familiar with the workflow. The commands look like this: west init -m https://github.com/nrfconnect/sdk-nrf-bm west update Once you're comfortable with the basics, start porting your peripheral drivers. The good news is that the underlying hardware hasn't changed—a GPIO is still a GPIO. The APIs have evolved, but the concepts map directly. Your nrf\_drv\_gpiote\_in\_config becomes nrf\_gpio\_cfg\_input, but it's doing the same thing under the hood. The SoftDevice migration is surprisingly smooth. Nordic has maintained API compatibility where it makes sense, so your BLE event handlers will need only minor tweaks. The biggest changes are in the initialization sequence and some of the configuration structures, but your core application logic can remain largely intact. The modern build system actually becomes an asset once you embrace it. Kconfig gives you a cleaner way to manage feature flags than the old sdk\_config.h. Devicetree provides a standardized way to describe your hardware that's more maintainable than scattered #defines. And CMake, for all its complexity, is more powerful and flexible than Make once you climb the learning curve. ### Starting Fresh with Bare Metal If you're starting a new project, you have the luxury of doing things right from the beginning. Here's the approach I recommend, learned from both successes and painful failures: Start by thinking about your application as a state machine. What states can your device be in? What events cause transitions between states? This mental model maps perfectly to bare metal's event-driven architecture. Draw it out on a whiteboard, argue about it with your team, and get it right before you write a single line of code. Memory planning might seem premature when you're just starting, but it's crucial for bare metal development. Make a spreadsheet. Budget RAM for your application data, your stack, the SoftDevice, and leave a healthy margin for the things you haven't thought of yet. It's much easier to optimize memory usage from the start than to frantically search for bytes when you're running out. Power optimization isn't something you bolt on at the end—it needs to be part of your architecture from day one. Every decision should be viewed through the lens of power consumption. Do you really need to sample that sensor every second, or would every five seconds work? Can you batch your BLE notifications to reduce radio on-time? Can you use the peripheral's hardware features like PPI (Programmable Peripheral Interconnect) to handle routine tasks without waking the CPU? Your testing strategy for bare metal needs to be different too. Without an RTOS to catch your mistakes, you need to be more rigorous. Unit test your business logic separately from your hardware interactions. Implement defensive programming practices—check your inputs, validate your assumptions, and always have a plan for when things go wrong. Because in embedded development, things always go wrong, usually at 3 AM in a customer's deployment. ## Performance Considerations Numbers don't lie, so let's look at the hard data. But more importantly, let's understand what these numbers mean for your product. ### Latency Analysis Interrupt latency is one of those specifications that doesn't matter until it really, really matters. In the standard SDK, when a hardware event triggers an interrupt, your code doesn't run immediately. First, the processor has to save its current context. Then Zephyr's interrupt handling framework kicks in, doing its bookkeeping. It might need to wake a thread, which triggers the scheduler, which needs to decide if a context switch is necessary. By the time your interrupt handler actually runs, you're looking at 100-300 CPU cycles—about 2-5 microseconds on a typical 64MHz processor. For most applications, 5 microseconds is nothing. Humans can't perceive anything that fast. Even most sensors and communication protocols are perfectly happy with that response time. But what if you're not "most applications"? Imagine you're implementing a custom protocol that bit-bangs data over GPIO. At 1 Mbps, each bit is only 1 microsecond wide. A 5-microsecond interrupt latency means you've missed five bits before your handler even starts. Game over. Or consider a motor control application where you're implementing field-oriented control. The difference between 200 nanoseconds and 5 microseconds of interrupt latency might be the difference between smooth, efficient operation and a motor that sounds like it's grinding coffee beans. Bare metal's zero-latency interrupts change the game. We're talking 12-20 CPU cycles from interrupt assertion to your handler running. At 64MHz, that's about 200 nanoseconds. Your interrupt handler can respond to events almost as fast as dedicated hardware. This opens up possibilities that simply aren't feasible with an RTOS. ### Power Consumption Profiles Power consumption in embedded systems is like compound interest—small differences add up over time. Let's look at a realistic example: a temperature sensor that wakes up every minute to take a reading. With bare metal, the device draws about 1.5μA in deep sleep mode using the WFE (Wait For Event) instruction. When it wakes up, it draws 5mA for about 100 milliseconds to read the sensor, process the data, and potentially send a BLE advertisement. The math works out to: - Sleep current: 1.5μA for 59.9 seconds = 89.85μA·s - Active current: 5mA for 0.1 seconds = 500μA·s - Average current: (89.85 + 500) / 60 = 9.83μA With the standard SDK, idle current is higher—about 3μA—because the kernel is maintaining timer queues and other data structures even when all threads are sleeping. Same active current and duration: - Sleep current: 3μA for 59.9 seconds = 179.7μA·s - Active current: 5mA for 0.1 seconds = 500μA·s - Average current: (179.7 + 500) / 60 = 11.33μA That's only a 1.5μA difference, which might not seem like much. But let's see what it means for battery life. With a typical CR2032 coin cell (230mAh capacity): - Bare Metal: 230mAh / 9.83μA = 23,400 hours = 2.67 years - Standard SDK: 230mAh / 11.33μA = 20,300 hours = 2.32 years That's four months of additional battery life—the difference between a product that lasts "over two years" versus one that dies just before the two-year mark. In consumer products, that distinction matters. ### Code Size Comparison Flash memory might be cheap, but it's not free. Every kilobyte of flash adds to your bill of materials, and in high-volume products, those pennies add up to real money. Plus, smaller code often means faster execution and lower power consumption during flash reads. Here's what I've seen in real-world applications: A minimal BLE peripheral (think a simple sensor that advertises data) implemented in bare metal typically compiles to about 120KB of flash and uses 20KB of RAM. The same functionality with the standard SDK comes in around 150KB flash and 40KB RAM. That's 25% more flash and 100% more RAM for essentially the same functionality. The gap narrows as applications get more complex. A sophisticated BLE central device (like a gateway that connects to multiple peripherals) might be 180KB/35KB in bare metal versus 220KB/60KB with the full SDK. The overhead becomes a smaller percentage of the total. But here's the thing: most BLE devices aren't sophisticated gateways. They're simple sensors, beacons, and peripherals where every byte counts. If you can fit your application in a chip with 256KB flash instead of 512KB, or 64KB RAM instead of 128KB, you've just saved significant money on every unit you manufacture. ## Advanced Topics Now let's venture into the deep end of the pool—the advanced techniques that separate good bare metal developers from great ones. ### Bare Metal with SoftDevice Optimization The SoftDevice is Nordic's secret weapon, and learning to work with it rather than against it is key to building efficient BLE applications. Think of the SoftDevice as a very specialized coprocessor that handles all the time-critical aspects of Bluetooth. Your job is to stay out of its way while still getting your work done. Connection parameters are your first lever for optimization. Most developers just copy-paste connection parameters from examples without understanding their impact. But these parameters fundamentally determine your power consumption and latency trade-offs: // Optimize for power with longer connection intervals static ble\_gap\_conn\_params\_t const conn\_params = { .min\_conn\_interval = MSEC\_TO\_UNITS(100, UNIT\_1\_25\_MS), .max\_conn\_interval = MSEC\_TO\_UNITS(200, UNIT\_1\_25\_MS), .slave\_latency = 4, .conn\_sup\_timeout = MSEC\_TO\_UNITS(4000, UNIT\_10\_MS) }; What do these numbers mean? The connection interval determines how often the devices talk to each other. At 100-200ms intervals with slave latency of 4, your device only needs to wake up every 400-800ms if there's no data to exchange. That's the difference between waking up 100 times per minute and waking up 7 times per minute. Your battery will thank you. The Radio Notification API is a lesser-known feature that can be a game-changer for certain applications. It lets you know when the radio is about to be used: ```c // Get notified before radio events for time-critical operations sd_radio_notification_cfg_set( NRF_RADIO_NOTIFICATION_TYPE_INT_ON_ACTIVE, NRF_RADIO_NOTIFICATION_DISTANCE_800US ); ``` Why would you want this? Imagine you're sampling an analog sensor that's sensitive to radio interference. By getting notified 800 microseconds before radio activity, you can pause your sampling, avoiding noisy readings. Or maybe you have a time-critical operation that can't be interrupted—schedule it between radio events. Even more advanced is the timeslot API, which lets you run proprietary protocols alongside BLE. Yes, even in bare metal, you can have your device speaking BLE to smartphones while simultaneously running a custom 2.4GHz protocol to talk to your proprietary sensors. The SoftDevice handles the complex scheduling, ensuring both protocols get their fair share of radio time without stepping on each other. ### Debugging Bare Metal Applications Debugging bare metal applications is an art form. Without an RTOS to provide nice stack traces and thread information, you need to be more creative. But the constraints of bare metal often lead to better debugging practices. First, let's talk about logging. In the RTOS world, you might be tempted to sprinkle printf statements everywhere. In bare metal, that's a recipe for disaster. Printf is blocking, uses tons of stack space, and can completely change your application's timing. Instead, use Nordic's deferred logging system: // Lightweight logging that doesn't block LOG\_INF("Sensor value: %d", reading); // Processes in main loop, not interrupt context This logging system buffers messages in a ring buffer and processes them in your main loop when there's time. It's the difference between your interrupt handler taking 10 microseconds versus 10 milliseconds. Hardware breakpoints become more critical in bare metal because software breakpoints can disturb timing-sensitive code. But use them sparingly: // Use hardware breakpoints sparingly \_\_BKPT(0); // Breakpoint with immediate value Most ARM cores have only 4-6 hardware breakpoints. Use them wisely on the truly mysterious bugs, not for routine debugging. My favorite bare metal debugging technique is what I call "GPIO debugging." It's primitive but incredibly effective: // Toggle pins to measure timing nrf\_gpio\_pin\_set(DEBUG\_PIN); critical\_function(); nrf\_gpio\_pin\_clear(DEBUG\_PIN); // Measure with oscilloscope Hook up an oscilloscope or logic analyzer, and you can see exactly how long functions take, when interrupts fire, and where your code is spending its time. It's like having X-ray vision into your application's behavior. Plus, unlike printf debugging, it has minimal impact on your code's timing. ## Common Pitfalls and How to Avoid Them Let me share some war stories—the kinds of bugs that will have you questioning your career choices at 2 AM. These are the pitfalls I've seen talented developers fall into, and more importantly, how to avoid them. ### 1\. Stack Overflow In the RTOS world, each thread has its own stack, and if you're lucky, the kernel might even detect overflows for you. In bare metal, you have one stack for everything, and when it overflows, you're writing into random memory. The symptoms are bizarre: variables that change mysteriously, functions that work fine until you add one more local variable, crashes that only happen when certain combinations of functions are called. I once spent three days debugging a device that would crash, but only when it received a BLE connection while processing sensor data during a timer interrupt. The root cause? The combined stack usage of nested interrupts was exceeding our allocated stack space by exactly 8 bytes. Those 8 bytes happened to contain a critical pointer, and corruption led to a crash minutes later in completely unrelated code. The solution is disciplined stack management. First, calculate your worst-case stack usage analytically. Add up your deepest function call chain, factor in local variables, and don't forget interrupt nesting. Then add 25% margin because your analysis will miss something. During development, use stack painting—fill your stack with a known pattern at startup, then periodically check how much has been overwritten. It's like a high-water mark for your stack usage. And always, always leave margin for the unexpected. ### 2\. Event Queue Overflow Without an OS managing your queues, it's easy to design yourself into a corner. I've seen systems where the event queue was sized for "normal" operation, but nobody thought about what happens during a BLE connection event storm or when a chattering button generates hundreds of events per second. The symptom is usually silent event loss. Your device just stops responding to certain inputs, or BLE notifications mysteriously disappear. By the time you notice, the queue has already overflowed and recovered, leaving no trace of what happened. The fix is defensive design. Size your queues for the worst case, not the average case. Implement overflow detection that logs a warning (or sets an error flag) when the queue gets close to full. Consider implementing back-pressure—if the queue is full, can you disable the interrupt source temporarily? And always use power-of-two sizes for circular buffers; the modulo operation becomes a simple bit mask, saving precious cycles. ### 3\. Timing Conflicts The SoftDevice is possessive about timing. It needs to handle radio events at precise moments, and if your code is busy doing something else, bad things happen. The symptoms range from increased power consumption (missed connection events lead to supervision timeouts) to complete connection failures. I learned this the hard way with a product that worked perfectly on the bench but failed intermittently in the field. Turns out, our temperature compensation algorithm would occasionally take just long enough to cause the SoftDevice to miss a connection event. The fix was simple once we understood the problem: break the algorithm into smaller chunks and check for pending SoftDevice events between chunks. The key is respecting the SoftDevice's timing requirements. Use the radio notification API to know when to get out of the way. Keep your interrupt handlers short. If you must do long calculations, break them into chunks and yield to the event loop periodically. And never, ever use busy-wait delays in bare metal—use timer callbacks instead. ### 4\. Power Management Mistakes This is the silent killer of battery life. Your code works perfectly, but the battery dies in days instead of years. You measure current consumption and find it's 10x higher than expected. What went wrong? Usually, it's forgetting to sleep properly. That innocent-looking empty while loop? It's burning power continuously. That GPIO you configured as an output but left floating? It's drawing current. That peripheral you initialized but aren't using? Its clock is still running. The solution is systematic power management. Your main loop should always end with \_\_WFE() or equivalent sleep instruction. Before sleeping, ensure all unused peripherals are clock-gated. Configure unused GPIOs as inputs with pull-up/down to avoid floating pins. And invest in a good power profiler—you can't optimize what you can't measure. ## Future of Bare Metal in nRF Connect SDK The embedded development landscape is constantly evolving, and Nordic Semiconductor's roadmap reflects a nuanced understanding that one size doesn't fit all. What excites me about the future of bare metal development isn't just the technology—it's the recognition that simplicity and efficiency still matter in our increasingly complex world. Looking ahead, I see several trends emerging. First, we're likely to see more protocol stacks adapted for bare metal use. Today, it's primarily Bluetooth LE via the SoftDevice, but imagine bare metal implementations of Thread, Zigbee, or even simplified TCP/IP stacks for specific use cases. The challenge will be maintaining the simplicity that makes bare metal attractive while adding these capabilities. Migration tools are another area ripe for innovation. Converting a legacy nRF5 SDK project to nRF Connect SDK Bare Metal is currently a manual process, but I wouldn't be surprised to see automated tools that can analyze your old code and generate a skeleton project with the appropriate Kconfig and devicetree settings. It won't be perfect, but it could dramatically reduce the migration burden. Perhaps most intriguing is the possibility of hybrid approaches. Imagine being able to selectively enable RTOS features—maybe you want just the scheduler for one specific use case, or just the memory protection unit for critical sections. This "à la carte" approach could give developers the best of both worlds: bare metal efficiency with RTOS features where they add value. Better profiling tools are desperately needed. Today, understanding where your bare metal application spends its time and power requires external equipment and manual analysis. Integrated profiling that can track power consumption, interrupt latency, and stack usage in real-time would be a game-changer for optimization work. ## Conclusion After thousands of words exploring the intricacies of bare metal versus RTOS development, let me leave you with this thought: the best solution is the one that solves your problem elegantly, efficiently, and maintainably. The nRF Connect SDK Bare Metal isn't just a nostalgic nod to simpler times—it's a recognition that for many real-world applications, simplicity is a feature, not a limitation. When you strip away the layers of abstraction, you're left with code that's predictable, efficient, and understandable. For the right applications, that's incredibly powerful. But let's be honest: bare metal isn't always the answer. If you're building a complex system with multiple concurrent activities, sophisticated user interfaces, or rich networking requirements, the standard nRF Connect SDK with Zephyr RTOS is probably the better choice. The overhead you pay in RAM and power consumption buys you powerful abstractions that can dramatically accelerate development and improve reliability. The key is making an informed decision based on your specific requirements. If you're building a simple BLE peripheral that needs to run for years on a battery, bare metal's efficiency is compelling. If you're creating a gateway device that juggles multiple protocols and complex business logic, the RTOS's task management and abstraction layers will save you months of development time. What excites me most about Nordic's approach is that they're not forcing you to choose sides. Both options are actively developed, well-documented, and supported. You can start with bare metal for a simple proof of concept and migrate to the full SDK if your requirements grow. Or you can prototype quickly with the full SDK and then optimize down to bare metal for production. In my years of embedded development, I've learned that dogma is the enemy of good engineering. Use the right tool for the job, understand the trade-offs, and always keep the end user in mind. Whether that tool is bare metal or RTOS, what matters is shipping products that work reliably, efficiently, and delight your users. ## Additional Resources Your journey with nRF Connect SDK Bare Metal doesn't end here. The Nordic ecosystem is rich with resources to help you succeed: The official [nRF Connect SDK Documentation](https://developer.nordicsemi.com/nRF%5FConnect%5FSDK/doc/latest/nrf/index.html?ref=novelbits.io) should be your first stop. It's comprehensive, well-maintained, and includes both conceptual guides and API references. Don't skip the getting started guides—even experienced developers will find nuggets of wisdom there. For deep technical details about the SoftDevice and chip specifications, the [Nordic InfoCenter](https://infocenter.nordicsemi.com/?ref=novelbits.io) is invaluable. This is where you'll find timing diagrams, register descriptions, and the nitty-gritty details you need for advanced optimizations. The [Nordic DevZone](https://devzone.nordicsemi.com/?ref=novelbits.io) community forum is where the magic happens. Nordic's engineers actively participate, and the community is generally helpful and knowledgeable. Before posting a question, search the archives—chances are someone has faced your exact issue before. Don't overlook the example projects in the SDK's `samples/` directory. These aren't just toy examples—they're production-quality code that demonstrates best practices. Start with these examples and modify them for your needs rather than starting from scratch. For those migrating from nRF5 SDK, the migration guides in the official documentation are essential reading. They'll save you days of head-scratching by highlighting the key differences and providing translation tables for common operations. Finally, remember that embedded development is a journey, not a destination. The tools, techniques, and best practices continue to evolve. Stay curious, keep learning, and don't be afraid to question conventional wisdom. Sometimes the best solution is the one that breaks the rules—as long as you understand why the rules existed in the first place. Happy coding, and may your devices run for years on a single battery! ### Mastering the Nordic Ecosystem: A Developer's Guide to Choosing the Right Tools for your Bluetooth LE Project URL: https://novelbits.io/nordic-bluetooth-le-development-tools/ Last updated: 2026-08-09T05:25:46.000Z *Sponsored by* [*Nordic Semiconductor*](https://nordicsemi.com/?ref=novelbits.io) If you're a wireless engineer, you know that things have changed. These days, Bluetooth Low Energy development is practically bursting with resources. What started with a simple compiler and flasher has now evolved into a vast world of cutting-edge SDKs, advanced debuggers, power profilers, protocol sniffers, easy-to-use configuration tools, and a multitude of mobile apps. The vibrant ecosystem surrounding Nordic Semiconductor’s industry-leading SoCs offers incredible potential. While it presents a modern challenge known as the paradox of choice, it also offers an exciting opportunity. With so many effective tools at your disposal, you can explore and discover the ones that best suit your needs, allowing you to find your path to success right from the start. But let me let you in on a secret that most seasoned developers already know: they typically utilize only a fraction of these tools on any given project. Is that a problem? Absolutely not. **It's the hallmark of an efficient workflow.** This post is your strategic guide to navigating a powerful ecosystem. Instead of listing every feature, my goal is to help you understand the landscape and choose the right components for your project, filtering out irrelevant information. Think of this as a roadmap to the Nordic Semiconductor ecosystem, highlighting developer choice and adaptability to help you build better products more efficiently. ## Your Command Center ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/command-center.png) In the world of development tools, every developer needs a reliable home base—a central workbench that offers structure, consistency, and functionality. For those working with Nordic Semiconductor's offerings, this command center is a combination of the **nRF Connect SDK** and the **nRF Connect for VS Code Extension**. While other tools play important roles, this duo serves as the essential foundation for almost any modern Bluetooth LE project. ## The Foundation: nRF Connect SDK ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3.png) The nRF Connect SDK is far more than a collection of drivers and Bluetooth libraries. It is a highly scalable and flexible Software Development Kit that has become the foundation of all new development for Nordic’s wireless SoCs, ranging from the workhorse [nRF52 Series](https://docs.nordicsemi.com/category/nrf-52-series?ref=novelbits.io) to the [multi-core nRF53 Series](https://www.nordicsemi.com/Products/nRF5340?ref=novelbits.io) and the [ultra-low-power nRF54L](https://novelbits.io/nrf54l15-unboxing-first-impressions/), as well as the upcoming high-performance nRF54H Series. Its power lies in its architecture. At its heart is the [**Zephyr RTOS**](https://www.zephyrproject.org/?ref=novelbits.io), a real-time operating system designed for resource-constrained devices. Building upon Zephyr brings several key advantages for developers: - **A Rich Ecosystem of Wireless Stacks and Functionality:** Beyond the core RTOS, the SDK integrates a vast array of essential libraries and stacks. This includes not only Nordic’s own finely tuned Bluetooth Low Energy protocol stack, but also a variety of sample applications and implementations of the standard SIG-adopted profiles, as well as stacks for other wireless protocols. This pre-integrated, pre-validated approach saves hundreds of hours of integration effort. - **Scalability and Portability:** Zephyr’s modular design allows you to include only the components your application needs, keeping your firmware efficient. An application written for one nRF SoC can be easily ported to another, often with minimal changes. This is a massive advantage when your product line evolves or when you need to target multiple hardware variants. - **Open-Source Accessibility:** Because the SDK is built on a foundation of the open-source Zephyr project, developers have full access to the source code of many parts of the stack. This also enables reusable software, faster bug fixing, and accelerates innovation. ## The Workbench: nRF Connect for VS Code Extension ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2025-07-02-at-7.38.54-E2-80-AFAM-scaled.png) If the SDK is the foundation, the nRF Connect for VS Code Extension is the integrated *workbench* you'll use every day. Visual Studio Code has become the de facto standard for developers across many disciplines, and Nordic has fully adopted it. The extension transforms the general-purpose editor into a specialized, powerful IDE for nRF development. This is the environment where you will write, build, and debug your code. Its key role is to act as the primary user interface to the underlying nRF Connect SDK and its associated command-line tools. For us developers, this means: - **Unified Toolchain Management:** The extension automatically locates and manages the toolchain components (compiler, linker, etc.). This solves one of the most common setup headaches in embedded development, ensuring that every developer on a team is using the same verified toolchain versions. - **Application and Board Awareness:** The extension is context-aware. It understands the concept of applications, boards, and build configurations. Through a simple, clean user interface, you can select the application you want to build and the target hardware (e.g., `nrf5340dk_nrf5340_cpuapp`), and the extension handles the complex task of passing the correct configuration flags to the build system. - **From Code to Flashing in One Click:** The core development loop is dramatically simplified. With your application and board selected, a single click on the "Build" button compiles your code. Once successful, you can flash the firmware to your connected development kit using the "Flash" button without ever leaving the VS Code window. In essence, this combination of SDK and VS Code extension provides the essential starting point for any project. It establishes a stable, powerful, and efficient environment, freeing you from the complexities of toolchain setup and project configuration. It is the command center from which you will launch into the more specialized tasks of hardware configuration, debugging, and testing, which we will explore next. ## The Developer's Toolkit: Choosing Your Tools by Task Now that we have our command center established, it's time to explore the specialized tools you'll pull from your toolkit. A key point to keep in mind for mastering the Nordic ecosystem is that you don’t need to use every tool on every project. The goal is to select the right tool for the specific job at hand. Let's break this down by common development tasks. ### A. For Day-to-Day Coding & Firmware Debugging **The Task:** You're deep in the development trenches. Your primary activity is the "inner loop": writing a new piece of application logic, compiling it, flashing it onto your target hardware, and then troubleshooting why it doesn't work exactly as planned. The speed and efficiency of this cycle directly impact your project's timeline more than almost any other factor. **Your Go-To Tools:** The integrated **Build/Flash buttons**, **nRF Debug**, and **Memory Explorer** within the nRF Connect for VS Code extension. When your firmware doesn't behave as expected, printing log messages can only get you so far. To truly understand what's happening inside the chip, you need a debugger. The **nRF Debug** feature is a full-featured, graphical debugger built directly into VS Code, and using it almost feels like a superpower! It allows you to pause the program's execution and inspect its state in detail, providing precise control over the logic flow, a clear view of your application's live data, and a deep understanding of the exact path the code took to reach that point, even across different application threads. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-5.png) Source: [Nordic DevAcademy Course](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/topic/debugging-in-vs-code/?ref=novelbits.io) Sometimes , you need to go even deeper, and for that, the **nRF Memory Explorer** provides direct access to the device's raw memory , including both RAM and Flash (or any other NVM, such as RRAM in the nRF54L Series). This powerful tool is crucial for solving complex problems, such as finding memory corruption, verifying intricate data structures, or directly inspecting the status of peripheral hardware registers. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-6.png) Source: [Nordic DevAcademy Course](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/topic/debugging-in-vs-code/?ref=novelbits.io) By combining the simple Build/Flash cycle with the powerful inspection capabilities of the Debugger and Memory Explorer, you can create a highly efficient workflow to solve nearly any firmware bug, all from the comfort of a single, unified application. ### B. For Initial Setup & Hardware Configuration **The Task:** You're kicking off a new project. It’s not on a standard Development Kit (DK); it’s for your own custom hardware. You need to tell the SDK which pins are connected to your LEDs, which I2C bus your accelerometer is on, and that you're using a specific SPI-based display. In a traditional workflow, this means manually editing complex, text-based configuration files, a process notoriously prone to syntax errors and typos that can take hours to debug. **Your Go-To Tool:** The **Devicetree Visual Editor**, integrated directly within the nRF Connect for VS Code extension. Before diving into the editor itself, it’s important to understand what a "devicetree" is. The nRF Connect SDK, via Zephyr RTOS, utilizes a devicetree to describe the hardware layout of a board in a manner decoupled from the application code. It’s a hierarchical data structure written in special source files (`.dts`, `.dtsi`) that represents everything from the CPU cores down to individual GPIO pins and peripheral controllers (such as UART, SPI, and I2C). The "correct" way to adapt a standard board configuration to your own hardware is by creating an **overlay file** (`.overlay`). This file simply specifies your changes and additions, which the build system intelligently "lays over" the base configuration. While this is a powerful and clean system, writing overlays by hand requires precise syntax and a deep understanding of the devicetree structure. This is where the visual editor changes the game. It parses these files and presents them in an intuitive graphical user interface. Instead of poring over text files, you're presented with a browsable list of all the peripherals available on your selected SoC. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2025-07-02-at-7.38.49-E2-80-AFAM-scaled.png) *Click image to enlarge.* The visual editor abstracts away the complexities of manual text-file editing for hardware configuration. It provides developers with a straightforward and interactive method for understanding and assigning system resources. ### C. For RF & Protocol-Level Validation **The Task:** Your code compiles, your firmware is flashed, and the device is running. But now you face a new set of critical questions. Is the device actually advertising? Is the signal strength strong enough? When a central device connects, are all the GATT services and characteristics you defined behaving as expected? **Your Go-To Tools:** The **nRF Connect for Desktop** application suite, specifically the **Bluetooth Low Energy App** and **RSSI Viewer** app. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2025-07-02-at-1.35.30-E2-80-AFPM.png) nRF Connect for Desktop acts as your ground-truth window into the wireless world. It uses a Nordic Development Kit (DK) or Dongle connected to your computer as a highly reliable radio interface. - **The Bluetooth Low Energy App:** This is the swiss-army knife for BLE protocol testing. It allows you to scan for devices, inspect their raw advertising data, establish a connection, and perform a full GATT service discovery. You can read, write, and subscribe to characteristics to test your device's application logic in a controlled, detailed environment. - **The RSSI Viewer:** This specialized tool provides a real-time, graphical plot of signal strength. It's invaluable for comparing antenna performance, validating the effective range of your product, or identifying potential RF interference issues. - **The Direct Test Mode (DTM) App:** DTM is a procedure defined by the Bluetooth SIG used for testing the radio's physical layer. Running DTM tests is a **mandatory requirement** for official Bluetooth qualification. This app provides the graphical interface needed to control a Device Under Test and perform these essential certification tests, demystifying a critical part of the product launch process. ### D. For Power Consumption Optimization **The Task:** Your device is functionally complete and communicating correctly over Bluetooth LE. But the product requirements demand a two-year battery life from a small coin cell. How can you be certain you are meeting your power budget? How do you find the specific lines of code or hardware peripherals that are consuming precious microamps and preventing your device from hitting its battery life target? **Your Go-To Tools:** The **Power Profiler Kit II (PPK2)** used in conjunction with the **Power Profiler app** within nRF Connect for Desktop. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-7.png) For any low-power application, optimizing firmware is critical. The Power Profiler Kit II (PPK2) is an essential tool for every developer's desk, providing precise current measurements from under a microamp up to 1A. It acts as both the power source for your Device Under Test (DUT) and the high-precision measurement instrument. Working in tandem with the Power Profiler app, the PPK2 makes it easy to visualize and analyze your design's power usage. In a typical workflow, you'll connect the PPK2 to your computer and use it to power your dev kit or custom board. Within the app, you can start a capture and immediately see a live graph of the current consumption. Zoom out to see the average current over several minutes, then instantly zoom in on a millisecond-long advertising spike to inspect its characteristics. By correlating these power consumption peaks with your code's execution, you can quickly identify and fix bugs—like a peripheral left on by mistake—that might otherwise drain your battery and compromise your product's performance in the field. ### E. For Mobile Integration & Field Testing **The Task:** Your device works perfectly on the bench, but you need to validate its functionality in a real-world setting. How will you update the firmware once it has been deployed? And how do you start building a custom companion mobile app without reinventing the wheel? **Your Go-To Tools:** **nRF Connect for Mobile** and Nordic Semiconductor's open-source **Mobile App Libraries & Examples** on GitHub. - **nRF Connect for Mobile:** Available for both Android and iOS, this is your untethered field-ready toolkit. It provides the same core GATT client functionality as the desktop app but adds the killer feature for any real-world product: **Over-the-Air Device Firmware Update (OTA DFU)**. You can test your entire DFU process—from generating the firmware package to securely transferring and activating it on your device—using this reliable, off-the-shelf tool. - **Open-Source App Accelerators:** When you're ready to build your own branded app, don't start from scratch. Nordic provides high-quality example apps like **nRF Blinky** and the more comprehensive **nRF Toolbox**. More importantly, these apps are built on robust, reusable libraries (e.g., `Android-BLE-Library`) that handle the complexities of mobile Bluetooth communication. By including these libraries in your own project, your mobile developers can save weeks or months of effort and focus on the UI and application logic, not on debugging low-level BLE state machines. ## The Unified Advantage: How It All Works Together The most profound accelerator in the Nordic ecosystem is that these instruments aren't isolated; they are part of a single, cohesive toolchain where the whole is far greater than the sum of its parts. Consider a common workflow: - You start in **VS Code**, using the **Devicetree Visual Editor** to configure your I2C pins. - You write your sensor driver code and use the **nRF Debugger** to step through the logic and fix a byte-swapping issue. - With the firmware running, you open **nRF Connect for Desktop**. - First, you use the **Power Profiler** to find and fix a high-current issue caused by leaving the sensor on. - Then you switch to the **Bluetooth Low Energy App** to validate that your custom GATT service is reporting the correct sensor data. - Finally, you take the device into the field, using **nRF Connect for Mobile** to test its range and perform a full OTA DFU to prove its serviceability. This seamless flow—from visual hardware configuration, to deep code-level debugging, to power profiling, to protocol validation, and finally to field testing—is the unified advantage in action. Each tool hands off to the next, allowing you to move with confidence and speed. ## Developer Enablement: Documentation, Community, and Support Great tools are only one part of the equation. Nordic provides a multi-layered support structure to ensure you have a path forward when you encounter a roadblock. - **Guided Learning (Nordic DevAcademy):** A free, online learning platform with structured courses and hands-on exercises to guide you from fundamental concepts to advanced topics. - **Definitive Answers (Official Documentation):** The comprehensive library for every technical detail, from hardware specifications to SDK API references. - **Community Collaboration (The DevZone Forum):** An incredibly active technical forum and knowledge base where you can find answers from thousands of developers and Nordic’s own application engineers. - **Direct, Professional Support (Nordic Ticketing System):** A confidential ticketing system for commercial customers to get private, one-on-one assistance from a Nordic engineer for project-halting issues. - **Built-in AI Chatbot (TechDocs AI Assistant):** An interactive tool that allows you to describe what documentation you're looking for in simple language. ## Final Thoughts: Develop Smarter, Not Harder The journey from a product concept to a market-ready connected device is complex, but it doesn't have to be frustrating. The key to mastering the Nordic ecosystem isn't about knowing every tool, but about learning how to choose the right tool for the job. It’s about knowing which tool to grab to solve a specific problem efficiently. The true, compounding advantage comes from their seamless integration, which eliminates friction and empowers you to innovate faster. By providing a robust and unified toolchain, Nordic handles the complexity, allowing you to focus your valuable time and energy on what you do best: building the unique features that make your product stand out. Ready to start your journey? - **Get started with Guided Learning:** Enroll in a free course at the [**Nordic DevAcademy**](https://academy.nordicsemi.com/?ref=novelbits.io). - **Install the "Command Center":** Download and install the [**nRF Connect SDK**](https://www.nordicsemi.com/Products/Development-software/nrf-connect-sdk?ref=novelbits.io) and the [**nRF Connect for VS Code Extension**](https://marketplace.visualstudio.com/items?itemName=nordic-semiconductor.nrf-connect-extension-pack&ref=novelbits.io). - **Explore the Community:** When you have questions, search for answers or ask the community on the [**DevZone Forum**](https://devzone.nordicsemi.com/?ref=novelbits.io). - **Leverage Open Source:** Explore the mobile app accelerators and other projects on [**Nordic Semiconductor's**](https://github.com/NordicSemiconductor?ref=novelbits.io)[ **GitHub**](https://github.com/NordicSemiconductor?ref=novelbits.io). - **Reference the TechDocs**: The [**TechDocs website**](https://docs.nordicsemi.com/?ref=novelbits.io) from Nordic provides you with all the documentation you need to learn how to use even the most specific parts of the SDK. - **Interact with the AI Chatbot**: Quickly find answers to your specific questions in the documentation by using the built-in AI Assistant. 💡 **Insider Tip:** Want to go deeper with Nordic's Bluetooth LE development ecosystem? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Hands-On with the em | bleu (EM9305) Bluetooth LE SoC: Tiny Chip, Huge Potential URL: https://novelbits.io/em9305-bluetooth-le-developer-guide/ Last updated: 2026-08-09T05:24:51.000Z *Sponsored by [EM Microelectronic](http://emmicroelectronic.com/?ref=novelbits.io)* As IoT continues to demand more compact, power-efficient, and secure wireless solutions, developers are looking beyond generic Bluetooth LE modules. Enter the **em | bleu** (**EM9305**) from **EM Microelectronic**, the **world's smallest Bluetooth® 5.4 SoC**, engineered for precision, performance, and longevity in compact connected devices. This blog serves as a hands-on guide to the **em | bleu** (EM9305) Evaluation Kit, offering a comprehensive walkthrough from unboxing to power profiling. Along the way, we'll highlight the key features that make EM9305 stand out—not just as another Bluetooth LE chip, but as a finely tuned, ultra-efficient platform optimized for the next generation of smart, low-power devices. ## EM Microelectronic and The Swatch Group: A Legacy of Miniaturization and Efficiency ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-8.png) When you think of cutting-edge semiconductor innovation, a watch company might not be the first thing that comes to mind. But **EM Microelectronic**, a proud member of the **Swatch Group**, has quietly built a reputation over the last few decades as a leader in **ultra-low-power, highly integrated IC design**—starting with the demanding constraints of the watch industry, and now spanning a wide range of high-impact markets. Founded in Switzerland in 1975, and celebrating their **50th anniversary** this year 🎉, EM Microelectronic began by creating custom chips for timekeeping applications, where **power consumption, size, and precision** aren’t just priorities—they’re non-negotiable. These early challenges became the foundation of EM Microelectronic’s DNA: a relentless focus on **efficiency, miniaturization, and performance without compromise**. Today, EM Microelectronic’s portfolio has expanded to include: - **Bluetooth® Low Energy (Bluetooth LE) SoCs** - **RFID and NFC transceivers** - **Energy harvesting solutions** - **Low-power displays and drivers** - **Custom mixed-signal modules** EM Microelectronic’s products now power systems in **automotive, industrial, healthcare, logistics, access control, smart home, and wearables**—while still serving millions of timepieces each year. EM Microelectronic also works closely with Swatch Group sister companies like **Micro Crystal** (oscillators) and **Renata** (batteries) to deliver integrated solutions that combine **timekeeping, energy, and wireless** capabilities in incredibly compact footprints. What sets EM Microelectronic apart isn’t just their chip specs—it’s how they apply decades of low-power experience to real-world problems, enabling devices that run longer, take up less space, and deliver more reliability in the field. So when EM Microelectronic launches a new Bluetooth LE SoC like the **EM9305**, it comes from a place of deep experience—not only in building radios, but also in architecting complete systems that sip power without sacrificing performance. ## What Makes EM9305 Unique? At a glance, the EM9305 may seem like just another Bluetooth LE SoC. But under the hood, it's packed with thoughtful engineering and system-level efficiency that make it truly stand out in the Bluetooth LE ecosystem—especially for applications that demand long battery life, compact footprints, and dependable wireless performance. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-1.png) em | bleu Packaging Options ### Ultra-Compact Design The EM9305 is currently the **smallest Bluetooth LE 5.4-compliant** **System-on-Chip (SoC)** available, measuring at a mere 1.8 × 1.8 mm in WLCSP format. Its minimal footprint makes it a perfect fit for ultra-miniaturized designs, such as: - Wearables (fitness trackers, rings, wristbands) - Medical devices (patches, hearing aids, sensors) - Asset tracking tags and smart labels - Smart home buttons and compact controllers When you're working with limited PCB area and strict industrial design constraints, EM9305 gives you the flexibility to build sleek, modern products without compromising on connectivity. ### Industry-Leading Power Efficiency Where the EM9305 really shines is in its **ultra-low-power performance**. Every power mode—from deep sleep to advertising—has been optimized for minimal current draw: - **Deep Sleep**: as low as **200 nA** - **Bluetooth LE Sleep (RC)**: **610 nA** (with 4 KB retention) - **TX @ 0 dBm**: **3.4 mA** - **RX**: **3.1 mA** These numbers translate to **years of battery life** on small coin cells or energy-harvested systems. And unlike some competitors, these aren't just theoretical values—they're backed by real-world measurements using tools like Joulescope (showcased in the demo video towards the end of the article).Additionally, EM Microelectronic offers [PMICs for optimized energy harvesting solutions](https://www.emmicroelectronic.com/product?title=&term%5Fnode%5Ftid%5Fdepth=27&ref=novelbits.io), supporting both solar cells and thermoelectric generation (TEG). ### Integrated, Flexible Power Management The EM9305 includes a highly configurable power management subsystem that simplifies your system design and extends battery life: - Operates directly from **1.5V, 3.0V, or 5.0V** sources and **can go as low as 1.1V (a unique feature not available on many other SoCs)!** - Built-in **DC-DC step-down and step-up converters** - **Inductorless voltage multiplier** for compact power regulation - Efficient regulators minimize power loss at every stage This power versatility makes the EM9305 ideal for platforms where supply voltage can vary over time—especially energy-harvesting and multi-chemistry battery systems. ### Strong RF Performance In Bluetooth LE applications, reliable connectivity is critical. The EM9305 delivers on that front with: - **+10 dBm** max transmit power - **\-97 dBm** receive sensitivity @ 1 Mbps - **\-103 dBm** receive sensitivity @ 125 kbps These values ensure robust communication even in dense environments—ideal for industrial plants, hospitals, smart homes, or anywhere interference is a concern. ### Developer-Friendly SDK and Tools A great chip means nothing without great tools. EM Microelectronic provides a clean, well-documented, and highly usable SDK that includes: - Reference examples (GATT profiles, beacon, heart rate, AoA) - Support for advanced Bluetooth LE 5.4 features: - **Coded PHY** for long-range applications - **PAwR** for electronic shelf labels and broadcast control - **Angle of Arrival (AoA)** for direction finding - Peripheral drivers (GPIO, I2C, SPI, ADC, etc.) - CMake-based build system - MetaWare-compatible debugger support Whether you're a seasoned Bluetooth LE developer or exploring new platforms, the EM9305 SDK gets you up and running quickly and supports full customization as your project scales. Specs alone don’t tell the full story. What makes the EM9305 truly unique is how it combines: - **Ultra-compact form factor** - **Best-in-class low-power operation** - **Broad Bluetooth LE 5.4 feature support** - **Integrated power management** - **Reliable RF performance** - **A developer-first SDK** **and toolchain** **Note:** the toolchain used is the[MetaWare toolchain by Synopsys](https://www.synopsys.com/dw/ipdir.php?ds=sw%5Fmetaware&ref=novelbits.io) and is provided free of charge to EM's customers (upon request), allowing customers to develop their products and solutions without any licensing constraints. All of this is backed by EM Microelectronic’s decades of experience in low-power design for wearables, industrial applications, and timekeeping systems. The result? A platform that enables more than just connectivity—it enables differentiation, efficiency, and long-term product success. ## But Wait… It's not ARM? Understanding ARC and Why You Shouldn't Worry One of the first questions developers ask when evaluating a new Bluetooth LE SoC is: *“Is it ARM-based?”* And understandably so—ARM Cortex-M cores have become the de facto standard for embedded development. They're familiar, well-documented, and supported by a massive ecosystem. But the **EM9305 doesn’t use an ARM core. It’s built on the ARC EM7D processor**, a 32-bit RISC architecture developed by Synopsys and purpose-built for ultra-low-power embedded applications. ### So... What is ARC? ARC (Argonaut RISC Core) is a family of compact, configurable CPU cores designed to maximize performance-per-milliwatt in embedded systems. While not as widely known as ARM outside of semiconductor circles, ARC is actually found in **billions of chips worldwide**—from audio codecs and SSD controllers to sensor hubs and wireless SoCs. The ARC EM7D core in the EM9305 is optimized specifically for: - **Small code size** - **Low active power and leakage** - **Fast wake-up times** - **Deterministic performance** for real-time tasks ### But I’ve Never Used ARC Before… That’s a common concern, and it’s one EM Microelectronic has anticipated and addressed. Here’s the good news: **you don’t need to learn a new architecture to be productive with the EM9305**. The SDK and tooling provided abstract the core completely. Development feels just like working on any other embedded platform: - You write firmware in **standard C** - You build using **CMake** or a command-line toolchain - You debug using **MetaWare-compatible tools**, with clear symbol output and step-through support - You don’t need to deal with ARC assembly unless you're optimizing at the lowest level (which most developers won’t need to do) The SDK also includes clean, modular examples with reusable drivers and reference GATT-based applications—so you're rarely starting from scratch. ### Comparing ARC and ARM at a High Level | Feature | ARM Cortex-M | ARC EM7D (in EM9305) | | --------------------------- | -------------- | ---------------------------- | | Architecture | 32-bit RISC | 32-bit RISC | | Code Density | Good | Excellent (smaller binaries) | | Toolchain | GCC, Keil, IAR | MetaWare, ARC GCC | | Ecosystem Size | Very large | Moderate but targeted | | Power Efficiency | Strong | Exceptional | | Real-time Performance | Good | Tuned for deterministic RT | | Customization by SoC Vendor | Limited | High (core can be tailored) | The ARC EM7D isn’t just an alternative—it’s actually **better optimized for ultra-low-power wireless applications** than some general-purpose Cortex-M cores. EM Microelectronic chose it deliberately to achieve a tighter, more efficient chip design without sacrificing development ease. ### Focus on What Really Matters The key takeaway? **It’s not about the architecture. It’s about the developer experience.** EM Microelectronic provides everything you need to work comfortably and productively on ARC: - A familiar SDK structure - A toolchain that “just works” - Solid documentation and application notes - Examples that compile, flash, and run out of the box So if you’re hesitating because it’s not ARM-based, don’t. With the EM9305, you won’t even notice the difference—except when you measure your battery life. ## Common Questions Developers Have About ARC Switching away from the familiar always raises questions. If you're used to working with ARM Cortex-M cores, you might have a few concerns about using an ARC-based SoC like the EM9305\. Below are some common objections—and why they shouldn’t hold you back. ### “I’ve never heard of ARC—why would I choose a less-known architecture?” ARC isn’t new or niche. In fact, **ARC cores are used in billions of chips** across SSD controllers, sensor hubs, and Bluetooth LE devices. The EM9305’s ARC EM7D core is highly optimized for **low-power embedded systems**, making it an ideal fit for wireless IoT. Here are just a few examples of ARC being used in products: - [Starblaze MB1000 Enterprise SSD Controller uses the Synopsys DesignWare ARC HS38 processor for high-performance SSDs](https://www.eetindia.co.in/arc-processor-interface-ip-boost-ssd-soc/?ref=novelbits.io) - [QLogic storage controllers (used in disk drives, RAID devices, tape drives, and SAN switches) incorporate ARC processors, specifically the ARCtangent-A4](https://www.design-reuse.com/news/202502620--arc-licenses-technology-to-qlogic-corporation-a-market-leader-in-chips-for-data-storage-networks/?ref=novelbits.io) - [ARC processors are also integrated into flash storage controllers for SSDs and similar devices](https://www.synopsys.com/articles/high-performance-ssd-designs.html , https://www.synopsys.com/articles/optimizing-high-end-designs.html?ref=novelbits.io) - ["Toshiba, ARC in configurable processor collaboration"](https://www.eetimes.com/toshiba-arc-in-configurable-processor-collaboration/?ref=novelbits.io) ### “What about the toolchain—will it be hard to use?” EM Microelectronic provides a complete SDK and toolchain that includes: - A **MetaWare-compatible compiler and debugger** - A **CMake-based build system** with modular examples - Command-line flashing tools and clean project structure You can be productive without needing to learn any low-level ARC internals. ### “Do I need to learn ARC assembly or change how I write firmware?” No. The EM9305 SDK is written in **portable, standard C**. You use the provided APIs just like you would with any Bluetooth LE SDK. Unless you’re optimizing at the lowest level, you **won’t need to write or understand ARC assembly**. ### “Will it integrate with my development workflow or CI setup?” Yes. The SDK supports **CMake**, making it CI/CD–friendly and easily integrated into automation pipelines. Build and flash operations can be scripted and deployed across teams. ### “Is there an easy way to test and evaluate it?" Absolutely. The **EM9305 Evaluation Kit** is designed for quick evaluation: - Easy-to-install SDK and toolchain (free) - Sample applications readily available in the SDK - CLI flashing tools You can get from unboxing to running a Bluetooth LE app in **under 30 minutes**. ### “What if my manager or customer insists on ARM?” Remind them that **ARC enables smaller die size, lower leakage, and longer battery life**—especially in ultra-compact or power-constrained designs. EM Microelectronic has a long-standing track record and ships millions of ARC-based chips across multiple markets. Choosing ARC in this context isn’t a risk—it’s a **purpose-driven decision**. ### Summary | Concern | Reality | | ------------------------------ | ---------------------------------------------------- | | ARC is obscure | Used in billions of devices worldwide | | Tools are limited | Full SDK, debugger, build system provided | | Need to learn new architecture | Standard C development with abstracted APIs | | Doesn’t fit CI/CD | CMake-based, CLI friendly | | Hard to evaluate | EVK is plug-and-play with demo apps | | Not “mainstream” | Proven reliability, lower power, tighter integration | The EM9305 may be based on ARC, but the development experience is polished, well-supported, and friendly. Don’t let unfamiliarity keep you from evaluating a platform that might be exactly what your next product needs. ## Unboxing the EM9305 Development Kit ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_2387-scaled.jpg) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-1.png) **Source**: [EM Microelectronic EM9305 DVK Factsheet](https://www.emmicroelectronic.com/sites/default/files/products/datasheets/EM9305%20SOC%20DVK%20FACTSHEET.pdf?ref=novelbits.io) Out of the box, the DVK includes the following components: - An EM Microelectronic EM9305 DVK board. - An EM Microelectronic EMREF9305QFN module. - A Digilent JTAG cable, allowing on-chip debugging. - A USB to USB mini cable to power the system and communicate with the PC, allowing, but not limited to, loading the FW and configuring the device. ## EM9305 DVK Unboxing, Development, Testing, and Current Measurement ## Summary & Next Steps The **EM9305** delivers on its promise: a compact, efficient, and accessible Bluetooth LE SoC. Whether you're evaluating for wearables, tags, sensors, or custom devices, this kit provides: - The hardware - The SDK - The toolchain - The documentation - Easy-to-build and use sample applications covering a variety of use cases ...and removes any barriers to getting started, regardless of whether you're familiar with ARC or not. ## Resources and Useful Links - [em | bleu (EM9305) Product Page](https://www.emmicroelectronic.com/product/standard-protocols/em-bleu-em9305?ref=novelbits.io) - [EM9305 Datasheet](https://www.emmicroelectronic.com/sites/default/files/products/datasheets/EM9305-DS.pdf?ref=novelbits.io) - [EM9305 DVK factsheet](https://www.emmicroelectronic.com/sites/default/files/products/datasheets/EM9305%20SOC%20DVK%20FACTSHEET.pdf?ref=novelbits.io) - [EM9305 Bluetooth Module Factsheet](https://www.emmicroelectronic.com/sites/default/files/products/datasheets/EM9305%20BLUETOOTH%C2%AE%20MODULE%20FACTSHEET.pdf?ref=novelbits.io) (used with the DVK) - [EM9305 DVK from Digikey](https://www.digikey.com/en/products/detail/em-microelectronic/EMDVK9305SOC/21442324?ref=novelbits.io) (to purchase for evaluation) 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE SoC development and learn how to build production-ready wireless applications? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### The nPM2100: Nordic’s Secret Weapon for Battery-Sipping Bluetooth LE Devices URL: https://novelbits.io/nordic-pmic-npm2100-ble-primary-cell-batteries/ Last updated: 2026-08-09T05:25:54.000Z *Sponsored by [Nordic Semiconductor](https://www.nordicsemi.com/?ref=novelbits.io)* Bluetooth® Low Energy (LE) is the backbone of modern low-power wireless products, from smart home sensors and medical monitors to asset trackers and industrial nodes. Yet, despite its efficiency at the radio level, the performance — and the user experience — is still often bottlenecked by poor power management at the system level. Most Bluetooth LE devices are powered by primary cells like AA, AAA, or coin cells, chosen for their long shelf life and compact form factor. However, managing energy from these sources isn't trivial. Designers face four persistent challenges when working with primary cell batteries: 1. How to boost voltage efficiently from a slowly dying battery. 2. How to accurately gauge remaining energy, especially near end-of-life. 3. How to minimize leakage current during storage, transport, and idle periods. 4. Shipping a product with the battery already inserted. Without addressing these power challenges, even the most optimized Bluetooth stack and device implementation can result in unpredictable battery life, device failure in the field, and unsatisfactory user experiences. Not to mention that these issues are even magnified in high-volume deployments, where battery replacement costs and downtime multiply quickly. This is where Nordic Semiconductor’s new [nPM2100 PMIC](https://www.nordicsemi.com/Products/nPM2100?ref=novelbits.io) enters the equation. Designed specifically for low-power wireless applications, the nPM2100 addresses the systemic energy loss that most Bluetooth LE designs tolerate by default. With 95% boost efficiency at typical Bluetooth LE current draws, sub-200nA idle modes, and industry-leading fuel gauge precision, it represents a fundamental shift in how engineers can approach power in primary-cell Bluetooth LE designs. In this blog post, we will explore: - How does the nPM2100 work? - What makes it different from traditional solutions? - How can it be leveraged to extend battery life, reduce system complexity, and design more sustainable Bluetooth LE products? - How can you evaluate the nPM2100? - A video demo of Nordic's [nPM PowerUP](https://docs.nordicsemi.com/bundle/nrf-connect-npm/page/index.html?ref=novelbits.io) tool paired with the [nPM2100 Evaluation Kit](https://www.nordicsemi.com/Products/Development-hardware/nPM2100-EK?ref=novelbits.io). ## Meet the nPM2100 ![Nordic Semiconductor nPM2100 PMIC chip](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-10.png) *Source: Nordic Semiconductor* nPM2100 is Nordic Semiconductor’s first power management IC (PMIC) engineered specifically for primary cell-powered Bluetooth LE applications. While traditional PMICs often cater to general-purpose power needs, the nPM2100 is optimized from the ground up for low-power wireless systems with strict energy and space constraints. One of its standout features is a built-in **model-based fuel gauge** that delivers accurate battery capacity estimates — without the need for external components. This allows Bluetooth devices to report remaining energy down to **5%** precision towards the end of battery life for AA and LiMnO2 batteries, helping prevent unexpected shutdowns and reducing premature battery replacements, which is especially valuable in remote or high-volume deployments. Additional feature highlights include: - **Exceptional efficiency** at ultra-low currents — with over 90% efficiency down to 10 µA and up to 95% at 70 mA - **Ultra-low power modes**, drawing just 35 nA in ship mode and 175 nA in hibernate mode - A **compact footprint**, available in 1.9 × 1.9 mm WLCSP or 4 × 4 mm QFN packages - A **minimal BOM**, requiring only six passive components, makes it ideal for space-constrained designs like wearables and smart tags This combination of high-efficiency regulation, accurate fuel gauging, and compact integration makes the nPM2100 a powerful enabler for longer-lasting, smarter Bluetooth LE devices. ## Deep Dive: What Makes the nPM2100 Different ### LDO and Boost Converters Bluetooth LE devices must operate within a narrow voltage range, even as battery voltage drops. Regulators ensure this stability, and the nPM2100 employs both boost converters and a Load Switch (pass-through mode) to manage power effectively. - LDOs, or Low Dropout Regulators, lower a higher input voltage to a lower output voltage. They're simple and quiet in terms of electrical noise but inefficient when the input voltage greatly exceeds the output. This inefficiency is especially apparent in primary cell designs where energy conservation is crucial. - In contrast, boost converters increase a lower input voltage to a higher, stable output. This is particularly valuable when working with depleted batteries that still hold usable energy. The nPM2100’s boost converter is optimized to deliver high efficiency, both during active radio bursts and in ultra-low power sleep states. When the battery voltage is already adequate to run the system, the nPM2100 switches to pass-through mode. This allows the battery to supply power directly to the system through a low-resistance path, avoiding unnecessary energy conversion losses. The chip can dynamically switch between boost and pass-through modes, ensuring optimal efficiency throughout the battery’s life. At the heart of the nPM2100 is a highly efficient boost converter that supports operation from input voltages as low as 0.9 V. It provides up to 95% efficiency at higher loads (70 mA) and maintains over 90% efficiency at currents as low as 10 µA. This ensures stable voltage output across the battery’s discharge curve, which is essential for Bluetooth LE operation. ### System Reliability The nPM2100 provides several safety and recovery features that increase system robustness. If a device fails to boot — perhaps due to memory corruption or voltage instability — the PMIC can automatically trigger a power cycle to restore operation. This is especially valuable for remote or hard-to-service installations. Additionally, the integrated watchdog timer ensures the system can recover from software hangs, while a hardware reset line offers a manual fallback for developers or end users. The device also supports one-button system control, enabling a single GPIO to act as an on/off toggle with the same ultra-low current draw as ship mode. ### Seamless Integration With a BOM consisting of just six passives, the nPM2100 integrates cleanly into any Bluetooth LE architecture, especially when paired with Nordic’s nRF52, nRF53, or nRF54 series SoCs via I²C. This minimal design footprint is ideal for products where space and battery life are both at a premium. ### Power Saving The nPM2100’s ultra-low power modes (hibernate mode at 175 nA current draw) enable remarkable energy savings when paired with Bluetooth LE SoCs in advertising-only use cases. Devices configured with a 2.5-minute advertising interval can achieve up to 25% longer battery life, while a 4-minute interval can yield a 50% improvement. At 9-minute intervals or longer, battery life can extend by up to 2 to 3 times. These improvements can significantly reduce maintenance frequency in battery-operated systems like Bluetooth LE beacons and environmental sensors. The device also supports zero-drain deployment. With a ship mode consuming only 35 nA, manufacturers can insert batteries at the factory without compromising shelf life. Devices can then wake via a button press or TWI command. The 175 nA hibernate mode enables scheduled wake-ups based on timers ranging from 16 ms to over 74 hours, offering significant flexibility for periodic sensing applications. ### The Fuel Gauge Accurate fuel gauging is another critical feature. The nPM2100 employs a model-based algorithm that provides precise estimates of battery life, especially near end-of-life conditions, achieving 5% accuracy. This level of detail is crucial for devices in regulated sectors or with strict replacement schedules, such as healthcare or industrial monitoring. ## Use Cases: From Bluetooth Beacons to Health Monitors Smart home sensors that report infrequently benefit immensely from the nPM2100’s hibernate mode, which reduces sleep current to sub-microamp levels. This can extend battery life to multiple years on a single coin cell. Asset trackers, often assembled and shipped in bulk, benefit from the ability to insert batteries at the factory using ship mode. The device can remain dormant during transit and activate only when deployed, saving energy and logistics complexity. Bluetooth LE-based remotes and peripherals gain reliability from an integrated watchdog and reset functionality, preventing lockups and ensuring consistent performance with minimal user intervention. Meanwhile, medical and industrial wearables benefit from precise battery monitoring, allowing scheduled maintenance and improved user trust. ### Real-World Example Consider a Bluetooth LE-enabled temperature and humidity sensor used in smart buildings. It sends data every 5 minutes and is expected to last at least 18 months on a CR2032 battery. - Without the nPM2100, such a design might consume 2.5 µA in sleep and struggle with boost converter inefficiencies. Fuel gauging might also be unreliable, leading to premature battery replacements. - With the nPM2100, sleep and hibernate current drops to between 0.5 and 1.0 µA. Boost efficiency is improved, battery reporting is accurate to within 5%, and the device can ship with a battery pre-installed. The result is a 2.5× increase in battery life, more reliable battery alerts, and lower BOM complexity, all of which lead to a more robust and scalable product. ## Environmental Impact By dramatically extending battery life, the nPM2100 supports more sustainable product lifecycles. In large-scale deployments, this translates into meaningful environmental and cost savings. For example, deploying 10,000 sensors with a 2-year battery lifespan requires 30,000 replacements over a 10-year span. Extending battery life to 5 years reduces that number to just 10,000 — a 66% reduction in e-waste and service overhead. Combined with its low-leakage modes and support for pre-assembly battery installation, the nPM2100 enables greener, more efficient designs that scale better both technically and economically. ## nPM2100 EK and the nPM PowerUP Application Nordic provides multiple tools to ease the adoption of the nPM2100: **The nPM2100 EK** ![Nordic nPM2100 Evaluation Kit board](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-3.png) *Source: Nordic Semiconductor* The nPM2100 Evaluation Kit is the simplest way to evaluate the nPM2100 solution. It interfaces seamlessly with Nordic development boards, offering rapid prototyping without a complex setup. **The nPM PowerUP App** ![nPM PowerUP application screenshot showing boost efficiency configuration](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-2.png) Part of the nRF Connect for Desktop suite of apps, it enables designers to simulate and optimize boost efficiency, fuel gauge settings, and wake-up configurations. Developers can select from pre-configured battery profiles or create their own in the nPM PowerUP App, tuning thresholds and gauging behavior to match their application. With I²C control via the nRF Connect SDK, developers can program wake timers, adjust power settings, and configure system events directly from firmware. ## 🎥 Video: Unboxing and Demo Now, it's time to demo the nPM2100 EK using the nPM PowerUP application available within the nRF Connect for Desktop suite of apps! ## Closing Thoughts The nPM2100 isn’t just a more efficient boost converter — it’s a comprehensive energy management platform tailored to the unique needs of Bluetooth LE products. Its combination of fuel gauging, intelligent regulation, supervisory controls, and ultra-low power modes makes it a compelling choice for any engineer designing small, battery-powered wireless systems. Whether you’re building a wearable, a beacon, or an industrial sensor node, the nPM2100 allows you to reduce BOM complexity, extend battery life, and deliver a better product experience. ## 🔗 Additional Resources - [Nordic Semiconductor Power Management Solutions](https://www.nordicsemi.com/Products/Power-Management-ICs?ref=novelbits.io) - [nPM2100 Datasheet](https://docs.nordicsemi.com/bundle/ps%5Fnpm2100/page/keyfeatures%5Fhtml5.html?ref=novelbits.io) - [Developing with the nPM2100](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/app%5Fdev/device%5Fguides/pmic/npm2100.html?ref=novelbits.io) - [Explore the nPM PowerUP App](https://docs.nordicsemi.com/bundle/nrf-connect-npm/page/index.html?ref=novelbits.io) - [nPM2100 Evaluation Kit](https://www.nordicsemi.com/Products/Development-hardware/nPM2100-EK?ref=novelbits.io) 💡 **Insider Tip:** Want to master power management for your Bluetooth LE designs and learn how to maximize battery life? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Raytac AN54L15Q: An nRF54L15 BLE Module That Simplifies RF Design and Worldwide Regulatory Approval URL: https://novelbits.io/raytac-an54l15q-nrf54l15-ble-module/ Last updated: 2026-08-09T05:26:21.000Z *Sponsored by [Raytac Corporation](https://www.raytac.com/?ref=novelbits.io).* In the world of wireless connectivity, Bluetooth Low Energy (Bluetooth LE) continues to dominate the IoT landscape, powering a vast range of applications, from wearables and smart home devices to industrial sensors and medical equipment. As Bluetooth LE evolves, manufacturers are constantly pushing the boundaries of performance, security, and energy efficiency. With the release of Nordic Semiconductor’s nRF54 series, Bluetooth LE developers now have access to next-generation capabilities featuring higher processing power, ultra-low power consumption, and improved security protocols. One of the most exciting implementations of this new chipset is found in **Raytac’s AN54L15Q**, a pre-certified Bluetooth LE module that significantly reduces development complexity by handling RF design, regulatory compliance, and antenna tuning—allowing developers to focus on building their applications rather than wrestling with low-level RF challenges. In this blog post, we will: - Take a first look at the Raytac AN54L15Q, its companion development board (AN54L15Q-DB), and how it simplifies Bluetooth LE development. - Also, compare module-based designs vs. chip-down approaches, providing insights into cost, certification, scalability, and engineering effort to help you decide which approach best fits your project. - Highlight how Raytac provides benefits beyond just the typical module-based ones. ## **Unboxing the Raytac AN54L15Q-DB Development Board** In any Bluetooth LE development project, having a robust, easy-to-use development board can significantly accelerate the prototyping process. The AN54L15Q-DB is designed specifically for this purpose, providing a plug-and-play experience that eliminates the need for custom PCB design during the early stages of development. ### Inside the Box ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_1398-scaled.jpg) *Unboxing the AN54L15Q-DB* Opening the AN54L15Q-DB kit, you’ll find: - AN54L15Q-DB Development Board – featuring the AN54L15Q module pre-mounted, along with a built-in antenna, debug connectors, and expansion headers. - 1x IDC Ribbon cable There are multiple module options from Raytac featuring the Nordic nRF54L15 SoC: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/an54l15q-an54l15v_250208.jpg) *Raytac's various nRF54L15-based modules* **Credit*: Raytac* The focus of this blog post will be on the AN54L15Q, which features the QFN packaging and a built-in chip/ceramic antenna. Other QFN modules are available and provide a PCB/printed antenna option (AN54L15Q-P) and a U.FL connector for an external antenna option (AN54L15Q-U). There are also a couple of WLCSP-based modules that will soon become available (AN54L15V and AN54L15V-P). To interface with the module (that's mounted on the development board), Raytac recommends the use of a Nordic nRF54L15 DK, which provides the debug and flashing capabilities. The Nordic DK also provides developers with a way to perform a rough comparison of the RF performance between it and the Raytac module. **Note**: while developers can use a J-Link tool to debug and flash the module, the solution would be at least 10 times more expensive than using the standard nRF54L15 DK from Nordic Semiconductor. There is also no guarantee that all versions of J-Link devices would work out of the box. The nRF54L15 DK method is the officially supported and recommended method. So, to summarize, to get started with development using the AN54L15Q-DB, you'll need: - The AN54L15Q-DB itself - The IDC Ribbon cable - A Nordic Semiconductor nRF54L15 DK - Two USB-C cables to connect the AN54L15Q-DB and the nRF54L15 DK to the computer ### Getting Started with the AN54L15Q-DB Setting up the AN54L15Q-DB is straightforward: - Connect the two boards via the IDC ribbon cable (J1 on the AN54L15Q-DB to the "Debug Out" port on the nRF54L15 DK). - Connect each of the boards to your computer via a USB-C cable. - Install the necessary software packages (used for standard Nordic development), including VS Code, nRF Connect VS Code Extension, and the Segger J-Link software. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_1397-edited-scaled.jpg) *Connecting the AN54L15Q-DB to the nRF54L15 DK to be used as a debugger* Once this is done, developers can immediately begin working with Nordic’s nRF Connect SDK, an extensive software framework for Bluetooth LE development. For those already familiar with Nordic Semiconductor’s nRF SDK, the development experience will feel natural, as it fully supports Nordic’s firmware ecosystem, including power management, security, and Bluetooth LE stack integration. A key advantage of the AN54L15Q-DB is its built-in RF design, allowing developers to test Bluetooth LE performance without additional tuning. This makes it an ideal reference platform for companies planning to integrate the AN54L15Q module into their own products. ### Hands-On Tutorial: Running a Sample Application **Important Info:** Nordic DevAcademy Lesson for setting up nRF Connect SDK: [https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-1-nrf-connect-sdk-introduction/topic/exercise-1-1/](https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-1-nrf-connect-sdk-introduction/topic/exercise-1-1/?ref=novelbits.io) To fix the error for the absent external flash on the demo board, you can add the lines highlighted below: ```kconfig # # Copyright (c) 2018 Nordic Semiconductor # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # CONFIG_NCS_SAMPLES_DEFAULTS=y # Disable External Flash (for AN54L15Q-DB) CONFIG_SPI_NOR=n CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DEVICE_NAME="Nordic_LBS" # Enable the LBS service CONFIG_BT_LBS=y CONFIG_BT_LBS_POLL_BUTTON=y CONFIG_DK_LIBRARY=y CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 ``` ## **The Case for Bluetooth LE Modules vs. Chip-Down Design: A Comprehensive Comparison** One of the most critical design decisions when developing a Bluetooth Low Energy (Bluetooth LE) product is choosing between a pre-certified module or a chip-down approach. This choice impacts everything from cost and scalability to engineering complexity, time-to-market, and regulatory compliance. In this section, we will break down the key factors that influence this decision, exploring when it makes sense to use a module and when a chip-down approach is the better option. --- ### **1\. Regulatory & Certification Requirements** Regulatory compliance is one of the biggest hurdles in Bluetooth LE development. Depending on the country and product category, a Bluetooth LE-enabled device may need to pass multiple certification processes, including: - **FCC (United States)** – Part 15C unlicensed wireless testing. - **CE/RED (Europe)** – Compliance with the Radio Equipment Directive. - **ISED (Canada)** – Wireless certification requirements for North America. - **Telec/MIC (Japan)** – Radio Wave for telecommunication conformity system. - **ANATEL (Brazil), SRRC (China), WPC/TEC (India)** – Region-specific requirements. #### **Using a Bluetooth LE Module (e.g., Raytac AN54L15Q)** A pre-certified module simplifies regulatory compliance significantly. Since the RF section, antenna, and transceiver are already tested and approved, the host product typically only needs minimal EMC (Electromagnetic Compatibility) testing. This can save thousands of dollars and months of testing time! In addition, Raytac also provides an easy path for upgrades from one module to a newer one. The customer can inherit the same FCC/IC/TELEC/KC ID from Raytac for their newer product(s) and not worry about obtaining a new RF wireless certificate/RF circuit design on the mother PCBA. #### **Going Chip-Down (Using nRF54L15 SoC Directly)** A chip-down design means you are responsible for full certification. This includes: - RF compliance testing - Antenna performance validation - Conducted and radiated emissions testing Each of these tests adds cost and complexity. Failing any part of the certification process means redesigning hardware and retesting, causing potential delays of 3-6 months. In contrast to going the Raytac module route, in the case of upgrading the product to a newer design, the manufacturer will have to perform total RF circuit design, including antenna matching, in addition to the RF compliance test & certification procedures. This not only involves new compliance testing but also the R&D effort necessary to prepare the system for these new tests. **Verdict**: Bluetooth LE Modules offer a massive advantage for companies that want faster compliance and reduced regulatory costs. --- ### **2\. Cost Breakdown & Scalability** One of the main reasons companies consider a chip-down approach is to reduce per-unit costs at high production volumes. However, the total cost of development also includes: | **Cost Factor** | **Bluetooth LE Module** (AN54L15Q) | **Chip-Down (nRF54L15 SoC)** | | ---------------------- | ---------------------------------- | ------------------------------------- | | **RF Certification** | Pre-certified (\~$0) | $10K–$100K+ (region-dependent) | | **PCB Design** | Simpler, fewer RF layers | Requires expert RF design | | **Antenna Tuning** | Pre-optimized | Needs lab testing & tuning | | **Component Costs** | Higher per unit | Lower per unit at scale (>100K units) | | **Manufacturing Cost** | Simpler assembly | More complex PCB fabrication | | **Time-to-Market** | Faster (\~3–6 months saved) | Longer (\~6–12 months) | #### **When Modules Make Sense** - Low-to-medium volume production (<100K units/product) - Startups, IoT devices, medical devices, industrial sensors - Limited RF engineering expertise - Time-sensitive projects (product launches, MVPs, Kickstarter campaigns) #### **When Chip-Down Designs Make Sense** - High-volume manufacturing (100K+ units/product) - Optimizing unit cost for large-scale production - Companies with in-house RF engineers - Custom antenna designs or size constraints **Rule of Thumb:** If you’re producing less than 100K units/product, a module is usually the better financial choice due to the lower NRE (Non-Recurring Engineering) costs. --- ### **3\. Engineering Effort & Expertise Required** The level of RF and PCB design expertise required for a Bluetooth LE product varies greatly depending on whether you choose a module or go chip-down. #### **Using a Bluetooth LE Module (e.g., AN54L15Q)**: - No RF expertise is required - Pre-optimized RF performance – Antenna placement has already been validated. - No manual tuning or debugging needed – The module is pre-tested for Bluetooth LE signal integrity. - Faster development cycles – Developers can focus on firmware and application logic rather than hardware design. #### **Going Chip-Down (Using nRF54L15 SoC)**: - Requires experienced RF engineers to design and optimize the antenna layout. - PCB design is more complex due to RF shielding, ground planes, and impedance matching. - RF debugging tools (e.g., spectrum analyzers) are required, which can cost thousands of dollars. - Any small mistake in the PCB layout can degrade Bluetooth LE performance and require redesigns. **Verdict**: Bluetooth LE Modules significantly reduce the engineering effort and technical risks. --- ### **4\. Global Market & Module Policies** Certain countries support modular certifications, while others require full device testing, even if a certified module is used. | **Region** | **Module-Friendly?** | **Certification Required for Chip-Down?** | | ---------------------------------- | ------------------------------- | ----------------------------------------- | | **United States (FCC)** | ✅ Yes | ✅ Full certification | | **Canada (ISED)** | ✅ Yes | ✅ Full certification | | **Japan (MIC)** | ✅ Yes | ✅ Full certification | | **Korea (KC)** | ✅ Yes | ✅ Full certification | | **Taiwan (NCC)** | ✅ Yes | ✅ Full certification | | **European Union (CE/RED)** | ❌ No | ✅ Full certification | | **Australia and New Zeland (RCM)** | ❌ No | ✅ Full certification | | **Brazil (ANATEL)** | ❌ No | ✅ Full certification | | **India (WPC/TEC)** | ⁉️ It depends! See note below\* | ✅ Full certification | | **China (SRRC)** | ⁉️ It depends! See note below\* | ✅ Full certification | ***\* Modules are considered approved or unapproved for these regions based on the end product type.*** **Key Takeaway:** In non-module-friendly countries like the EU, Australia and New Zealand, China, India, and Brazil, even if you use a pre-certified module, the end product must still undergo full RF testing. *The good news? Even for non-module-friendly regions, Raytac can help streamline the certification process for their customers, reducing the cost, stress, and time involved with RF certifications in these regions.* --- ### **Final Verdict: Module or Chip-Down?** If you're a startup, small business, or developing an IoT device that will ship in low-to-mid volumes, Raytac’s AN54L15Q Bluetooth LE module is the smarter choice. It simplifies RF design, reduces certification costs, and accelerates time-to-market. If you are manufacturing a large volume of units (100K+ units per product in the case of Bluetooth and around 600K+ units in the case of Wi-Fi) and have RF engineering expertise, a chip-down approach could reduce unit costs but requires significant investment in design, tuning, and certification. ### **Choosing the Right Path** - Need fast development with minimal risk? → Go with a Bluetooth LE module. - Shipping globally and want easier compliance? → Use a pre-certified module. - Have an in-house RF engineering team and mass production scale? → Consider chip-down. *For most companies, a module like the AN54L15Q is the best balance of cost, simplicity, and scalability.* ## The Raytac Advantage: Certifications and Beyond Beyond just offering pre-certified modules, Raytac also offers their customers a few additional complimentary services to ensure their success in launching their products to market in the shortest time possible. These include: - Schematic diagram review - PCB layout circuit review - Radio test sample preparation When planning to launch a device worldwide, there are a few aspects to keep in mind: 1. RF Wireless Regulations 2. Communication Protocol Licenses and Certifications (Bluetooth, Wi-Fi, etc.) 3. EMC (EMI + EMS) 4. Industrial Field and Safety Tests Raytac offers customers help with #1 and #2 above. Let's cover these points in more detail. ### **RF Wireless Regulations** - For module-friendly regions, customers minimal work is needed to achieve RF certification since Raytac offers pre-certified modules. - For non-module-friendly regions, Raytac helps customers streamline the radio testing and certification process by partnering with SGS, a world-renowned test lab. The process works as follows: - Customers will send their product sample(s) to Raytac. - Customers will inform Raytac what test samples they need to provide the test house (Raytac also helps customers determine this information by consulting with RF experts). - Raytac will prepare the product sample for the required radio tests and send it to the testing lab. - Raytac works exclusively with SGS, a world-known test laboratory, to streamline the radio testing process and certify the product for worldwide coverage. ### **External Antenna Options** Raytac also offers customers recommendations for external pre-certified antennas (PCB or u.FL connector-based) if they decide to incorporate these into their product. The antennas are shown in the following table: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/external-antenna-list.png) **Credit*: Raytac* ### **Communication Protocol Licenses and Certifications (Bluetooth, Wi-Fi, etc.)** The costs and effort/time associated with obtaining licenses and certifications for the wireless protocols used in a product can really pile up when going with the chip-down approach. As we already covered earlier, product makers can significantly reduce costs and time by using a pre-certified module. When designing a Bluetooth-enabled product, manufacturers must comply with the Bluetooth Special Interest Group (Bluetooth SIG) qualification process. The Bluetooth Qualification Program (BQP) ensures that all Bluetooth devices meet interoperability, compliance, and quality standards, allowing them to use the Bluetooth trademark legally. Using a pre-certified Bluetooth module significantly simplifies this process and reduces costs, time, and engineering effort compared to developing a chip-down solution. To qualify a Bluetooth product, manufacturers must complete one or more of the following qualification pathways: 1\. **Qualification of a New Bluetooth Product (Chip-Down Approach)** - Requires testing at a Bluetooth Qualification Test Facility (BQTF). - Time-consuming and expensive, especially for small teams. 2\. **Qualification of an End Product Using a Pre-Certified Bluetooth Module** - Most of the qualification process is already completed if a pre-qualified module is used. - The manufacturer inherits the module’s existing qualification. - It only requires a simplified listing rather than full testing. - Much faster and more cost-effective. - Using a module pre-tested by a BQTF (Bluetooth Qualification Test Facility) ensures reliable Bluetooth performance without requiring in-house RF engineers. For Wi-Fi, it is a completely different ball game and involves much higher costs when designing using a chip-down approach. To summarize, a pre-certified module is the fastest and most cost-effective path to market if you’re designing a Bluetooth LE-enabled product and want to avoid expensive Bluetooth testing. For most companies, using a pre-certified module is the best balance of efficiency, compliance, and performance. ## Summary Developing a Bluetooth Low Energy (Bluetooth LE) product requires balancing cost, development effort, regulatory compliance, and time-to-market. Whether you are a startup, an IoT manufacturer, or an enterprise scaling production, choosing between a pre-certified Bluetooth LE module like the Raytac AN54L15Q or a chip-down design using the Nordic nRF54L15 SoC is a critical decision. After analyzing key factors such as engineering effort, certification, cost, scalability, and Bluetooth qualification, here’s what we’ve determined: If speed, simplicity, and regulatory compliance are priorities, the Raytac AN54L15Q module is the best choice for most developers. - Faster Time-to-Market – Avoids RF tuning, antenna design, and certification delays. - Pre-Certified for Bluetooth & Regulatory Compliance – FCC, CE, IC, MIC, RCM, and Bluetooth SIG certified. - Minimal RF Engineering Effort – The RF front-end, power management, and antenna tuning are already optimized. - Cost-Effective for Small-to-Medium Volume Production – Best suited for <100K units/product. - Bluetooth SIG Qualification Simplified – Eliminates the need for full-stack testing and reduces Bluetooth certification costs. - Global Market Readiness – Eases entry into module-friendly countries (FCC, MIC, ISED, KC, NCC). For most companies, using a pre-certified module eliminates major risks associated with RF tuning, Bluetooth interoperability, and compliance testing. **Use a Bluetooth LE Module (Raytac AN54L15Q) if:** - You need fast product development with minimal RF engineering effort. - You want to avoid high certification costs and simplify Bluetooth SIG qualification. - Your expected production volume is less than 100K units/product. - You lack an in-house RF engineering team or need global regulatory compliance. **Go Chip-Down (nRF54L15 SoC) if:** - You have RF engineering expertise and can handle PCB layout, antenna tuning, and compliance testing. - You are producing 100K+ units per product, and unit cost is the top priority. - Your design requires custom RF tuning, shielding, or ultra-low power optimizations. The Raytac AN54L15Q Bluetooth LE module provides the best balance between performance, cost, and time-to-market for most IoT, wearable, and industrial Bluetooth LE applications. If you’re considering using the Raytac AN54L15Q in your next Bluetooth LE product, check out the following resources: - **[Raytac AN54L15Q Product Page](https://www.raytac.com/product/index.php?index%5Fm1%5Fid=81&index%5Fm2%5Fid=85&ref=novelbits.io)** - RaytacAN54L15Q Modules: - [**AN54L15Q**](https://www.raytac.com/product/ins.php?index%5Fid=158&ref=novelbits.io): deployed Chip Antenna, which offers excellent connectivity. [**AN54L15Q-P**](https://www.raytac.com/product/ins.php?index%5Fid=159&ref=novelbits.io): deployed PCB antenna and offers good connectivity. **[AN54L15Q-U](https://www.raytac.com/product/ins.php?index%5Fid=160&ref=novelbits.io)**: deployed u.FL connector for External Antenna and offers a super long-range connectivity ability 💡 **Insider Tip:** Want to learn how to design Bluetooth LE products using modules like the AN54L15Q and the nRF54L15 SoC? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth LE for Wi-Fi Onboarding: A Game-Changer for IoT Connectivity URL: https://novelbits.io/ble-wifi-onboarding-provisioning/ Last updated: 2026-04-26T17:48:50.000Z *Sponsored by* [*Nordic Semiconductor*](https://nordicsemi.com/?ref=novelbits.io) Wi-Fi has become a cornerstone of modern connectivity, powering everything from laptops and smartphones to smart home devices and industrial IoT systems. However, while Wi-Fi excels in delivering reliable, high-speed data transfer, Wi-Fi onboarding—especially for IoT devices—remains a significant challenge. ## What is Wi-Fi? Wi-Fi is one of the most widely used wireless technologies, enabling devices to connect to the internet or local networks without physical cables. Based on IEEE 802.11 standards, Wi-Fi operates in various frequency bands (2.4 GHz, 5 GHz, and, more recently, 6 GHz with Wi-Fi 6E). It powers everything from smartphones and laptops to smart home devices and industrial IoT solutions. While Wi-Fi is known for providing high-speed data connectivity, its role extends beyond web browsing and video streaming. In the IoT landscape, Wi-Fi is a critical backbone for devices requiring constant or periodic internet access while balancing power consumption and efficiency. However, traditional Wi-Fi onboarding—connecting a device to a network—can be a pain point, especially for constrained IoT devices. This challenge becomes particularly evident in IoT deployments where devices may need to be provisioned at scale, in environments with limited access, or by users with varying technical expertise. Traditional Wi-Fi onboarding methods often involve complex processes that can lead to setup failures, user frustration, and increased support costs. These limitations have driven the industry to seek more efficient and user-friendly alternatives for connecting IoT devices to Wi-Fi networks. Enter Bluetooth Low Energy (LE): a technology that offers a seamless, user-friendly solution for Wi-Fi onboarding. In this post, we will: - Learn about the role of Wi-Fi in IoT and low-power applications - Explore Bluetooth Low Energy's role in making onboarding IoT devices on Wi-Fi networks simpler and more user-friendly. - Learn how Wi-Fi onboarding using Bluetooth Low Energy works - Learn about Nordic Semiconductor's low-power Wi-Fi solutions - 🎥 **Run a live demo of Wi-Fi onboarding using Bluetooth LE** - Explain the process of Wi-Fi onboarding using Bluetooth LE via sniffer capture ## The Role of Wi-Fi in IoT and Low-Power Connectivity Wi-Fi is a go-to solution for many IoT applications, but its role in low-power, constrained devices differs greatly from its use in traditional computing. Unlike smartphones and laptops, which prioritize high throughput and low latency, IoT devices have unique connectivity requirements: - **Power Efficiency** – Many IoT devices run on batteries and need to minimize energy consumption. - **Intermittent Connectivity** – Devices like smart sensors or industrial monitors may only need to transmit data periodically. - **Scalability** – Networks must support a large number of connected devices without congestion. - **Security** – IoT devices often operate in environments with strict security requirements, such as smart homes and industrial settings. ## Wi-Fi 6 and Its Role in IoT Wi-Fi 6 (802.11ax) introduces several key enhancements that make it more suitable for IoT applications, addressing issues like congestion, power efficiency, and scalability. ### Features of Wi-Fi 6 Unique to IoT Applications ### **1\. Orthogonal Frequency-Division Multiple Access (OFDMA)** - Allows multiple devices to share a single transmission channel efficiently, reducing latency and improving performance in dense environments. - IoT devices, which often send small bursts of data, benefit from OFDMA as it reduces contention for airtime. ### **2\. Basic Service Set (BSS) Coloring & Beamforming** - BSS Coloring helps reduce interference by allowing access points (APs) to distinguish between overlapping networks. - Beamforming improves signal reliability and range, ensuring IoT devices can maintain stable connections even at the edge of coverage. ### **3\. Target Wake Time (TWT)** - One of the most critical features for IoT, TWT allows devices to schedule when they wake up and communicate, significantly extending battery life. - This is especially useful for battery-operated sensors and other low-power devices that don’t need to transmit data constantly. With these enhancements, Wi-Fi 6 is better suited for IoT deployments than its predecessors, but connectivity challenges still exist—especially when it comes to onboarding. This is where Bluetooth Low Energy (LE) plays a crucial role. ## Nordic’s Wi-Fi Solution and the nRF70 Series Nordic Semiconductor, known for its leadership in Bluetooth Low Energy (LE), has expanded into Wi-Fi with the **nRF70 series**—a low-power Wi-Fi 6 companion IC designed specifically for IoT applications. Unlike traditional Wi-Fi chipsets optimized for high throughput, the **nRF70 series** focuses on **power efficiency, coexistence with Bluetooth LE, and secure, scalable connectivity**. ### **Key Features of the nRF70 Series for IoT** - **Wi-Fi 6 for Low-Power Applications** - **Seamless Bluetooth LE Coexistence** - **Ultra-Low Power Consumption** - **2.4 GHz Wi-Fi 6 for IoT Applications** With Nordic’s **nRF70 Wi-Fi companion IC**, developers can create **low-power, dual-radio IoT solutions** that leverage Bluetooth LE for **seamless onboarding and control** while using Wi-Fi for **higher-bandwidth data exchange** when needed. ### Nordic's Wi-Fi Solution Options Nordic has a few solutions available for Wi-Fi connectivity based on the nRF70 Series. The series is designed to operate alongside Nordic’s existing nRF52 and nRF53 Series Bluetooth LE and nRF91 Series cellular IoT devices. In addition, the nRF70 Series can also be used with non-Nordic host devices. The portfolio consists of: - nRF7002 - nRF7001 - nRF7001 IC ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-11.png) ****Source**: [Nordic DevAcademy Wi-Fi Fundamentals Course](https://academy.nordicsemi.com/courses/wi-fi-fundamentals/lessons/lesson-1-wifi-fundamentals/topic/nrf70-series/?ref=novelbits.io) #### nRF7002 The nRF7002 is the first device in our portfolio of unique Wi-Fi products, and it provides all the features of the nRF70 Series. #### nRF7001 With its single-band 2.4 GHz radio, the nRF7001 IC is intended for customers who don’t need dual-band functionality. It has all the same main features as the nRF7002 IC. #### nRF7000 The nRF7000 IC is designed explicitly for SSID-based Wi-Fi locationing. It enables active and passive scanning of Wi-Fi networks to acquire the SSIDs of nearby APs for locationing purposes. ### Nordic's Wi-Fi Development Hardware Nordic also offers a few boards for Wi-Fi development: #### nRF7002 Development Kit ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-3.png) **nRF7002 DK* The [nRF7002 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK?ref=novelbits.io) combines the Wi-Fi 6 capabilities of the nRF7002 companion IC with the multi-protocol capabilities of the nRF5340 System on Chip (SoC), like Bluetooth LE, Bluetooth mesh, NFC, Matter, Thread, Zigbee, etc. The DK provides everything needed to start developing low-power Wi-Fi applications. #### nRF7002 Evaluation Kit ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-4.png) **nRF7002 EK* The [nRF7002 EK](https://www.nordicsemi.com/Products/Development-hardware/nRF7002-EK?ref=novelbits.io) comes in the form of an Arduino shield and is designed to complement the nRF52840 DK, nRF5340 DK, and nRF9160 DK. #### nRF7002 Evaluation Board ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-2.png) **nRF7002 EB* ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-4-1.png) **Thingy:53 with nRF7002 EB* The [nRF7002 EB](https://www.nordicsemi.com/Products/Development-hardware/nRF7002-Expansion-Board?ref=novelbits.io) is a plug-in board intended to add Wi-Fi 6 connectivity to the Nordic Thingy:53. ## Wi-Fi Onboarding: The Challenge Before an IoT device can communicate over Wi-Fi, it must be connected to a network—a process known as **Wi-Fi provisioning** or **onboarding**. This involves: 1. **Scanning for available networks** 2. **Selecting the correct Wi-Fi network** 3. **Entering credentials (SSID & password)** 4. **Authenticating and connecting to the network** For traditional consumer devices like laptops and smartphones, this is straightforward. But for IoT devices—**which often lack a screen, keyboard, or even user input options**—Wi-Fi provisioning can be a **frustrating** experience. ### **Problems with Traditional Wi-Fi Onboarding** **No Universal Standard for Onboarding** - Solutions like **Wi-Fi Easy Connect™ (DPP)** exist but are **not widely supported on iOS and many Android devices**, making it difficult to rely on a single approach. **The “Wi-Fi Network Shuffle”** - Many provisioning methods require users to **connect to the device’s temporary Wi-Fi network (Soft AP)**, select their home Wi-Fi, enter credentials, and then **wait for the device to reboot**—all while possibly losing internet access on their phone. - **Phones resist connecting to networks without internet**, leading to **confusion and frustration** for end-users. - Confusion for end-users on which step of the process they're at, especially when the process involves navigating to different screens to complete the onboarding. **Inconsistent User Experience Across Devices** - Different phones, OS versions, and settings result in **unpredictable behavior**, making support and troubleshooting difficult. **Lack of Feedback During the Process** - Many apps rely on **guesswork** to determine whether provisioning is successful, often leaving users confused when something goes wrong. For **industrial and commercial** applications, **IT-managed networks** and enterprise authentication add further complexity, making traditional Wi-Fi onboarding even more challenging or sometimes even impossible! 💡 **Solution? Use Bluetooth LE for Wi-Fi onboarding!** ## Why Use Bluetooth LE for Wi-Fi Onboarding? There are quite a few reasons to implement the use of Bluetooth LE for Wi-Fi onboarding (instead of the traditional SoftAP method). Here are some of the most prominent ones: ### **Seamless User Experience** - No need to switch Wi-Fi networks mid-process. - The phone remains connected to the internet while provisioning happens over Bluetooth LE. - Works consistently across **iOS, Android, and other platforms**. ### **Reliable Communication** - Bluetooth LE remains connected **even if the Wi-Fi network is temporarily down**. - **Stronger debugging capabilities**—Bluetooth LE allows mobile apps to receive **real-time feedback** on the provisioning process. ### **Security & Flexibility** - Bluetooth LE-based provisioning can include **additional configuration steps** beyond just Wi-Fi credentials. ### **Suitable for More Deployment Scenarios** - **Enterprise Environments** – Many corporate networks **block multicast traffic (mDNS)**, making Wi-Fi-based onboarding harder. - **Matter Support** – Bluetooth LE is the preferred method for **Wi-Fi onboarding in Matter-certified devices**. ## Wi-Fi Onboarding Sample Application and How It Works (nRF Connect SDK) Nordic Semiconductor provides a **Wi-Fi provisioning sample** in the **nRF Connect SDK**, demonstrating **Bluetooth LE-based Wi-Fi onboarding** for the **nRF70 Series**. In this article, we'll reference this example and demonstrate how it works down to the Bluetooth LE packet level. We'll be using the nRF Connect SDK (v2.9.0). Here's a simplified step-by-step of the Wi-Fi onboarding process using Bluetooth LE: - The Wi-Fi-enabled device advertises as a Bluetooth LE peripheral - The device advertises with a specific service UUID (provisioning service) and a specific device name - The phone scans for devices with the specific service UUID - The user selects the device in question - The phone connects to the device and then pairs with it (no bonding) - Once the user selects the Scan operation, the phone sends a message (GATT write) to initiate a Wi-Fi scan for networks to join - The results of the scan are sent back to the phone (via GATT notifications) - The user is presented with the scan results - The user can then choose a network from the list and enter the security passkey for the network - The phone will send a message (GATT write), including the Wi-Fi network name (SSID) and the Wi-Fi passphrase/password - The device will then attempt to join the network using the credentials entered by the user - During the process, the status is reported by the device back to the phone to provide the user with up-to-date status, including when the process is complete and whether it is successful or not The smartphone application that we'll be using is the [Nordic Semiconductor nRF Wi-Fi Provisioner app](https://www.nordicsemi.com/Products/Development-tools/nRF-Wi-Fi-Provisioner?ref=novelbits.io) (available for both iOS and Android): ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2025-03-04-at-10.05.51-E2-80-AFPM-scaled.jpeg) **nRF Wi-Fi Provisioner Mobile App (iOS)* As you can see, there are multiple Wi-Fi provisioning modes: over Bluetooth LE, over Wi-Fi, and over NFC. For our exercise, we'll be using the "Wi-Fi provisioning over Bluetooth LE" mode. **Step #1:** We'll start by creating a new project based on the existing example in the SDK: ![](https://downloads.novelbits.io/media/posts/ble-wifi-onboarding-provisioning/create-project-ble-wifi-provisioning.gif) **Creating a project from the Wi-Fi Provisioning using Bluetooth LE example* **Step #2:** Once we've created the project, we can go ahead and add a Build Configuration for it by choosing `nRF7002dk/nrf5340/cpuapp` as the **Board Target**. ![](https://downloads.novelbits.io/media/posts/ble-wifi-onboarding-provisioning/nrf7002-build-configuration.gif) **Adding a Build Configuration to the project* **Step #3:** If you left the box labeled "**Build after generating configuration**" checked, the project will be built automatically after adding the Build Configuration. This process will take a few seconds, but it should build fine with no issues out of the box. **Step #4:** Make sure you connect the nRF7002 DK to your computer and that it is recognized in Visual Studio Code within the nRF Connect Extension: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2025-03-04-at-9.49.53-E2-80-AFPM.png) **Development Kit connected and detected in nRF Connect Extension in VS Code* **\[Optional\] Step #5:** Since the DK and phone will be establishing Bluetooth LE pairing between them, and we want to sniff the communication in the process, we need to know the pairing key (i.e., the LTK). To do this, we'll enable one configuration that prints out the LTK so we can enter it into the sniffer's software and decrypt the Bluetooth LE communication between the DK and the phone. Add the following (highlighted) line to the `prj.conf` file in the project: ```kconfig # # Copyright (c) 2022 Nordic Semiconductor ASA # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # CONFIG_BT_LOG_SNIFFER_INFO=y CONFIG_WIFI=y CONFIG_WIFI_NRF70=y CONFIG_NRF70_SR_COEX=y CONFIG_NRF70_SR_COEX_RF_SWITCH=y # WPA supplicant CONFIG_WIFI_NM_WPA_SUPPLICANT=y # Networking CONFIG_NETWORKING=y CONFIG_NET_SOCKETS=y CONFIG_NET_LOG=y CONFIG_NET_IPV6=n CONFIG_NET_IPV4=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_DHCPV4=y CONFIG_DNS_RESOLVER=y CONFIG_NET_STATISTICS=y CONFIG_NET_PKT_RX_COUNT=8 CONFIG_NET_PKT_TX_COUNT=8 # Below section is the primary contributor to SRAM and is currently # tuned for performance, but this will be revisited in the future. CONFIG_NET_BUF_RX_COUNT=16 CONFIG_NET_BUF_TX_COUNT=16 CONFIG_HEAP_MEM_POOL_SIZE=183600 CONFIG_NET_TC_TX_COUNT=1 CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1 CONFIG_NET_MAX_CONTEXTS=5 CONFIG_NET_CONTEXT_SYNC_RECV=y CONFIG_INIT_STACKS=y CONFIG_NET_L2_ETHERNET=y CONFIG_NET_CONFIG_SETTINGS=y CONFIG_NET_CONFIG_INIT_TIMEOUT=0 CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.165.100.150" CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.165.100.1" CONFIG_NET_SOCKETS_POLL_MAX=10 # Memories CONFIG_MAIN_STACK_SIZE=5200 CONFIG_NET_TX_STACK_SIZE=4096 CONFIG_NET_RX_STACK_SIZE=4096 # Debugging CONFIG_STACK_SENTINEL=y CONFIG_DEBUG_COREDUMP=y CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y # Kernel options CONFIG_ENTROPY_GENERATOR=y # Logging CONFIG_LOG=y CONFIG_NET_L2_WIFI_MGMT=y CONFIG_BT=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_BUF_ACL_RX_SIZE=151 CONFIG_BT_L2CAP_TX_MTU=147 CONFIG_BT_BUF_ACL_TX_SIZE=151 CONFIG_BT_RX_STACK_SIZE=5120 CONFIG_BT_BONDABLE=n CONFIG_BT_DEVICE_NAME_DYNAMIC=y CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_SETTINGS_NVS=y CONFIG_WIFI_CREDENTIALS=y CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES=1 CONFIG_NANOPB=y CONFIG_BT_WIFI_PROV=y CONFIG_BT_WIFI_PROV_LOG_LEVEL_INF=y CONFIG_WIFI_MGMT_EXT=y # Setting BT supervision timeout to 75units (750ms) to avoid timeout of BT connection when radio is granted to Wi-Fi during scan. CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=75 # Similar to shell sample, add this option to ensure the event can get served. CONFIG_NET_MGMT_EVENT_QUEUE_TIMEOUT=5000 ``` Now we're ready to re-build our project and flash it to the DK. Click the **Rebuild** button, then **Flash** to the DK: ![](https://downloads.novelbits.io/media/posts/ble-wifi-onboarding-provisioning/screen-recording-1.gif) **Rebuilding the project* ![](https://downloads.novelbits.io/media/posts/ble-wifi-onboarding-provisioning/screen-recording-2.gif) **Flashing the application* **Step #6:** Open a serial terminal program (such as PuTTY, minicom, Serial, or within nRF Connect Extension in VS Code): ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2025-03-04-at-10.44.22-E2-80-AFPM.png) **Serial Terminal Output* **Step #7:** Launch the nRF Wi-Fi Provisioner mobile app: - Click "Provision over Bluetooth LE." - The app will scan for specific devices advertising the WiFi Provisioning Service UUID. - Select your device from the list, and you should be presented with the following screen that asks you to Pair with the Bluetooth LE device (the nRF7002 DK). - Once you pair, the following screen will show up. Press "Scan," and the phone will then instruct the DK (over LE) to scan for nearby Wi-Fi access points and return the results to the phone to display to you. ***Click each image below to expand.*** Once the Wi-Fi scan results are back and shown to you, select the one you'd like the DK to connect to and scroll to the bottom of the screen to enter the password for the access point. From there, press "Set," and the phone will send a message containing the Wi-Fi network and the password to which to connect. Once this is successful, the app will show that the device is now provisioned and connected to the Wi-Fi network. ***Click each image below to expand.*** And that's it! 🎉 Now you've provisioned your Wi-Fi device (the nRF7002 DK in this case) to connect to the Wi-Fi network of choice. For more details on the Bluetooth LE packets involved and a live demo of the whole process, check out the video in the next section. ## Video Tutorial and Demo To see this in action, check out our demo video where we: - Unbox the nRF7002 DK - Use Bluetooth LE to provision an IoT device onto Wi-Fi - Walk through the mobile app experience - Demonstrate real-time provisioning status and feedback - Walkthrough of BLE sniffer capture of the process (plus explanation of steps) ## Conclusion Wi-Fi is essential for IoT devices and deployments, but onboarding devices remains a major challenge. Traditional provisioning methods are often frustrating, inconsistent, and unreliable. Bluetooth LE simplifies this process, providing a seamless, secure, and user-friendly alternative. By eliminating network switching issues and offering real-time feedback, BLE ensures a smoother onboarding experience. Nordic Semiconductor’s **nRF70 series**, combined with **nRF Connect SDK**, enables low-power, dual-radio IoT solutions that leverage BLE for onboarding and Wi-Fi for data transfer. By adopting Bluetooth LE-based provisioning, developers can enhance user experience, reduce support issues, and streamline deployments. ## References and Important Links Here are some important references and links to learn more about Wi-Fi provisioning, Nordic's Wi-Fi solutions, and Bluetooth LE-based Wi-Fi provisioning: - Wi-Fi Hardware - Nordic Wi-Fi solutions: [https://www.nordicsemi.com/Products/Wireless/WiFi](https://www.nordicsemi.com/Products/Wireless/WiFi?ref=novelbits.io) - nRF7002 DK: [https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK](https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK?ref=novelbits.io) - Wi-Fi Provisioning \[Nordic DevAcademy Wi-Fi Fundamentals course\]: [https://academy.nordicsemi.com/courses/wi-fi-fundamentals/lessons/lesson-2-wifi-fundamentals/topic/wifi-provisioning/](https://academy.nordicsemi.com/courses/wi-fi-fundamentals/lessons/lesson-2-wifi-fundamentals/topic/wifi-provisioning/?ref=novelbits.io) - Nordic Wi-Fi Provisioning Documentation: - [https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/wifi/provisioning/ble/README.html#wifi-provisioning](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/wifi/provisioning/ble/README.html?ref=novelbits.io#wifi-provisioning) - [https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/libraries/bluetooth\_services/services/wifi\_prov.html](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/libraries/bluetooth%5Fservices/services/wifi%5Fprov.html?ref=novelbits.io) - [https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/libraries/networking/wifi\_credentials.html](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/libraries/networking/wifi%5Fcredentials.html?ref=novelbits.io) ### 7 Reasons a Professional BLE Sniffer is Better Than a Low-cost Sniffer for Debugging URL: https://novelbits.io/professional-ble-sniffer-vs-low-cost-sniffer-debugging/ Last updated: 2026-04-08T17:50:54.000Z ## Introduction Debugging Bluetooth Low Energy (BLE) devices can be a challenge. Whether you’re developing wearables, medical devices, IoT sensors, or any other BLE-enabled product, reliable packet capture and analysis are crucial for ensuring smooth performance. But if you’ve ever tried troubleshooting BLE connections with a low-cost sniffer, you know the frustration—missed packets, incomplete data, and limited insights can turn debugging into a guessing game. This is where professional Bluetooth sniffers shine. Unlike their budget-friendly counterparts, these advanced tools provide **precise, real-time insights**, allowing developers to capture every packet, analyze RF environments, and even troubleshoot custom protocols with ease. In this article, we’ll explore **seven key reasons why a professional** [**Bluetooth sniffer**](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) **is worth the investment**—and how it can save you time, effort, and headaches. If you’re serious about BLE development, keep reading to learn why a high-quality sniffer isn’t just a tool—it can make a significant difference in your workflow. ## 1\. Mobility: Debug Anywhere, Anytime When debugging Bluetooth Low Energy (BLE) devices, flexibility is key. Traditional low-cost Bluetooth sniffers often require a connection to a PC, making field testing inconvenient. In contrast, a professional BLE sniffer like the **RFcreations mini-moreph** supports connecting directly to an Android smartphone, removing the need for bulky hardware setups and enabling convenient packet capture on the go. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/mini-morephc-android-scaled.jpg) *RFcreations mini-morephC* **The Importance of Mobility for BLE Debugging** Many Bluetooth-enabled devices, such as **wearables, smart home products, and automotive systems**, operate in real-world environments where issues arise due to **interference, signal range, or power fluctuations**. Being able to **capture packets in the actual deployment environment** can make the difference between **guessing at a bug** and **pinpointing the exact cause**. **Real-World Example: Debugging a Smart Lock in the Field** Imagine you’re testing a **BLE-enabled smart lock** that intermittently fails to respond to smartphone commands. The issue only happens **at a specific location**, possibly due to **RF interference or environmental factors**. With a **professional BLE sniffer**, you can: - Capture packets **on-site** without needing a bulky setup (without even a laptop). - Share the captures with your colleagues or back to your computer to **analyze BLE communication**. Without a mobile-friendly sniffer, you’d have to **replicate the issue in a lab**, which isn’t always possible—making debugging much harder. A professional BLE sniffer gives you **true mobility**, helping you debug **real-world Bluetooth issues faster and more efficiently** than a low-cost alternative tied to a fixed workstation. ## 2\. 2.4 GHz Spectrum Mastery: More Than Just Bluetooth Bluetooth Low Energy (BLE) operates in the **2.4 GHz ISM (Industrial, Scientific, and Medical) band**, which is **crowded with other wireless technologies** like Wi-Fi, Zigbee, and 802.15.4-based protocols (e.g., Thread and Matter). This shared spectrum can lead to **interference, degraded performance, and unpredictable behavior** in BLE devices—issues that can be extremely difficult to debug without the right tools. A **professional BLE sniffer** provides deep insights into the entire 2.4 GHz spectrum, allowing you to **see not just BLE packets, but also other wireless signals that may be causing interference**. **How 2.4 GHz Spectrum Analysis Helps** - **Interference Detection:** Identify **Wi-Fi congestion, Zigbee traffic, and other RF noise** that may be impacting BLE connections. - **Coexistence Testing:** Ensure your BLE device **performs reliably in real-world environments** with multiple wireless technologies. - **Channel Utilization Analysis:** BLE devices hop across **37 data channels**, but **Wi-Fi operates on overlapping frequencies**—a professional sniffer helps analyze this interaction. - **Optimized RF Performance:** Reduce **packet collisions, dropped connections, and latency issues** by selecting the best **advertising and connection channels** for BLE. Unlike low-cost sniffers that focus solely on **BLE packets**, a **professional Bluetooth sniffer** provides a **full-spectrum view of the 2.4 GHz environment** by offering: - **Spectrum Visualization** – See real-time RF activity across BLE, Wi-Fi, Zigbee, and proprietary 2.4 GHz protocols. - **Interference Heatmaps** – Identify which frequencies experience the most congestion. - **BLE + Wi-Fi Coexistence Testing** – Ensure that BLE and Wi-Fi **don’t interfere with each other** in dual-radio devices. - **Adaptive Debugging** – Adjust BLE advertising channels or connection parameters **based on real-world RF conditions**. **Real-World Example: Debugging BLE Performance in a Smart Home Device** Imagine you’re developing a **BLE-based smart lighting system** for a home environment, but customers report occasional **delays in responsiveness** when they use their smartphone app. The problem? **The lights work fine in the lab but are unreliable in real-world conditions.** With a **professional BLE sniffer**, you can: - Detect whether **Wi-Fi congestion** is interfering with BLE signals. - Analyze the **BLE connection parameters** to ensure they aren’t contributing to the issue. - Adjust **channel selection strategies** to avoid RF conflicts. Without full **2.4 GHz spectrum analysis**, debugging this kind of issue would be **frustrating, time-consuming, and imprecise**—making a professional sniffer an invaluable tool. A professional BLE sniffer doesn’t just capture Bluetooth packets—it helps you understand the full RF environment, ensuring your BLE devices coexist seamlessly with other wireless technologies and operate at peak performance. ## 3\. Capture Every Packet – Even in Noisy Environments When debugging Bluetooth Low Energy (BLE) devices, **missing even a single packet** can mean overlooking critical issues like **connection drops, pairing failures, or unexpected latency spikes**. Unfortunately, many **low-cost Bluetooth sniffers struggle in congested environments**, leading to incomplete or unreliable data capture. A **professional BLE sniffer** ensures **near-zero packet loss** by offering **high-fidelity packet capture** and **multi-channel monitoring** even in **RF-heavy environments** like offices, warehouses, and smart homes. **Reasons Why Capturing Every Packet Matters** - **Troubleshooting Connection Issues** – If your BLE device randomly disconnects, you need to see **every packet leading up to the failure** to diagnose the root cause. - **Verifying Advertising & Scanning Behavior** – Missing **advertising packets** can make debugging connection failures nearly impossible. - **Analyzing Multi-Device Interactions** – In complex IoT ecosystems, BLE devices communicate simultaneously—missing packets makes it harder to track **how they interact**. Unlike budget sniffers that may **drop packets due to RF congestion**, professional tools provide: - **Full BLE Packet Capture** – No gaps, ensuring complete visibility into connection events, encryption handshakes, and data exchanges. - **Multi-Channel Sniffing** – Capture packets from multiple BLE devices at once, even if they are operating on different frequencies. - **High Sensitivity Receivers** – Detect weak signals that cheap sniffers might miss, crucial for debugging **low-power BLE devices**. **Real-World Example: Debugging Intermittent BLE Disconnections** Imagine you’re developing a **BLE-connected fitness tracker**, and some users report **random disconnections** while using it in a **crowded gym**. The issue isn’t reproducible in your lab, making it difficult to diagnose. With a **professional BLE sniffer**, you can: - Capture **every advertising and connection packet** in real-time. - Monitor for **interference from nearby Wi-Fi and BLE devices**. - Identify whether **packet collisions, signal fading, or firmware issues** are causing the disconnections. A low-cost sniffer might **miss critical packets**, leaving you with an incomplete picture of the problem. A professional BLE sniffer ensures that no packets are lost, giving developers full visibility into Bluetooth communication, even in RF-heavy environments. This level of accuracy is essential for troubleshooting connection failures, optimizing performance, and ensuring reliable BLE device operation. ## 4\. Real-Time LE Audio Sniffing and Playback With the rise of **Bluetooth LE Audio**, developers now need **more advanced debugging tools** to capture, analyze, and even listen to BLE audio packets in real-time. Unlike traditional Bluetooth Classic audio, **LE Audio introduces features like multi-stream audio, lower power consumption, and improved quality**, making it crucial to have a sniffer that can **properly decode and analyze these packets**. A **professional Bluetooth sniffer** goes beyond capturing raw data—it allows **real-time audio sniffing, playback, debugging** of LE audio frames, and analyzing audio latency metrics making it an essential tool for developers working on **wireless earbuds, hearing aids, and other LE Audio devices**. For example, pairing one of the RFcreations Bluetooth sniffers (mini-moreph or moreph30) with an **audiopod** allows you to analyze in real-time the various audio latency measurements of your setup. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/apandmm.png) *RFcreations mini-moreph paired with an audiopod* **Why Real-Time LE Audio Sniffing is Essential** - **Verify Audio Synchronization** – Ensure that multiple audio streams (e.g., left and right earbuds) stay in perfect sync. - **Debug Codec & Compression Issues** – Analyze packet loss or audio quality degradation due to **LC3 codec** misconfigurations. - **Detect Latency Issues** – Measure transmission delays and troubleshoot lip-sync problems in **wireless audio applications**. - **Monitor Audio in Real-Time** – Listen to live BLE audio transmissions for faster debugging and validation. Unlike basic sniffers that only capture **raw data**, a professional sniffer offers: - **Real-Time Audio Playback** – Directly listen to LE Audio frames in real-time as they are transmitted. - **Multi-Stream Analysis** – Debug **Auracast™ broadcasts**, **binaural audio**, and multi-device synchronization. - **Packet Loss & Jitter Monitoring** – Identify **audio dropouts, buffering issues, or excessive latency**. - **Detailed LC3 Codec Inspection** – Ensure that the **new LE Audio codec is implemented correctly** for maximum efficiency. **Real-World Example: Debugging Audio Dropouts in Wireless Earbuds** Imagine you’re developing a pair of **LE Audio-enabled wireless earbuds**, but some users report **occasional audio glitches** when they move between rooms. With a **professional Bluetooth sniffer**, you can: - Capture and **listen to real-time audio streams** to detect distortions. - Analyze **latency and packet jitter** to pinpoint timing issues. - Monitor **multi-stream synchronization** between the left and right earbuds. - Identify **packet loss patterns** caused by interference from Wi-Fi or other BLE devices. Without real-time audio sniffing, debugging LE Audio issues would be **significantly harder and more time-consuming**. For developers working on **LE Audio devices**, a **professional BLE sniffer** with **real-time playback** is a **essential capability**, allowing for **faster troubleshooting, better synchronization, and improved audio quality**. ## 5\. Replay RF Environments for Advanced Debugging One of the biggest challenges in BLE debugging is **reproducing intermittent issues**—problems that only occur in specific conditions, such as a **certain location, time of day, or when multiple devices are active**. Manually recreating these conditions is often difficult, if not impossible. A **professional BLE sniffer** eliminates the guesswork by allowing developers to **record and replay RF environments**, making it easier to debug real-world connectivity problems. For example, the **RFcreations morephE** precisely addresses this scenario. It allows you to capture up to 3 hours and 40 minutes of the full 2.4 GHz spectrum and then replay it (fully or partially) for recreation of a specific real-world environment. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/moreph30-etherstore-for-pb.png) *RFcreations morephE (capture and replay full 2.4 GHz spectrum)* **How RF Replay Can Help** - **Diagnose Intermittent Failures** – Capture and replay exact RF conditions when a **connection drops or a device malfunctions**. - **Analyze Interference Patterns** – Identify **Wi-Fi congestion, Zigbee traffic, or other RF interference** affecting BLE performance. - **Improve Regression Testing** – Reuse captured RF environments to test **firmware updates and new device versions** without needing to reproduce conditions manually. Unlike budget sniffers that only provide **live packet capture**, professional BLE sniffers offer: - **RF Recording & Playback** – Save RF activity **exactly as it happened** and replay it for debugging. - **Time-Synchronized Event Analysis** – View precise **timing relationships** between BLE packets and RF interference sources. - **Multi-Device Interaction Capture** – Record BLE communication **from multiple devices simultaneously** to analyze complex interactions. - **Repeatable Debugging** – Developers can test **new firmware versions** under the exact same RF conditions. **Real-World Example: Debugging BLE Dropouts in a Smart Fitness Tracker** Imagine you’re developing a **BLE-based fitness tracker**, and users report that **heart rate monitoring fails randomly** in crowded gyms. The issue is difficult to reproduce in the lab. With a professional Bluetooth sniffer like the **morephE from RFcreations**, you can: - **Record** BLE and RF activity in a gym to capture the real-world interference. - **Replay** that environment in the lab to analyze the device’s response. - **Compare different firmware versions** under identical conditions to see if an update fixes the issue. - **Identify specific RF conditions** (e.g., peak gym hours with heavy Wi-Fi usage) that trigger failures. Without **RF replay capabilities**, debugging such issues would require **on-site testing each time**, which is **time-consuming and unreliable**. A **professional BLE sniffer** with **RF recording and playback** enables developers to **capture, analyze, and reproduce real-world conditions**, making debugging **intermittent BLE issues easier and more efficient**. ## 6\. Optimize Throughput Without The Guesswork Bluetooth Low Energy (BLE) is designed for power efficiency, but **optimizing throughput** is crucial for applications that require **fast data transfer**—such as **sensor networks, file transfers, and streaming applications**. However, many factors affect BLE throughput, including **PHY settings, connection intervals, MTU size, and packet structure**. A **professional BLE sniffer** provides **detailed throughput analysis**, allowing developers to **fine-tune their BLE settings for maximum efficiency** without relying on trial and error. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/sniffer-img1.png) *Analyzing Data Throughput using an RFcreations Bluetooth sniffer and blueSPY* **Why Throughput Optimization Makes a Difference** - **Maximize Data Transfer Speed** – Bluetooth v5.0 (and later) supports higher data rates, but only with the **right PHY settings and connection parameters**. - **Balance Power Consumption** – Higher throughput often means **higher power usage**, so it’s crucial to find the optimal trade-off. - **Ensure Reliable Performance** – Avoid **packet loss, retransmissions, and congestion issues** that can reduce throughput. Unlike low-cost sniffers that only provide **basic packet capture**, a professional BLE sniffer offers: - **Live Throughput Monitoring** – Measure **actual data transfer rates** in real time. - **PHY & Connection Parameter Analysis** – Analyze settings like **2M PHY, Coded PHY (Long Range), and connection intervals**. - **MTU & Data Length Optimization** – Evaluate **Maximum Transmission Unit (MTU) and Data Length Extension (DLE)** to maximize efficiency. - **Error Rate & Retransmission Analysis** – Detect **packet loss, retries, and congestion** that affect throughput. **Real-World Example: Optimizing Data Transfer in a BLE-connected Medical Device** Imagine you’re developing a **BLE-based glucose monitor** that transmits large amounts of sensor data to a smartphone. Users report **slow data transfer speeds**, causing frustration. With a **professional BLE sniffer**, you can: - Measure **actual vs. expected throughput** and identify bottlenecks. - Adjust **connection intervals and MTU size** to increase data transfer efficiency. - Test **different PHY settings** (1M, 2M, Coded PHY) to find the best balance of speed and range. - Reduce **packet retransmissions** by identifying interference sources. Without proper throughput analysis, **developers may waste time tweaking settings blindly** without knowing what’s actually affecting performance. A **professional BLE sniffer** helps developers **optimize throughput with precision**, ensuring **faster data transfer, lower latency, and efficient power usage**—all without guesswork. ## 7\. Multi-Device Synchronization: Capture Traffic from Multiple BLE Devices Simultaneously Many modern BLE applications involve **multiple devices communicating at the same time**—such as **wireless earbuds, smart home ecosystems, medical monitoring systems, and industrial IoT networks**. Debugging these **multi-device interactions** is nearly impossible with a basic Bluetooth sniffer that can only track **one connection at a time**. A **professional BLE sniffer** allows developers to **capture and analyze traffic from multiple BLE devices at once**, including all advertisements and connections across different devices. This ensures that all communication of interest is captured and ready for analysis. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/sniffer-img2.png) *Capturing multiple connections simultaneously using RFcreations mini-moreph and blueSPY* **The Importance of Multi-Device Sniffing** - **Debug Complex Interactions** – Track BLE communication between **peripheral and central devices** in real-world scenarios. - **Analyze Cross-Device Latency & Synchronization** – Ensure that devices like **LE Audio earbuds or smart home sensors** stay in perfect sync. - **Improve Multi-Device Performance** – Optimize connection parameters for environments where **multiple BLE devices operate simultaneously**. Unlike low-cost sniffers that can only monitor **one BLE connection at a time**, a professional BLE sniffer offers: - **Multi-Device Capture** – Track **multiple concurrent BLE connections** with timestamps and event correlation. - **Cross-Device Timing Analysis** – Measure synchronization **between multiple BLE peripherals and a central device**. - **Multi-Channel Monitoring** – Capture packets across different BLE channels to analyze **coexistence and interference effects**. - **Traffic Filtering by Device** – Quickly isolate and inspect packets from **specific BLE devices** in complex environments. A **professional BLE sniffer** provides **multi-device capture and analysis**, allowing developers to **debug complex BLE interactions, ensure synchronization, and optimize multi-device performance** in **IoT, audio, medical, and industrial applications**. ## **Final Thoughts: Why a Professional BLE Sniffer is a Must-Have for Serious Developers** Debugging Bluetooth Low Energy (BLE) devices requires **precision, efficiency, and reliability**—things that **low-cost Bluetooth sniffers simply can’t deliver**. Whether you’re troubleshooting **intermittent connection drops, optimizing throughput, debugging LE Audio, or analyzing multi-device synchronization**, a **professional BLE sniffer** provides the **advanced capabilities needed to capture every packet, eliminate guesswork, and accelerate development**. ### **Key Takeaways:** - **Capture every packet**—even in noisy RF environments. - **Analyze full 2.4 GHz spectrum** for interference and coexistence testing. - **Debug multi-device synchronization** in IoT ecosystems. - **Optimize latency, throughput, and power efficiency.** - **Replay RF environments** to reproduce and fix intermittent issues. If you’re serious about **BLE development, testing, or debugging**, investing in a **professional BLE sniffer** isn’t just an upgrade—it's a necessity. --- ## Ready to Elevate Your Bluetooth Debugging? Schedule a demo to see RFcreations professional sniffers in action and discuss your specific testing requirements. [Book a Demo](https://calendly.com/novelbits/bluetooth-sniffer-tools?ref=novelbits.io) [Contact Us](https://novelbits.io/contact/) ### Introducing Channel Sounding: Secure Fine-Ranging using Bluetooth LE URL: https://novelbits.io/introduction-to-channel-sounding/ Last updated: 2026-05-01T15:53:33.000Z *Sponsored by [Nordic Semiconductor](https://nordicsemi.com/?ref=novelbits.io)* The release of **Bluetooth 6.0** marks a significant milestone in the evolution of Bluetooth technology, introducing **Channel Sounding**, a groundbreaking feature for **precise distance measurement**. With this advancement, Bluetooth Low Energy (BLE) devices can now estimate distances with **sub-meter accuracy**, enabling a wide range of new applications and enhancing existing ones. In this blog post, we’ll delve into what Bluetooth Channel Sounding is, why it’s important, and how it has the potential to transform industries such as **industrial automation**, **healthcare**, **consumer electronics**, and many more! ## **The Need for Channel Sounding** Bluetooth technology is already widely used in billions of devices, offering reliable wireless connectivity for data exchange. However, its ability to provide accurate distance measurements has historically been limited, relying on techniques like **Received Signal Strength Indication (RSSI)** and **Direction Finding (AoA/AoD)**. ### **Limitations of Existing Methods** - **RSSI (Received Signal Strength Indication):** RSSI measures the strength of the signal between two devices to estimate distance. While simple and low-cost, it is highly sensitive to environmental interference, leading to inaccuracies of up to **3-5 meters**, especially in environments with walls, human bodies, furniture, or other obstacles. The one advantage it has over other methods is that it's available for all devices, regardless of communication topology or Bluetooth version used. - **Direction Finding (AoA/AoD):** Direction Finding improves upon RSSI by measuring the angle of arrival or departure of signals to estimate distance. However, it requires additional hardware, such as multiple locators, each with antenna arrays, which can significantly increase cost and complexity. Its accuracy can also degrade in multipath environments, where signals reflect off surfaces before reaching their destination. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/rssi-and-direction-finding.gif) ### **The Demand for Precision and Security** The rise of **IoT**, **smart devices**, and **automation** has driven the need for highly accurate, secure, cost-effective, and reliable proximity-based solutions. Applications like **remote keyless entry systems** **(RKE**) and **industrial asset tracking** require precise distance measurements that existing methods cannot consistently provide. Channel Sounding fills this gap by offering a robust solution that's accurate, secure, and low-cost. ## **What is Bluetooth Channel Sounding?** Bluetooth Channel Sounding is a new feature introduced in **Bluetooth 6.0** that enables devices to measure distance with **sub-meter accuracy**. It combines advanced signal processing techniques to deliver precise and reliable proximity measurements, even in challenging environments. At its core, Channel Sounding is designed to: 1\. Provide **precise distance measurements** in real time. 2\. Enhance **security** by preventing attacks like signal spoofing or relay attacks. 3\. Operate effectively in **complex environments**, such as indoor spaces with significant interference or multipath effects. Channel Sounding achieves this by leveraging two complementary methods: • **Phase-Based Ranging (PBR):** Measures the phase differences of signals exchanged between devices to calculate distance. • **Round-Trip Time (RTT):** Determines distance by measuring the time it takes for a signal to travel between devices and return. These methods work together to ensure both accuracy and security. PBR provides accurate distance measurement, and RTT is mainly used to address security. They can be used independently or in combination. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/channel-sounding-security-1.gif) ## **How Bluetooth Channel Sounding Works** Channel Sounding operates in a **one-to-one topology**, meaning only between **connected** Bluetooth LE devices. It defines 79 channels in a new PHY (in contrast to 40 channels in the standard LE operation), of which only 72 are used. One device acts as the **Initiator**, while the other serves as the **Reflector**. Each of these roles can be assumed by either the LE Peripheral or Central. It can operate either over a single antenna path (single antenna on each end) or with multiple antenna paths (up to 4—e.g., a dual antenna configuration on each end). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/initiator-vs-reflector.gif) The Channel Sounding process involves several modes of operation, each designed to handle specific aspects of the ranging procedure: - **Mode-0:** Synchronization between the devices and basic information exchange. - **Mode-1:** Round-Trip Timing (RTT) packets are exchanged to verify and secure the distance measurement. - **Mode-2:** Unmodulated tones are transmitted for Phase-Based Ranging (PBR), allowing for highly accurate distance calculations. - **Mode-3 (Optional):** Combines RTT and PBR to enhance the measurement’s precision and security. By utilizing multiple frequency channels within the **2.4 GHz spectrum**, Channel Sounding minimizes interference and improves reliability, even in environments with significant signal reflections. ### Phase-Based Ranging (PBR) In simplified terms, the basic operation of PBR is as follows: - The wavelength is known for a specific frequency - The transmitter sends a signal at a known phase on a specific frequency - The receiver then reflects the signal at the exact phase it was received (basically, a continuation of the original signal) - The phase is then recorded at the transmitter of the signal sent back by the reflector - This is repeated for different frequencies to account for multi-path - Based on the phase measurements from the operation over the different frequencies, the distance calculation is performed ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/channel-sounding-pbr-1.png) **Credit**: *[Bluetooth SIG Channel Sounding Technical Overview](https://www.bluetooth.com/channel-sounding-tech-overview/?ref=novelbits.io)* ### Round-Trip Timing (RTT) In simplified terms, the basic operation of RTT is as follows: - Based on the fact that RF transmissions travel at the speed of light, which is constant, the distance between two points is calculated using the time it takes for the signal to travel between these two points - For round-trip, the time would be for 2x the distance - The initiator takes into account the turnaround time (which corresponds to the processing time of the signal at the reflector before it is transmitted back to the initiator) - The figure below showcases how this works. ToD: Time of Departure, ToA: Time of Arrival, ToF: Time of Flight. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/channel-sounding-rtt.png) **Distance ambiguity** refers to the fact that after a certain distance, the difference between the phases will not result in a single distance measurement. This occurs **after around 150 m**. To work around this, the second method, Round-Trip Timing (RTT), can be used in conjunction with PBR to provide a more accurate distance measurement. ### Distance Calculation Algorithms One caveat of the Channel Sounding spec is that it does not define the algorithm(s) for the actual distance measurement. Instead, it defines the process and procedures for producing the raw data that goes into the distance calculation algorithm(s). This is the responsibility of the application and higher-level implementation. ## **Key Benefits of Channel Sounding** **1\. Increased Accuracy** Channel Sounding enables devices to measure distances with unprecedented precision. This is essential for applications like **keyless entry systems**, where minor inaccuracies can lead to false activations or security risks. Another application that can highly benefit from Channel Sounding and its more accurate ranging characteristics is in **safety-critical operations**. Imagine, for example, that a dangerous machine requires its operator to either: - Operate at a **minimum safe distance** - Or operate **within a specific proximity/distance** of the machine In both scenarios, Channel Sounding can be used to authenticate the operator *and* ensure they are within the required distance/zone before operating the machine (typically via their smartphone/tablet/remote control). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/safety-critical-v3.gif) Scenario where a machine requires the *user to operate from a minimum safe distance* **2\. Enhanced Security** With **Round-Trip Time (RTT)**, Channel Sounding introduces secure distance measurement mechanisms that protect against **relay attacks** and other forms of signal spoofing. This makes it particularly valuable for proximity-based security applications. **3\. Reliable Performance in Complex Environments** Channel Sounding’s ability to operate across multiple frequency channels reduces the impact of interference and multipath effects, ensuring consistent and reliable performance in indoor and industrial settings. **4\. Broad Applicability** Channel Sounding is flexible enough to support a wide range of use cases, from consumer electronics and healthcare devices to industrial automation and logistics. Beyond access control, ranging will find use in reliable presence detection, distance estimation, and various other applications yet to be fully explored. ## **Applications of Bluetooth Channel Sounding** **1\. Remote Keyless Entry Systems (RKE)** Channel Sounding allows a machine to detect a remote control (or key fob) with **high precision**, ensuring that a door or any other access control system activates only when the user is within a specific range. This reduces false activations and enhances security. **2\. Asset Tracking and Logistics** In industries like warehousing and shipping, accurate location tracking is essential. Channel Sounding enables **real-time monitoring** of assets, improving efficiency and reducing errors. This application will probably be limited regarding the number of assets that can be monitored since Channel Sounding requires a connection between devices. **3\. Collaborative Robotics** Industrial robots often work in environments where precise distance measurement is critical to avoid collisions and enable synchronized operations. Channel Sounding ensures robots can operate safely and effectively in these shared spaces. **4\. Healthcare and Medical Devices** Channel Sounding can enhan ce **patient monitoring, equipment tracking, and real-time location systems** for critical resources in healthcare applications. **Note:** Some of these applications will be limited in terms of the number of devices that can be monitored via Channel Sounding. This is due to the fact that it *currently* requires a connection between devices. However, this may change in the future if/when connectionless communication becomes supported. ## Channel Sounding Support on Nordic Semiconductor SoCs In terms of support for Channel Sounding on the Nordic Semiconductor platforms, here are a few points to take note of: - The Softdevice Controller Subsystem and nRF Connect SDK Host for Channel sounding basics are already available in the SDK. - The existing support provides the bare basics for developers eager to start using this exciting new feature in their projects. - Samples with a certified Controller and Host will be available later in 2025. - These samples will provide the easiest way for developers to start designing Channel Sounding applications. - The functionality will be available on the **nRF54L15,** to begin with. ## **The Future of Bluetooth Channel Sounding** As industries continue to adopt **proximity-based solutions**, the need for accurate and secure distance measurement will only grow. Bluetooth Channel Sounding is poised to become a cornerstone technology, unlocking new possibilities in **IoT**, **automation**, **consumer electronics**, and beyond. Future developments may focus on: - Improving energy efficiency for battery-powered devices. - Expanding support across mobile platforms to enable seamless integration. - Enabling more complex topologies for multi-device environments. Major potential with Channel Sounding will be achieved if/once it becomes supported on smartphones, which seems very promising at the moment! ## **Conclusion** Bluetooth Channel Sounding is a transformative technology that addresses the limitations of traditional distance measurement methods, offering **unmatched accuracy**, **robust security**, and **reliable performance** in real-world environments. From enabling smarter keyless entry systems to enhancing industrial automation, its applications are as diverse as they are impactful. As Bluetooth technology continues to evolve, Channel Sounding is set to play a pivotal role in shaping the future of wireless connectivity, bridging the gap between precision and practicality in a wide range of industries. Free 12-Day Email Course Learn Bluetooth LE in 12 Days A free crash course delivered to your inbox. One lesson per day — just the fundamentals you need to start building. Start the Free Course Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. 💡 **Insider Tip:** Want to learn Bluetooth Low Energy in depth, including hands-on projects and advanced topics like Channel Sounding? Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) for comprehensive courses that take you from beginner to expert! ### nRF54L15 vs nRF52840 First Impressions and Power Tests URL: https://novelbits.io/nrf54l15-unboxing-first-impressions/ Last updated: 2026-05-12T12:21:13.000Z *Sponsored by Nordic Semiconductor.* Nordic Semiconductor has once again raised the bar in wireless technology by introducing the nRF54L series of System-on-Chips (SoCs). An evolution of the popular nRF52 series, this new chip brings significant improvements in processing power, energy efficiency, and wireless capabilities. In this post, I'll be diving into my first impressions of the Flagship SoC within the nRF54L series, the nRF54L15\. I'll also provide a comparison to its very popular predecessor, the nRF52840 SoC. ## Background and History It's been about a decade since Nordic Semiconductor released the nRF52 series of SoCs! This series, with the nRF52840 being the flagship SoC, became one of the most popular Bluetooth LE chipsets on the market, found in everything from smart appliances to beacons to wearables, medical devices, and a lot more. Nordic Semiconductor has built its reputation not just on its cutting-edge SoCs but also on the developer tools and frameworks it provides. Over time, Nordic’s development environment went through a significant transformation—from nRF5 SDK and Segger Embedded Studio to the more modern Zephyr RTOS and Visual Studio Code (VS Code). This shift, while challenging, has proven to be an investment and a risk worth taking. For many years, the **nRF5 SDK** served as the primary development platform for Nordic’s SoCs. This framework offered simplicity and reliability. Despite its strengths, the SDK’s limitations began to emerge. From its single-threaded nature to its tight coupling with the SoftDevice, it was less suitable for more complex or concurrent applications, particularly as IoT requirements grew. As IoT and BLE applications evolved, Nordic shifted its focus toward the open-source **Zephyr RTOS**. This marked a significant pivot in its development strategy but sparked excitement and controversy. As part of the transition, Nordic introduced the **nRF Connect SDK** (to replace the nRF5 SDK). Nordic’s evolution from the nRF5 SDK and SES to Zephyr and VS Code reflects a forward-looking strategy that prepares its ecosystem for the future of IoT. While the shift was not without challenges, it ultimately enabled more robust and scalable solutions for developers worldwide. But how does this fit within the context of releasing the new nRF54L SoC series? We'll find out in the "First Impressions and Hands-On" section! ## Features Overview The nR54L series is the first from Nordic to use the 22nm process node. It also includes a RISC-V processor for the first time. Let's take a look at the most important features of the nRF54L15 SoC, while also comparing it with the nRF52 series Flagship SoC, the nRF52840 SoC. ### Key Improvements Over the nRF52840 - **Processing Power:** The nRF54L15 doubles the clock speed from 64 MHz to 128 MHz, providing a significant boost in processing capabilities. - **Energy Efficiency:** Despite the increased power, the new 22 nm process allows for improved energy efficiency, crucial for battery-powered IoT devices. - **Wireless Capabilities:** Support for Bluetooth 6.0 and Channel Sounding puts the nRF54L15 at the forefront of Bluetooth technology. - **Memory:** An increase to 1.5 MB of memory (compared to 1 MB in the nRF52840) allows for more complex applications and larger codebases. - **ADC Resolution:** The upgrade from a 12-bit to a 14-bit ADC provides more precise analog-to-digital conversion, beneficial for sensitive sensor applications. - **Size:** The nRF54L15 comes in an incredibly small 2.4x2.2 mm WLCSP package, significantly smaller than the nRF52840's 3.544 x 3.607 mm package. ## Other Notable New Features The nRF54L15 introduces several new features that set it apart: - **Improved Radio Performance:** With better receiver sensitivity and a new 4 Mbps proprietary mode, the nRF54L15 offers enhanced range and data throughput capabilities. - **Global RTC in System OFF mode:** This feature allows for ultra-low power timekeeping, enabling new use cases for long-term battery-operated devices. - **Enhanced Security Features:** The nRF54L15 includes advanced security features like TrustZone isolation, a new cryptographic engine with side-channel leakage protection, and tamper detectors that can detect an attack in progress and take appropriate action. The nRF54L Series provides a complete set of features to comply with current regulatory requirements. - **An additional processor for time-critical tasks:** The nRF54L adds a RISC-V processor for handling time-critical tasks is a significant advancement, allowing for more efficient task distribution and potentially reducing the need for external ICs. ## Power Consumption and Current Draw Highlights Following is a diagram showcasing the power efficiency and low-power features of the nRF54L series in various scenarios: ![](https://novelbits.io/content/files/2025/07/block_diagram_table-svg.xml) *Source: [Nordic Semiconductor documentation for nRF54L15](https://docs.nordicsemi.com/bundle/ps%5Fnrf54L15/page/keyfeatures%5Fhtml5.html?ref=novelbits.io)* ## First Impressions and Hands-On Development with nRF54L15 DK I got my hands on a couple of nRF54L15 DKs a few weeks before its release. From the outside, the packaging looks very familiar and similar to previous DKs (nRF5340 DK, nRF52840 DK, etc.), but the inside is a different story! For comparison, here's a closer look at both the nRF54L15 DK and the nRF52840 DK: ![nRF54L15 DK](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nrf54l15-dk-0-9-0_prod_page-1.png) **nRF54L15 DK** **Source*: [nRF54L15 DK Product Listing Page](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK?ref=novelbits.io)* ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nrf52840-dk-prod-page.png) **nRF52840 DK** **Source*: [nRF52840 DK Product Listing Pag](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK?ref=novelbits.io)[e](https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK?ref=novelbits.io)* Here are a few things that I like about this new DK form factor: - The DK is more compact (especially compared to the nRF52840 DK), less "busy," and has a cleaner/simpler layout. - The DK now features a USB-C interface rather than a Micro-USB interface. - The DK is ready out-of-the-box for current draw and power consumption measurements using the Power Profiler Kit II (previously, you'd have to cut a PCB trace to prepare the DK for current measurements, but this *is no longer the case*). You'll notice the move away from the Arduino-compatible pin header configuration. The one thing I wish it had (available on previous DKs) is built-in coin cell battery support, though it is not a deal-breaker. ### nRF Connect SDK and Development Getting started with the nRF54L15 DK is a breeze. It's just like developing for any of the Nordic DKs. It has out-of-box support in the nRF Connect SDK (≥ v2.8.0). > **If this is your first time working with a Nordic DK, then I highly recommend following the step-by-step tutorial available in Nordic's DevAcademy in the nRF Connect SDK Fundamentals Course for installing and setting up the nRF Connect SDK. Ensure that you install nRF Connect SDK version 2.8.0\. You can find the installation lesson** [**here**](https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-1-nrf-connect-sdk-introduction/topic/exercise-1-1/?ref=novelbits.io)**.** Once you've got everything set up, then you can simply create a project based on any of the existing samples available in the nRF Connect SDK or Zephyr: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Recording-2024-11-19-at-2.35.54-E2-80-AFPM-1.gif) **Click to enlarge the image.** The next step is to add a Build Configuration for the nRF54L15 DK: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Recording-2024-11-19-at-2.41.59-E2-80-AFPM-3.gif) **Click to enlarge the image.** That's how simple it is! Basically, it's just like creating a project for any of the previous Nordic Semiconductor DKs. Another tool available for the nRF54L series is the Board Configurator Tool, part of the nRF Connect for Desktop application. This tool is unavailable when working with any of the nRF52 series DKs or even the nRF5340 DK. The tool allows you to update the configuration of the board controller on the nRF54L15 DK. Here's what this looks like: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2024-11-22-at-8.56.02-E2-80-AFPM.png) **Click to enlarge the image.** ## Power Consumption Comparison: nRF54L15 vs nRF52840 One of the significant upgrades in the nRF54L series compared to the nRF52 series is more power efficiency, leading to lower power consumption. As you probably know, power consumption is one of the most critical aspects of building a Bluetooth LE-connected device. Since we are focused on Bluetooth LE functionality, it only makes sense to compare the nRF54L to its predecessor, the nRF52, from the aspect of power consumption and current draw during Bluetooth LE operations. To make this an "*apples to apples*" comparison, we'll use the same sample application, configure it for each board, then run it and compare the current draw in various scenarios. For measuring the current draw and power consumption, we'll be using the Power Profiler Kit II, another great hardware tool that Nordic provides that is very cost-effective. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ppk2_topview_transparent.png) ***Source:*** *[Nordic Semiconductor Power Profiler Kit II Product Page](https://www.nordicsemi.com/Products/Development-hardware/Power-Profiler-Kit-2?ref=novelbits.io)* ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2024-11-24-at-6.40.38-E2-80-AFPM.png) Power Profiler App \[part of nRF Connect for Desktop\] - (Example Setup) **Click to enlarge the image.** The Power Profiler Kit II is a handy hardware tool that allows us to measure current draw from as low as sub-uA and as high as 1A. Another useful tool available to us without any hardware is [Nordic's Online Power Profiler tool](https://devzone.nordicsemi.com/power/w/opp/2/online-power-profiler-for-bluetooth-le?ref=novelbits.io), which allows us to estimate the current draw based on the SoC used and the parameters configured for a Bluetooth Low Energy application. Here is what it looks like: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-3.png) ### Test Setup For testing, we'll be using the popular [LED Button Service Peripheral sample application](https://github.com/nrfconnect/sdk-nrf/tree/main/samples/bluetooth/peripheral%5Flbs?ref=novelbits.io), which operates as a simple Bluetooth LE peripheral device, advertising in connectable mode and then allowing a central device to control the LED (turn it on/off) and receive notifications of the Button 0 presses on the DK. We'll be running different tests that represent common Bluetooth LE scenarios: - Advertising mode - Connection mode For each of these, we'll measure the: - Overall average current draw (averaged over a period of 10 seconds) - Average current draw in active radio mode **Project Configuration Setup** As part of the standard setup for all test cases, we'll add the `prj_minimal.conf` configuration file to the project. This configuration disables several features (e.g., console, serial interface, logging, and more), reducing code size, memory usage, and power consumption. To do this, add the `prj_minimal.conf` file to the configuration during the Build Configuration step as shown below: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2024-11-24-at-6.11.41-E2-80-AFPM.png) In addition, we will disable the **Scan Response data** in the advertising setup to remove any inconsistencies across the various advertising events. We can do so by modifying the following line in `main.c` (line 236) to set the **4th and 5th parameters** toNULL and zero, respectively: err = bt\_le\_adv\_start(BT\_LE\_ADV\_CONN, ad, ARRAY\_SIZE(ad), NULL, 0); **Power Profiler App Setup** The default voltage supplied to the nRF54L15 is 1.8 V, while on the nRF52840 DK, the default voltage is 3.0 V. To have an accurate comparison between the two platforms in each of the tests, we'll be using the Power Profiler Kit II in the **Source Meter** mode, enabling the power output, and configuring it to 3.0 V: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2024-11-24-at-6.23.21-E2-80-AFPM.png) Ok, now we're ready to start running the different tests. --- #### Test Case #1: Advertising mode (100 ms interval) This is the default setting for the LBS Peripheral example, so no change to the code is needed. **nRF52840** (click images to enlarge): Overall average current draw: **100.74 uA** Average current draw in active radio mode: **2.77 mA** **nRF54L15** **(click images to enlarge):** Overall average current draw: **79.02 uA** Average current draw in active radio mode: **2.17 mA** --- #### Test Case #2: During the connection state (no user activity) To run this test, we don't need to make any code changes. But we'll be using the nRF Connect for Mobile app to connect to our peripheral (the DK): ![nRF Connect for Mobile app showing BLE peripheral connection](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_543954a0f622-1-jpeg.jpg) **nRF52840** **(click images to enlarge):** Overall average current draw: **123.52 uA** Average current draw in active radio mode: **1.55 mA** **nRF54L15** **(click images to enlarge):** Overall average current draw: **84.06 uA** Average current draw in active radio mode: **1.24 mA** --- ## Final Thoughts & Next Steps As you can see from all the tests and current draw measurements, the nRF54L15 outperforms the nRF52840 in all aspects and scenarios. This marks a new era of Bluetooth LE SoCs, enabling devices with a smaller footprint, lower power consumption, longer battery life, and more processing power, all enabled with the help of the powerful nRF Connect SDK. Free Course nRF54L15 Deep Dive — Free 8-Module Course Learn the key hardware features of Nordic Semiconductor's nRF54L15 by building a heart rate monitor from scratch. 8 modules, 23 hands-on lessons covering SAADC, DPPI, GRTC, Bluetooth LE, security, and power measurement. [Enroll Free →](https://learn.novelbits.io/courses/nrf54l15-deep-dive?ref=novelbits.io) In partnership with Nordic Semiconductor. No payment required. ## Resources and Additional Information Here are some links to resources that you may find helpful: - [Installing the nRF Connect SDK (from the Nordic DevAcademy "nRF Connect SDK Fundamentals" course)](https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-1-nrf-connect-sdk-introduction/topic/exercise-1-1/?ref=novelbits.io) - [nRF54L15 Product Page](https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK?ref=novelbits.io) - [nRF54L15 Datasheet & Documentation](https://docs.nordicsemi.com/bundle/ps%5Fnrf54L15/page/keyfeatures%5Fhtml5.html?ref=novelbits.io) - [nRF54L15 DK Documentation](https://docs.nordicsemi.com/bundle/ug%5Fnrf54l15%5Fdk/page/UG/nRF54L15%5FDK/intro/intro.html?ref=novelbits.io) - [Online Power Profiler](https://devzone.nordicsemi.com/power/w/opp/2/online-power-profiler-for-bluetooth-le?ref=novelbits.io) - YouTube video demos of nRF54L15: - [nRF54L vs nRF52 - What's New in Nordic Semiconductor's Latest Release?](https://www.youtube.com/watch?v=AG7FEgWj6CQ&ref=novelbits.io) - [nRF54L vs nRF52 Demo with Nordic Semiconductor](https://www.youtube.com/watch?v=E0kzPo91so4&ref=novelbits.io) - [nRF54L Series now widely available for development](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/nrf54l-series-now-widely-available-for-development?ref=novelbits.io) \[Blog Post\] ### How to Build a Scalable Ultra-Low Power Bluetooth Low Energy-based Weather Station URL: https://novelbits.io/scalable-ultra-power-bluetooth-low-energy-based-weather-station/ Last updated: 2026-08-09T05:43:21.000Z *Sponsored by [Nordic Semiconductor](https://www.nordicsemi.com/?ref=novelbits.io)* ## Introduction In this blog post, we’ll cover the details of a Bluetooth Low Energy-based system that serves as a foundation for a scalable centralized wireless system consisting of low-power nodes that gather environmental sensor data. Traditionally, with Bluetooth Low Energy (LE), it has been impossible to design a low-power and scalable system that also allows bidirectional communication from the end nodes to a central node. However, this is all now possible with the proper hardware and by utilizing a relatively new Bluetooth feature called Periodic Advertising with Responses (PAwR). In the project laid out in this post, we'll be utilizing Nordic Semiconductor's popular Bluetooth Low Energy platform (including SDK, hardware, tools, and more!). Specifically, we'll be using a few [nRF52840 development kits](https://hubs.li/Q02CMxQt0?ref=novelbits.io). ## System Design and Operation The example project we'll design and build is a **Bluetooth LE-based Weather Station**. ![PAwR-based weather station system design overview](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/pawr-nordic-system-design.png) For simplicity, we'll use a single sensor (on each sensor node) that can read both temperature and humidity. This can easily be expanded to include more sensors or a different sensor that can read other environmental parameters (e.g., barometric pressure, CO, CO2, gas, etc.). Below is a diagram that shows the different components of the system: ![Weather station system components diagram showing sensor collector, sensor nodes, and smartphone](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/system-diagram.png) As you can see, our system has three main types of components. Let's list each one and describe its role and behavior. - **Sensor Collector**: - The sensor collector will be very simple in terms of hardware components. It will consist of only an nRF52840 DK without peripherals or additional attached components. - This is the "central" node in the system (not to be confused with the Bluetooth LE *central* role). - Instead, this refers to the device acting like a gateway, access point, or hub, meaning the system will not operate without it. The system will be configured in a star topology setup (hub spoke model). - The sensor collector's role is to collect data from all the sensors and expose the data to the user(s) via a smartphone interface. - It acts in **three LE roles**: the PAwR advertiser (receiving data and sending commands from/to the sensor nodes), LE Central (connecting to the sensor nodes), and LE Peripheral (exposing the sensor data to a smartphone app). - It will be mains-powered, so no power optimization is needed. - The sensor collector stores the last received values and exposes them via a GATT Server that can be read by a connected smartphone. - **Sensor Nodes**: - In terms of hardware, each sensor node will be made up of the following: - nRF52840 DK - e-Paper display - A temperature+humidity sensor (the Sensirion SHT40) - Sensor nodes will act in both LE PAwR synchronized and LE Peripheral roles. - PAwR allows the sensor nodes to report the sensor data to and receive commands from the sensor collector. - The LE Peripheral role allows the sensor collector to transfer the periodic advertising sync information to each sensor node (via the Periodic Advertising Sync Transfer procedure). - This process helps save power on the sensor nodes since they don't have to go through the process of discovering the PA (Periodic Advertising) train. This might not seem significant, but over time, if the devices repeatedly lose sync and need to re-sync, then power consumption from the PA train discovery process adds up. - This device will be battery-powered, so we have to optimize its operation for power consumption. - The e-paper display will be used to report three pieces of information: - Device ID - Temperature reading - Humidity reading - A sensor node will periodically read both temperature and humidity. - It will also print those to the local e-paper display. - A Sensor Node will receive commands from the sensor collector. - A command will indicate whether it wants to read the temperature or humidity reading. - The command will apply to all synchronized Sensor Nodes, and they will all report these values back to the sensor collector. - Each Sensor Node will be assigned an ID at compile-time - The ID will be included in the advertising data and the responses that are sent back to the sensor collector for identification purposes. - **Smartphone**: - To mimic a real-world application, we will design the sensor collector to implement an LE Peripheral. - This will allow the sensor collector to report the temperature and humidity measurements coming from all the sensor nodes in the system in a unified manner. - A connected smartphone can read each sensor node’s latest data, including temperature and humidity measurements. - A connected smartphone can subscribe to notifications of temperature and humidity readings from each sensor node and will know exactly which sensor node the readings come from. - We'll use the Nordic nRF Connect for Mobile application to interface (as an LE Central) with the sensor collector. - It is recommended to use an Android phone for this purpose due to some necessary features not being available in the iOS version of the nRF Connect for Mobile app. For the purposes of the project implementation in the course, we will be using only three sensor nodes. However, the system design allows us to scale it to potentially thousands of sensor nodes without having to change much in the architecture. This is the power of PAwR! ## Hardware Components In terms of hardware components, here's a complete list of what you'll need to build the whole project: | Quantity | Hardware Component | | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | 4 | [Nordic Semiconductor nRF52840 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK?ref=novelbits.io) | | 1 | [Nordic Semiconductor Power Profiler Kit II](https://www.nordicsemi.com/Products/Development-hardware/Power-Profiler-Kit-2?ref=novelbits.io) | | 3 | [Waveshare 250×122, 2.13inch E-Ink raw display panel](https://www.waveshare.com/2.13inch-e-paper.htm?ref=novelbits.io) | | 3 | [Waveshare Universal E-Paper Raw Panel Driver Shield (B)](https://www.waveshare.com/e-paper-shield-b.htm?ref=novelbits.io) | | 3 | [Adafruit Sensirion SHT40 Temperature & Humidity Sensor](https://www.adafruit.com/product/4885?ref=novelbits.io) | | 3 | [STEMMA QT / Qwiic JST SH 4-pin to Premium Male Headers Cable](https://www.adafruit.com/product/4209?ref=novelbits.io)[Alternative Link (in case out of stock)](https://www.electromaker.io/shop/product/stemma-qt-qwiic-jst-sh-4-pin-to-premium-male-headers-cable-150mm-long?ref=novelbits.io) | | 1 | [Glarks 240Pcs 2.54mm Straight Single Row PCB Board Female Pin Header Kit](https://www.amazon.com/dp/B09BDX9L66?psc=1&ref=ppx%5Fyo2ov%5Fdt%5Fb%5Fproduct%5Fdetails) | | 1 | [Soldering Iron Kit](https://www.amazon.com/Weller-WE1010EDU-Soldering-Education-Kit/dp/B07J49HJ4T?ref=novelbits.io) | ## Software Components Here's a list of the various software components used in the project: - **nRF Connect SDK**: we'll start with v2.6.0, but the course will be updated to support newer versions as they get released. - [**Visual Studio Code IDE**](https://code.visualstudio.com/?ref=novelbits.io) - **[nRF Connect for VS Code Extension Pack](https://hubs.li/Q02D978m0?ref=novelbits.io)** - **Third-Party Modules** - [LVGL](https://lvgl.io/?ref=novelbits.io) - [State Machine Framework](https://docs.zephyrproject.org/latest/services/smf/index.html?ref=novelbits.io) - Various patches that have not been merged into the current SDK version (included in the GitHub repo, linked below) - [**nRF Connect for Desktop**](https://hubs.li/Q02CMx090?ref=novelbits.io) - **[nRF Connect for Mobile](https://hubs.li/Q02CZR3z0?ref=novelbits.io)** **We also have all the source code hosted in a GitHub repo to accompany the course. You can find the repo** [**here**](https://github.com/mafaneh/nordic-pawr-course?ref=novelbits.io)**.** ## Power Consumption Optimization Achieving low power consumption is crucial for the sensor nodes in our system, especially since they will be running on batteries. For this purpose, we dedicate a full lesson to optimizing power consumption on the sensor node devices in the course. For this, we employ a few strategies: - We will use Nordic Semiconductor's [Power Profiler Kit II (PPK2)](https://hubs.li/Q02CMw-Q0?ref=novelbits.io) to measure our application's current draw and electric charge consumption. - This is used alongside [nRF Connect for Desktop](https://hubs.li/Q02CMx090?ref=novelbits.io) (and specifically the Power Profiler application included within it). - After the measurement process, we prioritize the device operations based on electric charge consumption (the higher the consumption, the higher the priority). - We employ a few strategies to optimize power consumption, including turning off peripherals, adjusting how often operations occur, and adjusting the PAwR timing parameters. ## Video Demo ## Course Prerequisites - **\[Required\]** Nordic DevAcademy [nRF Connect SDK Fundamentals course](https://hubs.li/Q02CMx1Y0?ref=novelbits.io) - **\[Required\]** Nordic DevAcademy [Bluetooth Low Energy Fundamentals course](https://hubs.li/Q02CMx6p0?ref=novelbits.io) ## My Honest Thoughts On The nRF Connect SDK Even though this is a sponsored course and blog post, you may already know that I've been working with Nordic Semiconductor's solutions and ecosystem long before they sponsored any of my work. So, I wanted to weigh in with my honest personal opinion on the whole nRF Connect SDK ecosystem: - **Pros** - A comprehensive collection of tools that are well-integrated and streamlined. - Integrated with Visual Studio Code, which is fast, modern, and user-friendly. - The availability of third-party modules helps you focus on designing and developing the more important parts of your application rather than reinventing the wheel! - The solution's modularity helps you keep your application organized from a source code perspective and makes it easy for teams to collaborate on projects. - The solution is updated regularly with new features and bug fixes, which gives you confidence that you're working with a robust and up-to-date ecosystem. - **Cons** - It can have a steep learning curve in the beginning. - However, it becomes a hard-to-give-up ecosystem once you are past the learning curve and up and running. - Also, it helps that there are numerous resources available to help make the learning process faster and easier: - [Nordic DevAcademy nRF Connect SDK Fundamentals course](https://hubs.li/Q02CMx1Y0?ref=novelbits.io) - [Nordic DevAcademy Bluetooth Low Energy Fundamentals course](https://hubs.li/Q02CMx6p0?ref=novelbits.io) - [Nordic DevAcademy nRF Connect SDK Intermediate course](https://hubs.li/Q02CMx7f0?ref=novelbits.io) - [Novel Bits Bluetooth Developer Academy](https://novelbits.io/academy) So, overall, this is my verdict: > The nRF Connect SDK is a pleasure to work with, and its advantages far outweigh the challenges you may encounter at the beginning of the learning journey. Once you get used to it, you want to keep on using it for every project from thereon! > > Mohammad Afaneh - Novel Bits, LLC ## Where To Go From Here? Now that we've covered the application at a higher level, the next step is to register for the course and go through the complete implementation of the project! 🙂 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Harnessing Ambient Energy for IoT: Silicon Labs' New Energy Harvesting Solution URL: https://novelbits.io/ambient-iot-silicon-labs-energy-harvesting/ Last updated: 2026-08-09T05:23:23.000Z *Sponsored by* [*Silicon Labs*](https://silabs.com/?ref=novelbits.io) ## Introduction There’s a groundbreaking new concept emerging in the IoT (Internet of Things) world. We've now reached a stage where devices can draw power from their environment, leading to a substantial decrease in energy costs and environmental footprint. This concept, the **Ambient IoT**, is poised to transform the IoT landscape, and Silicon Labs has just unveiled the xG22E series of chipsets that meet the demand for this new era of devices. Energy harvesting and energy conservation are at the core of the Ambient IoT. IoT devices in this category draw energy from their environment, extending battery life or mitigating the need for them altogether. This not only reduces the environmental footprint of IoT devices but also significantly lowers their operational and maintenance costs. ## Battery-Free IoT Devices: The Next Big Leap Innovations in technology are continually pushing the boundaries of what's possible. One of the most transformative advancements in the Internet of Things (IoT) is the emergence of battery-free devices, which are at the heart of the Ambient IoT. This idea, while simple, is a game-changer for the industry. By eliminating the need for batteries, we can completely overhaul the standard operating procedures for IoT devices. Batteries have long been a limiting factor for IoT devices. They require regular replacements or recharging, which incurs **costs** and demands **time**. Moreover, batteries present an **environmental challenge**. With millions, if not billions, of IoT devices worldwide, the disposal of used batteries poses a significant ecological concern. Energy harvesting solutions draw energy from surroundings, effectively harnessing the power they need for operation without the need for a traditional power source. This is where Silicon Labs' new energy solutions come into play. The BG22E, MG22E, and FG22E (the new xG22E family of chipsets) are designed to help facilitate this transition towards battery-free IoT devices by satisfying the stringent requirements needed to make these energy harvesting feasible. Energy harvesting solutions present a host of benefits: - They significantly reduce the environmental footprint of IoT devices, as there are no batteries to dispose of. - They also reduce the operational and maintenance costs associated with running these devices, as batteries are no longer needed to be replaced or recharged. - Furthermore, battery-free IoT devices can operate continuously without interruption. This constant operation can lead to more accurate data collection and improved performance, particularly in critical applications such as healthcare monitoring or industrial automation. ## Technical Specs and Compatibility Silicon Labs' new solutions, the BG22E, MG22E, and FG22E, embody the principles of the Ambient IoT. They are designed with **ultra-fast, low-energy cold-start,** and **deep sleep wake-up** capabilities. These features significantly contribute to energy conservation, resulting in extended battery life for IoT devices (or even going battery-free). They are also designed for maximum compatibility and interoperability. They can operate seamlessly with various power sources, power management systems, and energy harvesters. This flexibility allows IoT device manufacturers to choose the most suitable components for their needs and use cases. Even with the impressive low power consumption numbers achievable by the existing xG22 series of chipsets, the new **xG22E** series has taken it even further. Here are some featured highlights: - **Ultra-fast, low-energy cold start** for applications that start from a zero-energy state to transmit packets and then rapidly return to sleep. An xG22E wakes up in only 8 ms, contributing to a 20% reduction in energy consumption during boot-up, making it ideal for battery-less applications. - **Energy conserving deep sleep swift wake-up: t**hey provide a 78% reduction in EM4 wake-up energy, enabling 10+ year coin cell battery operation for ultra-low power and extended storage applications. - **Power-efficient energy mode transition** to smoothly transition in and out of energy modes by mitigating current spikes or inrush, which can harm energy storage capacity. - **Multiple deep sleep wake-up options,** such as RFSense, GPIO, and RTC wake-up sources from the deepest EM4 sleep mode, are ideal for extended storage. - Additionally, the new chipsets are **compatible with Silicon Labs' existing Series 2 catalog**. This compatibility means these new solutions can be integrated into existing IoT designs with minimal modifications, reducing the time and cost of bringing new, energy-efficient IoT devices to market. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-4.png) Power Efficiency Metrics Comparison between xG22E and xG22 ## Interoperability and Third-Party Partners To kick off the *interoperability* piece, Silicon Labs has partnered with [e-peas](https://e-peas.com/?ref=novelbits.io), a provider of industry-leading Power Managed Integrated Circuits (PMICs) designed for energy harvesting. Together, they’ve co-developed **two energy harvesting shields** for the xG22E Explorer Kit: - The [AEM13920 dual-harvester](https://c212.net/c/link/?t=0&l=en&o=4145982-1&h=3962154410&u=https%3A%2F%2Fwww.prnewswire.com%2Fnews-releases%2Fe-peas-introduces-first-energy-harvesting-pmic-to-handle-two-independent-energy-sources-at-the-same-time-301910276.html&a=AEM13920+dual-harvester&ref=novelbits.io), which allows it to pull energy simultaneously from two distinct energy sources, like indoor or outdoor light, thermal gradients, and electromagnetic waves without sacrificing energy conversion efficiency. - The [AEM00300 shield](https://c212.net/c/link/?t=0&l=en&o=4145982-1&h=477979876&u=https%3A%2F%2Fe-peas.com%2Fproduct%2Faem00300-ambient-energy-manager-battery-charger-pulsed%2F&a=AEM00300+shield&ref=novelbits.io), which is dedicated to harvesting power from random pulsed energy sources. ## Energy Harvesting Sources You might be wondering: “What kind of sources can be utilized to harvest energy?”. Here are a few examples: 1. **Solar Energy**: Solar energy is one of the most abundant and widely used sources for energy harvesting. Solar panels can convert sunlight directly into electricity. 2. **Thermal Energy**: This refers to energy harvested from the heat difference between two objects. Thermoelectric generators, for example, can convert waste heat into usable energy. 3. **Vibration Energy**: In environments with constant movement, such as factories or busy roadways, the vibration caused by machinery or vehicles can be converted into electrical energy using piezoelectric materials. 4. **Radio Frequency (RF) Energy**: RF energy emitted from sources such as communication towers can be captured and converted into electricity. 5. **Wind Energy**: Like solar, wind energy is a well-known source for energy harvesting. Small wind turbines can be used to generate electricity in windy locations. 6. **Kinetic Energy**: This is energy harvested from the movement of objects or people. For example, some wristwatches are powered by the wearer's movement. 7. **Chemical Energy**: This is energy released in a chemical reaction, including energy from batteries or fuel cells. 8. **Tidal Energy**: Energy harvested from the movement of water in the oceans or seas during tides. 9. **Geothermal Energy**: This is energy harvested from the heat stored beneath the Earth's surface. 10. **Bioenergy**: This is energy obtained from organic materials (biomass), such as plants, waste, and even some types of algae. Each of these sources has its unique strengths and challenges, and the choice of energy source for harvesting will depend on several factors, including location, application requirements, and available technology. ## Applications In terms of applications, many can benefit from energy harvesting solutions. Here are some examples: - Remote Controls - Smart Home Doors & Switches - Smart Sensors - Asset Tags - Electronic Shelf Labels - Smart Building Switches and Sensors - Smart Metering - Condition Monitoring & Factory Automation - Tire Pressure Monitor Sensors (TMPS) - Agriculture Sensing - Governmental Compliance/Regulations ## The Role of Bluetooth LE in the Ambient IoT Bluetooth Low Energy is a unique technology compared to other low-power wireless technologies. Instead of staying stagnant, it has adapted and developed over the years to address a variety of markets and use cases. Here are just a few of the strong properties of Bluetooth LE that make it a great fit for the Ambient IoT: - Ultra-low power consumption - Low integrated circuit (IC) costs - Flexible topologies - Long-term support and backward compatibility Overall, Bluetooth LE's low-power capabilities, affordability, flexible topologies, long-term support, large infrastructure base, and interoperability make it a central technology enabling the Ambient IoT's development and growth. ## The Future of the Ambient IoT The Ambient IoT market holds great promise, with increasing demand for energy-efficient, maintenance-free devices. Silicon Labs' new energy solutions, the xG22E series of chipsets, are perfectly positioned to meet these market needs and drive the sustainable growth of the IoT industry. As more IoT devices begin to use ambient energy for their operation, we can anticipate a significant reduction in the environmental impact of the IoT industry. This shift will also lead to lower operational costs for IoT deployments, making the technology more affordable and accessible for a broader range of applications and use cases. ## Conclusion and Next Steps Silicon Labs' introduction of the BG22E, MG22E, and FG22E represents a significant stride towards a more sustainable and energy-efficient IoT industry. These new energy solutions offer several benefits, including lower energy consumption, extended battery life, and compatibility with a variety of power sources and energy harvesters. The next step for IoT device manufacturers and solution providers is to explore these new solutions and consider how they can be integrated into their products. With the help of Silicon Labs' application expertise and partner reference designs, this process can be smoother and more efficient. The future of the IoT industry hinges on energy-efficient, maintenance-free devices. With its new energy solutions, Silicon Labs is leading the charge toward this future. ## References & Additional Resources - [Silicon Labs Energy Harvesting Solutions](https://www.silabs.com/wireless/energy-harvesting?ref=novelbits.io) - [Bluetooth SIG Ambient IoT White Paper](https://www.bluetooth.com/wp-content/uploads/2024/01/MRN%5FAmbient-IOT.pdf?ref=novelbits.io) - e-peas Solutions - [e-peas Introduces First Energy Harvesting Pmic To Handle Two Independent Energy Sources At The Same Time](https://www.prnewswire.com/news-releases/e-peas-introduces-first-energy-harvesting-pmic-to-handle-two-independent-energy-sources-at-the-same-time-301910276.html?ref=novelbits.io) - [Ambient Energy Manager Battery Charger Pulsed](https://e-peas.com/product/aem00300-ambient-energy-manager-battery-charger-pulsed/?ref=novelbits.io) --- 💡 **Want to learn more? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up.** ### Taking Bluetooth LE Security to the Next Level with Certificate-Based Authentication and Pairing URL: https://novelbits.io/bluetooth-le-security-cbap/ Last updated: 2026-08-09T05:23:55.000Z *Sponsored by [Silicon Labs](https://silabs.com/?ref=novelbits.io)* ## Introduction With the rise of smart devices and the Internet of Things (IoT), Bluetooth technology has become an integral part of our daily lives. However, as our reliance on these devices grows, so does the need for secure and reliable connections. Secure pairing/bonding and authentication are crucial elements in the world of Bluetooth Low Energy (LE) devices. Ensuring these two aspects are intact can be a big challenge, primarily due to the need for manual pairing and the lack of a scalable approach to verifying the authenticity of the connections using standard LE-based security mechanisms. However, innovation has paved the way for a method known as **Certificate-Based Authentication and Pairing (CBAP)**, which is significantly transforming how Bluetooth LE devices are authenticated and paired. CBAP is a method developed by Silicon Labs that leverages digital certificates' ability to authenticate devices. Digital certificates are a type of identity credential that contains a public key and other identification information. They are signed by a trusted entity, typically a Certificate Authority (CA), and can be issued for a user, a server, or a device. In the context of Bluetooth LE, these certificates are used to verify the identity of devices and establish a secure connection. This process eliminates the need for manual pairing, which is often prone to errors and security issues. Instead of relying on the user to verify and confirm the connection, the authentication is done automatically by *checking the validity of the digital certificates*. This enhances connection security and provides a much more user-friendly experience. Moreover, CBAP provides a scalable approach to authenticate devices and connections. As the number of Bluetooth LE devices continues to grow exponentially, traditional methods of authentication and pairing are neither feasible nor efficient. With CBAP, the authentication process can be easily scaled, making it a suitable solution for large networks with thousands of devices. In this article, we will explore the principles of Certificate-Based Authentication and Pairing (CBAP), the process of creating and using digital certificates, and how this method is implemented in Bluetooth LE devices. We will also discuss some practical CBAP examples and tools provided by Silicon Labs to make this process easier to implement. ## The Limitations of Standard LE Security Mechanisms As we mentioned previously, the problem with traditional Bluetooth LE security mechanisms is their lack of scalability and reliability in verifying the authenticity of the connections. Standard LE-based security mechanisms often require manual pairing, which is prone to errors and inefficient for large networks with numerous devices. Manual pairing involves physically accessing each device, entering a passkey, or confirming two numbers, which can be prone to human error and is not feasible for large-scale networks. Another issue with traditional LE security mechanisms is that they often rely on secure Out-Of-Band (OOB) methods like QR codes or Near Field Communication (NFC) for pairing. While these methods provide a certain level of security, they require proximity between the devices and can be inconvenient, especially in scenarios involving multiple devices. Furthermore, a significant concern is the lack of proof of identity and authentication in traditional LE security mechanisms. Without a reliable way to verify a device or user identity, the entire network's security can be compromised. This is a critical issue, especially in applications where the integrity and confidentiality of the data being transmitted are of the utmost importance. In summary, while traditional LE security mechanisms provide some security level, they have several limitations that make them unsuitable for today's increasingly connected and complex environments. These limitations include: - Lack of scalability - Reliance on manual pairing - Lack of reliable identity verification and authentication To overcome these challenges, we can utilize Silicon Labs’ Certificate-Based Authentication and Pairing (CBAP) method. ## CBAP Principles and Process CBAP operates on the basis of public key cryptography, a method that involves a pair of keys—a public key and a private key—and the use of certificates. In this section, we’ll go over some concepts related to certificates and public key cryptography that are important to understand in the context of CBAP. ### **Public Key Cryptography** The following points describe how a public-private key pair is used for signing data and verifying the signature: - A **private key** is always generated (needs to be sufficiently random) - A **public key** is derived from the private key - The ****private key** must be stored securely (must never leave the device!) - The **public key** can be openly distributed and shared with other devices - The **private key** can be used to generate a signature (usually operated on a hash of the original data and using a cryptographic algorithm) - The **public key** can then be used to verify the signature on the data. In this case, the original data, the public key, and the signature are needed. ### **Certificates** The following points describe how certificates are used in the context of CBAP: - A digital certificate is a small, verifiable data file that contains identity credentials and a public key - That data is then signed either with the corresponding private key (AKA self-signed certificate) or a Certificate Authority’s (CA) private signing key (AKA root or CA certificate) - The certificate can then be used to prove the ownership of a public key - A Certificate Authority (CA) is a party **trusted** by both the owner of the certificate and the party relying on the certificate to verify the ownership - Concatenation of certificates builds what’s called “**a chain of trust**” - At the root of the chain is the CA certificate (AKA root certificate) - The CA certificate can then be used to sign another certificate - The resulting certificate can then be used to sign another one, and so on, creating a chain of trust - The private key is **never** included in the certificate, and it must be stored privately and securely. **Protecting this private key is crucial!** ## CBAP Implementation Let’s now dive into how CBAP is implemented in a Bluetooth LE system. Here are the necessary steps for preparing the system: - It begins with creating a root certificate or Certificate Authority (CA) certificate. This certificate, which includes a public key, is self-signed by the CA - Protecting and securely storing the CA's private key is crucial, preferably in a hardware security module (HSM) - A private-public key pair is generated on the device - The public key (only) is read out from the device (the private key must never leave the device!) - A device certificate is created externally for the device and includes the device's public key (which was read out in the previous step) - The device certificate is then signed by the Certificate Authority (CA) - This signed device certificate is flashed/programmed to the device - The certificates between the central and peripheral are sent over the Bluetooth LE connection between these two devices (which is characterized as an “Out-Of-Band (OOB)” channel in this scenario, even though it is technically still "in-band") - The process also leverages a new CBAP service that is included in advertising (technically, the UUID is what's included in the advertising data) Now that we understand what’s involved in preparing the system and devices let’s examine how this is implemented as part of the Bluetooth LE security process. ### The Bluetooth LE Security Process I won’t get into the nitty gritty details of security in Bluetooth LE as this has been covered in many resources around the web (**links**) and otherwise (**in my book**). Let’s instead focus on how CBAP is used within the context of the LE Security process. As mentioned earlier, the security process defined in the Bluetooth standard requires manual interaction and lacks scalability. CBAP can be used to overcome these limitations. Assuming all the setup steps have been done (the device stores a private key, a CA certificate, and its own CA-signed device certificate), the following steps are performed: - Upon startup, each device verifies its own certificate using the stored CA certificate (the CA signature on the device certificate is verified using the CA’s public key, which is stored in the CA certificate) - Two devices connect and signal to each other that they want to use the CBAP method for authentication and pairing - The two devices exchange their certificates over the Bluetooth LE connection - Both devices will then verify the validity of the other device’s certificate using the CA public key (stored as part of the CA certificate, which is stored on each device) - If that verification succeeds, the peer device is considered a “potentially” trusted device; the peer device must still prove that it possesses the private key that corresponds to the device certificate to fully verify its identity - The devices initiate the standard LE OOB pairing - The OOB data is actually sent in-band over the Bluetooth LE connection. The pairing process ensures an authenticated connection, provided that the OOB data is exchanged without a Man-In-The-Middle (MITM) - To ensure MITM protection, each device signs its OOB data using its own private key. This signature is exchanged along with the OOB data. - Each device will then verify this signature using the peer’s public key, which was included in the (already-verified) device certificate previously sent by the peer. - If the verification process checks, this proves that the OOB data comes from a trusted device and not an MITM - The security process continues as normal (according to the standard Bluetooth LE process), and the devices now have an encrypted and authenticated connection Here’s a diagram summarizing these steps: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-4.png) The Certificate-Based Authentication and Pairing (CBAP) process *Source: Silicon Labs CBAP Application Note* ### CBAP Deployment There are two main options when it comes to deploying CBAP in your own Bluetooth LE system/product: **1\. You (the device manufacturer) handle everything yourself** This includes the generation of private keys on the device side, ensuring the device keys are stored securely, creating the device certificates, signing the device certificates by a CA, and storing the device certificates on the devices. Here's a diagram that details this process: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-5.png) **Device Provisioning (Certificate Injection)** *Source: Silicon Labs CBAP Presentation* **2\. Utilize Silicon Labs' Custom Part Manufacturing Service (CPMS)** If, instead, you do not want to worry about managing the process of generating keys, creating certificates, signing them, etc., then you can utilize a service from Silicon Labs called CPMS. This offloads this whole provisioning/premanufacturing stage to Silicon Labs and provides the following: - **Device certificates are provided by Silicon Labs and flashed to the ordered parts before shipping** - A private key is generated on the ordered part and never leaves the device - A public key and X.509 certificate parameters are signed by Silicon Labs’ Certificate Authority (CA) and stored on the device - **Certificate** **Authority (CA) certificates are shared publicly to enable verification of device certificates** - It can be flashed to the central device along with the FW to enable verification without internet access - **CA certificate may be** **either**: - Self-signed Silicon Labs root certificate(root of trust) - or Factory/Batch certificatesigned by a root certificate (Silicon Labs or 3rd party) - **CPMS also offers flashing the firmware to the devices in the factory** Here's a simple diagram summarizing the process: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-5.png) **Device Provisioning (Certificate Injection)** *Source: Silicon Labs CBAP Presentation* The combination of CBAP and CPMS provides a unique set of advantages: - Lowers the cost – less time spent by technicians, less prone to human errors - Prevents counterfeit or malicious devices from entering the network - By removing the need for a display and/or input methods, it can lead to reduced size and cost of end devices ## Advantages of CBAP To recap, CBAP offers several advantages over traditional methods of authentication and pairing: - It eliminates the need for manual interaction, making the process much more convenient and faster. This method is particularly helpful in large-scale networks involving thousands of devices, where manual authentication would be labor-intensive, error-prone, and **costly $$$**! - Additionally, CBAP provides proof of origin and identity, which standard Bluetooth LE authentication methods can't guarantee. The CA certificate can be used to verify the end device’s certificate, offering an added layer of security. Here's a table summarizing the comparison between using CBAP and using only traditional Bluetooth LE pairing mechanisms: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-12.png) **Table comparing standardized Bluetooth LE security mechanisms vs. CBAP** *Source: Silicon Labs CBAP Presentation* ## Conclusion The rise of smart devices and IoT has necessitated more secure and reliable connections. CBAP, developed by Silicon Labs, addresses this need by offering a scalable and secure method for Bluetooth LE device authentication and pairing. By leveraging the power of digital certificates and public key cryptography, CBAP eliminates the need for manual pairing, enhancing security and improving user experience. ## Resources Here are some additional resources that I recommend referring to for more information about CBAP, CPMS, and digital certificates: - **[Silicon Labs AN1396: Certificate-Based Bluetooth® Authentication and Pairing](https://www.silabs.com/documents/public/application-notes/an1396-bluetooth-certificates.pdf?ref=novelbits.io)** - **[Silicon Labs AN1268: Authenticating Silicon Labs Devices Using Device Certificates](https://www.silabs.com/documents/public/application-notes/an1268-efr32-secure-identity.pdf?ref=novelbits.io)** - **Silicon Labs Scripts and Examples:** - [SoC - Certificate-Based Authentication and Pairing Sample Application](https://github.com/SiliconLabs/gecko%5Fsdk/tree/gsdk%5F4.4/app/bluetooth/example/bt%5Fsoc%5Fcbap?ref=novelbits.io) - [Python Scripts for Certificate Authority (CA)](https://github.com/SiliconLabs/gecko%5Fsdk/tree/gsdk%5F4.4/app/bluetooth/script/certificate%5Fauthorities?ref=novelbits.io) - **[Silicon Labs Custom Part Manufacturing Service (CPMS)](https://www.silabs.com/services/custom-part-manufacturing-service?ref=novelbits.io)** 💡 **Insider Tip:** Want to go deeper into Bluetooth LE security? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### NXP's LE Audio Solution for Auracast URL: https://novelbits.io/nxp-nxh3675-bluetooth-le-audio-soc-auracast/ Last updated: 2026-08-09T05:43:29.000Z NXP recently launched the NXH3675, a dedicated Bluetooth LE Audio SoC built specifically for Auracast and connected audio applications. In the video below, we take a closer look at what this chipset brings to the table and why it matters for LE Audio development. In this video, we introduce the new NXH3675 Bluetooth LE chipset from NXP Semiconductors, a state-of-the-art chipset that supports the new LE Audio standard. This includes support for both Broadcast/Auracast™ (up to 2 stereo streams) and Connection-oriented audio (up to 7 CISes or 5 CISes for High Definition Audio). Learn more about the new NXH3675 Bluetooth LE Audio Chipset [HERE](https://www.nxp.com/products/wireless-connectivity/bluetooth-le-audio/ultra-low-power-bluetooth-low-energy-audio-solution-with-integrated-flash:NXH3675?ref=novelbits.io). Learn more about NXP's LE Audio solutions [HERE](https://www.nxp.com/products/wireless-connectivity/bluetooth-le-audio:2.4GHz-AUDIO-STREAMING?ref=novelbits.io). --- 💡 Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### NXP's LE Audio Solution for Home Audio URL: https://novelbits.io/nxp-nxh3675-bluetooth-le-audio-soc-home-audio/ Last updated: 2026-04-26T17:49:22.000Z In this video, we introduce the new NXH3675 Bluetooth LE chipset from NXP Semiconductors, a state-of-the-art chipset that supports the new LE Audio standard. This includes support for both Broadcast/Auracast™ (up to 2 stereo streams) and Connection-oriented audio (up to 7 CISes or 5 CISes for High Definition Audio). Learn more about the new NXH3675 Bluetooth LE Audio Chipset [HERE](https://www.nxp.com/products/wireless-connectivity/bluetooth-le-audio/ultra-low-power-bluetooth-low-energy-audio-solution-with-integrated-flash:NXH3675?ref=novelbits.io). Learn more about NXP’s LE Audio solutions [HERE](https://www.nxp.com/products/wireless-connectivity/bluetooth-le-audio:2.4GHz-AUDIO-STREAMING?ref=novelbits.io). ### A Practical Guide to Debugging BLE Communication on iOS URL: https://novelbits.io/debugging-sniffing-secure-ble-ios/ Last updated: 2026-08-09T05:24:35.000Z Debugging Bluetooth LE is tricky, and on mobile devices, it can be even more so! In this guide, I lay out the different steps in detail on how you can debug and sniff Bluetooth LE communication on iOS devices. Specifically, we'll be capturing the HCI commands and events between the Host and Controller on the iOS device. ## Host Controller Interface (HCI) Before we dive into the details of how to achieve this, let's go over a few essential concepts. The **Host Controller Interface (HCI)** layer is a communication interface defined in the Bluetooth Core Specification document. It standardizes the way that a Bluetooth Host communicates with a Bluetooth Controller. ![Host Controller Interface (HCI)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/additional-images_05-1.png) Host Controller Interface (HCI) It is an optional interface that is needed in cases where the controller and host are present on separate hardware components. If it is omitted, it means in such a device, the same processor will implement the functionality of a host and a controller. Here's an example: ![Host and Controller on the same microcontroller](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/additional-images_06-1.png) Host and Controller on the same microcontroller If it is included, then it allows a device to implement the Bluetooth LE functionality using a host from one vendor and a controller from another vendor (on different chipsets). Physically, the HCI may run on top of an interface like UART, RS-232, USB, or SD. The set of packets that can be exchanged on this interface is defined by the Bluetooth specification. Examples of where the Host and Controller are separated across different microcontrollers/processors, and HCI is implemented include: A. Bluetooth USB dongle connected to a PC: ![Bluetooth USB Dongle HCI](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/additional-images_07-1.png) Bluetooth USB Dongle HCI B. Smartwatch ![Smartwatch HCI](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/additional-images_08-1.png) Smartwatch HCI The different aspects of HCI include: - **HCI Commands**: these are sent from the Host to the Controller to request an operation. Examples include creating a connection, starting advertising, stopping advertising, starting scanning, stopping scanning, creating CIS, creating BIS, etc. - **HCI Events**: these are sent from the Controller to the Host, reporting back with important information such as the status of a command. Examples include connection complete, advertising report, scan request received, etc. Different operations in Bluetooth LE are split across the Host and Controller. Some are the Host's responsibility, while others are the Controller's. If we can get a peek at the commands and events that are being passed between the two subsystems, this gives us developers a lot more insight into what's happening in a Bluetooth LE device (or app). Many might not know that both Android and iOS actually expose the HCI layer to us (*I* certainly didn't realize this until later in my Bluetooth LE development journey!). This is a powerful feature that can be very useful in many debugging scenarios. For example, did you know that: - You can capture the GATT operations being triggered by any mobile app? - Or, that you can capture the advertising reports from the smartphone's Controller when scanning for Bluetooth LE devices? - Or, that you can capture the security keys used to secure communication between the smartphone and another Bluetooth LE device? and then use that to decrypt the encrypted data exchanged between the two devices?! All of these are possible on both iOS and Android. In this post, we'll cover how to do this on iOS. In a follow-up article, we'll cover the Android case. ## Requirements To be able to do this on iOS, we need the following: - A macOS laptop/desktop - An Apple Developer Account - An iOS device running iOS 13 or later - A cable for connecting the iOS device to the Mac ## HCI Capture Steps on iOS Here are the steps to take to capture HCI communication on iOS: **Step 1:** Download and install Apple's Bluetooth Profile on an iOS device. You can do this in two ways: - Download the [Bluetooth for iOS Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/?name=bluetooth&ref=novelbits.io) directly on your iOS device - Or you can [download it on your Mac](https://developer.apple.com/bug-reporting/profiles-and-logs/?name=bluetooth&ref=novelbits.io), AirDrop it to your iOS device, and then open it there. Here's a short screen recording detailing this step: *Downloading Apple's *Bluetooth for iOS Profile** Once installed, you'll be able to find it under **Settings** → **General** → **VPN & Device Management**: ![Bluetooth for iOS Profile installed on iPhone](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_2393-1.png) **Bluetooth for iOS Profile** installed **Step #2:** Now that we have the Profile installed on our iOS device, we can move on to the next step, which is to download and run a tool from Apple called the Packet Logger. You can download the Packet Logger tool from the Additional Tools for Xcode package **[here](https://developer.apple.com/download/all/?q=additional%20tools%20for%20Xcode&ref=novelbits.io)** \[*simply download the latest version*\]. ![Apple Packet Logger Tool](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/packet-logger-tool-1.jpg) Packet Logger Tool **Step #3:** Now, let's run the Packet Logger tool (you can also drag and drop it to your local Applications folder so you can quickly run it next time). ![Packet Logger Tool Window](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2024-02-26-at-9.40.21-E2-80-AFPM.png) Packet Logger Tool Window **Step #4:** Next, connect your iOS device to your Mac (and accept any dialogs asking to allow access to your device). **Step #5:** Click on the **File** → **New iOS Trace** menu item: ![New iOS Trace in the Packet Logger Tool](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ios-trace-1.jpg) New iOS Trace in the Packet Logger Tool **Step #6:** After starting the iOS Trace, you should start seeing some Bluetooth traffic, and the iOS device should show a "signal" status at the top of the screen: ![Bluetooth for iOS Profile running on iOS device](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_2393-copy-1.png) Bluetooth for iOS Profile running on iOS device **Step #7:** As an advanced tip, you can actually export the log file to a BTSnoop format, which can be opened in Wireshark for additional analysis. 💡 **BTSnoop** is a file format defined for storing a log of Bluetooth HCI traffic (commands and events). Wireshark and many different sniffer software packages support this file format for analysis. ![Exporting HCI data in BTSnoop format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/btsnoop-1.jpg) Exporting HCI data in BTSnoop format **Step #8:** So, what do you do from here now that you have access to the HCI logs? At this point, you can view all the HCI traffic between the Bluetooth Host and Controller on your iOS device. In order to understand the different HCI commands and events, I recommend referring to the **Bluetooth Core Specification document Vol 4, Part E, Section 7**. Here are examples of some common Bluetooth LE HCI Commands on the Central side (the most common role for a smartphone): - LE Set Scan Parameters command - LE Set Scan Enable command - LE Create Connection command - LE Enable Encryption command ## Capturing BLE Security Keys (LTK) One handy use case for the Packet Logger tool is to extract the LTK for a secure connection between two BLE devices (utilizing the LE Secure Connections pairing method). To demonstrate this, I am going to use the following: - A [Nordic nRF52840 board](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dk?ref=novelbits.io) running the nRF Connect SDK (Zephyr-based) peripheral\_sc\_only example (this one runs in LE Secure Connections only mode) - [nRF Connect mobile app](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile?ref=novelbits.io) on an iPhone 14 Pro Max (running iOS 17) - [Ellisys Bluetooth Tracker](https://www.ellisys.com/products/btr1/index.php?ref=novelbits.io) (Bluetooth LE Sniffer tool) \[Used for sniffing over the air traffic and inputting the LTK for traffic decryption. Alternatively, you can use Wireshark in combination with nRF Sniffer on one of the Nordic dev boards\] ### Exercise Steps Make sure the nRF DK is not bonded with the iOS device. If it already is, then remove it from the Bluetooth Settings menu by clicking on the **(i) icon** and then clicking "**Forget This Device**": ![Forget This Device to remove Bluetooth LE Bond](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/sc-only-peripheral-scaled-1.jpg) "Forget This Device" to remove Bluetooth LE Bond Now navigate to the nRF Connect mobile app and discover the device: ![Discovering the Bluetooth LE Peripheral](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nrf-mobile-app-discovering-peripheral-scaled-1.jpg) Discovering the Bluetooth LE Peripheral **Note:** Make sure the Packet Logger Tool is running an iOS Trace before continuing with the next step. Click "Connect." then, you'll be presented with a Passkey entry form: ![Pairing Passkey entry on the smartphone](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bluetooth-pairing-request-scaled-1.jpg) Pairing Passkey entry on the smartphone You'll find the passkey displayed in the serial terminal from the nRF DK: ![Passkey from the board shown in the serial terminal](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/passkey-capture-in-serial-terminal-scaled-1.jpg) Passkey from the board shown in the serial terminal Make sure you enter the passkey reasonably quickly. Otherwise, the pairing process will time out. Once paired, the device serial terminal output will indicate a successful pairing: ![Pairing complete](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/entering-passkey-on-nrf-board-scaled-1.jpg) Pairing complete Once this is completed, you can now stop the Packet Logger trace and filter for HCI Commands: ![Filtering for HCI Commands in Packet Logger](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/packet-capture-1-1.jpg) Filtering for HCI Commands in Packet Logger Now, look for the HCI Command "LE Start Encryption" and expand the command for more information. In there, you will find the LTK for the bond. **Voila!** ![Capturing the LTK in Packet Logger during Pairing](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ltk-capture-1-1.jpg) Capturing the LTK in Packet Logger during Pairing/Bonding Even if you miss capturing the pairing process using the Packet Logger, you can disconnect the nRF DK (or any other device you're looking to capture) and capture the reconnection operation to the DK. From there, you can again look for the same HCI command: "LE Start Encryption" (you can also verify this is the same LTK used when first establishing the pairing between the two devices): ![Capturing the LTK in Packet Logger upon reconnection](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ltk-capture-2-1-1.jpg) Capturing the LTK in Packet Logger upon reconnection between bonded devices After extracting the LTK from the Packet Logger tool, you can now fully decrypt the traffic between the two BLE devices (the nRF DK and the iOS device)! Free Download iOS Bluetooth LE Debugging Guide A complete PDF guide to iOS Bluetooth LE debugging: Console.app filters, packet-level inspection, common iOS-specific pitfalls, and the workflow I use on every iOS Bluetooth LE project. Send Me the Guide Check your email! We sent the download link to . No spam. Unsubscribe with one click. 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE debugging and security? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ## Summary In this post, we covered a very practical technique that we can use when debugging Bluetooth LE communication with a smartphone, whether that's from an app that you've developed or even any other app on your phone! ## Credits - [A New Way to Debug iOS Bluetooth Applications](https://www.bluetooth.com/blog/a-new-way-to-debug-iosbluetooth-applications/?ref=novelbits.io) - BTSnoop File Format - [2019 WWDC Session](https://developer.apple.com/videos/play/wwdc2019/901/?ref=novelbits.io) ### Location Awareness of Bluetooth LE Connections by Monitoring RSSI From Multiple Devices URL: https://novelbits.io/location-awareness-ble-connections-monitoring-rssi/ Last updated: 2026-08-09T05:25:34.000Z *Sponsored by [Silicon Labs](https://silabs.com/?ref=novelbits.io)* ## Introduction Over the years, Bluetooth Low Energy has proven to be great for establishing a connection between two devices and maintaining it within a reasonable RF range. As we already know, connections are the way to go for applications that require consistent bidirectional data communication between two Bluetooth LE devices. However, connections rely on the two Bluetooth LE devices being within a reasonable RF range of each other in order to be maintained. But what if you have an application where a Bluetooth LE medical device must constantly be connected within a large area (e.g., a medical facility) to relay its sensor readings to a cloud server? In such a scenario, deploying a single Bluetooth LE gateway may not be sufficient (especially for large coverage areas). The natural solution here is to deploy multiple Bluetooth LE gateways to maintain a more comprehensive connection to the Bluetooth LE sensor. **But how do you manage the connection from multiple gateways to a single device? And how do you make it seamless across these gateways?** Let’s imagine another scenario where you have a Bluetooth LE-enabled mobile device connected to a Bluetooth LE-enabled vehicle access control system. In this case, RSSI measurement from the vehicle could be utilized to approximate the distance of the mobile device. However, RSSI is prone to many environmental factors, and its accuracy is usually unsatisfactory. One solution to this is to add multiple Bluetooth LE devices within the vehicle to monitor the RSSI of the mobile device and employ trilateration to determine better location accuracy. **But again, how do you manage this without overcomplicating the implementation? And how do you ensure that the multiple nodes are able to consistently monitor the RSSI?** To address these traditional problems with Bluetooth LE (limited RF range and inaccuracies of RSSI), Silicon Labs just introduced a new feature in their Bluetooth SDK called the **Bluetooth Connection Analyzer**. **This new feature is available in Silicon Labs' [Bluetooth SDK version 7.0.1.0](https://www.silabs.com/documents/public/release-notes/bt-software-release-notes-7.0.1.0.pdf?ref=novelbits.io)**. ## The Bluetooth Connection Analyzer So, what is the Bluetooth Connection Analyzer? Simply put, it’s a simplistic Bluetooth sniffer implementation that allows multiple devices to measure the RSSI levels on 3rd party devices connected to a *friend* device by monitoring the connection between this device and the 3rd party devices. You are probably asking, well, what makes this feature special? And how does it make my life easier? Great questions! With this new feature, with just a few API calls, you can enable *friend nodes* to monitor the RSSI of a 3rd party device’s connection with a main device and utilize this information for multiple scenarios. Some of these include: - **Connection handover**: where a device can roam within an area and remain connected to multiple Bluetooth LE gateway devices appearing as if they were one (trusted) device - **More accurate positioning**: where a device’s location can be better estimated via multiple nodes measuring the RSSI of the connection between two trusted devices Now, even though RSSI measurements of a device may be easily measured for non-connected devices (e.g., in advertising mode), it is much more difficult to achieve the same for connections, especially between bonded devices, which is where this new feature comes in! ## How does it work? Let’s run through the steps of how a system would utilize the Bluetooth Connection Analyzer feature by looking at the vehicle access control system example application we referred to earlier. ### System Diagram ![Bluetooth Connection Analyzer system diagram for a vehicle access control system with friend devices](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/vehicle-v2.jpg) Bluetooth Connection Analyzer System Example (*Vehicle Access Control System*) ### System Components The system comprises the following main components: - A Bluetooth LE-enabled **V**ehicle **A**ccess **C**ontrol **S**ystem (we'll refer to it as **VACS**) - A **Trusted** **M**obile **D**evice that the user can utilize to unlock/lock the vehicle and perform other access control functions (we'll refer to it as **Trusted MD**) - Multiple Bluetooth LE devices deployed within the vehicle at strategic locations. These act as trusted “Friend” Devices to the main access control system (we'll refer to them as **Friend Devices** – not to be confused with *friend nodes* in Bluetooth mesh!) ### System Functionality - VACS acts in the peripheral role and has a secure connection established with the Trusted MD - A secure “connection” is established between VACS and the Friend Devices within the vehicle (this can be a wired or wireless communication channel) - Once a connection is established between VACS and the Trusted MD, VACS can call an API (sl\_bt\_get\_scheduling\_details) to get all the details of the established connection (Access Address, CRC seed, channel map, channel selection algorithm, event counter, connection interval, bonding information, and more) - VACS can then share this information with all the Friend Devices - The Friend Devices can then pass this information to a new API called sl\_bt\_connection\_analyzer\_start() to start the Connection Analyzer and “follow” the connection for the purpose of monitoring the RSSI of the Trusted MD. - Events from the stack are reported to each Friend Device with RSSI values for both the peripheral and central. - These RSSI values for the Trusted MD are then shared back to VACS (via the wired or wireless channels), which can then utilize trilateration and other positioning algorithms and techniques to approximate the location of the Trusted MD in relation to the main system. - Based on this calculated (approximate) position, the VACS can determine which operations are allowed or triggered automatically. - For example: - Determining whether the smartphone is within a certain radius of the vehicle, allowing the unlocking of the vehicle when a button is pressed on the Trusted MD (or automatically doing so) - Determining whether the smartphone is inside the vehicle and allowing/disallowing certain actions. - For example, if the smartphone is inside the vehicle, the vehicle can be turned on. It may also prevent auto-locking if the vehicle is in park mode and the user walks away, leaving the phone in the vehicle (preventing the user from locking themselves out). ## How to Get Started with Connection Analyzer Now that we've covered the basics of this new feature and gone through how it works in an example use case let's look at how you, as a developer or system architect, could utilize it and where to go from here. ### Understanding the APIs Involved The APIs you would use to utilize this feature are: - [**sl\_bt\_connection\_get\_scheduling\_details()**](https://docs.silabs.com/bluetooth/7.0.0/bluetooth-stack-api/sl-bt-connection?ref=novelbits.io#sl-bt-connection-get-scheduling-details): this API would be called from the primary device after it has established a connection to the third-party device. It would return all the information and details needed for the friend nodes to follow the connection between the primary and third-party devices. - [**sl\_bt\_connection\_analyzer\_start()**](https://docs.silabs.com/bluetooth/7.0.0/bluetooth-stack-api/sl-bt-connection-analyzer?ref=novelbits.io#sl-bt-connection-analyzer-start): this API would be called from the different friend nodes and supplied with the information retrieved from the previous API (sl\_bt\_connection\_get\_scheduling\_details()) to start the process of monitoring the RSSI values for the third-party device. - The stack will provide a report of the monitored RSSI values via a stack event of type **[sl\_bt\_evt\_connection\_analyzer\_report\_t](https://docs.silabs.com/bluetooth/7.0.0/bluetooth-stack-api/sl-bt-evt-connection-analyzer-report?ref=novelbits.io#sl-bt-evt-connection-analyzer-report-t),** which contains **central\_rssi** and **peripheral\_rssi**. Depending on the role of the third-party device, the friend node would pass the corresponding RSSI values to the primary device. - When multiple friend devices distributed in strategic locations within the field of interest are set up to provide this information to the primary device, it allows the primary device to formulate a much more accurate view of the location of the third-party device. ### Sample Example using Connection Analyzer Silicon Labs has published a great example application that utilizes Connection Analyzer. The **Bluetooth Roaming** example application is available on [GitHub](https://github.com/SiliconLabs/pybgapi-examples/tree/master/example/bt%5Froaming?ref=novelbits.io). Sample Application Description: > *This pair of examples models a medical application. The goal is to gather data from several Bluetooth LE heart rate (HR) sensors in a large facility using multiple access points (AP). Whenever a person with the HR sensor moves out from the radio range of an AP and loses connection, a nearby AP shall find it and continue the HR data collection. The access points are supervised by a network coordinator.* > > Source: [Silicon Labs GitHub Repo – BT Roaming Example Application](https://github.com/SiliconLabs/pybgapi-examples/tree/master/example/bt%5Froaming?ref=novelbits.io) ![BT Roaming example application diagram showing access points and heart rate sensors](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-13.png) BT Roaming Example (using Silicon Labs' Connection Analyzer) With this example, you can set up a system that maintains a Bluetooth LE connection to a moving medical device in order to continuously capture its sensor data. All this while making it a seamless connection handover from the medical device's perspective. The APs would appear to the medical device as a single device that ensures that the connection covers a large space (something that traditionally wouldn't be possible with a one-to-one Bluetooth LE topology). ## Important Notes Here are a few important things to keep in mind when implementing an application that uses the Connection Analyzer: - The communication channel between the main and friend devices can be **wired** (UART, CAN bus, Ethernet) **or** **wireless** (Bluetooth, Wi-Fi, etc.). This is left up to the implementation as appropriate. - As of now, only RSSI measurements are monitored by the Connection Analyzer (packet details are not captured) - Friend devices can operate in NCP mode (controlled by an external host) or SoC mode. - Changes in the connection parameters between the primary and third-party devices require resending the connection details to the friend devices. - Bonding information can be shared from the primary device with the friend nodes to allow them to re-use this bonding relationship and make them appear to the third-party device as a single device that's also trusted. Obviously, the APIs that provide this solution will still require some additional work on your part to fully utilize it. This would include designing the architecture of the system, such as the number of friend nodes, their distribution within the field of interest, their configuration (SoC or NCP mode), the communication channel used between the friend devices and the primary device (wireless or wired), how the data is shared between devices, etc. ## Summary In this post, we covered a new feature introduced by Silicon Labs to address a real problem with Bluetooth LE-based systems. The **Connection Analyzer** feature provides a solution for two main use cases: - **Connection handover**: where a device can roam within an area and remain connected to multiple Bluetooth LE gateway devices appearing as if they were one (trusted) device - **More accurate positioning**: where a device’s location can be better estimated via multiple nodes measuring the RSSI of the connection between two trusted devices 💡 **Insider Tip:** Want to master RSSI monitoring, connection management, and location-aware Bluetooth LE applications? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Coded PHY: Bluetooth's Long-Range Feature URL: https://novelbits.io/bluetooth-long-range-coded-phy/ Last updated: 2026-08-09T05:43:37.000Z Bluetooth Low Energy was designed to considerably reduce power consumption and cost while maintaining communication ranges similar to Bluetooth Classic (50-100m max). However, that is no longer the case. With the new Bluetooth long-range mode, you can now achieve ranges of over 1 kilometer using BLE! This is useful for extending the range of a Bluetooth connection or discovering advertisements, but it also helps achieve more robust communication in noisy RF environments and areas with many obstacles. Now, you may be interested in learning more about long-range mode and implementing it into your own application, but you probably don’t want to go through the 3,000+ pages of the Bluetooth Specification document to figure out the steps and configurations necessary for this. Well, you’ve come to the right place! In this post, we’ll go over: - What is long-range mode (Coded PHY)? - Use cases for long-range mode - Coded PHY vs. 1M PHY vs. 2M PHY - Coded PHY packet format - Two methods for utilizing Coded PHY Once you finish reading this blog post, you will understand the overall concepts and the steps required to implement ranges of over 1 km on your BLE Peripheral and Central devices. **Check out the following YouTube video for a real-life drone demo testing Bluetooth long-range!** ## **What is Bluetooth long-range mode?** **Bluetooth long-range** (also known as Coded PHY) is a new mode introduced in Bluetooth Version 5.0 to extend the range of Bluetooth devices from 30-100 feet to ranges of 1 kilometer and beyond. With this powerful range extension, you’ll see some tradeoffs in radio-on time, power consumption, and duty cycle for scheduling and coexistence over the air. As you might expect, this new mode requires some hardware changes. Because support for this new mode is optional, **not all** Bluetooth LE chipsets and modules (even those qualified for Bluetooth 5.0 and later) will support this new mode. Make sure you choose carefully. ## Use cases for long-range mode Long-range mode is not only useful for extending the range of Bluetooth devices. It’s also helpful to achieve a more reliable connection in signal-congested environments or environments with many obstacles. Examples of applications include: - Remote control and remote identification system for drones [\[1\]](https://www.suasnews.com/2019/12/pierce-aerospace-tdrs-set-remote-id-distance-and-altitude-records/?ref=novelbits.io) - Monitoring sensors deployed on large-area farms - Making connections more robust in areas with many obstacles, such as in industrial environments ## Coded PHY (aka Bluetooth long-range) vs. 1M PHY vs. 2M PHY Let’s step back for a minute. If you’ve been working with Bluetooth Low Energy for a while, you’ll know that 1M PHY is the original PHY introduced when Bluetooth Low Energy launched with Version 4.0 of the Bluetooth Core Specification. This PHY allows you to achieve a raw data rate of 1 Megasymbol per second. With Version 5.0 of the Bluetooth specification came two new PHYs: 2M PHY and Coded PHY. So, today (as of v5.4), we have three PHYs available: 1. **1M PHY** (1 Megasymbols per second) – the original PHY supported by all BLE devices 2. **2M PHY** (2 Megasymbols per second) – introduced in Bluetooth 5.0, achieves approximately double the speed of 1M PHY 3. **Coded PHY** (1 Megasymbols per second) – introduced in Bluetooth 5.0, achieves ranges up to four times the range of 1M PHY. This is what we call Bluetooth long-range mode ![Summary of BLE PHYs, modulation schemes, and coding schemes](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-14.png) *Source: Bluetooth Core Specification document* For long-range Bluetooth, we are most concerned with the third PHY we mentioned above - the Coded PHY. This PHY allows us to reach long ranges with BLE. In it, the raw data is still transmitted at the rate of 1Mbps, but we’re transmitting multiple symbols for each of the bits of data that come from the user, the link layer, header, and packet. Effectively, this means that Coded PHY uses multiple symbols to represent each transmitted bit. There are two configurations for Coded PHY: - S2, where each data bit is represented by two symbols. Data rate = 500 kbps (1/2 of 1M PHY data rate) - S8, where each data bit is represented by eight symbols. Data rate = 125 kbps (1/8 of 1M PHY data rate) One thing to note is that not all the fields within a packet are coded with the same configuration, as some will always be configured to use the S=8 configuration. ***Power consumption will vary significantly based on the configuration selected due to its effect on radio-on time.*** Below, we can see a comparison of the radio on-time between the 1M and Coded PHYs: ![Bluetooth long range radio on-time ](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/coded-phy-time-advertising-event.png) *Source: Bluetooth Core Specification document* ## Coded PHY packet format Coded PHY BLE packets have a different format than the standard 1M or 2M PHYs. ![Coded PHY packet format showing FEC blocks, preamble, and coding indicator](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-6.png) *Source: Bluetooth Core Specification document* A few important things to note about the Coded PHY format: - The Preamble is never coded, which allows the packet to be detected in any mode (Coded PHY, 1M PHY, or 2M PHY) before determining which mode was used for the remaining packet’s data. - FEC block 1 is always coded with S=8, - FEC block 2 is coded with S=2 or S=8 (depending on the configuration). - The CI (Coding Indicator) is used to indicate which coding scheme is used in FEC block 2 (S=2 or S=8). - The timing values shown indicate how long it takes to transmit the specific field within the packet. ## How to utilize Bluetooth long-range (Coded PHY)? Now that we understand what the Coded PHY packet format looks like let’s talk about how to actually utilize it in our applications. Coded PHY can be utilized in three ways: - **Advertising-only State**: Use Coded PHY for advertising and for discovery by a device that supports Coded PHY and receiving data included in the advertising packets (great for one-to-many communication) - **Connection State:** Switch to using Coded PHY during an existing (1M or 2M) connection via the PHY update procedure ( - **A Combination of the Two States**: If you're looking to utilize communication that utilizes long distances during the advertising and connection states ### Advertising-only state For two Bluetooth LE devices to successfully connect over long-range mode, one device (the Peripheral) will need to advertise on the Coded PHY while the other (the Central) will need to be configured to look for advertisements on the Coded PHY. In this mode, Extended Advertisements are used. The way this works is by advertising on the Primary Advertisement channels, where these Primary Channel Advertisements point to Secondary Channel Advertisements that hold the advertising information needed to establish a connection. Understanding the appropriate Advertising types used in the Coded PHY mode is crucial for developing BLE applications that can operate using long-range mode. Without the correct setup, a BLE Central device will not be able to discover and/or connect to a BLE Peripheral over the Coded PHY. Let’s look at the different Advertising types used in Coded PHY: ![Advertising types allowed in Coded PHY showing primary and secondary channel PDUs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-7.png) *Source: Bluetooth Core Specification document* Notice that the only Primary Advertising type allowed in Coded PHY is of type ADV\_EXT\_IND. The rest of the Advertising types allowed in Coded PHY are Secondary Advertising packets (AUX\_SCAN\_REQ, AUX\_CONNECT\_REQ, AUX\_ADV\_IND, AUX\_SCAN\_RSP, AUX\_SYNC\_IND, AUX\_CHAIN\_IND, and AUX\_CONNECT\_RSP). This means that connection requests on Coded PHY do not occur on the Primary Advertisement channels, rather, they occur on the Secondary Advertisement channels. The PDU types used in this case are the AUX\_CONNECT\_REQ (the connection request packet) and AUX\_CONNECT\_RSP (the response to the connection request) types. ### During a Connection (PHY update procedure) Bluetooth provides the flexibility to switch to using different PHYs during a connection. Different PHYs can be used in each direction as well between the two connected devices. For example, this procedure can be used to switch to using the Coded PHY after two devices have connected using the standard 1M PHY, allowing the two devices to increase the range at which they maintain the connection. The PHY Update Procedure can be initiated by either the Central or the Peripheral after the connection is established. When the Central initiates the PHY update procedure: - Central sends LL\_PHY\_REQ PDU - Peripheral responds with LL\_PHY\_RSP PDU - Central then responds to this with LL\_PHY\_IND PDU ![Central-initiated PHY update procedure sequence diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-5-2.png) When the Peripheral initiates the PHY update procedure: - Peripheral sends LL\_PHY\_REQ PDU - Central then responds to this with LL\_PHY\_IND PDU ![peripheral-initiated PHY update procedure to utilize Bluetooth long range](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/peripheral-initiated-phy-update-procedure.png) *Source: Bluetooth version 5.1 Core Specification document* The PDU includes both the preferred transmit- and receive-PHYs. ## Coded PHY Peripheral implementation The steps for implementing Coded PHY (long-range Bluetooth) will vary based on the BLE stack and development vendor, platform, or kit you use. However, in general, the implementation of Coded PHY on the Peripheral side involves the following steps: 1. Enabling Extended Advertisements in the BLE stack (Host + Controller) 2. Setting the Primary PHY to use the Coded PHY 3. Setting the Secondary PHY to use the Coded PHY 4. Setting the advertisement data ## Coded PHY support on smartphones The reality is that support for Coded PHY on smartphones varies significantly from device to device. Typically, you will see devices providing one of the following levels of support: - No Coded PHY support - Support for Coded PHY during a connection but not during advertising - Support for advertising extensions and scanning but no support for Coded PHY on the advertising channels - Full Coded PHY support, including both Coded PHY advertising extensions and Coded PHY connections I’ve found that Samsung and OnePlus phones offer the best support for development and testing. ## Summary In this post, we went over the steps you will need to achieve ranges of over 1 kilometer for communication between two BLE devices. We covered: - Basics and use cases of long-range Bluetooth (Coded PHY) - The technical details of Coded PHY, including the two different configurations available (S=2 and S=8) - The details of Coded PHY packets - The steps required to implement Coded PHY for BLE Central and BLE Peripheral devices ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) ### Eddystone Beacon Tutorial: Implementation using Silicon Labs BG22 Explorer Kit URL: https://novelbits.io/eddystone-beacon-tutorial-silicon-labs-bg22/ Last updated: 2026-08-09T05:24:43.000Z ## Introduction In the [previous blog article](https://novelbits.io/ibeacon-tutorial-silicon-labs-bg22), we covered the iBeacon standard, which is a beacon standard developed by Apple. After Apple released the iBeacon standard back in 2013, Google followed suit with its Eddystone standard in 2015. Unfortunately, both Eddystone and iBeacon have not changed much or improved since their releases. In fact, the Eddystone project repo was even recently archived on GitHub. Nevertheless, they have both remained pretty popular due to the fact that they provide a sort of reference or standard for Bluetooth beacons. iBeacon is also a special case for iOS since it’s the only way on iOS to be able to reliably and continuously monitor Bluetooth LE devices in the background. If you prefer to watch the full tutorial with step-by-step implementation and testing, then check out the accompanying YouTube video: ## Eddystone Packet Format Here’s what the Eddystone format looks like: Flags Length 0x02 Type 0x01 Value 0x06 Complete List of 16-bit UUIDs Length 0x03 Type 0x03 16-bit Eddystone UUID 0xAA 0xFE Reversed - Little Endian Service Data - 16-bit UUID Length 0xXY Type 0x16 16-bit Eddystone UUID 0xAA 0xFE Reversed - Little Endian Service Data Eddystone-UID, Eddystone-URL, Eddystone-TLM, or Eddystone-EID If you recall, advertising packets are formatted in **Length-Type-Value** tuples. In this case, the packet includes the following advertising data types: - Flags - Complete list of 16-bit UUIDs - and Service Data for a 16-bit UUID Similar to iBeacon, the *Flags* field in Eddystone is also set to enable the "BR/EDR not supported" and "LE General Discoverable" bits. The complete list of 16-bit UUIDs includes the Eddystone UUID which is 0xFEAA (shown here in little-endian format which reverses the bytes). The Service data includes a length field that depends on the frame type included in the packet, the type which is 16 hex, the 16-bit Eddystone UUID 0xFEAA (little endian format here as well), and finally, the actual data which could be one of the following frames: - **Eddystone-UID**, which is used to broadcast a unique 16-byte Beacon ID composed of a 10-byte namespace and a 6-byte instance - **Eddystone-URL**, which is used to broadcast a URL using a compressed encoding format in order to fit more within the limited advertisement packet - **Eddystone-TLM**, which is used to broadcast telemetry data. This data includes battery voltage level reading, temperature reading, advertising count, and time since power-on - and **Eddystone-EID**, which is used to broadcast an encrypted ephemeral identifier that changes periodically at a rate determined during the initial registration with a web service As you can see, the Eddystone standard (just like iBeacon) really just defines the format of the data included in the advertising packets. You can find more details about the Eddystone standard on the [Eddystone Specification GitHub page](https://github.com/google/eddystone/tree/master?ref=novelbits.io). ## Setup Now, let’s go ahead and implement an Eddystone beacon on the BG22 Explorer Kit, which is a $10 development kit provided by Silicon Labs. We’ll be discovering the Eddystone beacon device from the Silicon Labs EFR Connect mobile app. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bg22-explorer-kit.png) **Silicon Labs BG22 Explorer Kit ($10)** The Eddystone beacon we'll be implementing will include two Eddystone frames: - Eddystone-UID (for identification) - and Eddystone-TLM (for telemetry data) We'll accomplish this by sending out alternating advertising packets (UID and TLM). We'll utilize the **Advertising Sets** feature to do this. We first have to download and install [Simplicity Studio](https://www.silabs.com/developers/simplicity-studio?ref=novelbits.io), which is the official IDE from Silicon Labs for working with their chipsets and development kits. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-6.png) Once installed and set up, we'll want to connect our development kit, the BG22 Explorer Kit, to the computer. Next, we'll want to flash the bootloader to the dev kit. The easiest way to do this is to load one of the existing demos. Let's go ahead and load the "SoC Blinky" demo: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2023-09-10-at-8.45.54-E2-80-AFAM.png) Bluetooth - SoC Blinky Demo (needed to load the bootloader onto the dev kit) Now, we'll start the implementation of the project. We'll be using the "SoC Empty" example as a starting point: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2023-09-10-at-8.47.43-E2-80-AFAM.png) Bluetooth - SoC Empty Example Once you've gone through the process of creating the project using the SoC Empty example, let's go ahead and install a couple of Software Components in our project so we can print out log messages to the serial terminal. The way we do this is by opening the .slcp file, then navigating to the Software Components tab: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-4-3.png) Software Components Let's search for the following components: - "**io stream**", and then install Services --> IO Stream --> Driver --> IO Stream: USART - "**log**", and then install Application --> Utility --> Log - "**advertising base feature**", and then configure the "**Max number of advertising sets reserved for user**" to 2: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screenshot-2023-09-10-at-9.12.23-E2-80-AFAM.png) ## Implementation Now that we have all the configurations set up, we can move on to the code implementation portion. Let's open up `app.c` and start implementing. **Step #1: Advertising Set Handles** Let's start by adding the following variables: ```c // The advertising set handle allocated from Bluetooth stack. static uint8_t advertising_set_handle_uid = 0xff; static uint8_t advertising_set_handle_tlm = 0xff; ``` We'll be using these handles for creating the two advertising sets (one for UID and the other for TLM). **Step #2: Define the advertising data** For this, we'll define a data structure to define the advertising data and then we'll instantiate two variables, one for holding the UID data and the other for the TLM data. Both types will include the following fields: - **Flags** - Length field (1 byte) = 0x02 - Type field (1 byte) = 0x01 - Flags value field (1 byte) = 0x06 (LE General Discoverable + BR/EDR not supported) - **16-bit UUID List** - Length field (1 byte) = 0x03 - Type field (1 byte) = 0x03 - UUID list value field (2 bytes, little-endian) = { 0xAA, 0xFE } - **16-bit UUID Service Data** - Length field (1 byte) = variable depending on the frame type (UID, EID, TLM, URL) - Type field (1 byte) = 0x16 - 16-bit Service UUID (2 bytes, little-endian) = { 0xAA, 0xFE } - Service Data (variable length. For UID, this will be 20 bytes, and for TLM, it will be 14 bytes). In this example, I chose arbitrary values for the various fields. ***See the linked YouTube video at the top of the article for more details.*** ```c // Advertising Data typedef struct { // Flags uint8_t flags_len; uint8_t flags_type; uint8_t flags_value; // 16-bit UUID List uint8_t uuid_list_len; uint8_t uuid_list_type; uint8_t uuid_list_value[2]; // Service Data (16-bit UUID) uint8_t service_data_len; uint8_t service_data_type; uint8_t service_data_uuid[2]; union { uint8_t service_data_uid[20]; uint8_t service_data_tlm[14]; }; } eddystone_data_t; static const eddystone_data_t adv_data_uid = { // Flags .flags_len = 0x02, .flags_type = 0x01, .flags_value = 0x06, // 16-bit UUID List .uuid_list_len = 0x03, .uuid_list_type = 0x03, .uuid_list_value = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) // 16-bit UUID Service Data .service_data_len = 0x17, .service_data_type = 0x16, .service_data_uuid = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) .service_data_uid = { 0x00, \ 0x00, \ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,\ 0x11, 0x022, 0x33, 0x44, 0x55, 0x66, \ 0x00, 0x00 \ } }; static const eddystone_data_t adv_data_tlm = { // Flags .flags_len = 0x02, .flags_type = 0x01, .flags_value = 0x06, // 16-bit UUID List .uuid_list_len = 0x03, .uuid_list_type = 0x03, .uuid_list_value = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) // 16-bit UUID Service Data .service_data_len = 0x11, .service_data_type = 0x16, .service_data_uuid = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) .service_data_tlm = { 0x20,\ 0x00,\ 0x00, 0x64,\ 0x48, 0x80,\ 0x00, 0x00, 0x00, 0x01,\ 0x00, 0x00, 0x00, 0x02 \ } }; ``` **Step #3: Add code to create the two advertising sets and set the corresponding advertising data** ```c /**************************************************************************//** * Bluetooth stack event handler. * This overrides the dummy weak implementation. * * @param[in] evt Event coming from the Bluetooth stack. *****************************************************************************/ void sl_bt_on_event(sl_bt_msg_t *evt) { sl_status_t sc; switch (SL_BT_MSG_ID(evt->header)) { // ------------------------------- // This event indicates the device has started and the radio is ready. // Do not call any stack command before receiving this boot event! case sl_bt_evt_system_boot_id: app_log_info("Eddystone Example Started!\n"); // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle_uid); app_assert_status(sc); sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle_uid, sl_bt_advertiser_advertising_data_packet, sizeof(adv_data_uid), (uint8_t *)&adv_data_uid); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle_uid, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle_uid, sl_bt_advertiser_non_connectable); app_assert_status(sc); // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle_tlm); app_assert_status(sc); sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle_tlm, sl_bt_advertiser_advertising_data_packet, sizeof(adv_data_tlm), (uint8_t *)&adv_data_tlm); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle_tlm, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle_tlm, sl_bt_advertiser_non_connectable); app_assert_status(sc); break; /////////////////////////////////////////////////////////////////////////// // Add additional event handlers here as your application requires! // /////////////////////////////////////////////////////////////////////////// // ------------------------------- // Default event handler. default: break; } } ``` And that's it! That completes our implementation of an Eddystone beacon. For details on testing and final steps, refer to the linked YouTube video at the top of the article. ## Full Source Code (`app.c`) ```c /***************************************************************************//** * @file * @brief Core application logic. ******************************************************************************* * # License * Copyright 2020 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #include "em_common.h" #include "app_assert.h" #include "sl_bluetooth.h" #include "app.h" // The advertising set handle allocated from Bluetooth stack. static uint8_t advertising_set_handle_uid = 0xff; static uint8_t advertising_set_handle_tlm = 0xff; // Advertising Data typedef struct { // Flags uint8_t flags_len; uint8_t flags_type; uint8_t flags_value; // 16-bit UUID List uint8_t uuid_list_len; uint8_t uuid_list_type; uint8_t uuid_list_value[2]; // Service Data (16-bit UUID) uint8_t service_data_len; uint8_t service_data_type; uint8_t service_data_uuid[2]; union { uint8_t service_data_uid[20]; uint8_t service_data_tlm[14]; }; } eddystone_data_t; static const eddystone_data_t adv_data_uid = { // Flags .flags_len = 0x02, .flags_type = 0x01, .flags_value = 0x06, // 16-bit UUID List .uuid_list_len = 0x03, .uuid_list_type = 0x03, .uuid_list_value = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) // 16-bit UUID Service Data .service_data_len = 0x17, .service_data_type = 0x16, .service_data_uuid = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) .service_data_uid = { 0x00, \ 0x00, \ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,\ 0x11, 0x022, 0x33, 0x44, 0x55, 0x66, \ 0x00, 0x00 \ } }; static const eddystone_data_t adv_data_tlm = { // Flags .flags_len = 0x02, .flags_type = 0x01, .flags_value = 0x06, // 16-bit UUID List .uuid_list_len = 0x03, .uuid_list_type = 0x03, .uuid_list_value = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) // 16-bit UUID Service Data .service_data_len = 0x11, .service_data_type = 0x16, .service_data_uuid = { 0xAA, 0xFE }, // Little endian UUID (0xFEAA) .service_data_tlm = { 0x20,\ 0x00,\ 0x00, 0x64,\ 0x48, 0x80,\ 0x00, 0x00, 0x00, 0x01,\ 0x00, 0x00, 0x00, 0x02 \ } }; /**************************************************************************//** * Application Init. *****************************************************************************/ SL_WEAK void app_init(void) { ///////////////////////////////////////////////////////////////////////////// // Put your additional application init code here! // // This is called once during start-up. // ///////////////////////////////////////////////////////////////////////////// } /**************************************************************************//** * Application Process Action. *****************************************************************************/ SL_WEAK void app_process_action(void) { ///////////////////////////////////////////////////////////////////////////// // Put your additional application code here! // // This is called infinitely. // // Do not call blocking functions from here! // ///////////////////////////////////////////////////////////////////////////// } /**************************************************************************//** * Bluetooth stack event handler. * This overrides the dummy weak implementation. * * @param[in] evt Event coming from the Bluetooth stack. *****************************************************************************/ void sl_bt_on_event(sl_bt_msg_t *evt) { sl_status_t sc; switch (SL_BT_MSG_ID(evt->header)) { // ------------------------------- // This event indicates the device has started and the radio is ready. // Do not call any stack command before receiving this boot event! case sl_bt_evt_system_boot_id: app_log_info("Eddystone Example Started!\n"); // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle_uid); app_assert_status(sc); sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle_uid, sl_bt_advertiser_advertising_data_packet, sizeof(adv_data_uid), (uint8_t *)&adv_data_uid); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle_uid, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle_uid, sl_bt_advertiser_non_connectable); app_assert_status(sc); // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle_tlm); app_assert_status(sc); sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle_tlm, sl_bt_advertiser_advertising_data_packet, sizeof(adv_data_tlm), (uint8_t *)&adv_data_tlm); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle_tlm, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle_tlm, sl_bt_advertiser_non_connectable); app_assert_status(sc); break; /////////////////////////////////////////////////////////////////////////// // Add additional event handlers here as your application requires! // /////////////////////////////////////////////////////////////////////////// // ------------------------------- // Default event handler. default: break; } } ``` ## Conclusion In this article, we covered: - The basics of the Eddystone Beacon standard - Step-by-step implementation of an Eddystone device that sends out two frame types: UID and TLM - Implementation using the Silicon Labs BG22 Explorer Kit 💡 **Insider Tip:** Want to learn more about Bluetooth LE beacon development? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### PAwR: Bidirectional Bluetooth LE Advertising URL: https://novelbits.io/periodic-advertising-with-responses-pawr/ Last updated: 2026-08-09T05:43:25.000Z PAwR: Bidirectional Bluetooth LE Advertising *Sponsored by [Silicon Labs](https://silabs.com/?ref=novelbits.io)* If you've wondered whether advertising in Bluetooth Low Energy can be bidirectional, then this post is for you. If you've recently come across the term PAwR and you've wondered what it means, then this article is also for you. But first, a bit of background information... ## Introduction Since the introduction of Bluetooth Low Energy in 2010 (in version 4.0 of the Bluetooth Core Specification), the advertising feature has proven to be a game-changing new topology for the standard. It’s specifically great for broadcasting data in one-to-many applications (e.g., beacons). However, it’s always been unidirectional, which means it was very limiting and not feasible for many use cases. In these cases, developers have had to resort to designing systems that rely on connections between Bluetooth LE devices. Unfortunately, one of the most significant downsides of connections is that only a limited number can be established from one device. This is primarily due to the following: - Each connection requires continuously dedicated radio airtime to exchange data and even to keep the connection alive (in the case that no data is exchanged), which means it can only support so many connections before it runs out of airtime. - Each connection requires the use of additional memory resources. With memory resources usually being very limited, especially on embedded devices, this can quickly add up, so Bluetooth stacks usually limit the number of connections supported. Due to these limitations, connections are **not suitable** for large-scale network deployments. One solution to the large-scale/many-devices communication dilemma is to use **Bluetooth mesh**, which enables many-to-many communication. However, mesh does not serve well for centralized applications (think a star topology. E.g., thousands of nodes monitored/controlled by a single access point), nor is it well suited for low-power applications in battery-operated devices. 🎥 [See a live PAwR + Coded PHY demo using Silicon Labs development kits at the end of this post.](#pawr-coded-phy-s-8-demo) ## Periodic Advertising with Responses (PAwR) That was the case until January 2023, when a new version of the Bluetooth Core Specification was released, [version 5.4](https://www.bluetooth.com/specifications/specs/core-specification-5-4/?ref=novelbits.io), and an exciting new feature called **Periodic Advertising with Responses (PAwR)** was introduced. PAwR builds upon a couple of *relatively* new features of Bluetooth LE: **Extended Advertising** and **Periodic Advertising** (both introduced in version 5.0). It solves a significant problem that couldn’t be solved with Bluetooth advertising or connections before: **Achieving large-scale communication* (not possible with connections) that's also *bidirectional* (not possible with advertising).* So, it’s, in fact, the best of both worlds! In this article, we will: - Recap the foundations and building blocks of PAwR - Explore what PAwR is and how it works in detail - Go over the general steps of designing a PAwR system - Talk about the different types of applications that would benefit from implementing PAwR - Explore the use of PAwR in combination with Coded PHY (long-range mode) for expanding the range ## PAwR vs. Bluetooth mesh While Bluetooth mesh can serve as a solution for large-scale bidirectional communication, it’s suitable for different applications than PAwR. Let’s take a look at the differences between PAwR and Bluetooth mesh systems: | Protocol ➡Aspect ⬇ | PAwR | Bluetooth mesh | | ---------------------------- | ----------------------------------------------------------- | ----------------------------------- | | **Topology** | Centralized (star), 1-to-many | Decentralized (mesh), many-to-many | | **Collision** **Mitigation** | Response slots assignment for nodes to eliminate collisions | No collision mitigation available | | **Range** | Long-range via Coded PHY | Long-range via relay nodes | | **Security** | Optional security via Encrypted Advertising Data (EAD) | Security is mandatory | | **Power Consumption** | Low-power by design | A limited number of low-power nodes | | **Scalability** | Support for over 10,000 nodes | 1,000s of nodes | | **Complexity** | Simpler to implement | More complex to implement | *A table comparing PAwR to Bluetooth mesh* Let’s break it down based on the most crucial aspects: - **Power consumption**: Bluetooth mesh does not support creating a system mainly comprised of low-power devices. PAwR, on the other hand, is optimized for low-power nodes. - **Topology**: if you are looking for a centralized (star topology) type of system, then PAwR is the way to go. This makes sense in applications that require a centralized device (such as a gateway, router, or access point) to communicate with thousands of nodes. Bluetooth mesh operates in a many-to-many style where self-healing is one of its primary goals, so it's a more decentralized system. - **Collision**: with PAwR, response slots are assigned to individual nodes, leading to collision mitigation. This is not possible with Bluetooth mesh since it's based on traditional Bluetooth LE Advertising methods. - **Complexity**: PAwR systems are much simpler to implement in terms of the features required by the stack. Bluetooth mesh requires a more complex implementation, a more complex stack, and a more complex system deployment. As you can see, the two types of systems have quite a few differences. PAwR fills a noticeable gap where Bluetooth mesh was sometimes chosen as a viable solution, **only due to the lack of options** and not because it was the best fit. ## How does PAwR work? To understand how PAwR works, we have to revisit a few important concepts in Bluetooth Low Energy: Advertising, Extended Advertising, and Periodic Advertising. Let’s briefly revisit each of these before getting into the details of PAwR. 💡 **Also refer to my previous blog posts on Bluetooth Low Energy Advertising:** [How Bluetooth Low Energy Works: Advertisements (Part 1)](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/) [How Bluetooth Low Energy Works: Advertisements (Part 2)](https://novelbits.io/bluetooth-low-energy-advertisements-part-2/) ### Bluetooth LE Advertising Advertising is a crucial part of any Bluetooth-connected system. It’s the way by which Bluetooth LE (peripheral/broadcaster) devices get discovered. This works by sending packets on all (or a subset) of the three primary advertising channels (labeled 37, 38, and 39). ![Bluetooth LE RF Channels and Spectrum](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/chapter-2-d3-small.png) Bluetooth LE RF Channels and Spectrum A few important notes on advertising packets (referred to as advertising PDUs): - There are multiple aspects that characterize advertising PDUs: connectable vs. non-connectable, scannable vs. non-scannable, and directed vs. undirected - Advertising packets can accommodate up to 31 bytes of advertising data - Advertising data included in the packets include zero or more 3-tuples, each made up of **length - type - value** (LTV) - Examples of advertising data types include: Tx power, Device Name, Manufacturer Specific Data (which is provided as a way to include proprietary data). - Since **length** and **type** are both mandatory for each advertising data type, it reduces the space available for actual data in the advertising packet. For example, if an advertising packet were to include only a long device name, the maximum number of bytes available for that string would be 31 - 1 (length) - 1 (type) = 29 bytes. - Due to the proliferation of Bluetooth LE devices, the three primary advertising channels have become increasingly congested. *We’ll see in the next section how Extended Advertising was designed to overcome this (partially).* ### Bluetooth LE Extended Advertising In Bluetooth version 5.0, a new feature called Extended Advertising was introduced. The goal was to offset as much of the advertising data to less congested channels and allow the sending of more data than what can fit into a single primary advertising packet (up to 254 bytes in a single packet or up to 1650 bytes via packet chaining). This is how it works: 1\. The advertising device sends packets (`ADV_EXT_IND`) on the three primary advertising channels (or a subset of them) 2\. These packets **do not** contain any advertising data. Rather, they contain what’s called an *auxiliary packet pointer (`AuxPtr`)*. 3\. This pointer includes the following information: channel index, clock accuracy, offset units, auxiliary offset, and auxiliary PHY ![AuxPtr field in the Common Extended Advertising Packet Format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-6.png) AuxPtr field within the Common Extended Advertising Packet 4\. This information helps a scanner locate where the upcoming extended advertising packet is sent on the secondary advertising channels (0-36) 5\. The advertising packet sent on the secondary advertising channels (`AUX_ADV_IND`) is the one that contains the actual advertising data 6\. Extended Advertising packets sent on the secondary advertising channels can contain up to 254 bytes of advertising data 7\. Chained Extended Advertising allows sending multiple consecutive Extended Advertising packets that can total up to 1,650 bytes of advertising data Here’s a diagram showing an example of one scenario: ![Extended Advertising Example Diagram. Needed for PAwR.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-1-1.png) Extended Advertising Packets on primary and secondary advertising channels ### Bluetooth LE Periodic Advertising Now that we’ve learned about Extended Advertising let’s cover another essential feature of Bluetooth LE: **Periodic Advertising**. Periodic Advertising takes advertising to a whole new level. It provides a way for scanning devices to **synchronize** to a “train” of advertising packets that are used to send out advertising data (that’s usually changing). A good example of this might be a system comprised of multiple temperature sensors, each sending out its latest temperature readings along with timestamps at regular intervals. The two main advantages of Periodic Advertising are: - It allows an unlimited number of scanning devices to synchronize to one or more peripherals and receive their advertising data at predictable fixed intervals without needing to establish a connection - It helps reduce power consumption, even at the scanner side, since the scanning devices only need to turn on the radio at pre-defined intervals after they’ve synchronized to the periodic advertising train (vs. having to continuously scan for legacy or extended advertising packets that are not transmitted at deterministic times) Periodic Advertising does require the use of Extended Advertising in order for the scanner to discover and synchronize with the Periodic Advertising train. So, that is a minor downside since the scanner will have to go through the following sequence at least once: - Discovering extended advertising packets sent on the primary advertising channels (`ADV_EXT_IND`) - Parsing these advertising packets to find where and when the auxiliary advertising packets are sent on the secondary advertising channels (via the `AuxPtr` field) - Locating (and then parsing) the auxiliary advertising packets (`AUX_ADV_IND`) to find out how to locate the periodic advertising train (via the `SyncInfo` field) - Finally, synchronizing to the periodic advertising train of packets (`AUX_SYNC_IND`), which are consistently being transmitted at fixed precise intervals (Periodic Advertising Interval) Here’s a diagram showing what this looks like: ![Periodic Advertising Example Diagram. Needed for PAwR.](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-5.png) Periodic Advertising in Bluetooth Low Energy ### Bluetooth LE Periodic Advertising with Responses (PAwR) Now that we’ve covered all the background information on advertising and how periodic advertising trains are synchronized to, we are ready to tackle Periodic Advertising with Responses (PAwR). PAwR takes Periodic Advertising to the next level. It was introduced primarily for the application of Electronic Shelf Labels (ESLs). Accompanying its release in the [5.4 specification](https://www.bluetooth.com/specifications/specs/core-specification-5-4/?ref=novelbits.io), a new [ESL Profile specification](https://www.bluetooth.com/specifications/specs/electronic-shelf-label-profile-1-0/?ref=novelbits.io) was also released. It specifies exactly how the PAwR feature is used for ESL applications and introduces it as a Bluetooth LE standardized profile. However, PAwR can be used in many other applications outside of ESL. Some examples include: - Healthcare applications, such as remote patient monitoring in hospitals and medical facilities - Industrial applications, such as condition monitoring in factories - Smart Home applications, such as temperature, humidity, and environmental sensing in homes - and more ### The Technical Aspects Ok, now let’s go over how the PAwR feature works. We’ll use the following diagram to explain it. ![PAwR Timing Parameters](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-4-2.png) Detailed view of the timing parameters of a PAwR system Let’s break down the different elements: - In PAwR systems, the roles are a bit reversed from what we are traditionally used to - The **advertiser** will be the “center hub” device that’s usually mains-powered (referred to as an Access Point - AP). It also acts in the role of a Central for establishing connections to the Responders in order to commission/configure the devices and for transferring large amounts of data (such as image files, firmware updates, etc.). So, this device will act in two roles: Broadcaster + Central. - The scanner/responder devices will usually be battery-powered devices. These devices will also act as peripherals for configuration purposes and for the purpose of receiving relatively large amounts of data (such as image files, firmware updates, etc.). So, this device will act in two roles: Observer + Peripheral. - The Periodic Advertising Interval is the same as what we’re used to with Periodic Advertising - Periodic Advertising Interval: 7.5 ms to 81.91875 sec - However, now we have the concept of **Subevents** - Number of subevents: 1 to 128 - Subevent Interval: 7.5 ms to 318.75 ms - Within each Subevent, we have a transmit slot where a single packet is sent by the Broadcaster - After a specific delay from the start of the Subevent, there are a number of **Response Slots** defined - Number of response slots: 0 to 255 - Response Slot Delay: 1.25 ms to 317.5 ms - Response Slot Spacing: 0.25 ms to 31.875 ms ### PAwR System Design The most crucial part of designing a PAwR system is going to be **defining the timing parameters** for the system (Periodic Advertising Interval, Number of Subevents, Subevent Interval, Number of Response Slots, Response Slot Delay, Response Slot Spacing). *Why is this crucial?* Because each packet requires a specific amount of time to be transmitted, we need to consider the time required to send the maximum-size packet and ensure it fits within the timing periods defined in the PAwR system. ### PAwR Timing Parameters This is what the design thought process could look like for such a system: - Define the **Periodic Advertising Interval** - Keep in mind that the longer the interval, the higher the latency, but that leads to lower power consumption. So, we need to strike a balance with the interval value we choose. - This interval value should also be revisited after defining the below parameters to ensure the most efficient design. - Define the **Number of Subevents** - This would depend on the application and use case. For example, how many end nodes (scanning devices) will there be? - Subevents can be used to group a set of devices so they see and receive the same advertising data at the same time (synchronized). - Devices can also be assigned different Subevents so each can be targeted independently. - As an example, we could have five devices, each assigned a specific Subevent (total of 5 Subevents), and then a 6th Subevent to send data to all of these devices as a group. This would lead to a total number of Subevents of 6. - Define the **Subevent Interval** - The Subevent Interval would be defined based on the number of subevents and the Periodic Advertising Interval - It also needs to accommodate the time it takes to transmit the packet sent by the AP, the Response Slot Delay (which we can define later), and the time it takes to transmit the total number of Responses (which we can also define later) - The Number of Responses will be shared across all Subevents. Going back to the example described above, even if only one device responds in 5 of the defined Subevents (Subevents #0-4) and we have Subevent #5 where all 5 Responders are sending responses, we would need to define the Number of Responses to be 5 (which will be defined across all Subevents). - Define the **Response Slot Delay** - This needs to accommodate the time it takes to transmit the packet from the AP - It also should take into account the maximum amount of time needed for processing on the receiver nodes to prepare the responses - Define the **Periodic Advertising Response Slot Spacing** - This needs to accommodate the amount of time it takes to transmit a packet of the maximum expected size from the responders - After the parameters are designed, they should be revisited to ensure that they are defined to achieve the most efficient design As you can see, defining the PAwR timing parameters is pretty involved and not entirely straightforward. So, the system architect should probably spend enough time designing these parameters and even prototyping and testing them out on a real system to validate the design. ### Security and Encryption of Advertising Data In some use cases, devices in a PAwR system transmit sensitive data, or they simply don't want the data to be exposed to other devices in the area. Sounds like a great candidate for encryption and security, right? Traditionally, encryption of (and securing) advertising data was not defined in the Bluetooth specification and was left to implementation at the application level. Fortunately, along with the introduction of PAwR in version 5.4, a new feature called **Encrypted Advertising Data (EAD)** was introduced. This feature solves the issue at the protocol level, which means it's standardized and can be used across devices from different vendors. The one caveat for utilizing this feature is that it requires two Bluetooth LE devices to connect and pair (at least once) in order to exchange the information necessary for the decryption of the advertising data by the scanner device. Here’s a high-level overview of how it works: - A new characteristic called “Encrypted Data Key Material” is added to the GAP service of the peripheral device - This characteristic provides the basis by which a peripheral device can share the information needed to decrypt its encrypted advertising data - This requires the central device to connect to the peripheral then: - read this characteristic and - subscribe to indications in order to receive the new value if it ever changes. \* This is required in order to be able to decrypt the encrypted data in the advertising packets - A new AD Type called Encrypted Data is used to encapsulate the encrypted advertising data - The encrypted advertising data may contain multiple AD Types within the single payload. In this case, the AD structures are concatenated first before being encrypted Without implementing the new EAD feature, you will have to either handle the encryption of your device’s advertising data at the application level. In highly sensitive use cases, you may still want to add app-level encryption to achieve higher levels of data security. In the near future, we'll cover this feature in more detail including a walkthrough of implementing it. ### Important Design Aspects Here are some important aspects to keep in mind when designing a PAwR-based system: - The Core Specification (≥ version 5.4) defines the foundation for a system utilizing this feature, specifically regarding the timing conditions and value ranges, packets, and methods/operations used. The rest is left up to the implementation. - Examples of aspects left to implementation include: - Defining the number of response slots - Defining the groupings of end-nodes - Assigning the Subevents to each end-node - Assigning the response slot for each end node - Defining the payloads of the messages sent from the advertiser to the end-node devices, and vice versa - and more - Assigned response slots allow the system to handle thousands of nodes (over 10,000) without suffering from collisions since each node is assigned a specific response slot to respond in. This ensures that each device is using a specific assigned time period to send data back to the AP when no other device is allowed during that time period. - Response slots assignment is left to the implementation and can be defined in different ways. They can be: - Assigned to each node in the packet sent by the AP (potentially split between devices across multiple Subevents) - Assigned to each node via a GATT operation during a connection between the AP and the end node - Hardcoded assignment at each end node ## Going the Distance! In contrast to Bluetooth mesh, PAwR does not operate in a way where nodes can relay messages to increase the coverage of the network. Instead, it is exactly like a traditional Bluetooth LE system, where devices are mainly communicating directly with each other. So, to increase the coverage area and distance for communication, we would need to utilize Bluetooth's Coded PHY (long-range) feature instead. I won't be going into a lot of detail on Coded PHY since I've already covered it in a previous blog post: 📖 Blog Post: [**Coded PHY: Bluetooth's Long-Range Feature**](https://novelbits.io/bluetooth-long-range-coded-phy/) The main aspect (yet again!) of designing a PAwR system is defining the timing parameters. This is further emphasized when utilizing Coded PHY. Ok, you may be wondering: why? This is due to the fact that a **Coded PHY packet is larger than a traditional (1M PHY) Bluetooth LE packet**, which means it requires a longer time to transmit. By how much? Good question! Let's dig into this. For the 1M PHY, here's what the packet transmission timing looks like: ![Uncoded 1M PHY Advertising Packet Format and Duration](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-5-1.png) Total Packet Transmission Time Required > 80 µs **Uncoded 1M PHY Advertising Packet Format and Duration** In contrast, here's what the transmission timing for a Coded PHY packet looks like: ![Coded PHY Advertising Packet Format and Duration](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-6-1.png) Total Packet Transmission Time Required > 462 µs, for S=2 Total Packet Transmission Time Required > 720 µs, for S=8 **Coded PHY Advertising Packet Format and Duration** ### LE Coded PHY vs. LE 1M PHY Packet Transmission Duration As you can see, in the case of Coded PHY, the timing varies depending on the Coding scheme used (S=2 vs. S=8), but in either case, it is much longer than when using the 1M PHY. **So, the important point is to ensure that when designing a PAwR system that uses the LE Coded PHY, you want to pay close attention to the packet duration and design the system timing parameters accordingly.** To recap and make things easier to calculate, here's a list of equations (rough timing estimation) that can be used as a guideline for defining the timing parameters of a PAwR system: - *Periodic Advertising Interval* \> (*\# of SubEvents* \* *Subevent Interval*) - *SubeventInterval* \> *Response Slot Delay* \+ (*\# of Response Slots* ∗ *Response Slot Spacing*) - *Response Slot Delay* \> *Amount of time needed to transmit a Transmit packet* - *Response Slot Spacing* \> *Amount of time needed to transmit a Response packet* ### PAwR + Coded PHY (S=8) Demo To showcase the potential of using Coded PHY in combination with PAwR to achieve longer-range communication, I've built a demo using a few Silicon Labs development kits and based on an existing example provided by Silicon Labs. The example is called "Bluetooth - PAwR Thermometer". It does not utilize Coded PHY (instead, it uses the standard 1M PHY), so changes had to be made to support that in addition to re-designing the PAwR timing parameters of the system. You can find the example on Silicon Labs' GitHub repo [here](https://github.com/SiliconLabs/bluetooth%5Fapplications/tree/master/bluetooth%5Fpawr%5Fthermometer?ref=novelbits.io). ![Bluetooth PAwR Thermometer Example from Silicon Labs](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-7-1.png) Bluetooth - PAwR Thermometer Example (Silicon Labs) Ok, onto the video. Enjoy! ## Summary & Recap In this article, we covered a lot of ground (*no pun intended*!): - The reasoning and history behind the new Periodic Advertising with Responses (PAwR) feature introduced in Bluetooth version 5.4 - The foundations of PAwR, including LE Extended Advertising and LE Periodic Advertising - What is PAwR? - How does PAwR work? - How to design a PAwR system - Important design aspects - Achieving longer range with LE Coded PHY - A video demo showcasing a system designed using a combination of PAwR and Coded PHY 💡**Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Mastering iBeacon: Step-by-step Silicon Labs BG22 Implementation Tutorial URL: https://novelbits.io/ibeacon-tutorial-silicon-labs-bg22/ Last updated: 2026-08-09T05:25:15.000Z It feels like an eternity since Bluetooth beacons were introduced! Sure, it's been about 10 years, and yet they still show up in new use cases every single day. In today's tutorial, we are going to focus on Apple's iBeacon technology standard and implement our own iBeacon device step-by-step on the Silicon Labs BG22 Explorer Kit. The BG22 Explorer Kit is a powerful, yet cost-effective, development kit priced at only $10! It serves as the perfect development kit for the task of implementing an iBeacon device. ## What are Bluetooth Beacons? As the name *beacon* implies, it is simply a term given to Bluetooth devices that operate in transmit-only mode, broadcasting data for other Bluetooth devices to discover them. Here are a few common properties of Bluetooth beacons: - They are battery-powered - They broadcast data that includes one or more unique identifiers - In some cases, they also broadcast telemetry data such as battery voltage reading, temperature, timestamp since power up, etc - They are commonly used in location-based services and applications - and finally, the RSSI of the beacon is used to approximate the location of the beacon Beacons are used in many applications. some examples include: - Wireless sensors (temperature, humidity, pressure, motion, etc.) - Payment systems (e.g., triggering financial transactions on mobile phones) - Indoor navigation systems - Asset tracking - Any combination of the above A couple of very popular beacon standards that you’ve probably heard of, iBeacon and Eddystone. But, keep in mind that a beacon standard is nothing more than a definition for the format of data that’s included in the advertising packets. So it’s not some new protocol or wireless standard or anything like that. iBeacon is a standard that was introduced by Apple and Eddystone by Google. For this tutorial, we will focus on iBeacon. For a general overview of Bluetooth beacons, refer to my [previous blog post on the topic](https://novelbits.io/what-is-a-beacon-guide-to-bluetooth-beacon-technology/). ## Refresher: Advertising Data Format Before getting into the format for the iBeacon standard, let’s recap what advertising data looks like: #### LTV #1 Length Type Value **Flags** 02 01 06 #### LTV #2 Length Type Value **Complete List 16-bit UUIDs** 03 03 AA FE ... #### LTV #3 Length Type Value **Complete Local Name** 0B 09 4E 6F 76 65 6C 20 42 69 74 73 N o v e l B i t s The advertising data is arranged in Length-Type-Value tuples. Each of these contains a specific type of advertising data. So in this example, you can see that we have three different advertising data types included: - Flags indicate whether the device is *general discoverable*, *limited discoverable*, or *not* *discoverable* at all. They also indicate whether BR/EDR is supported or not (needed for dual-mode devices). - Complete list of 16-bit UUIDs. This is a "shortcut" for informing the scanner what 16-bit services are included in the GATT database for the device. - A *complete local name*, which is basically a device name. ## iBeacon Data Format This is what the iBeacon data format looks like (click the image to view in full-screen mode): #### Flags 0x02 0x01 0x06 #### Manufacturer Specific Data 0x1A 0xFF Company ID: Apple (0x4C 0x00) Subtype (iBeacon) 0x02 Subtype Length 0x15 UUID (16 bytes) Major (2 bytes) Minor (2 bytes) Tx Power (1 byte signed) An iBeacon is required to send out the following advertising data types: - **Flags**: - *BR/EDR not supported* bit **set** - *General discoverable mode* bit **set** - **Manufacturer Specific Data**, which is a way to include proprietary vendor data. For iBeacon, it contains the following: - The first is the **length** (standard and fixed) - The second is the **type** (standard and fixed) - The third is the **company ID** (registered with the SIG, **0x004C** in the case of Apple), but in reverse byte order, since it needs to be in Little Endian format - And then actual data which includes: - Subtype, set to **0x02** which corresponds to iBeacon per Apple’s spec. - Subtype length (**0x15**) - Next comes the user-defined fields. These include: - 16-byte UUID (defined by the user), think of it as a unique ID you define for all your devices or product line - A 2-byte major number: think of it as a location - A 2-byte minor number: think of it as a sub-location - And finally, a signed 1-byte value, which represents the Tx power: the average signal power measured at 1 meter from the device As you can see, the standard really just defines the format of the data included in the advertising packets, nothing more! ## iBeacon Implementation on Silicon Labs BG22 Explorer Kit Now, let’s go ahead and implement each of these on the [BG22 Explorer Kit](https://www.silabs.com/development-tools/wireless/bluetooth/bg22-explorer-kit?tab=overview&ref=novelbits.io), which is a $10 development kit provided by Silicon Labs, and we’ll be discovering the beacon device via the [Silicon Labs EFR Connect mobile app](https://www.silabs.com/developers/efr-connect-mobile-app?ref=novelbits.io). To do this, we first have to download and install Simplicity Studio, which is the official IDE from Silicon Labs for working with their chipsets and development kits. You can do so [here](https://www.silabs.com/developers/simplicity-studio?ref=novelbits.io). Once you have Simplicity Studio downloaded, connect the BG22 Explorer Kit to your computer. Now, navigate to the **Launch** perspective and it should now show up there under Connected Devices. Then, hit **Start**. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/dff7263e-c422-47b4-a99b-14268542dda3.png) ### Loading Bootloader Now, first, we want to run one of the demo applications in order to load the bootloader onto the device. We'll be running the **SoC Blinky Demo example**: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/fe06e4a0-a2d8-4085-9675-360e1ac71e63.png) Once you run the demo, the device will now have the bootloader installed on it, so we don't have to worry about it from here on. ### Creating a Project Based on Example Next, we want to create a project based on the **SoC Empty** example. Hit create and set a name for your project: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/003e3853-6a70-4226-a21f-2c6d370155c6.png) Now that we have the project ready, we will start adding code to set our advertising data for the device. ### Defining the Advertising Data In terms of advertising data, recall that we need two advertising data types included with certain settings: - Flags: fixed value - Manufacturer Specific Data: includes fixed values and four variables (UUID, Major, Minor, and Tx Power) We'll use the following values: - **UUID**: `01020304-0506-0708-090A-0B0C0D0E0F10` - **Major**: 1 - **Minor**: 2 - **Tx Power**: 0 #### Defining the Flags If you remember, the advertising data entries follow the format Length-Type-Value. For **Flags** that would be: `0x02-0x01-0x06`. In `app.c`, let's add the following code right below the #include statements for the Flags: ```c // Flags #define ADVERTISE_FLAGS_LENGTH 0x02 #define ADVERTISE_FLAGS_TYPE 0x01 #define ADVERTISE_FLAGS_VALUE 0x06 ``` #### Defining the Manufacturer Specific Data The Manufacturer Specific Data entry is the one containing the most important information: - **Length**: `0x1A` (fixed) - **Type**: `0xFF` (fixed) - **Value**: - **Company ID (Apple)**: `0x004C` (fixed) - **Manufacturer Specific Data Value**: - **iBeacon Subtype**: 0x02 (fixed) - **Subtype Length**: 0x15 (fixed) - **UUID**: `0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10` - **Major**: `0x0001` - **Minor**: `0x0002` - **TX Power**: `0x00` Let's put this all together in code! In app.c, let's add the following code right below the Flags definition: ```c // Manufacturer Specific Data #define ADVERTISE_MANDATA_LENGTH 0x1A #define ADVERTISE_MANDATA_TYPE 0xFF #define ADVERTISE_MANDATA_COMPANY_ID 0x004C #define ADVERTISE_MANDATA_VALUE { 0x02, 0x15, 0x01, 0x02, 0x03, 0x04, 0x05,\ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,\ 0x00, 0x01,\ 0x00, 0x02,\ 0x00} ``` We added "\\" in order to break up lines into a more readable format. The company ID is a two-byte value (0x004C), but it needs to be stored in the advertising data in Little Endian format, so we'll add a macro to do that conversion for us (and also convert from a 16-byte value to an array of two bytes): ```c #define UINT16_TO_BYTES(x) { (uint8_t)(x), (uint8_t)((x) >> 8) } ``` #### Advertising Data Struct For storing the advertising data, we will define a struct as follows: ```c typedef struct { uint8_t flags_length; uint8_t flags_type; uint8_t flags_value; uint8_t mandata_length; uint8_t mandata_type; uint8_t mandata_company_id[2]; uint8_t mandata_value[23]; } ble_advertise_data_t; ``` Now, we're going to store the values we decided on in a macro so we can assign a struct to statically contain these values: ```c #define ADVERTISE_DATA_DEFAULT \ { \ .flags_length = ADVERTISE_FLAGS_LENGTH, \ .flags_type = ADVERTISE_FLAGS_TYPE,\ .flags_value = ADVERTISE_FLAGS_VALUE,\ .mandata_length = ADVERTISE_MANDATA_LENGTH,\ .mandata_type = ADVERTISE_MANDATA_TYPE,\ .mandata_company_id = UINT16_TO_BYTES(ADVERTISE_MANDATA_COMPANY_ID),\ .mandata_value = ADVERTISE_MANDATA_VALUE\ } ``` Again, the "\\" is added here at the end of each line in order to break it up into more readable code (since a macro needs to sit on one line we can't just break it up into separate lines without the special character). Now we define a struct variable and assign it: ```c static const ble_advertise_data_t adv_data = ADVERTISE_DATA_DEFAULT; ``` ### Setting the Advertising Data Now we need to modify the code in **sl\_bt\_on\_event**() to set the advertising data we just defined. Just under the following switch case: ```c case sl_bt_evt_system_boot_id: ``` Replace the code with the following: ```c // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle); app_assert_status(sc); // Set Advertising data sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle, sl_bt_advertiser_advertising_data_packet, sizeof(ble_advertise_data_t), (uint8_t *)&adv_data); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_advertiser_non_connectable); app_assert_status(sc); ``` Let's recap what we did here: - We did **not** change anything with creating the advertising set - For setting the advertising data, we called **`sl_bt_legacy_advertiser_set_data()`** - We passed it the advertising set handle (`advertising_set_handle`) - We set the type to `sl_bt_advertiser_advertising_data_packet` - We set the data length to `sizeof(ble_advertise_data_t)` - We set the data to `(uint8_t *)&adv_data` - We did **not** change anything with the advertising interval setting - We modified the advertiser start function `sl_bt_legacy_advertiser_start`to set the type to `sl_bt_advertiser_non_connectable`(for non-connectable, non-scannable type) ### Remove Connection-Based Handlers The final change we need to make it remove the handlers for the connection and disconnection scenarios (since we changed our advertising set to non-connectable). For the following switch-cases, make the following change (removing the function calls): ```c // ------------------------------- // This event indicates that a new connection was opened. case sl_bt_evt_connection_opened_id: break; // ------------------------------- // This event indicates that a connection was closed. case sl_bt_evt_connection_closed_id: break; ``` ### Adding Logging of Bluetooth Device Address Let's add one more thing before we start testing: *logging the Bluetooth Device Address*. #### Installing the Necessary Software Components To do this, we need to first add two Software Components: **Log** and **IO Stream USART**. These will enable logging to the UART which can be monitored via a serial terminal on the development PC. We can do this by: - Navigating and double-clicking on the file *.slcp* file in your project - Navigating to Software Components (you might have to wait for a few seconds before everything loads up) - Search for "io stream" and look for **Services -> IO Stream -> Driver -> IO Stream: USART** and install it - Search for "log" and look for **Application -> Utility -> Log** and install it Now we're ready to add some log messages to our application. #### Adding Log Messages Under **case* sl\_bt\_evt\_system\_boot\_id:* let's add the following log message: ```c app_log("iBeacon example started!\r\n"); ``` Finally, we'll add code to retrieve and print out the Bluetooth Device Address (BD\_ADDR): ```c // Retrieve the BT Address. sc = sl_bt_system_get_identity_address(&address, &address_type); app_assert_status(sc); app_log("BT Address: "); for (int i=0; i<5; i++) { app_log("%02X:", address.addr[5-i]); } app_log("%02X (%s)\r\n", address.addr[0], address_type == 0 ? "Public device address": "Static random address"); ``` Now we can build and run our application and by running a serial terminal program on your development machine, you should see the following (obviously, your device's address will probably be different): ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/299add45-3d83-46e4-9ad9-3246c524e8b8.png) ### Testing from the EFR Connect Mobile App We're at the final stage, and ready to test our application! We'll be using the EFR Connect mobile app from Silicon Labs for this test. You can download it from [here](https://itunes.apple.com/us/app/silicon-labs-blue-gecko-wstk/id1030932759?mt=8&ref=novelbits.io) (iOS) and [here](https://play.google.com/store/apps/details?id=com.siliconlabs.bledemo&ref=novelbits.io) (Android). #### Filtering via Bluetooth Device Address Launch the EFR Connect mobile app and add a filter for your device address in the scanning view (you can probably get away with just the first 2 bytes of the address): ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/046d83e2-de15-4d11-ad16-1f57ffda8028.png) #### Discovering Your Device Hit **Apply Filters** and you should now see your device discovered and shown with the correct iBeacon data fully parsed: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/485bb177-2636-4fc7-9a5f-c765d207b3a6.png) And that's it! We are done! Now, you can go back and modify the iBeacon data and watch it change in the scanner view and make any changes necessary for your own application. ## Source Code Here's the complete source code for app.c: ```c /***************************************************************************//** * @file * @brief Core application logic. ******************************************************************************* * # License * Copyright 2020 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #include "em_common.h" #include "app_assert.h" #include "sl_bluetooth.h" #include "app.h" // AD: Length Type Value //iBeacon: Flags + Man Specific Data // Flags #define ADVERTISE_FLAGS_LENGTH 0x02 #define ADVERTISE_FLAGS_TYPE 0x01 #define ADVERTISE_FLAGS_VALUE 0x06 // Manufacturer Specific Data #define ADVERTISE_MANDATA_LENGTH 0x1A #define ADVERTISE_MANDATA_TYPE 0xFF #define ADVERTISE_MANDATA_COMPANY_ID 0x004C #define ADVERTISE_MANDATA_VALUE { 0x02, 0x15, 0x01, 0x02, 0x03, 0x04, 0x05,\ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,\ 0x00, 0x01,\ 0x00, 0x02,\ 0x00} #define UINT16_TO_BYTES(x) { (uint8_t)(x), (uint8_t)((x) >> 8) } #define ADVERTISE_DATA_DEFAULT \ { \ .flags_length = ADVERTISE_FLAGS_LENGTH, \ .flags_type = ADVERTISE_FLAGS_TYPE,\ .flags_value = ADVERTISE_FLAGS_VALUE,\ .mandata_length = ADVERTISE_MANDATA_LENGTH,\ .mandata_type = ADVERTISE_MANDATA_TYPE,\ .mandata_company_id = UINT16_TO_BYTES(ADVERTISE_MANDATA_COMPANY_ID),\ .mandata_value = ADVERTISE_MANDATA_VALUE\ } typedef struct { uint8_t flags_length; uint8_t flags_type; uint8_t flags_value; uint8_t mandata_length; uint8_t mandata_type; uint8_t mandata_company_id[2]; uint8_t mandata_value[23]; } ble_advertise_data_t; // The advertising set handle allocated from Bluetooth stack. static uint8_t advertising_set_handle = 0xff; static const ble_advertise_data_t adv_data = ADVERTISE_DATA_DEFAULT; /**************************************************************************//** * Application Init. *****************************************************************************/ SL_WEAK void app_init(void) { ///////////////////////////////////////////////////////////////////////////// // Put your additional application init code here! // // This is called once during start-up. // ///////////////////////////////////////////////////////////////////////////// } /**************************************************************************//** * Application Process Action. *****************************************************************************/ SL_WEAK void app_process_action(void) { ///////////////////////////////////////////////////////////////////////////// // Put your additional application code here! // // This is called infinitely. // // Do not call blocking functions from here! // ///////////////////////////////////////////////////////////////////////////// } /**************************************************************************//** * Bluetooth stack event handler. * This overrides the dummy weak implementation. * * @param[in] evt Event coming from the Bluetooth stack. *****************************************************************************/ void sl_bt_on_event(sl_bt_msg_t *evt) { sl_status_t sc; bd_addr address; uint8_t address_type; switch (SL_BT_MSG_ID(evt->header)) { // ------------------------------- // This event indicates the device has started and the radio is ready. // Do not call any stack command before receiving this boot event! case sl_bt_evt_system_boot_id: app_log("iBeacon example started!\r\n"); // Retrieve the BT Address. sc = sl_bt_system_get_identity_address(&address, &address_type); app_assert_status(sc); app_log("BT Address: "); for (int i=0; i<5; i++) { app_log("%02X:", address.addr[5-i]); } app_log("%02X (%s)\r\n", address.addr[0], address_type == 0 ? "Public device address": "Static random address"); // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle); app_assert_status(sc); // Set Advertising data sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle, sl_bt_advertiser_advertising_data_packet, sizeof(ble_advertise_data_t), (uint8_t *)&adv_data); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_advertiser_non_connectable); app_assert_status(sc); break; // ------------------------------- // This event indicates that a new connection was opened. case sl_bt_evt_connection_opened_id: break; // ------------------------------- // This event indicates that a connection was closed. case sl_bt_evt_connection_closed_id: break; /////////////////////////////////////////////////////////////////////////// // Add additional event handlers here as your application requires! // /////////////////////////////////////////////////////////////////////////// // ------------------------------- // Default event handler. default: break; } } ``` ## Conclusion In this article, we covered: - The basics of Bluetooth beacons - The basics of the Apple iBeacon standard - Recap of Bluetooth LE advertising data format - Step-by-step implementation of an iBeacon device using the Silicon Labs BG22 Explorer Kit 💡 **Insider Tip:** Want to explore more Bluetooth LE beacon projects and tutorials? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth LE Audio Explained: Isochronous Channels & LC3 (5.2 Spec) URL: https://novelbits.io/bluetooth-version-5-2-le-audio/ Last updated: 2026-05-09T00:34:26.000Z ## Introduction At CES 2020 (January 2020), the Bluetooth SIG introduced the latest version of Bluetooth, version 5.2\. This announcement was made alongside the announcement of the next generation of Bluetooth audio, named: LE Audio. The major change introduced in version 5.2 is a new feature called **Isochronous Channels (ISOC)**. ISOC lays the foundation for the implementation of LE Audio in BLE devices, supporting Bluetooth 5.2 or later. However, ISOC is not the only newly added feature in this latest version. In today's post, we'll look at the three major features introduced in version 5.2, two of which are not directly related to LE Audio. The three features are: - Isochronous Channels (ISOC) - LE Power Control (LEPC) - Enhanced Attribute Protocol (EATT) ## The Next Generation of Bluetooth Audio: LE Audio Before we cover the Isochronous Channels feature in more detail, let's talk a bit about LE Audio and what it means for us as both consumers and developers. From the very start, Bluetooth technology has proven itself to be the go-to solution for wireless audio. These days, Bluetooth audio devices are everywhere from wireless speakers and vehicle infotainment systems to wireless headphones and earbuds. In fact, the most common use of Bluetooth is in streaming audio applications. Traditionally, the Bluetooth radio used for these applications is the original Bluetooth radio commonly referred to as Bluetooth Classic or BR/EDR (Basic Rate/Enhanced Data Rate) which existed since version 1.0 of the specification. The new LE Audio, on the other hand, operated on Bluetooth Low Energy (BLE). LE Audio not only accomplishes the same features and specifications of Bluetooth Classic but also introduces a few new features as well as improve on existing ones. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/audio-classic-le.png) Source: [https://www.bluetooth.com/learn-about-bluetooth/bluetooth-technology/le-audio/](https://www.bluetooth.com/learn-about-bluetooth/bluetooth-technology/le-audio/?ref=novelbits.io) Here are some highlights of the new LE Audio: - Introduces a new **high quality**, **low-power** **audio codec** called the Low Complexity Communications Coded (LC3). - LC3 provides high quality even at lower data rates than the standard SBC codec used in Bluetooth Classic implementations. - Supports multiple, synchronized audio data streams. This characteristic allows the implementation of truly wireless earbuds (independent synchronized audio streams directly to each earbud: L & R) as well as broadcasting audio streams to multiple listeners. - Multi-stream capabilities also provide support for streaming audio streams in multiple languages. It also allows sharing of audio content whether it's a personal use-case such as sharing with friends and family or a location-based use-case such as public venues, TVs in gyms, or public announcements in airports. - One of the major applications that will benefit from LE Audio is Bluetooth hearing aids. Hearing aid devices require low and efficient power consumption. Being able to utilize BLE with its efficient power consumption characteristic, hearing aids are not only able to last longer on a single charge but manufacturers are also able to make these devices smaller and more discreet. Keep in mind that the implementation of LE Audio in devices from different manufacturers while achieving interoperability relies on multiple LE Audio profiles that are set to be released in the latter part of 2020. ## 1\. Isochronous Channels (ISOC) If you look up the definition of the word "Isochronous", you'll find that it means "occurring at the same time". In the context of BLE, it means supporting **(1)** **data transmissions that are time-sensitive and (2) synchronized rendering of these data streams across multiple receivers**. As we mentioned earlier, this new feature serves as the foundation for LE Audio. It introduces a new Physical channel in BLE: the **Isochronous Physical Channel** **(ISOC)**, which can be used on any of the LE PHYs: the 1M, 2M PHY, and LE Coded PHY (including both s=2 and s=8 configurations). ### Connection-oriented and Connectionless Communication ISOC supports both connection-oriented and connectionless communication. In BLE terminology, this means that both connections and broadcasts are supported. In connections, each stream is referred to as a Connected Isochronous Stream (CIS). When CISes need to be synchronized, such as ones sent to left and right earbuds, they are configured to be part of a single group referred to as a **Connected Isochronous Group (CIG)**. Streams that are part of the same CIG share timing reference data which is necessary for synchronized stream rendering on multiple receivers. CIGs allow bi-directional data transfer such as in earbuds that contain microphones and for sending control data to the source device. Note that a device may create multiple Connected Isochronous Groups. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/cig-color.png) Connected Isochronous Streams and Connected Isochronous Groups (Bi-directional communication) For connectionless communication (broadcasts), a group of synchronized streams may be used to stream data from a single source to multiple sinks. Each stream is referred to as a **Broadcast Isochronous Stream (BIS)**. A group of BISes are referred to as a **Broadcast Isochronous Group (BIG)**. An example of this is a TV streaming audio data to multiple sinks such as different individuals wearing earbuds. Just as in the case of CIGs, a device may create multiple BIGs. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/big-color-1.png) Broadcast Isochronous Streams and Broadcast Isochronous Groups (Uni-directional communication) ### ISO Interval The most important parameter that pertains to ISOC is the ISO Interval. It defines the interval at which Events occur. Each event is split into multiple subevents. The ISO Interval ranges from **5 milliseconds** to **4 seconds**. In Connection-oriented communication, in each subevent, the master will send a packet to the slave, and the slave will respond with a packet. In connectionless communication, however, only the master will send a packet in each subevent. In this case, these packets could either be isochronous data or broadcast control information. ### Retransmissions Data retransmissions are supported by Isochronous channels, but they differ between connection-oriented and connectionless communication. In the case of Broadcast Isochronous Streams, retransmissions are sent by the Master without influence from the slave(s), and in the case of Connected Isochronous Streams, retransmissions are sent when a Slave has not acknowledged a packet. Also, note that retransmissions are sent on different channels than the original packet to reduce the risk of packet loss or corruption. ## 2\. LE Power Control (LEPC) In wireless communication, the received signal strength indicator (RSSI) can be used to estimate the distance of the receiver from a transmitter if the original transmit power is known to the receiver. Wireless receivers have an optimal received signal strength range. Higher or lower than this range may cause issues with decoding the received signal, so the RSSI within this range provides better signal quality. With the new LE Power Control feature (LEPC), a receiving device monitoring the level of the signal (the RSSI) from a connected device may request a change in the transmit power level used by its peer in either direction. A transmitter may also change the transmit power voluntarily and relay that information to the receiver. Utilizing LEPC and keeping the RSSI within the optimal range of the receiver provides a few benefits including: - Better control over the quality of the signal. - Reducing error rates at the receiving end. - Improving coexistence with other signals in the 2.4 GHz band, including ones other than Bluetooth (such as Wi-Fi and Zigbee). Support for this feature is optional, but if the two devices support this feature, then they **must** use it for power management control. ## 3\. Enhanced Attribute Protocol (EATT) The new **Enhanced Attribute Protocol (EATT)** is an upgraded version of the original **Attribute Protocol** **(ATT)**. Whereas the original unenhanced Attribute protocol operates in a sequential manner, the Enhanced Attribute Protocol provides a way to perform concurrent/parallel transactions between a BLE client and a server and potentially reduce the latency of operations in some applications. For example, this is useful on a smartphone where multiple apps may be interfacing with a Bluetooth Low Energy device. By utilizing EATT, an app’s Attribute transaction would not be blocked while another app’s ATT transaction is in progress, essentially allowing different apps to interact with a Bluetooth Low Energy device in parallel and potentially reducing latency. The way this works is by separating the L2CAP layer Maximum Transmission Unit (MTU) from the Attribute layer’s MTU. Here’s an example to better visualize this: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/eatt.png) Enhanced Attribute Protocol: ATT MTU vs. L2CAP MTU If the L2CAP layer MTU is smaller than the Attribute layer MTU, then this will cause the L2CAP layer to break up the PDUs coming from the (upper) Attribute layer into smaller chunks and interleave the PDU chunks coming from different applications. In this example, we have App A that is sending a PDU larger than the L2CAP MTU size, which means it will be broken up into chunks of sizes up to the L2CAP MTU. This will allow the PDUs from App A and App B to be interleaved instead of App B’s PDU being blocked by App A’s PDU. The last couple of things we want to mention is that: - The Enhanced Attribute Protocol is optional per the specification - It requires encryption of the connection between the two Bluetooth Low Energy devices. This makes it inherently more secure than the original unenhanced Attribute Protocol. ## Summary & Closing In this post, we reviewed the three major features introduced in the latest version of Bluetooth: version 5.2\. The features are: - Isochronous Channels (ISOC) - LE Power Control (LEPC) - Enhanced Attribute Protocol (EATT) --- 💡 **Insider Tip:** Want to dive deeper into Bluetooth Low Energy, including LE Audio, EATT, and other advanced features? Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) for comprehensive courses covering everything from the basics to the latest Bluetooth specifications! ### Mastering Bluetooth LE: A Guide to Peripherals and Centrals URL: https://novelbits.io/ble-peripherals-centrals-guide/ Last updated: 2026-05-01T15:52:36.000Z ## Introduction to Bluetooth LE [Bluetooth Low Energy (Bluetooth LE)](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) is a power-efficient variant of the classic Bluetooth technology, designed specifically for devices that need to consume less power and may need to run for long periods on a battery. Bluetooth LE has become the de facto choice for most wireless communication between devices in close proximity. Bluetooth LE is the backbone of many modern wireless solutions found in various sectors, including consumer electronics, healthcare, home automation, and many more. From fitness trackers and smartwatches that record our health metrics to smart home devices that enable a connected living experience, Bluetooth LE has shaped the way we interact with the world around us. The primary strength of Bluetooth LE lies in its power efficiency, making it perfect for applications that require periodic data transfers. Unlike Classic Bluetooth which maintains a continuous connection, Bluetooth LE operates through brief exchanges of data, conserving energy and extending device battery life. This makes Bluetooth LE an ideal choice for many Internet of Things (IoT) applications. However, to fully leverage the benefits of Bluetooth LE technology, it's crucial to understand the roles of Bluetooth LE devices in the communication process, primarily the Peripheral and Central roles. In the upcoming sections, we will delve deeper into these roles and their interaction in the Bluetooth LE ecosystem. By the end of this guide, you should have a comprehensive understanding of Bluetooth LE Peripherals and Centrals, their key differences, and how to choose between them in various scenarios. ## Understanding Bluetooth LE Roles In the world of Bluetooth Low Energy (Bluetooth LE), devices are designed to play specific roles that dictate how they interact within the Bluetooth LE ecosystem. The two primary roles are the Peripheral and Central roles: - **Peripheral devices** are typically low-power, resource-constrained devices that provide data. They act as "*servers*" in the Bluetooth LE communication framework, advertising their presence to other devices in their vicinity. Examples of peripherals include heart rate monitors, temperature sensors, or any other device that generates data to be consumed by other devices. - **Central devices** act as "*clients*" and are typically more powerful and less constrained by resources. These devices scan for peripherals, initiate connections, and consume the data provided by the peripherals. A smartphone is a common example of a central device, capable of connecting to multiple peripherals simultaneously, collecting, and processing data from each. The connection between a peripheral and a central device is initiated by the central device. Once connected, the peripheral device stops advertising, and the central device stops scanning, thereby conserving energy. This division of roles in Bluetooth LE communication allows for flexible, efficient, and power-optimized device interactions. It's also crucial for developers and engineers to understand these roles to make the right design decisions when building Bluetooth LE-connected products. ## Key Differences Although Bluetooth LE Peripherals and Centrals operate in tandem to facilitate Bluetooth LE communication, they each carry distinct characteristics, capabilities, and requirements. Understanding these differences is pivotal when designing and developing Bluetooth LE-connected products: - **Power Consumption** \- Peripherals, being low-power devices, are designed to operate on minimal energy. They spend most of their time in a low-power sleep state, waking up only to advertise their availability or transmit data. Centrals, however, are typically more power-hungry as they continuously scan for peripherals and usually manage multiple connections. - **Data Role** \- In a Bluetooth LE connection, peripherals are typically the data providers or servers. They generate and advertise data for centrals to consume. Centrals, on the other hand, are typically data consumers or clients. They initiate connections and receive data from peripherals. - **Connection Initiation** \- Connection establishment in Bluetooth LE is always initiated by the central device. The peripheral device advertises its presence, and the central device, upon detecting this advertisement, initiates the connection. - **Multiple Connections** \- Central devices are typically capable of maintaining multiple simultaneous connections with different peripherals. This capability allows a single central device (like a smartphone) to collect data from various peripherals. Peripherals, on the other hand, usually maintain a single active connection due to their resource constraints. - **Use Cases** \- Peripherals are often found in battery-powered devices like sensors, wearable devices, and IoT devices that generate data. Centrals are more common in devices that need to aggregate and process data, such as smartphones, tablets, and computers. Understanding these differences is not just essential for choosing between a peripheral and central role for your device, but also for optimizing your device's performance and power consumption. ## Choosing Between Peripherals and Centrals When designing a Bluetooth LE-connected product, one critical decision is choosing whether your device should act as a peripheral or a central. This decision can significantly impact your device's power consumption, functionality, and complexity. Here are some factors to consider: - **Power Constraints** \- If your device is battery-powered and needs to conserve energy, it might be more suitable as a peripheral. Peripherals can spend most of their time in a low-power sleep state, preserving battery life. - **Data Role** \- If your device primarily generates data for other devices to consume, it's likely better suited as a peripheral. Conversely, if your device needs to collect and process data from other devices, it might be more appropriate as a central. - **Connection Needs** \- If your device needs to connect to multiple other devices simultaneously, it would likely function best as a central. However, if your device only needs to connect to one other device at a time, it could operate effectively as a peripheral. - **Processing Power and Resources** \- Central devices typically require more processing power and resources as they need to manage multiple connections and process data from multiple peripherals. If your device is resource-constrained, it may function better as a peripheral. - **Application Requirements** \- Finally, your specific application requirements can dictate the choice between a peripheral and central role. For instance, a wearable health tracker (peripheral) needs to send data to a smartphone (central), but a smart home hub (central) needs to collect data from various home automation sensors (peripherals). Making an informed choice between a peripheral and central role is crucial to the success of your Bluetooth LE device. In the next section, we will delve into the design considerations for these roles. ## Design Considerations Designing a Bluetooth LE-connected product involves various considerations, many of which depend on whether the device is a peripheral or a central. Here, we outline some key points to keep in mind for each role. **Peripheral Devices**: 1. **Power Management**: As peripherals are often battery-powered, it's essential to optimize power consumption. Techniques include adjusting the advertising interval, minimizing data transmission, and maximizing sleep periods. For more details, check our previous [article on the topic of optimizing power consumption](https://novelbits.io/ble-power-consumption-optimization/). 2. **Advertising Data**: The advertising packet's content can greatly affect the discoverability and connection process. Ensure the advertisement includes the necessary information for centrals to identify and connect to the peripheral. 3. **Data Format and Volume**: As data providers, peripherals must structure their data in a way that centrals can easily consume. Minimizing the data volume can also help save energy. **Central Devices**: 1. **Scanning Strategy**: Centrals need to balance between scanning often enough to discover peripherals promptly and minimizing scanning to save power. 2. **Managing Multiple Connections**: As centrals often connect to multiple peripherals, they must manage these connections effectively. This includes handling disconnections and reconnections, managing different data formats, and processing data efficiently. 3. **Power and Resource Allocation**: Centrals, being typically less constrained by power and resources, need to allocate these efficiently. Power can be saved by reducing scanning frequency, and resources can be optimized by effectively managing multiple peripheral connections. In the end, the design considerations for your Bluetooth LE device will depend heavily on your specific use case, desired functionality, and power and resource constraints. In the next section, we will provide some practical tips for developing Bluetooth LE-connected products. ## Bluetooth LE Development Tips Developing a Bluetooth LE-connected product can be a complex task, but understanding the intricacies of Bluetooth LE and having a robust development strategy can make the process smoother. Here are some tips: 1. **Understand the Bluetooth LE Specification**: Before starting your development process, make sure you have a solid understanding of the Bluetooth LE specification. This includes understanding the roles of peripherals and centrals, connection parameters, advertising data, and more. There's no better way to start learning Bluetooth LE than to start with a concise book on the topic. [Learn more about the new "Intro to Bluetooth Low Energy" book](https://novelbits.io/intro-bluetooth-low-energy-version-2/). 2. **Choose the Right Hardware and Software**: Select a Bluetooth LE chipset that fits your power, cost, and functionality requirements. Also, choose a software stack that supports your chosen hardware and provides the necessary Bluetooth LE features. 3. **Optimize Power Consumption**: Always design with power optimization in mind, especially for battery-powered devices. Use techniques like adjusting advertising and scanning intervals, minimizing data transmission, and maximizing sleep periods. 4. **Prioritize Security**: Security is crucial in Bluetooth LE applications. Implement features like pairing and encryption to protect against unauthorized access and data breaches. 5. **Test Thoroughly**: Testing is a vital part of the development process. Test your device in various conditions, with different devices, and over different ranges. Also, consider edge cases and potential failure modes. 6. **Consider Certification**: If you plan to market your device, consider Bluetooth certification. It can help ensure compatibility and increase customer confidence in your product. Whether you're developing a peripheral or central device, these tips can help guide your development process and lead to a successful, efficient, and reliable Bluetooth LE product. In the next section, we will explore some real-world examples of peripherals and central. ## Real-world Examples To better understand the roles of peripherals and centrals in Bluetooth LE communication, let's look at some real-world examples. **Fitness Tracker (Peripheral) and Smartphone (Central)**: A fitness tracker collects health and fitness data, such as heart rate, steps, and sleep patterns. It operates as a peripheral, advertising this data for other devices to consume. A smartphone, acting as a central, connects to the fitness tracker, collects the data, and displays it to the user in an easy-to-understand format. **Smart Home Sensors (Peripherals) and Smart Home Hub (Central)**: In a smart home setup, various sensors (like temperature sensors, motion sensors, and light sensors) act as peripherals, collecting data about the home environment. A smart home hub or a smartphone app acts as a central, connecting to these sensors, gathering their data, and using it to control various aspects of the home, like heating, lighting, and security. **Beacon (Peripheral) and Shopper's Smartphone (Central)**: In a retail store, a beacon can act as a peripheral, advertising promotional information or helpful store navigation tips. A shopper's smartphone can act as a central, scanning for these beacons, connecting to them, and displaying the relevant information to the shopper. These examples illustrate the flexibility of Bluetooth LE roles and how they can be used in various scenarios to facilitate efficient, effective, and power-optimized communication. In the final section, we will discuss upcoming trends and developments in Bluetooth LE technology. ## Future of Bluetooth LE As we move further into the era of IoT and connected devices, the role of Bluetooth Low Energy (Bluetooth LE) becomes increasingly prominent. The adaptability of Bluetooth LE roles - peripherals and centrals - allows Bluetooth LE to cater to a wide array of applications, from fitness trackers and smart homes to retail beacons and industrial sensors. Bluetooth LE technology continues to evolve, with the Bluetooth SIG (Special Interest Group) regularly releasing updates to the Bluetooth LE specification. These updates often aim to improve power efficiency, increase range and speed, enhance security, and introduce new features. For instance, the latest Bluetooth LE versions have introduced features like [long-range operation](https://novelbits.io/bluetooth-long-range-coded-phy/) for increased coverage, high-speed mode for faster data transfer, and improved mesh capability for more extensive device networks. These advancements open up even more possibilities for Bluetooth LE applications, making it a technology to watch in the coming years. As a developer or engineer working on Bluetooth LE-connected products, staying up-to-date with these advancements is crucial. Understanding and leveraging the latest Bluetooth LE features can help you create more efficient, reliable, and innovative products, setting you apart in the rapidly growing market of connected devices. 💡 **Insider Tip:** Want to master Bluetooth LE development from the ground up? The [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) offers comprehensive courses covering peripherals, centrals, GATT, advertising, and much more with hands-on implementation guides. ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ### What is Amazon Sidewalk & How Does it Work? URL: https://novelbits.io/what-is-amazon-sidewalk-developer-guide/ Last updated: 2026-08-09T05:43:45.000Z There’s a lot of confusion in the developer community - not only about what Amazon Sidewalk *is* \- but also about what it can and can’tdo. To help you make sense of this new technology and start developing your own Amazon Sidewalk-enabled devices, in this article, we'll walk through: - The basics of Amazon Sidewalk - Sidewalk bridge devices vs. Sidewalk-enabled devices - The network architecture - Sidewalk network communication technologies - How Bluetooth LE is used on the network **And - be sure to check out the [video at the end](#video-demo) for a step-by-step demo using an Amazon Sidewalk kit provided by Silicon Labs.** ## What is Amazon Sidewalk? Amazon Sidewalk is a low-bandwidth network developed by Amazon to allow low-power devices to communicate over longer distances than Bluetooth or Wi-Fi would typically allow for. The idea is to provide a free community network that will open up the possibility for the development of new types of devices for things like tracking packages, finding lost pets, or even remotely detecting wildfires. There are many business and personal applications for the Sidewalk network. You can read more about Amazon's positioning of the Sidewalk network [here](https://www.aboutamazon.com/news/devices/everything-you-need-to-know-about-amazon-sidewalk?ref=novelbits.io). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ce34b53d-7b19-4fc8-8f84-3ebe898d1650.png) ## What are Sidewalk Enabled Devices? Sidewalk enabled devices, or *endpoints* as Amazon Sidewalk calls them, are devices that can connect to the Sidewalk network. These end-user devices could be things like smart lights, motion sensors, security sensors, and door locks. As a developer, your focus will likely be on designing and creating these low-power Sidewalk devices. **Note:** I'll use "sidewalk-enabled device" and "endpoint" interchangeably in this article. ## What are Sidewalk Bridges? A sidewalk-enabled device connects to the network through what are called Sidewalk Bridges, or Sidewalk Gateways. These gateways are Amazon devices like an Amazon Echo or the Ring Spotlight Cam Wired. The Echo or Ring devices share a portion of their internet bandwidth with the Sidewalk community to provide connectivity to the endpoints. **Note:** I'll use "Gateway" and "Sidewalk Bridge" interchangeably in this article. ## Amazon Sidewalk Wireless Protocols Amazon Sidewalk utilizes a few wireless protocols in order to support both short and long range communication on the network: - For short-distance communication, it uses **Bluetooth Low Energy**. - For medium range, it uses **SubG-FSK** (HDR). - For longer distances, it uses LoRa - also referred to as **SubG-CSS** (LDR). Sidewalk Bridges (i.e. the Echo and Ring devices) support all three technologies, but automatic switching between the three modulations is not currently supported at the Amazon Sidewalk endpoints. It's also important to note that CSS provides the lowest data rates, while FSK and Bluetooth LE provide higher data rates. We'll take a closer look at how Bluetooth LE is used by the Ring devices and Echo devices later in this article. ## Communication on the Sidewalk Network Amazon Sidewalk supports both synchronous and asynchronous communication modes. For any communication between Sidewalk devices on the network, the Sidewalk devices must register with the Sidewalk network, which requires keys that are defined at the time of manufacturing of the endpoint. After registration, communication can start. Communication occurs through what’s called *frames*, which contain either commands to control the connection or data sent to the Sidewalk Cloud servers. Just as you would expect with Bluetooth LE communication, Amazon Sidewalk supports low power mode to help optimize the endpoints’ power consumption. ## Amazon Sidewalk Network Architecture Now that we’ve covered the basics of Amazon Sidewalk, let’s look more in-depth at the architecture. You can see a visual representation of the Sidewalk architecture below. Let's walk through each of the elements of the architecture. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ba2c1ac7-9fc0-490d-add8-a42890344a40.png) ### User Interface - Mobile App or Web Interface The end-user interface, in the case of Amazon Sidewalk, could be a mobile app or web interface. This is what allows the user to interact with the endpoints - to configure settings, initiate actions or commands, and get responses from other sidewalk devices or sidewalk bridges (like the Echo and Ring devices). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/2fe6f09a-e83e-4123-9a5e-18c0786c31a3.png) ### The Cloud The cloud is the central entity of the system, which: - Provides application-level services for various types of endpoints - Participates in communication between end-user applications and endpoints - Acts as a database for central routing and storing information about the endpoints - Has knowledge about the network topology, coverage, and gateways currently configured to support roaming The cloud works to select the best gateways based on the RSSI and other parameters to route downlink traffic. This is especially important when the endpoint is not within range of its user’s gateways, and so it’s in roaming mode. ### Amazon Bridges (Gateways) Sidewalk Bridges, like Echo and Ring devices, are nodes that: - Provide connectivity to endpoints - Act as passthrough nodes for routing traffic from endpoints to the cloud - Perform periodic scans of neighboring nodes and relay this information to the cloud It's important to note that a Sidewalk Bridge doesn't have access to the application data that’s sent from or received by the endpoints because data is encrypted at the network and the application level. ### Sidewalk-Enabled Devices (Endpoints) Finally, let’s talk about endpoints. Remember, endpoints are things like sensors, outdoor lights, smart locks, Tile trackers, and other smart home devices. Essentially, they provide specific functionality to the owner of the device. They are only responsible for routing their data and maintaining their own connection with the network. They also don’t connect to the internet themselves. Instead, they rely on the Sidewalk Bridge to access Sidewalk. ## Amazon Sidewalk Network Configurations - WAN & PAN With a general understanding of the architecture of an Amazon Sidewalk network, let’s talk about the two possible network modes: WAN and PAN. ### Wide Area Network (WAN) The Amazon Sidewalk network operates in WAN - or wide area network mode - when it involves Sidewalk-enabled devices and Sidewalk Bridges from different owners. In this mode, neighboring Sidewalk Bridges cooperate in order to provide network coverage to the endpoints. Keep in mind that, by default, Sidewalk Bridges participate in the WAN, but if an owner chooses, they can opt out of this via their account settings in the Alexa app or Ring app. In that case, the gateways would only participate in their own private area network - which we will get to shortly. A few important things to know about WAN mode: - Endpoint-to-endpoint communication is not supported - All three technologies - SubG-FSK, SubG-CSS, and Bluetooth LE can be used by endpoints in the WAN. - There are some restrictions on how many messages endpoints can transmit on the WAN: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/e9123139-b651-4ce0-878e-c4d865b289bc.png) Another important thing to keep in mind is that each network topology has its own privacy and security model. For the WAN, endpoints have a unique device key, which changes periodically, and in this scenario the cloud bears the responsibility of verifying the authenticity and integrity of incoming messages from the endpoint. ### Personal Area Network (PAN) The network operates in a personal area network, or PAN, mode when involving only endpoints and gateways that belong to the same user. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/b98a73cd-10ed-430e-b806-ea63cabdb4a1.png) A few important things to know about PAN mode: - When in PAN mode, the user can set their own data usage limits and routing prioritization - The PAN uses Bluetooth LE for communication between the endpoints and gateways - The PAN restricts the number of messages over Bluetooth LE to 600 per minute, which and when, if exceeded, the device may be disconnected from the Sidewalk network Like with the WAN, the PAN has its own security model. Endpoints within the same PAN share the same security key, referred to as the PAN key, or broadcast key, which is provided at the time of provisioning. ## Bluetooth Low Energy & Amazon Sidewalk Now that we've covered much of the basics of the Amazon Sidewalk network, its architecture, and how it operates, let's take a closer look specifically at how Bluetooth LE is used to enable Sidewalk. As we’ve seen, Amazon Sidewalk utilizes three different communication technologies, with Bluetooth LE being a major one. Bluetooth LE provides power-efficient, low-latency communication within the network. In fact, it’s the most efficient technology of the three and provides the highest data rate, but with that comes a *shorter* range. In Bluetooth LE terminology: - The Sidewalk endpoints act as Bluetooth LE peripherals - The Bridges (i.e. echo devices or ring devices) act as Bluetooth LE centrals. When utilizing Bluetooth LE, the endpoints must support at least Bluetooth version 4.2\. Both the 1M and 2M PHYs are supported, but only one connection at a time can be maintained and no extended advertising or connection-oriented channels are supported. - **During advertising**, endpoints start out with 160 ms as the advertising interval for 30 seconds and then switch to a 1-second interval after that. - **During connection**, the central enforces a 30 ms - 4s interval. ### Supported Bluetooth LE Messages There are two types of Bluetooth LE messages supported on Amazon Sidewalk. The first is a B**eacon frame,** which is sent during advertising and used for: - Initiating registration of an endpoint on the network - Initiating the counter-based time synchronization procedure from the cloud - Initiating an endpoint encrypted connection - And for presence detection or determining a device's state - in other words, if it’s online or offline. The Beacon frame contains a header with information related to the Bluetooth LE advertising type and UUID of the service, which is called Alexa Mobile Accessory, or AMA. It also contains manufacturer-specific data such as information about the Amazon Sidewalk application, network service, device state, and other application-specific data The second type of Bluetooth LE message supported by Amazon Sidewalk is a **Data frame**, which has a few different types of commands that can be used: - **Management commands:** used for managing endpoints in the Sidewalk network - **Custom commands**: used to exchange data for a user’s own application - **Metrics commands:** used to send various statistics and measurements about the communication link itself - **Security commands:** implement Sidewalk security and registration These commands use a few different types of interactions: - **Get/Read**: used by the sender to request data from the receiver. - **Set/Write**: used to request an action to be performed by the receiver. - **Notify:** used to provide information to the receiver. - **Response**: the receiver responding to the Get/Read, Set/Write, or Notify interactions. ## Summary & Amazon Sidewalk - Silicon Labs Demo Amazon Sidewalk technology is still early, but it holds a lot of potential for enabling a new era of Bluetooth LE devices. If you'd like to see the Amazon Sidewalk in action, be sure to check out the video version of this article which includes a step-by-step demo using an Amazon Sidewalk Kit provided by Silicon Labs. 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### RSSI vs. Direction Finding - The Ultimate Guide to Bluetooth RTLS URL: https://novelbits.io/bluetooth-rtls-direction-finding-and-rssi/ Last updated: 2026-08-09T05:43:41.000Z In today's interconnected world, the ability to track and monitor assets and people in real-time has become increasingly important. That’s where real-time location systems come into play, specifically Bluetooth-based systems utilizing RSSI and/or Bluetooth Direction Finding. Real-time location systems - or RTLS - can be used to identify and track the location of objects in real time. It uses a combination of wireless communication, sensor networks, and data processing to approximate an object's location - and sometimes - direction. **Prefer video?** There's a step-by-step Direction Finding demo and explainer video at the [end of this post](#direction-finding-explainer-video-demo). ## Asset Tracking Asset tracking with RTLS allows for real-time monitoring and management of movable assets in many environments. Consider scenarios like nurses locating medical equipment in hospitals, keeping track of the locations of high-value manufacturing assets throughout the supply chain, or locating specific pallets within a warehouse. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/asset-tracking_bluetooth-direction-finding.jpg) *Asset Tracking Scenario* In the asset tracking scenario, you have three distinct components: 1. **Transmitters** (aka tags): typically moving beacons that are attached to the assets being tracked. 2. **Receivers** (aka readers or locators): stationary Bluetooth devices (i.e., anchors) that relay information about the moving beacons via ethernet, Wi-Fi, or cellular up to a central server. 3. **Server:** as this central backend system receives information from the receivers, it uses it to approximate the location of the moving beacons. It can then project those locations on a map showing the tracked assets. ## Indoor Navigation Indoor navigation systems (aka indoor positioning systems) are very similar to RTLS solutions but with a different goal: to enable users to find their way inside buildings or facilities where GPS signals are weak or nonexistent. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/indoor-navigation_bluetooth-direction-finding.jpg) *Indoor Navigation Scenario* In this scenario, you also have three components: 1. **Transmitters**: stationary beacons deployed in specific positions within a facility where an indoor navigation system is being set up. 2. **Receivers**: typically mobile phones, but could also be specialized devices designed to accept the information from the stationary beacons. The key thing to understand here is that the receivers move *with* the person who wants to utilize the navigation system. The receivers will relay information to the backend server via Wi-Fi or cellular. 3. **Server**: these will do the actual location calculations based on the information received from the receivers. ## Bluetooth RTLS (Bluetooth Location Services) Bluetooth LE is increasingly being used for RTLS due to its: - Wide availability - Low cost - Long battery life - Relatively long range, especially compared to some alternatives like RFID So far, we’ve been talking about RTLS in a general sense to give you a framework for understanding what they are used for - and how they are typically configured. But RTLS is just that - it is a general term describing many different location tracking systems. Depending on the specific application, requirements, and project constraints, one or more techniques will be used to actually do the location approximation and direction finding within an RTLS. The two techniques that we will look at are **RSSI** and **Direction Finding**. We’ll start with RSSI because it is, by far, the most commonly used methodology and will work for a majority of RTLS applications. ## Received Signal Strength Indicator (RSSI) So, first of all, what is RSSI? RSSI stands for **received signal strength indicator** and measures the strength of a received radio signal in a wireless communication system. In the context of RTLS, RSSI-based location estimation is based on the strength of the signal sent from the transmitter - or transmitters - to the receiver - or receivers. In reality, this works differently depending on the specific use case. For simple proximity applications, just one receiver could be used. In an asset tracking scenario where proximity information isn’t sufficient, and you need to estimate the actual *location* of an asset, you would need to use three or more receivers or locators and rely on the trilateration and the path loss model to estimate the transmitter’s location relative to the receivers. When comparing that to an indoor navigation scenario, three or more [Bluetooth beacons](https://novelbits.io/what-is-a-beacon-guide-to-bluetooth-beacon-technology/) would be needed to accurately locate the receivers: smartphones or other Bluetooth LE devices used for navigation. Recall how asset tracking systems are set up, with a transmitter attached to an asset. But imagine that instead of having just one stationary receiver in a warehouse, you have 10\. In this case, the receivers would pass the signal strength information on to the server. The server would generally then use a trilateration algorithm to approximate the location of the asset. As I mentioned, RSSI is very commonly used in RTLS systems mainly because of its simplicity and cost-effectiveness. This simplicity does come with a cost; RSSI can be inaccurate. It is very susceptible to noise and obstacles in the environment, particularly the signal's line of sight. ### RSSI Advantages - General simplicity - Minimal hardware requirements - simple RSSI system could be set up with just a single locator for monitoring one or more beacons, *with some limitations* - Compatible with smartphones, which can be used as readers in the RTLS ### RSSI Limitations - Only provides approximate location information. - Can't provide information about what *direction* a device is located relative to the locator - Lack of accuracy ### RSSI Accuracy Because RSSI is based on signal strength, anything in the environment that could affect the signal’s strength will reduce the accuracy of the distance and hence location calculation. A few notable things that can reduce the accuracy of RSSI are: - Environmental factors like humidity - Interference from other wireless devices - Multipath propagation phenomenon which occurs when radio signals bounce off surfaces and arrive at the receiver from multiple directions - Signal attenuation, which is a weakening of the signal as it passes through objects or travels over long distances Now, remember that even though all of these factors can degrade the accuracy of the RSSI calculation, for most applications, RSSI’s accuracy will be *good enough.* ## When is RSSI Not Good Enough? But, let’s say the assets you want to track are very small and therefore require a higher degree of accuracy to locate effectively, or you’re tracking assets that are used in emergency situations where you want to reduce the risk of low accuracy. In situations like this, RSSI may not be the right choice - or at least not on its own. Another major consideration is, of course, Bluetooth direction finding. RSSI will give you the approximate distance a transmitter is away from the receiver, but it will not tell you *which* direction it is away from the receiver. In other words, let’s say you have a warehouse with one receiving device in the center of each room and a transmitter attached to a high-value asset. RSSI could tell you which room the asset is in, but it wouldn’t be able to tell you *where exactly* in the room it is, or even in *which direction* it is relative to the receiver. Also, consider an access control system where Bluetooth Low Energy is used to unlock the door as a person approaches it from the outside. In this case, RSSI would not be sufficient because it would only tell you if the person is near the door, not on which side of the door they are in. You would need direction information to detect if a person is approaching the door from the outside. There are many other potential scenarios where high accuracy, direction information, or both are required. In these scenarios, you’ll want to consider using direction finding instead of, or maybe in conjunction with, RSSI. ## Bluetooth Direction Finding What is direction finding exactly? The Bluetooth Direction Finding feature is used to estimate the direction of a Bluetooth signal from a transmitter to one or more receivers. To understand device direction, it relies on **Angle of Arrival (AoA)** or **Angle of Departure (AoD)** methods. ### Angle of Arrival (AoA) In the Angle of Arrival method, multiple antennas are placed at the receiver side, typically a fixed device like an access point or gateway. These antennas capture special direction finding data, called Constant Tone Extension (CTE), sent by the transmitter. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/40d6f570-52a0-4acb-ac8c-7cd333a8e96c.png) AoA Architecture (Source: *Silicon Labs -* *[UG103.18: Bluetooth® Direction Finding Fundamentals](https://www.silabs.com/documents/public/user-guides/ug103-18-bluetooth-direction-finding-fundamentals.pdf?ref=novelbits.io))* The CTE is a continuous, unmodulated signal appended to a standard Bluetooth LE packet. This continuous tone is used to accurately measure the phase difference between the received signals, the critical data used to calculate the relative signal direction. ### Angle of Departure (AoD) In the Angle of Departure method, the transmitter has multiple antennas, while the receiver has a single antenna. The transmitter transmits the special direction finding signal from different antennas in a known pattern or sequence. The receiver measures the phase difference between the received signals to determine the AoD. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/32a6f8aa-c0d4-4d5d-b380-d589b01a3b54.png) AoD Architecture (Source: *Silicon Labs - [UG103.18: Bluetooth® Direction Finding Fundamentals](https://www.silabs.com/documents/public/user-guides/ug103-18-bluetooth-direction-finding-fundamentals.pdf?ref=novelbits.io))* Similar to AoA, the CTE that is appended to the standard Bluetooth LE packet provides a clear, continuous signal, which can be more precisely analyzed for phase differences or antenna sequencing. This then helps to improve the accuracy of the Bluetooth device direction. ### Direction vs. Position Information It’s important to note that when only one receiver is used in a direction-finding system, it works like a compass application, where only the *direction* of the transmitter is calculated, but not its exact position. This is because a single antenna array cannot provide accurate distance information about the asset or account for its potential movement in a two-dimensional plane. To accurately determine the *position* of the transmitter, two or more receivers with antenna arrays are needed. By using two or more locators equipped with antenna arrays, the transmitter’s position can be pinpointed through a process known as trilateration. In this method, the asset's location is identified at the intersection of lines drawn in the directions determined by the direction-finding algorithm. When multiple receivers are used, high-precision timing synchronization must be used to ensure accuracy. For even higher accuracy position estimation, it can be combined with RSSI measurements. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-16.png) Asset Positioning using AoA with Multiple Antenna Arrays (Source: *Silicon Labs - [UG103.18: Bluetooth® Direction Finding Fundamentals](https://www.silabs.com/documents/public/user-guides/ug103-18-bluetooth-direction-finding-fundamentals.pdf?ref=novelbits.io))* ### Factors Affecting Direction Finding Accuracy I’ve already mentioned that Direction Finding-based location estimation provides greater accuracy than RSSI. However, there are still several factors that can affect the accuracy of Bluetooth location services solutions that utilize direction finding: - Environmental factors like multipath propagation and reflections. - Interference from other wireless devices - Placement of the antennas and configuration of the receivers c - The sophistication of the signal processing algorithms ### Direction Finding Advantages - Higher accuracy than RSSI-based systems, particularly in environments with significant interference and physical obstacles - It can function well even in the absence of a clear line of sight between the transmitter and receiver - Can provide valuable direction data for locating devices, which is not possible to obtain with an RSSI-based system, especially using a single locator device - In some situations, such as locating a single device within a specific area, direction finding could be less complex than RSSI, which often requires multiple receivers or anchors and complex algorithms to determine the location - It may be less prone to false positives compared to RSSI-based systems ### Direction Finding Limitations - Generally requires more sophisticated and expensive hardware compared to RSSI-based systems - Due to the need for antennas, Direction Finding systems can be more complex to calibrate and configure, often requiring additional expertise that wouldn’t normally be needed to implement an RSSI-based system - Multiple receivers are required if you want to pinpoint a device’s location and not just its direction - It is not currently compatible with smartphones, although this could change as the technology becomes more widely adopted in the future ## Direction Finding Explainer Video & Demo Would you like to get more in-depth on this topic? Want to see how Direction Finding works in practice? Then check out my recent YouTube video, where I go into much more detail and walk through a step-by-step Direction Finding demo using the [Silicon Labs BG22 Bluetooth Dual Polarized Antenna Array Pro Kit (BG22-PK6022A)](https://www.silabs.com/development-tools/wireless/bluetooth/bgm22-pro-kit?tab=overview&ref=novelbits.io). 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth LE Power Consumption: How to Optimize Battery Life URL: https://novelbits.io/ble-power-consumption-optimization/ Last updated: 2026-08-09T05:38:30.000Z In my search for a comprehensive guide for optimizing Bluetooth Low Energy power consumption, I found multiple guides from different vendors. These guides were great, but were more focused on specific chips and modules from the vendors. My goal here is to **summarize the findings and make this a comprehensive guide for anyone looking to optimize Bluetooth Low Energy power consumption** and achieve maximum battery life – no matter which vendor you end up choosing. More specifically, I'll be focusing on optimization for BLE peripheral devices and not BLE central devices. By the end of this article, we'll have answered these key questions: - Why is reducing power consumption important for BLE devices? - What is the average power consumption of BLE modules? - What are the main ways to achieve low power consumption? - Which BLE parameters should be tuned? - What should be measured when optimizing power consumption? - How to measure power consumption? ## Why Optimize Power Consumption for BLE Devices? Many new electronic products – whether consumer, medical, industrial…etc – are moving towards being powered by batteries. Some of the reasons behind this: - **Modules and chips are becoming more power efficient**, so more applications and use-cases can be run on battery-powered devices without requiring the end user to change the battery too often (think 6+ months). - **The explosion of the Internet of Things applications and devices**, where data is being captured for all types of environments and scenarios, requiring more flexibility and use of completely wireless solutions. - **Chips and modules are becoming much smaller physically,** allowing you to embed them within small devices. As a result of these trends, the need for optimizing power consumption to extend battery life in BLE devices has become increasingly crucial, especially for certain applications including: - **Remote health monitoring:** Wearable medical devices such as heart rate monitors, glucose meters, and blood pressure monitors require long battery life to ensure continuous and reliable monitoring of patients' health. - **Asset tracking:** BLE beacons and trackers used for monitoring the location of valuable assets in various industries (logistics, manufacturing, agriculture) need to function for extended periods without frequent battery changes, as constant maintenance can be time-consuming and expensive. - **Environmental monitoring:** IoT sensors that measure air quality, temperature, humidity, or water levels in remote areas need to operate efficiently for long periods since it's often difficult and costly to perform routine battery replacements. - **Smart agriculture:** BLE-enabled devices that help farmers monitor soil moisture, nutrient levels, and crop health must have a long battery life to ensure consistent and accurate data collection. By focusing on power optimization, developers can create devices that deliver exceptional performance and reliability, ultimately enhancing user experience and meeting strict battery life requirements. ## What is the average power consumption of a BLE module? BLE modules are generally designed to be low power, but the current draw between modules can vary greatly based on the specifics of the device design, chip selection, and software implementation. Generally, you can expect the following, based on the state the device is in: - **In the idle state,** the BLE device isn't doing anything, so it's mostly in low power or sleep mode. The current draw can be very low, often in the microamp (µA) range, sometimes even less. For example, it might be somewhere around 1 µA to 10 µA, depending on the specific chip and power-saving features used.Here you can see the current consumption during deep sleep mode: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/em2.png) *Current consumption during deep sleep mode (Source: "[Silicon Labs - Optimizing Current Consumption in Bluetooth Low Energy Devices](https://docs.silabs.com/bluetooth/5.0/general/system-and-performance/optimizing-current-consumption-in-bluetooth-low-energy-devices?ref=novelbits.io)")* - **During advertising,** the device's radio is on and actively broadcasting packets to let other devices know it's there. This takes more power, but it's usually done in short bursts. Current draw during these bursts might be in the range of 3 milliamps (mA) to 10 mA, again depending on the specifics of the device and the advertising settings (like advertising power level, interval, and payload size). For example, you can see an iBeacon's average current consumption at various advertising intervals here: ![](https://images.surferseo.art/52d70f9a-eabd-45d3-8480-f2acb24db146.png) *iBeacon average current consumption at various advertising intervals (Source: "[Silicon Labs - Optimizing Current Consumption in Bluetooth Low Energy Devices](https://docs.silabs.com/bluetooth/5.0/general/system-and-performance/optimizing-current-consumption-in-bluetooth-low-energy-devices?ref=novelbits.io)")* - **During connection**, the device is actively communicating with another BLE device. The power usage can vary significantly based on the Bluetooth connection settings, like connection interval and connection event length. However, it might be in a similar range to the advertising state, perhaps around 5 mA to 30 mA (give or take a few mA) during active communication. But keep in mind that this is often averaged out over time since the device is typically not constantly transmitting or receiving data. Between data transmissions, the device can go into a lower power mode, as you can see demonstrated here: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/connection_interval_1.png) *Current consumption during a 15 ms connection interval (Source: "[Silicon Labs - Optimizing Current Consumption in Bluetooth Low Energy Devices](https://docs.silabs.com/bluetooth/5.0/general/system-and-performance/optimizing-current-consumption-in-bluetooth-low-energy-devices?ref=novelbits.io)")* These are only rough estimates, and the actual current draw can vary a lot based on the specifics of the device design and usage. ## The 3 main ways to minimize power consumption At a high level, energy consumption is mainly decreased in microcontroller applications, and embedded systems in general, by reducing radio communication and increasing sleep/idle cycles as much as possible. In theory, this sounds simple and straightforward. However, when trying to accomplish this in practice, it can be much more complicated. For example, variables such as the changes in the environment (temperature, humidity, obstacles, and radio interference causing transfer retries) make the task exponentially more difficult. There are three ways to minimize power consumption: 1. **Choose the right hardware components** – including the battery. 2. **Optimize the firmware** via static configurations (such as peripheral bus speeds and pin configurations) and dynamic/run-time parameters (such as Bluetooth low energy parameters). 3. **Optimize firmware source code** in terms of both: writing efficient code and using the right compiler optimizations (for speed and size) can help you achieve your low power goals. This also includes your system design for protocol efficiency and packet sizes being transferred over the air or to/from external peripherals. In this post, I’m focusing on Bluetooth Low Energy devices (rather than Bluetooth Classic (BR/EDR) devices) and how to **optimize the different Bluetooth Low Energy parameters**. Again, it all basically comes down to **how long your MCU spends in idle/sleep mode vs. active mode.** User experience is the most important in determining the changes and parameters that could potentially affect power consumption. **Make sure it’s always the top priority for your product.** 💡 **Looking for more Bluetooth LE tutorials?** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## Which BLE parameters should be tuned? Optimization is achieved by tuning the parameters for the two states of Bluetooth LE devices: - **Connected state** - **Connection interval (connInterval):** - Ranges from **7.5 milliseconds to 4 seconds** (in multiples of 1.25 milliseconds). - **Peripheral latency (connPeripheralLatency):** - Allows a peripheral to skip connection events without the central device dropping the connection. Thus, a peripheral device can skip several connection events, especially if it does not have additional data, resulting in power savings. - The Peripheral Latency ranges from **0 to ((connSupervisionTimeout/ connInterval) – 1).** - A peripheral latency of **0** means the peripheral is not allowed to skip any connection events. - **Connection supervision timeout** **(connSupervisionTimeout):** - Defines the maximum time between two received Data Packet PDUs before the connection is considered lost. The connSupervisionTimeout shall be a multiple of **10 ms in the range of 100 milliseconds to 32.0 seconds,** and it shall be larger than **(1 + connSlaveLatency) \* connInterval**. - **Advertising state** - **Advertising interval:** - Theoretically, it ranges from **20 milliseconds to 10,485.759375 seconds (yes, you read that max number right!)**. However, most stacks cap the maximum to a smaller number, usually **10.24 seconds.** The longer the interval, the less current the device will consume during the advertising state. This is a more important parameter when working with broadcast-only devices such as beacons. - For connected devices, increasing the advertising interval will have a limited impact on energy savings after a certain point: the current consumption will be lower during the advertising state, however, the central will take longer to find the advertising device causing the advertising period to be higher (which may lead to higher power consumption than in the case where the advertising interval is shorter). - For some scenarios, it may be beneficial to advertise periodically instead of advertising all the time. The advertising period can then be tuned to achieve the optimal user experience. For example, it is also a best practice to advertise at a lower interval (higher frequency) in the beginning (say for 30 seconds or so) and then switch to a longer advertising interval. This can be upon boot-up or based on some user interaction (like pressing a button) and allows the central device to discover the peripheral much faster if it's in range while also allowing the peripheral to reduce power if not discovered or connected to by a central after that initial period. - **Advertising data length:** - Another parameter affecting current advertising consumption is how many payload bytes are sent in each advertising packet. Therefore, it may be beneficial in terms of current consumption to only place primary advertising data in the advertising packet and place all secondary data in the scan response packet, as advertising packets are sent much more frequently than scan response packets. **If you plan to transfer data in large bursts** you may exceed the recommended peak, which may negatively impact both the capacity and lifetime of the battery. For sending large quantities of data, look for ways to optimize the transfer: - Adjust connection intervals, advertising intervals, and peripheral latency parameters accordingly. - Combine small packets into fewer large ones (enable Data Length Extension (DLE), introduced in version 4.2 of the core specification). - Compress data before transmission. - Send lower priority data at slower rates. - For sensor-based devices, only measure and prepare data if the client has subscribed to the associated characteristic. The same is true on the other side (on the client/mobile side), only subscribe to characteristics that you’re interested in. - Consider how much of the time the device will be used. If the device will mostly stay in the idle state, then focus on optimizing the power consumed during the sleep state as much as possible. Conversely, if the device will be active most of the time, then focus on reducing the active-state current draw. One last thing to keep in mind is to test with debug mode turned off since BLE power consumption will usually be higher than with debug turned off. ## What to measure? It is not possible to compare the power consumption of a BLE device to another using a single metric. Sometimes a device gets rated by its **“peak current”**. While the peak current plays a part in the total power consumption, a device running the BLE stack will only be consuming current at the peak level while it is transmitting. Even in very high throughput systems, a BLE device is transmitting only for a small percentage of the total time that the device is connected. In a typical application, a device running the BLE stack will spend most of the time in a sleep state between connection events. The primary metric that takes these other time and current measurements into account is the **“average current”**. It is this value that can be used to determine the battery life of a BLE device. Note that a single “average current” value cannot be given for a device in its datasheet or in the device’s specifications, as the average current is highly dependent on the connection parameters used. Anytime an “average current” specification is given, it is very important to understand the exact use case in which the measurement was made. With that said, here are some other useful metrics that should be kept in mind: - **Peak current:** useful when comparing to what the battery vendor indicates as the recommended maximum peak – going above the value may negatively impact the capacity and lifetime of the battery. - How much power is used to **transfer a certain amount of data** - **Sleep-state current** consumption ## How to measure Bluetooth power consumption? Now, let’s talk about testing the power consumption of your device. The most important thing is to **ensure you test in an environment as close as possible to what a user’s environment would be like (real-life testing and not just in a lab setting)**. This will make your estimations much closer to real-life usage and ultimately make your users much happier. - The simplest way to measure current with an oscilloscope is to use a current probe and directly monitor the current going into the system. - If you do not have a current probe available, an easy alternative is to use a small resistor in line with the power supply input to the system. You can then use a standard oscilloscope voltage probe to measure the voltage across the resistor and effectively measure the current by dividing the voltage by the resistance. A good resistor value to use is 10 Ω, as this value is small enough that it shouldn’t affect the existing circuitry and large enough to provide a voltage that can be measured with decent precision (in addition, using a value of 10 Ω makes the calculations very simple). - When performing measurements, it is best to use a regulated DC power supply as opposed to an actual battery. This eliminates variables that might be caused by a defective or low battery. - Other methods of measurement include specialized hardware and software solutions provided by the vendor of the chip/module you’re using. For example, Silicon Labs provides the Energy Profiler tool as part of [Simplicity Studio](http://www.silabs.com/products/development-tools/software/simplicity-studio?ref=novelbits.io). Nordic Semiconductor provides the [Nordic Power Profiler Kit (PPK).](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/Power-Profiler-Kit?ref=novelbits.io) ## Summary and Closing Ultimately, each application will dictate how low your device’s power consumption can get. If the parameters are modified to a point where they negatively affect the user experience, then this will not help your product or users. Always keep the **user experience (UX)** as the top priority and design the system (including power optimization) in a way to enhance the UX. Finally, I will leave you with a summarized list of points/questions to keep in mind when optimizing your BLE device’s power consumption: - How long will it run on a coin cell battery? - What’s the current draw at peak usage? - How much power is used to transfer a certain amount of data? - How much data does the app need to transfer? - How often does it need to transfer data? - The battery capacity declared by the manufacturer is in ideal conditions. - Keep in mind that longer periods of peak current draw can affect/damage the battery. - If the power source is current-limited, then the peak current is just as important as the average current. - If you plan to transfer data in large bursts, you may exceed the recommended peak current, which negatively impacts both the capacity and lifetime of the battery. 💡 **Insider Tip:** Want to master Bluetooth Low Energy power optimization and battery life management? Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) for comprehensive courses covering everything from power consumption fundamentals to advanced optimization techniques! ### Choosing a Wireless Technology For Your Project URL: https://novelbits.io/choosing-wireless-technology/ Last updated: 2026-08-09T05:24:27.000Z If you're building a connected product — whether it's a smart home sensor, an industrial monitor, or a wearable fitness tracker — one of the first decisions you'll face is: **which wireless technology should I use?** It's a question I get asked a lot, and the answer is almost never straightforward. The wireless landscape is wide, and each technology comes with its own set of trade-offs. Wi-Fi, Bluetooth LE, Zigbee, LoRaWAN, Z-Wave, cellular IoT — they all have their strengths, and choosing the wrong one can mean redesigning your product later (which is never fun). In this post, we'll cover: - The key factors you should evaluate when selecting a wireless technology - A practical overview of the most popular [wireless protocols](https://novelbits.io/communications-protocols-and-why-we-need-them/) used in IoT - A side-by-side comparison to help you narrow down the right fit - How to match a technology to your specific project requirements Let's get into it. ## Key Factors to Consider Before diving into individual technologies, let's first understand the criteria that actually matter when making this decision. I recommend evaluating your project against these seven factors: ### 1\. Range How far does your data need to travel? This is often the single biggest differentiator between wireless technologies. Some protocols are designed for short-range communication (a few meters to about 100 meters), while others can reach kilometers. For example, Bluetooth LE is great for connecting a sensor to a phone across a room, but if you need to send data from a remote weather station 5 km away, you'll want something like LoRaWAN. Here's a rough breakdown: - **Short range** (up to \~100 m): Bluetooth LE, Zigbee, Z-Wave, NFC - **Medium range** (up to \~200 m): Wi-Fi - **Long range** (1–15+ km): LoRaWAN, Sigfox, NB-IoT, LTE-M ### 2\. Power Consumption If your device runs on a battery (especially a coin cell), power consumption is critical. Technologies like Bluetooth LE and Zigbee were specifically designed for ultra-low power operation, allowing devices to run for months or even years on a single battery. On the other hand, Wi-Fi is notoriously power-hungry. It's great when you have a wall outlet, but I do not recommend it for battery-powered devices — your battery will be dead before you know it. The exception is Wi-Fi HaLow (802.11ah), which was specifically designed for low-power IoT, but it hasn't seen widespread adoption yet. ### 3\. Data Rate and Throughput How much data do you need to send, and how fast? A temperature sensor reporting once per minute has very different needs than a security camera streaming video. Wi-Fi leads here with throughput in the hundreds of Mbps. Bluetooth LE offers up to 2 Mbps (with the LE 2M PHY), which is plenty for most sensor data and even firmware updates. Technologies like LoRaWAN and Sigfox trade speed for range — they're designed for tiny payloads (a few bytes to a few hundred bytes) sent infrequently. ### 4\. Cost Cost shows up in several places: the chip or module itself, the antenna design, certification fees, and any recurring connectivity costs (like cellular data plans). Bluetooth LE and Zigbee tend to be very affordable on the hardware side. Cellular IoT (NB-IoT, LTE-M) adds ongoing subscription costs, which can add up fast when you're deploying thousands of devices. LoRaWAN sits in an interesting middle ground — you can deploy your own gateway and avoid recurring fees, or use a public network like The Things Network. ### 5\. Security Every wireless technology has its own security model, and they're not all equal. Bluetooth LE supports AES-128 encryption and multiple pairing methods (including Secure Connections with ECDH key exchange). Wi-Fi uses WPA3\. Zigbee has network-level encryption built into the protocol. For any product that handles sensitive data — medical devices, access control, payment systems — I recommend going beyond the default security features and implementing application-layer encryption on top. ### 6\. Interoperability Will your device need to talk to smartphones, other IoT devices, or cloud services? Bluetooth LE has a huge advantage here because virtually every smartphone on the market supports it. Wi-Fi is similarly ubiquitous. Zigbee and Z-Wave are more common in dedicated smart home hubs (like Amazon Echo or Samsung SmartThings). If phone-to-device communication is important for your use case (and it usually is), Bluetooth LE is hard to beat. ### 7\. Scalability How many devices do you need to support in one network? A smart home with 10 sensors has different requirements than an industrial facility with 10,000. Mesh networking protocols like Zigbee and Bluetooth Mesh can scale to hundreds or thousands of nodes. LoRaWAN gateways can handle thousands of end devices. Wi-Fi access points, by comparison, typically support a few dozen concurrent connections before performance degrades. ## Popular Wireless Technologies: An Overview Now that we've established the evaluation criteria, let's take a closer look at the most commonly used wireless technologies in IoT projects. ### Bluetooth Low Energy (Bluetooth LE) [Bluetooth LE](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) is one of the most widely adopted wireless technologies in IoT. It operates in the 2.4 GHz ISM band and is designed for short-range, low-power communication. What makes Bluetooth LE particularly attractive is its universal smartphone support — every modern iOS and Android device includes a Bluetooth LE radio. This makes it the go-to choice for consumer products like fitness trackers, smart watches, medical devices, and beacons. Key characteristics: - **Range:** Typically 10–100 meters (up to 400+ meters with Coded PHY in Bluetooth 5.0+) - **Data rate:** 1 Mbps (LE 1M PHY) or 2 Mbps (LE 2M PHY) - **Power:** Ultra-low — great for coin-cell-powered devices - **Topology:** Point-to-point, broadcast, and mesh (via Bluetooth Mesh) - **Best for:** Wearables, health/medical, beacons, smart home accessories, asset tracking ### Wi-Fi [Wi-Fi](https://www.wi-fi.org/?ref=novelbits.io) needs no introduction. It's the workhorse of home and enterprise networking, operating in the 2.4 GHz and 5 GHz bands (and now 6 GHz with Wi-Fi 6E). For IoT, Wi-Fi makes sense when you need high throughput, have access to mains power, and want direct IP connectivity to the internet without a gateway. Think smart displays, security cameras, and voice assistants. Key characteristics: - **Range:** \~50–200 meters (varies by environment and standard) - **Data rate:** Up to several Gbps (Wi-Fi 6/6E) - **Power:** High — not ideal for battery-powered devices - **Topology:** Star (access point to clients) - **Best for:** High-bandwidth devices with access to mains power ### Zigbee [Zigbee](https://csa-iot.org/all-solutions/zigbee/?ref=novelbits.io) is a low-power, low-data-rate mesh networking protocol based on IEEE 802.15.4\. It operates in the 2.4 GHz band and is widely used in smart home and building automation. Zigbee's strength is its mesh networking capability — each node can relay messages for other nodes, extending the effective range of the network and providing redundancy. This makes it well-suited for whole-home or whole-building deployments with many sensors and actuators. Key characteristics: - **Range:** 10–100 meters per hop (extended via mesh) - **Data rate:** 250 kbps - **Power:** Low — suitable for battery-powered devices - **Topology:** Mesh - **Best for:** Smart home, lighting control, building automation, industrial sensors ### Z-Wave [Z-Wave](https://z-wavealliance.org/?ref=novelbits.io) is similar to Zigbee in many ways — it's a low-power mesh networking protocol designed for smart home applications. The key difference is that Z-Wave operates in the sub-1 GHz band (around 908 MHz in North America), which gives it better wall penetration and less interference from Wi-Fi and Bluetooth devices that crowd the 2.4 GHz band. The trade-off is that Z-Wave has a lower data rate (100 kbps) and the ecosystem is more controlled — all Z-Wave devices must be certified by the Z-Wave Alliance, which ensures interoperability but limits the number of available chipsets. Key characteristics: - **Range:** \~30–100 meters per hop (extended via mesh) - **Data rate:** 100 kbps - **Power:** Low - **Topology:** Mesh - **Best for:** Smart home (especially in Wi-Fi-congested environments) ### LoRaWAN LoRaWAN (Long Range Wide Area Network) is built on Semtech's LoRa modulation technology and is designed for long-range, low-power communication. It operates in sub-1 GHz ISM bands and can achieve ranges of 5–15 km in rural environments. LoRaWAN is ideal for applications where you need to send small amounts of data over long distances — think agricultural sensors, environmental monitoring, and smart city infrastructure. The data rates are low (0.3–50 kbps), but for many IoT use cases, that's more than enough. Key characteristics: - **Range:** 5–15+ km (rural), 1–5 km (urban) - **Data rate:** 0.3–50 kbps - **Power:** Very low — multi-year battery life possible - **Topology:** Star-of-stars (end devices to gateways to network server) - **Best for:** Agriculture, environmental monitoring, asset tracking, smart cities ### Cellular IoT (NB-IoT and LTE-M) Cellular IoT technologies like NB-IoT (Narrowband IoT) and LTE-M leverage existing cellular infrastructure to provide wide-area IoT connectivity. They're managed by mobile network operators, which means you get broad coverage out of the box — but you also pay for a data subscription. NB-IoT is optimized for stationary devices sending small, infrequent payloads (like smart meters). LTE-M supports higher data rates and mobility, making it suitable for asset trackers and connected vehicles. Key characteristics: - **Range:** Cellular coverage area (km+) - **Data rate:** NB-IoT \~250 kbps, LTE-M \~1 Mbps - **Power:** Low (with PSM and eDRX power-saving modes) - **Topology:** Star (device to base station) - **Best for:** Smart metering, fleet tracking, remote monitoring where other infrastructure doesn't exist ## Side-by-Side Comparison Let's put it all in a table to make it easier to compare. Keep in mind that these are typical values — actual performance varies based on environment, configuration, and implementation. | Technology | Range | Data Rate | Power | Best For | | ---------------- | ----------------- | ----------- | --------- | ----------------------------------------- | | **Bluetooth LE** | 10–100 m | 1–2 Mbps | Ultra-low | Wearables, health, beacons, smart home | | **Wi-Fi** | 50–200 m | Up to Gbps | High | Cameras, displays, mains-powered devices | | **Zigbee** | 10–100 m (mesh) | 250 kbps | Low | Smart home, lighting, building automation | | **Z-Wave** | 30–100 m (mesh) | 100 kbps | Low | Smart home (sub-1 GHz, less interference) | | **LoRaWAN** | 1–15+ km | 0.3–50 kbps | Very low | Agriculture, environment, smart cities | | **NB-IoT** | Cellular coverage | \~250 kbps | Low | Smart metering, remote monitoring | | **LTE-M** | Cellular coverage | \~1 Mbps | Low | Fleet tracking, mobile assets | ## How to Decide: A Practical Framework With all these options, how do you actually make the decision? Let's walk through five questions that I've found get you to the right answer pretty quickly: 1. **Does your device need to communicate with a smartphone?** If yes, Bluetooth LE is almost certainly part of your solution (either as the primary protocol or for provisioning/configuration). 2. **Is your device battery-powered?** If yes, eliminate Wi-Fi and lean toward Bluetooth LE, Zigbee, or LoRaWAN depending on range needs. 3. **How far does the data need to travel?** Under 100 meters? Short-range protocols work fine. Over 1 km? You're looking at LoRaWAN, cellular IoT, or Sigfox. 4. **How much data and how often?** Frequent, large payloads favor Wi-Fi or LTE-M. Infrequent, small payloads open up all the low-power options. 5. **Do you need mesh networking?** If you have many devices that need to relay messages across a large area, Zigbee, Z-Wave, or Bluetooth Mesh are your best options. In many real-world products, the answer is actually a combination of technologies. For example, a smart home hub might use Zigbee or Z-Wave to communicate with sensors, Wi-Fi to connect to the internet, and Bluetooth LE for initial setup via a phone app. Don't feel like you have to pick just one. ## Conclusion In this post, we covered the key factors to evaluate when choosing a wireless technology — range, power consumption, data rate, cost, security, interoperability, and scalability. We also walked through the most popular options (Bluetooth LE, Wi-Fi, Zigbee, Z-Wave, LoRaWAN, and cellular IoT) and how they compare across these dimensions. Here are the key takeaways: - **Bluetooth LE** is the best choice for short-range, battery-powered devices that need smartphone connectivity. - **Wi-Fi** is your best bet when you need high throughput and have mains power available. - **Zigbee and Z-Wave** excel in smart home mesh networks with many nodes. - **LoRaWAN** is unmatched for long-range, low-power applications where data rates are small. - **Cellular IoT** (NB-IoT/LTE-M) makes sense when you need wide-area coverage without deploying your own infrastructure. - Many products use **multiple technologies** — don't feel locked into picking just one. You should now have a solid framework for evaluating which wireless technology fits your next project. The right choice depends on your specific requirements, and taking the time to evaluate these factors upfront will save you from costly redesigns down the road. 💡 **Insider Tip:** Want to master Bluetooth LE and understand how it compares to other wireless technologies for your IoT projects? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth GATT: How to Design Custom Services & Characteristics [MIDI device use case] URL: https://novelbits.io/bluetooth-gatt-services-characteristics/ Last updated: 2026-08-09T05:23:43.000Z You're probably aware that adding Bluetooth Low Energy (BLE) to your device is one of the best ways to achieve a great user experience for your IoT device. ⚠️ **Note:** This tutorial was originally written using the Nordic nRF5 SDK, which has since been deprecated. The GATT concepts, service/characteristic design principles, and UUID guidelines covered here are still fully applicable. However, the code examples use the deprecated nRF5 SDK — for new projects, use the [nRF Connect SDK](https://developer.nordicsemi.com/nRF%5FConnect%5FSDK/doc/latest/nrf/index.html?ref=novelbits.io) (Zephyr-based). ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. Why is that, you may ask? Well, adding BLE allows your device to be connectable from a smartphone app. And we can all agree that smartphone apps have become very familiar to end-users and are very user-friendly. **However**, designing BLE devices can be a confusing process! You're probably thinking: "Where do I even start?" The one thing I wish I had when I started developing for BLE is **more resources that walk you step-by-step** on how to tackle the different phases of the system design and implementation. The **Bluetooth GATT** (Generic Attribute Profile) is the foundation for the design of any BLE system and defines the way two BLE devices interact with each other. Keep in mind that GATT is used exclusively after a connection has been established between the two devices, and not during the advertising/scanning states. The Bluetooth SIG defines quite a few standard Profiles, Services, and Characteristics. However, many times you will find that none of these satisfies the use case you’re designing. That’s where custom **profiles**, **services**, and **characteristics** come in. Reader João Neves sent in a question asking about implementing a BLE MIDI controller: > *I'm trying to be able to send MIDI over Bluetooth... I'm trying to advertise that device as a BLE MIDI controller...* > > *There's not a lot of info on internet for this subject and I can't find any for the nRF52 DK.* In today’s tutorial, I’ll be covering a detailed **step-by-step guide** on how to **design your custom GATT** to satisfy your product’s requirements and go through a **complete design and simplistic implementation of a MIDI device using the nRF52 platform**. Before explaining what **services** and **characteristics** are, we first need to cover two very important concepts: the **Generic Attribute Profile (GATT)** and the **Attribute Protocol (ATT)**. GATT stands for **Generic Attribute Profile**. To understand what GATT is, we first need to understand the underlying framework for GATT: the Attribute Protocol (ATT). The GATT only comes into play after a connection has been established between two BLE devices. ## Attribute Protocol (ATT) ATT defines how a *server* exposes its data to a *client* and how this data is structured. There are two roles within the ATT: - **Server**: This is the device that exposes the data it controls or contains, and possibly some other aspects of server behavior that other devices may be able to control. It is the device that accepts incoming commands from a peer device and sends **responses**, **notifications**, and **indications**. For example, a thermometer device will behave as a server when it exposes the temperature of its surrounding environment, the unit of measurement, its battery level, and possibly the time intervals at which the thermometer reads and records the temperature. It can also **notify** the client (defined later) when a temperature reading has changed rather than have the client poll for the data waiting for a change to occur. - **Client**: This is the device that interfaces with the server with the purpose of reading the server’s exposed data and/or controlling the server’s behavior. It is the device that sends commands and requests and accepts incoming notifications and indications. In the previous example, a mobile device that connects to the thermometer and reads its temperature value is acting in the Client role. The data that the server exposes is structured as **attributes**. An attribute is the generic term for any type of data exposed by the server and defines the structure of this data. For example, services and characteristics (both described later) are types of attributes. Attributes are made up of the following: - **Attribute type (Universally Unique Identifier or UUID)** This is a 16-bit number (in the case of Bluetooth SIG-Adopted Attributes), or 128-bit number (in the case of custom **attribute types** defined by the developer, also sometimes referred to as **vendor-specific UUID**s). For example, the UUID for a SIG-adopted temperature measurement attribute value is **0x2A1C**. SIG-adopted attribute types (UUIDs) share all but 16 bits of a special 128-bit base UUID:0000**0000**\-0000-1000-8000-00805F9B34FB. The published 16-bit UUID attribute values replace the 2 bytes in **bold** in the base UUID. A custom UUID, on the other hand, can be any 128-bit number that does not use the SIG-adopted base UUID. For example, a developer can define their own attribute type (UUID) for a temperature reading as: F5A1287E-227D-4C9E-AD2C-11D0FD6ED640. One benefit of using a SIG-adopted UUID is the reduced packet size since it can be transmitted as the 16-bit representation instead of the full 128-bit value. - **Attribute Handle** This is a 16-bit value that the server assigns to each of its attributes — *think of it as an address*. This value is used by the client to reference a specific attribute and is guaranteed by the server to uniquely identify the attribute during the life of the connection between two devices. The range of handles is **0x0001-0xFFFF**, where the value of **0x0000** is reserved. - **Attribute Permissions** Permissions determine whether an attribute can be **read** or **written** to, whether it can be **notified** or **indicated**, and what **security levels** are required for each of these operations. These permissions are not defined or discovered via the Attribute Protocol (ATT) but rather defined at a higher layer (GATT layer or Application layer). The following figure shows a logical representation of an Attribute: ![Attribute structure](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/attribute-structure-be528107546b4df284978c3ab889e0dd.png) Figure 1: Attribute structure ## The Generic Attribute Profile (GATT) Now that we’ve covered the concept of **attributes**, we’ll go over three important concepts in BLE that you will come across very often: - **Services** - **Characteristics** - **Profiles** These concepts are used specifically to allow hierarchy in the structuring of the data exposed by the Server. Services and characteristics are types of attributes that serve a specific purpose. Characteristics are the lowest level attribute within a database of attributes. Profiles are a bit different and are not discovered on a server — we will explain them later below. GATT defines the format of services and their characteristics, and the procedures that are used to interface with these attributes such as service discovery, characteristic reads, characteristic writes, notifications, and indications. GATT takes on the same **roles** as the Attribute Protocol (ATT). The roles are not set per device — rather they are determined per transaction (such as request-response, indication-confirmation, and notification). So, in this sense, a device can act as a server serving up data for clients, and at the same time act as a client reading data served up by other servers (all during the same connection). ## BLE Services and Characteristics ### Services A **service** is a grouping of one or more attributes, some of which are characteristics. It’s meant to group together related attributes that satisfy a specific functionality on the server. For example, the SIG-adopted **Battery Service** contains one characteristic called the **Battery Level**. Other types of services are the Device Information Service, Environment Sensing Service, and Power Management Service. A service also contains other attributes (non-characteristics) that help structure the data within a service (such as **service declarations**, **characteristic declarations**, and others). Here’s what a service looks like: ![GATT Profile, Services, Characteristics Hierarchy](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-16.png) Figure 2: Profiles, Services, and Characteristics (Source: Core Bluetooth specification document) From the figure, we can see the different attributes a service is made up of: - One or more **include services** - One or more characteristics - Characteristic properties - A characteristic value - Zero or more characteristic descriptors An included service allows a service to refer to other services for purposes such as extending the included service. However, they are barely used in practice. There are two types of services: - **Primary Service:** represents the primary functionality of a device. - **Secondary Service:** provides the auxiliary functionality of a BLE device and is referenced (included) by at least one other primary service on the device (it is rarely used and won't be discussed here). ### Characteristics A **characteristic** is always part of a service and it represents a piece of information/data that a server wants to expose to a client. For example, the battery level characteristic represents the remaining power level of a battery in a BLE device that can be read by a client. The characteristic contains other attributes that help define the value it holds: - **Properties:** represented by a number of bits and which define how **characteristic values** can be used. Some examples include: **read**, **write**, **write without response**, **notify**, and **indicate**. - **Descriptors:** used to contain related information about the characteristic value type. Some examples include: **extended properties**, **user description**, fields used for **subscribing to notifications and indications**, and a field that defines the **presentation of the value** such as the **format** and the **unit of the value**. Understanding these concepts is important, however, as an application developer, you’ll probably interface with APIs provided by the chipset or mobile operating system SDK that abstract out many of these concepts. For example, you may have an API for enabling notifications on a certain characteristic that you can simply call (*you don’t necessarily need to know that the stack ends up writing a value of *0x0001* to the characteristic’s *Client Characteristic Configuration Descriptor (CCCD)* on a server to enable notifications*). It’s important to keep in mind that while there are no restrictions or limitations on the characteristics contained within a service; services are meant to group together related characteristics that define a specific functionality within a BLE device. For example, even though it’s technically possible — it does not make sense to create a service called the **humidity service** that includes both a **humidity** characteristic and a **temperature** characteristic. Instead, it would make more sense to have two separate services specific to each of these two distinct functionalities (temperature reading, and humidity reading). It’s worth mentioning that the SIG has adopted quite a few services and characteristics that satisfy a good number of common use cases. For these adopted services, specification documents exist to help developers implement them along with ensuring conformance and interoperability with this service. If a BLE device claims conformance to a service, it must be implemented according to the service specification published by the Bluetooth SIG. This is essential if you want to develop a device that is guaranteed to be connectable with third-party devices from other vendors. The SIG-adopted services make the connection specification “pre-negotiated” between different vendors. You can find the list of **adopted services** **and characteristics** [here](https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%5FNumbers.pdf?ref=novelbits.io) and their respective **specifications** [here](https://www.bluetooth.com/specifications/gatt?ref=novelbits.io). ### Profiles **Profiles** are much broader in definition than services. They are concerned with defining the behavior of both the client and server when it comes to services, characteristics, and even connections and security requirements. Services and their specifications, on the other hand, deal with the implementation of these services and characteristics on the server side only. Just like in the case of services, there are also **SIG-adopted** profiles that have published specifications. In a profile specification, you will generally find the following: - Definition of roles and the relationship between the GATT server and the client. - Required Services. - Service requirements. - How the required services and characteristics are used. - Details of BLE connection establishment requirements including advertising and connection parameters. - Security considerations. Following is an example of a diagram taken from the Blood Pressure Profile specification document. It shows the relationship between the roles (server, client), services, and characteristics within the profile. ![Blood Pressure Profile](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/blood-pressure-profile-3bbd36b6243d4f3f8938aaa8cb407fc0.png) Figure 3: Blood Pressure Profile (Source: Blood Pressure Profile Specification) The roles are represented by the yellow boxes, whereas the services are represented by the orange boxes. You can find the list of **SIG-adopted profiles** [here](https://www.bluetooth.com/specifications/gatt?ref=novelbits.io). ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ## Example GATT Let’s look at an example of a GATT implementation. For this example, we’ll look at an example **GATT.xml** file that’s used by the Silicon Labs Bluetooth Low Energy development framework (BGLib). ![GATT xml example](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/gatt-xml-example-e669c901bf754a4eaf7498a29ae479e8.png) Figure 4: GATT XML example In this XML, you’ll notice the following: - There are two services defined: - Generic Access Profile (GAP) service with UUID: **0x1800** (SIG-adopted service). - Cable Replacement service with UUID: **0bd51666-e7cb-469b-8e4d-2742f1ba77cc** (a custom or vendor-specific service). - The Generic Access service is mandatory per the spec, and it includes the following mandatory characteristics: - **Name** with UUID **0x2a00** and value: **Bluegiga CR Demo**. - **Appearance** with UUID **0x2a01** and value **0x4142**. **Note:** the creation and inclusion of this Service are usually handled by the chipset’s SDK, and usually APIs are provided to simply set the Name and Appearance values. - The Cable Replacement service has one characteristic named **data** - The **data** characteristic has a UUID: **e7add780-b042-4876-aae1-112855353cc1** - It has both **writes** and **indications** enabled. ## GATT Design Guidelines While GATT is a pretty flexible framework, there are a few general guidelines to follow when designing it and creating the services and characteristics within it. Following are some recommendations: - Make sure to implement the following mandatory service and its characteristics: - **Generic Access Profile** (GAP) service. - **Name** and **Appearance** characteristics within the GAP service. - One thing to keep in mind is that vendor SDKs usually do not require you to explicitly implement this service, but rather they provide APIs for setting the name and **appearance**. The SDK then handles creating the GAP service and setting the characteristics according to the user-provided values. - Utilize the Bluetooth SIG-adopted profiles, services, and characteristics in your design whenever possible. This has the following benefits: - You get the benefit of reducing the size of data packets involving UUIDs for services and characteristics (including advertisement packets, discovery procedures, and others) — since 16-bit UUID values are used instead of 128-bit values. - Bluetooth chipset and module vendors usually provide implementations of these profiles, services, and characteristics in their SDKs — reducing development time considerably. - Interoperability with other third-party devices and applications, allowing more devices to interface with your BLE device and provide a richer user experience. - Group characteristics that serve related functionality within a single service. - Avoid having services with too many characteristics. A good separation of services makes it faster to discover certain characteristics and leads to a better GATT design that’s modular and user-friendly. ### Step 1: Document the different user scenarios and data points Even though the GATT is usually more focused on the peripheral role (since a peripheral is usually the server exposing the data), the central can still act as the server in some cases for specific data points it needs to expose. Also, if you're designing both ends (central and peripheral), it helps to think in terms of what needs to happen from each side since this could affect some aspects of the system and GATT design. In this step, you’ll think about your system from a high level in terms of data elements that need to be exposed on the Server device. It helps to not think too much about the technical aspects of BLE. Instead, focus on the following: - Defining the data elements that the server needs to expose to the Client. - Defining whether each of these elements will be available for: *Read*, *Write*, *and Notifications of value changes back to the Client*. - Thinking about eliminating any redundant data elements. This is important for two reasons: - It reduces the amount of data being transferred, which in turn reduces power consumption. - It makes the design simpler and easier to understand and update later on. - Grouping the data elements into a meaningful number of groups based on related functionality. This encourages clarity in design and also helps others (within your team or outside) understand your design. It also helps in making maintenance and future updates easier. ### Step 2: Define the services, characteristics, and access permissions The next step is to group the **characteristics** into meaningful groups (**services**) based on their functionalities and define the access permissions for each of these characteristics. ### Step 3: Re-use Bluetooth SIG-adopted services & characteristics Take a look at the data elements and data groups you brainstormed in the previous step. Now refer to the standard [Services](https://www.bluetooth.com/specifications/gatt/services?ref=novelbits.io) and [Characteristics](https://www.bluetooth.com/specifications/gatt/services?ref=novelbits.io) and see which ones match the data elements you came up with within the design. This is not mandatory per the Bluetooth spec since users are given the freedom to create custom Services and Characteristics. However, there are two benefits to this approach: - Allowing your BLE device to be interoperable with other devices. - Vendors usually provide many examples that utilize the standard Services and Characteristics, which makes your development work easier. ### Step 4: Assign UUIDs to Custom Services and Characteristics For any **custom services** and **characteristics** within the GATT, we can use an online tool to generate UUIDs such as the [Online GUID Generator](http://www.guidgenerator.com/?ref=novelbits.io). A common practice is to choose a base UUID for the custom service and then increment the **3rd** and **4th** **Most Significant Bytes (MSB)** within the UUID of each included characteristic. For example, we could choose the UUID: 0000**0001**\-1000-2000-3000-111122223333 for a specific service and then 0000000**\[N\]**\-1000-2000-3000-111122223333, (where **N > 1**) for each of its characteristics. So, in this case, the service and its characteristics' UUIDs would look something like this: **Service A**: 0000**0001**\-1000-2000-3000-111122223333 |---- **Characteristic 1**: 0000**0002**\-1000-2000-3000-111122223333 |---- **Characteristic 2**: 0000**0003**\-1000-2000-3000-111122223333 |.... |---- **Characteristic n**: 0000**000\[n-1\]**\-1000-2000-3000-111122223333 The only restriction for choosing UUIDs for custom BLE services and characteristics is that they must not collide with the Bluetooth SIG base UUID: **XXXXXXXX-0000-1000-8000-00805F9B34FB** You could also randomly choose a unique UUID for each element (including services and characteristics). However, following the previously mentioned common practice makes it a bit easier to relate services and their characteristics to one another. For a step-by-step guide on how to do to choose a single UUID, refer to my blog post:[**How do I choose a UUID for my custom services and characteristics?**](https://novelbits.io/uuid-for-custom-services-and-characteristics/) ### Step 5: Implement your GATT using the framework and APIs provided by the BLE solution vendor The solutions provided by the different vendors vary widely, so this step will be specific to the BLE module and development framework that you end up choosing. I'll be using the nRF52 APIs in the next section which goes over a full design and implementation example. ## Example using nRF52 Development Kit \[MIDI device use case\] Let's take a look at the definitions for services and characteristics within the MIDI BLE Specification (found here: [BLE MIDI Specification](https://midi.org/midi-over-bluetooth-low-energy-ble-midi?ref=novelbits.io)): ![BLE MIDI Services and Characteristics](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-10-43-22-am.png) Figure 5: BLE MIDI Services and Characteristics We notice that there is **one service** and **one characteristic** defined: - **MIDI Service** (UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700) - **MIDI Data I/O Characteristic** (UUID: 7772E5DB-3868-4112-A1A9-F2669D106BF3) - write (encryption recommended, write without response is required) - read (encryption recommended, respond with no payload) - notify (encryption recommended) Since the services and characteristics for a standardized MIDI device are already defined, we can simply skip all the steps except for **step #5** where we implement it for the nRF52 development kit. Then, upon successful implementation, you will be able to scan for the device, connect it, discover its Services and Characteristics, and verify that the GATT structure matches the MIDI spec. Before you follow along with the implementation, **make sure you have**: - An nRF52840 development kit (the nRF52832 could be used instead, but the companion source code will have to be modified to be compatible with this chipset. Alternatively, you could follow the steps and modify the project example for the nRF52832 chipset). - The development environment set up and ready to interface with the development kit. The steps we will go through: 1. Use the **ble\_app\_template** example provided in the nRF52 SDK (**version 15.0.0** or the latest **17.1.0**). 2. Open the project in Segger Embedded Studio and add the necessary files to the project. 3. Modify the example to add the MIDI Service and Characteristic (according to the spec). 4. Compile the code and flash it to the **nRF52840 development kit**. 5. Scan for the device via a Client emulator app such as the [Nordic nRF Connect App](https://www.nordicsemi.com/eng/Products/Nordic-mobile-Apps/nRF-Connect-for-mobile-previously-called-nRF-Master-Control-Panel?ref=novelbits.io) (iOS, Android, or desktop). 6. Connect to the device and discover the Services and Characteristics. 7. Verify that the GATT matches the MIDI spec. Let’s get started! ### Step 1: Setup If you haven’t already done so, you will want to follow the tutorial step-by-step to get your development and debugging environment set up: [**The complete cross-platform nRF development tutorial**](https://novelbits.io/cross-platform-nrf-development-tutorial/) **Note:** You can use **SDK version 15.0.0** or the latest **17.1.0 version** to run this example. ### Step 2: Project Setup Once you have SES (Segger Embedded Studio) installed, open the example project located at /examples/ble\_peripheral/ble\_app\_template. ![Template Project](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-01-at-11-41-08-am.png) Figure 6: BLE Peripheral Template Example Now that you have the project open, we'll take the following steps: - Enable Debug messages to show up in the debug terminal (using the Segger RTT backend). - Modify the **vendor-specific UUID count** to 2 (one for the MIDI service, and one for the MIDI Data I/O characteristic). - Add the `midi_service.h` and `midi_service.c` files to the project under the **Application** folder. - Make any necessary changes to the **section placement macros** in the project. Let's go through each of these steps. - Enable Debug messages to show up in the debug terminal (using the Segger RTT backend). First, right-click on the **`sdk_config.h`** file under the **Applications** folder, and click on **CMSIS Configuration Wizard**. ![CMSIS Configuration Wizard](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-11-11-59-am.png) Figure 7: CMSIS Configuration Wizard Navigate to **nRF\_Log** \--> **NRF\_LOG\_BACKEND\_RTT\_ENABLED** and make sure it is **checked** **\[✓\]**. ![NRF LOG RTT BACKEND](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-11-12-38-am.png) Figure 8: Configuring RTT Backend for nRF Logging Make sure you hit the **save** button (**File icon**). - Modify the vendor-specific UUID count to 2 (one for the MIDI service, and one for the MIDI Data I/O characteristic). - Right-click on the **sdk\_config.h** file under the **Applications** folder, and click on **CMSIS Configuration Wizard**. - Navigate to **nRF\_SoftDevice** \--> **NRF\_SDH\_BLE\_ENABLED** \--> **BLE Stack configuration** \--> **NRF\_SDH\_BLE\_VS\_UUID\_COUNT**, and make sure it is set to **2.** - Make sure you hit the **save** button (**File icon**). ![Vendor Specific UUID Count](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-11-14-43-am.png) Figure 9: Setting the Vendor-Specific UUID Count value - Add the midi\_service.h and midi\_service.c files to the project under the **Application** folder. Right-click on the **Applications** folder, then click "**Add New File...**" ![Adding a New File in SES](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-11-at-11-24-17-pm.png) Figure 10: Adding a New File Choose **C File (.c)** and type **midi\_service** in the **Name** field. Also, make sure the location is appropriate (I suggest putting it in the root folder of the project). Repeat the same steps for midi\_service.h (but choose **Header File (.h)** instead). - Make any necessary changes to the **section placement macros** in the project. - To make sure the section placement macros values are set correctly, compile and flash the project (in Debug mode) to the development kit. - If the macros need adjusting, a debug message will be displayed prompting you to use different values: ![RAM Location and Size](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-11-at-11-21-48-pm.png) Figure 11: Debug message showing correct RAM location and size If you get the debug message, copy the values for the RAM start location and Maximum RAM size and adjust the macros accordingly. You can do so by right-clicking on the Project (not Solution), then clicking on **Options:** ![Project Options](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-11-28-12-am.png) Figure 12: Project Options Then choose **Common** from the configuration drop-down menu ![Common Configuration](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-11-28-34-am.png) Figure 13: Common Project Configuration Next, choose **Linker** under **Code**: ![Linker Configuration](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-08-at-11-29-42-am.png) Figure 14: Linker Configuration On the right-hand side, double-click on **Section Placement Macros** ![Section Placement Macros](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-11-at-11-16-32-pm.png) Figure 15: Section Placement Macros Now, modify the macros **RAM\_START** and **RAM\_SIZE** to match the values displayed in the debug message. ### Step 3: Source Code Modifications Now that we have made all the project modifications necessary, we're ready to write the code for the MIDI service (and its characteristic) and the code needed to initialize them in **main.c**. #### midi\_service.h The header file will define the data structures and function prototypes needed to implement the MIDI service. Let's go through implementing it line by line. Add the conditional macro and the necessary **#include** files: ```c #ifndef MIDI_SERVICE_H #define MIDI_SERVICE_H #include #include #include "ble.h" #include "ble_srv_common.h" ``` Add the macro used for instantiating and defining the service object: ```c /**@brief Macro for defining a ble_midi_service instance. * * @param _name Name of the instance. * @hideinitializer */ #ifndef BLE_MIDI_BLE_OBSERVER_PRIO #define BLE_MIDI_BLE_OBSERVER_PRIO 2 #endif #define BLE_MIDI_DEF(_name) \ static ble_midi_service_t _name; \ NRF_SDH_BLE_OBSERVER(_name ## _obs, \ BLE_MIDI_BLE_OBSERVER_PRIO, \ ble_midi_service_on_ble_evt, &_name) ``` Now, we add the macros that define the UUIDs for the service and the characteristic. These values are defined in the BLE MIDI spec, so we don't have to come up with our own values. Following the spec, we define the following: ```c // MIDI Service UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700 // MIDI Data I/O Characteristic UUID: 7772E5DB-3868-4112-A1A9-F2669D106BF3 // The bytes need to be in reverse order to match the UUID from the spec // Note: They are stored in little endian, meaning that the Least Significant Byte // is stored first. #define BLE_UUID_MIDI_SERVICE_BASE_UUID {0x00, 0xC7, 0xC4, 0x4E, 0xE3, 0x6C, 0x51, 0xA7, 0x33, 0x4B, 0xE8, 0xED, 0x5A, 0x0E, 0xB8, 0x03} #define BLE_UUID_MIDI_SERVICE_UUID 0x0E5A #define BLE_UUID_MIDI_DATA_IO_CHAR_BASE_UUID {0xF3, 0x6B, 0x10, 0x9D, 0x66, 0xF2, 0xA9, 0xA1, 0x12, 0x41, 0x68, 0x38, 0xDB, 0xE5, 0x72, 0x77} #define BLE_UUID_MIDI_DATA_IO_CHAR_UUID 0xE5DB ``` Define the different MIDI event types and a data structure to represent a MIDI event. ```c /**@brief MIDI Service event type. */ typedef enum { BLE_DATA_IO_EVT_NOTIFICATION_ENABLED, /**< Custom value notification enabled event. */ BLE_DATA_IO_EVT_NOTIFICATION_DISABLED, /**< Custom value notification disabled event. */ } ble_midi_evt_type_t; /**@brief MIDI Service event. */ typedef struct{ ble_midi_evt_type_t evt_type; } ble_midi_evt_t; ``` Forward-declare the MIDI service data structure: ```c // Forward declaration of the ble_midi_service_t type. typedef struct ble_midi_service_s ble_midi_service_t; ``` Define the MIDI Data I/O write handler function: ```c typedef void (*ble_midi_evt_handler_t) (ble_midi_service_t * p_midi_service, ble_midi_evt_t * p_evt); ``` Define the init data structure that is used to configure a callback function that can be called back to the main application: ```c typedef struct { ble_midi_evt_handler_t evt_handler; /**< Event handler to be called when a MIDI event occurs. */ } ble_midi_service_init_t; ``` Define the main MIDI Service data structure that contains the service handle, any characteristic handles, the UUID type, the connection handle, and more: ```c /**@brief MIDI Service structure. This contains various status information for the service. */ struct ble_midi_service_s { uint16_t service_handle; ble_gatts_char_handles_t data_io_char_handles; uint8_t uuid_type; uint16_t conn_handle; ble_midi_evt_handler_t evt_handler; }; ``` Define the function prototype for the initializer function. This function gets called from the main application to initialize the service: ```c /**@brief Function for initializing the MIDI Service. * * @param[out] p_midi_service MIDI Service structure. This structure will have to be supplied by * the application. It will be initialized by this function, and will later * be used to identify this particular service instance. * @param[in] p_midi_service_init Information needed to initialize the service. * * @return NRF_SUCCESS on successful initialization of service, otherwise an error code. */ uint32_t ble_midi_service_init(ble_midi_service_t * p_midi_service, const ble_midi_service_init_t * p_midi_service_init); ``` Define the BLE event handler for the MIDI service. This will get called by the stack whenever a BLE event is reported and may need to be processed by the MIDI service: ```c /**@brief Function for handling the Application's BLE Stack events. * * @details Handles all events from the BLE stack of interest to the MIDI Service. * * * @param[in] p_midi_service LED Button Service structure. * @param[in] p_ble_evt Event received from the BLE stack. */ void ble_midi_service_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); ``` Close the conditional macro for the header file: ```c #endif /* MIDI_SERVICE_H */ ``` #### midi\_service.c The source .c file will handle the implementation of the service including initialization, the creation of services and characteristics, as well as event handling. Let's go through implementing it line-by-line. Add the necessary **#include** for header files: ```c #include "midi_service.h" #include "nordic_common.h" #include "ble_srv_common.h" #include "app_util.h" #include "nrf_log.h" ``` Implement the function that handles the connection event. The function simply sets and stores the connection handle: ```c /**@brief Function for handling the Connect event. * * @param[in] p_midi_service LED Button Service structure. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_connect(ble_midi_service_t * p_midi_service, ble_evt_t const * p_ble_evt) { p_midi_service->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; } ``` Implement the function that handles the **disconnection** event. The function simply resets the connection handle associated with the service: ```c /**@brief Function for handling the Disconnect event. * * @param[in] p_midi_service LED Button Service structure. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_disconnect(ble_midi_service_t * p_midi_service, ble_evt_t const * p_ble_evt) { UNUSED_PARAMETER(p_ble_evt); p_midi_service->conn_handle = BLE_CONN_HANDLE_INVALID; } ``` Implement the **write handler** function that processes the write event and verifies that it's valid. *The implementation/processing is left to the developer.* It also handles the case where notifications are enabled/disabled and passes this event back up to the main application (via the event handler that was set in the initialization function). ```c /**@brief Function for handling the Write event. * * @param[in] p_midi_service LED Button Service structure. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_write(ble_midi_service_t * p_midi_service, ble_evt_t const * p_ble_evt) { ble_gatts_evt_write_t * p_evt_write = (ble_gatts_evt_write_t *) &p_ble_evt->evt.gatts_evt.params.write; if ((p_evt_write->handle == p_midi_service->data_io_char_handles.value_handle) && (p_evt_write->len == 1) && (p_midi_service->evt_handler != NULL)) { // Handle what happens on a write event to the characteristic value } // Check if the Custom value CCCD is written to and that the value is the appropriate length, i.e 2 bytes. if ((p_evt_write->handle == p_midi_service->data_io_char_handles.cccd_handle) && (p_evt_write->len == 2) ) { // CCCD written, call application event handler if (p_midi_service->evt_handler != NULL) { ble_midi_evt_t evt; if (ble_srv_is_notification_enabled(p_evt_write->data)) { evt.evt_type = BLE_DATA_IO_EVT_NOTIFICATION_ENABLED; } else { evt.evt_type = BLE_DATA_IO_EVT_NOTIFICATION_DISABLED; } p_midi_service->evt_handler(p_midi_service, &evt); } } } ``` Implement the BLE event handler function. This function gets called automatically by the SoftDevice and is set up by the **BLE\_MIDI\_DEF** macro we defined at the top of the midi\_service.h file. It processes the BLE event and hands it off to the appropriate function to be processed. It handles the **connection event,** the **disconnection event**, and the **write event**: ```c void ble_midi_service_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) { ble_midi_service_t * p_midi_service = (ble_midi_service_t *) p_context; NRF_LOG_INFO("BLE event received. Event type = %d\r\n", p_ble_evt->header.evt_id); if (p_midi_service == NULL || p_ble_evt == NULL) { return; } switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: on_connect(p_midi_service, p_ble_evt); break; case BLE_GAP_EVT_DISCONNECTED: on_disconnect(p_midi_service, p_ble_evt); break; case BLE_GATTS_EVT_WRITE: on_write(p_midi_service, p_ble_evt); break; default: // No implementation needed. break; } } ``` Now, we'll implement the function for creating and adding the **data I/O** characteristic as part of the MIDI service. ```c /**@brief Function for adding the Data I/O characteristic. * */ static uint32_t data_io_char_add(ble_midi_service_t * p_midi_service, const ble_midi_service_init_t * p_midi_service_init) { uint32_t err_code; ble_gatts_char_md_t char_md; ble_gatts_attr_md_t cccd_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; // Configure the CCCD which is needed for Notifications and Indications memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; // Configure the characteristic metadata. memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; char_md.char_props.write_wo_resp = 1; char_md.char_props.notify = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = &cccd_md; char_md.p_sccd_md = NULL; // Add the MIDI Data I/O Characteristic UUID ble_uuid128_t base_uuid = {BLE_UUID_MIDI_DATA_IO_CHAR_BASE_UUID}; err_code = sd_ble_uuid_vs_add(&base_uuid, &p_midi_service->uuid_type); if (err_code != NRF_SUCCESS) { return err_code; } ble_uuid.type = p_midi_service->uuid_type; ble_uuid.uuid = BLE_UUID_MIDI_DATA_IO_CHAR_UUID; // Configure the characteristic value's metadata memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 0; // Configure the characteristic value memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = sizeof(uint8_t); attr_char_value.init_offs = 0; attr_char_value.max_len = sizeof(uint8_t); attr_char_value.p_value = NULL; return sd_ble_gatts_characteristic_add(p_midi_service->service_handle, &char_md, &attr_char_value, &p_midi_service->data_io_char_handles); } ``` Next, we will write the service initializer function: **ble\_midi\_service\_init().** ```c uint32_t ble_midi_service_init(ble_midi_service_t * p_midi_service, const ble_midi_service_init_t * p_midi_service_init) { uint32_t err_code; ble_uuid_t ble_uuid; // Initialize service structure p_midi_service->conn_handle = BLE_CONN_HANDLE_INVALID; p_midi_service->evt_handler = p_midi_service_init->evt_handler; // Add service ble_uuid128_t base_uuid = {BLE_UUID_MIDI_SERVICE_BASE_UUID}; err_code = sd_ble_uuid_vs_add(&base_uuid, &p_midi_service->uuid_type); if (err_code != NRF_SUCCESS) { return err_code; } ble_uuid.type = p_midi_service->uuid_type; ble_uuid.uuid = BLE_UUID_MIDI_SERVICE_UUID; err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_midi_service->service_handle); if (err_code != NRF_SUCCESS) { return err_code; } err_code = data_io_char_add(p_midi_service, p_midi_service_init); if (err_code != NRF_SUCCESS) { return err_code; } return NRF_SUCCESS; } ``` The last function we want to implement is one to handle updating the data I/O sending notifications to the client whenever the data I/O characteristic value is updated. ```c uint32_t ble_midi_data_io_value_update(ble_midi_service_t * p_midi_service, uint8_t data_io_value) { if (p_midi_service == NULL) { return NRF_ERROR_NULL; } uint32_t err_code = NRF_SUCCESS; ble_gatts_value_t gatts_value; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = sizeof(uint8_t); gatts_value.offset = 0; gatts_value.p_value = &data_io_value; // Update database. err_code = sd_ble_gatts_value_set(p_midi_service->conn_handle, p_midi_service->data_io_char_handles.value_handle, &gatts_value); if (err_code != NRF_SUCCESS) { return err_code; } // Send value if connected and notifying. if ((p_midi_service->conn_handle != BLE_CONN_HANDLE_INVALID)) { ble_gatts_hvx_params_t hvx_params; memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = p_midi_service->data_io_char_handles.value_handle; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; hvx_params.offset = gatts_value.offset; hvx_params.p_len = &gatts_value.len; hvx_params.p_data = gatts_value.p_value; err_code = sd_ble_gatts_hvx(p_midi_service->conn_handle, &hvx_params); NRF_LOG_INFO("sd_ble_gatts_hvx result: %x. \r\n", err_code); } else { err_code = NRF_ERROR_INVALID_STATE; NRF_LOG_INFO("sd_ble_gatts_hvx result: NRF_ERROR_INVALID_STATE. \r\n"); } return err_code; } ``` #### main.c So far, we've written the code to implement the MIDI service (both header (.h) and source (.c) files), but we haven't modified the main application to initialize the service. We also need to make some other modifications to the main.c. Let's go through each of them. We first need to #include the header file for the MIDI service. ```c #include "midi_service.h" ``` Next, we want to modify the advertised Device Name to indicate this is the MIDI example. ```c #define DEVICE_NAME "Nordic_MIDI" /**< Name of device. Will be included in the advertising data. */ ``` We instantiate the MIDI Service via the macro we defined in **midi\_service.h** (highlighted line below): ```c BLE_MIDI_DEF(m_midi_service); ``` We can **delete** the following block of code: ```c /**@brief Function for handling the YYY Service events. * YOUR_JOB implement a service handler function depending on the event the service you are using can generate * * @details This function will be called for all YY Service events which are passed to * the application. * * @param[in] p_yy_service YY Service structure. * @param[in] p_evt Event received from the YY Service. static void on_yys_evt(ble_yy_service_t p_yy_service, ble_yy_service_evt_t p_evt) { switch (p_evt->evt_type) { case BLE_YY_NAME_EVT_WRITE: APPL_LOG("[APPL]: charact written with value %s. ", p_evt->params.char_xx.value.p_str); break; default: // No implementation needed. break; } } */ ``` Instead, we replace it with a function to handle MIDI events in our main application: ```c static void midi_evt_handler(ble_midi_service_t * p_midi_service, ble_midi_evt_t * p_evt) { // Action to perform when the Data I/O characteristic notifications are enabled // Add your implementation here if (p_evt->evt_type == BLE_DATA_IO_EVT_NOTIFICATION_ENABLED) { // Possibly save to a global variable to know that notifications are ENABLED NRF_LOG_INFO("Notifications ENABLED on Data I/O Characteristic"); } else if (p_evt->evt_type == BLE_DATA_IO_EVT_NOTIFICATION_DISABLED) { // Possibly save to a global variable to know that notifications are DISABLED NRF_LOG_INFO("Notifications DISABLED on Data I/O Characteristic"); } // Handle any other events necessary... } ``` Next, let's modify the **services\_init()** function to initialize the MIDI service: ```c /**@brief Function for initializing services that will be used by the application. */ static void services_init(void) { ret_code_t err_code; ble_midi_service_init_t midi_init; nrf_ble_qwr_init_t qwr_init = {0}; // Initialize Queued Write Module. qwr_init.error_handler = nrf_qwr_error_handler; err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); APP_ERROR_CHECK(err_code); // Initialize the MIDI service memset(&midi_init, 0, sizeof(midi_init)); midi_init.evt_handler = midi_evt_handler; err_code = ble_midi_service_init(&m_midi_service, &midi_init); NRF_LOG_INFO("Done with services_init()\r\n"); APP_ERROR_CHECK(err_code); } ``` The final change to **main.c** is to change the debug output for the name of the example (in the **main()** function): ```c NRF_LOG_INFO("MIDI example started."); ``` ### Step 4: Build and flash the updated project Now that we've made all the source code changes necessary, it's time to build the project and flash it to the development board. Compile and flash the updated project. Refer to the previous [*The complete cross-platform nRF development tutorial*](https://novelbits.io/cross-platform-nrf-development-tutorial/) for step-by-step instructions on how to do this. Note 1: Sometimes you may want to clean and rebuild the project from scratch to make sure you don't have any stale code. You can do so by **right-clicking** the Project and then selecting the **Clean** option. Note 2: If you run into issues and your application does not run. you may want to perform an **Erase All** to the development board. You can do this by navigating to **Target --> Connect J-Link**. ![Connect J-Link](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-11-at-3-56-36-pm.png) Figure 16: Connect J-Link option Once it's connected, click on **Target --> Erase All.** ![Erase All](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2018-11-11-at-3-56-45-pm.png) Figure 17: Erase All option Now, flash the project to the board. ## Testing ### Steps 5 & 6: Run the nRF Connect or LightBlue app on your smartphone and start a Scan: ![nRF Connect Scanning](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_8178.png) Locate and connect to the device named **Nordic\_MIDI**, and verify that the Services listed match the following: ![MIDI Service](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_8179.png) Click on the **Unknown Service** (which matches the MIDI Service), and verify that the Characteristic matches the following. Also, notice the properties for the characteristic and that they match what we defined in the nRF application: **read**, **write without response**, and **notify**. ![MIDI Data I/O Characteristic](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_8180.png) That’s it! You have just implemented a custom BLE device with a custom GATT that matches the MIDI spec! ## Summary & Conclusion In this tutorial we covered the following: - Attribute Protocol (ATT) and the Generic Attribute Profile (GATT). - Profiles, Services, and Characteristics. - How to Design your custom GATT (step-by-step). - Implementation of a custom GATT using a real-life example of a MIDI device (*including full source code*). - Testing and verification using the nRF Connect mobile application. I hope you’ve enjoyed this tutorial and found it helpful. Continue Learning [ **The Complete Guide to Bluetooth LE** Fundamentals, architecture, and protocol stack ](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) [ **How BLE Advertisements Work** Channels, PDU types, and advertising data ](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/) [ **Generating a UUID for Custom Services** Step-by-step UUID creation guide ](https://novelbits.io/bluetooth-5-uuid-for-custom-service/) [ **nRF52840 Wireshark Sniffer Guide** Capture and analyze BLE packets ](https://novelbits.io/nordic-ble-sniffer-guide-using-nrf52840-wireshark/) ## Frequently Asked Questions What is a Bluetooth UUID? A UUID (Universally Unique Identifier) is a 128-bit number that uniquely identifies services, characteristics, and descriptors. The Bluetooth SIG defines 16-bit short UUIDs for adopted services (like 0x180D for Heart Rate). For custom implementations, use full 128-bit UUIDs to avoid collisions. What is the difference between a service and a characteristic? A service groups related characteristics that represent a device feature (e.g., Heart Rate Service). A characteristic holds the actual data value within that service (e.g., heart rate measurement). Services organize; characteristics expose data. How do I create a custom GATT service? Define your data elements and group them logically. Assign unique 128-bit UUIDs (avoiding the SIG base UUID range). Set characteristic properties (read, write, notify). Then implement using your SDK — this tutorial walks through the full process with Nordic's nRF5 SDK. What is the difference between notifications and indications? Both are server-initiated updates. Notifications are unacknowledged (faster, no confirmation required). Indications are acknowledged (the client confirms receipt, adding latency but ensuring delivery). Notifications are more common for high-frequency sensor data. Can a device be both a GATT server and client? Yes. A single Bluetooth LE device can act as both simultaneously. For example, a fitness tracker can serve heart rate data to a phone while reading the phone's time service. GATT roles are independent of GAP central/peripheral roles. ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE GATT, custom services, and real-world implementations? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Master BLE Sniffing: nRF52840 USB Dongle & Wireshark Guide URL: https://novelbits.io/nordic-ble-sniffer-guide-using-nrf52840-wireshark/ Last updated: 2026-08-19T17:39:53.000Z *Disclosure: Novel Bits is a US distributor of the BleuIO dongles featured in this post.* In a [previous article](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/), we covered the basics of Bluetooth sniffers (aka Bluetooth protocol analyzer), how they work, and even a comparison of the different BLE sniffers available on the market. If you haven't read that article, I recommend reading it before continuing with this post. The list of Bluetooth LE sniffers varied from those costing under $50 to others costing tens of thousands of dollars $$$! One noteworthy BLE sniffer from that list is the Nordic Semiconductor nRF52840 USB Dongle (in combination with the nRF Sniffer and Wireshark). This combination is probably the most versatile and cost-efficient solution available today for sniffing BLE! Here are some unique advantages of this solution: - It only costs $10! - It is physically small and portable. - It plugs directly into the USB port on your computer, so there is no need for cables. - It integrates with Wireshark, an open-source, free software tool with many powerful features. ## Why Use a Bluetooth Sniffer? By becoming proficient at BLE sniffing techniques, you can troubleshoot bugs more efficiently and optimize performance by adjusting the settings of your Bluetooth Low Energy product accordingly. As a Bluetooth developer, this unique skill gives you "magical powers" to uncover the unknowns in many scenarios where things *just* aren't working as expected with your Bluetooth Low Energy devices. *Then you can blame your mobile developer or embedded developer for that pesky bug! (j/k!* 😊*)* ![Debugging a Bluetooth Low Energy device with Wireshark](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ee9d7dd4-1cc7-446d-905f-9d4ccb6f9113.png) Moreover, reading and interpreting raw packet data gives you greater insight into how BLE works – something that would take much longer by only reading the theory, specifications, and even developing applications! In this tutorial, we will focus on capturing and analyzing Bluetooth Low Energy advertising packets using the combination of the nRF52840 USB Dongle, nRF Sniffer software tool, and Wireshark. All BLE devices start in the advertising state, so this is the perfect place to start! *We will cover the topic of sniffing BLE connections in a follow-up tutorial.* ## Set Up Your Environment To use this BLE sniffer solution, you will need to make sure you have a few things in place. Let's go through each of them. ### Requirements and hardware setup - [Nordic Semiconductor nRF52840 USB Dongle](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle?ref=novelbits.io) **Note**: You can use any Nordic Semiconductor nRF52 series development kit as an alternative. However, I do not recommend the nRF51 series development kit or USB dongle as this does not support many of the latest Bluetooth features. - [Nordic nRF Sniffer software](https://www.nordicsemi.com/Products/Development-tools/nrf-sniffer-for-bluetooth-le?ref=novelbits.io) - [Nordic nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop/Download?ref=novelbits.io#infotabs) - [Wireshark](https://www.wireshark.org/?ref=novelbits.io) - [Python v3.6](https://www.python.org/downloads/?ref=novelbits.io) or later - [SEGGER J-Link Software](https://www.segger.com/downloads/jlink/?ref=novelbits.io#J-LinkSoftwareAndDocumentationPack) The solution works for all major operating systems: Windows, macOS, and Linux (make sure you check Wireshark prerequisites for version compatibility). ### Install and Configure the nRF Sniffer for Bluetooth LE Software We don't need to go through the details of the installation and setup since Nordic has a comprehensive guide for this. You can access this at Nordic's dedicated [Infocenter page](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fug%5Fsniffer%5Fble%2FUG%2Fsniffer%5Fble%2Fintro.html&ref=novelbits.io) or in the nRF Sniffer User Guide \[PDF; downloadable from the Infocenter page\]. In summary, the main steps involved are: 1. Download the nRF Sniffer software package 2. Download and install the nRF Connect for Desktop application 3. Download and install the SEGGER J-Link Software package 4. Flash the nRF52840 USB Dongle with the BLE sniffer firmware hex file via the Programmer app within the nRF Connect for desktop application 5. Download and install Wireshark 6. Copy the nRF Sniffer software to the appropriate Wireshark folder 7. \[*Optional*\] Copy the nRF Sniffer Wireshark Profile to the appropriate Wireshark folder Once you've completed all these steps, you're ready to sniff some BLE packets! ### Enable the nRF Sniffer Interface Toolbar Before we start getting into the technical details of sniffing advertising packets, I recommend enabling the nRF Sniffer Interface toolbar. You can do so from the following menu in Wireshark: ![Enabling the nRF Sniffer Interface Toolbar in Wireshark](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/1c204636-397e-4a1f-997b-edff91b99d51.png) Once you have it enabled, you will see it at the top of the window right below the generic Wireshark toolbar: ![nRF Sniffer Interface Toolbar](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/259c10bf-6865-44c1-802f-f6ee108d6380.png) The toolbar provides a few useful options: - Selecting the ***interface***, which can be helpful when you have multiple nRF52840 USB dongles attached. - Select a **specific** **device**, whether via the Bluetooth address or by using an IRK (which a bonded BLE device uses to resolve a previously bonded BLE device's random Bluetooth address). - Selecting a **key (type** and **value):** which applies during a connection (primarily keys related to pairing and bonding). This allows you to decrypt encrypted data being exchanged between two paired or bonded BLE devices. - Selecting the **RF channels** to hop on when searching for advertising packets. If you recall, advertising BLE devices broadcast packets on the three primary advertising channels (37, 38, and 39). The default mode for the nRF Sniffer is scanning all three of these channels, but you can modify that within the nRF Sniffer Interface Toolbar. ## Capture Advertising Packets using a Bluetooth Low Energy Sniffer To start sniffing BLE data, click the green Wireshark button, and you should start seeing some BLE traffic: ![Starting the Capture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/0ce9362f-ecf4-4bb3-a9e0-6a123a73e15c.png) ![Wireshark capturing BLE traffic](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/aa8c1708-cf1b-4f57-9e53-83df781225e7.png) To stop the capture, click the red Stop button. Typically, you'll find that Wireshark shows a lot of data from nearby BLE devices, and that's due to the fact that BLE devices have become very ubiquitous. This can be overwhelming and make your life very difficult when trying to find the device(s) you are most interested in! We'll share a few tips for cleaning this up when we get to the Display filters section later in the tutorial. > 💡**Note:** You'll also notice that the data keep scrolling off the screen, making it difficult to look at and analyze the data closely. This is because Wireshark, by default, enables the automatic scrolling option. To disable this option, click on the icon highlighted in the screenshot below: ![Disabling the Auto-Scroll option](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/7ea9e397-3aef-441c-a8a7-e23a4a079e04.png) Now you can scroll through the rows freely and click on any packet you're interested in without it scrolling off the screen. ## Identify BLE Devices In general, there are a few ways you can identify a BLE device that you're interested in: - By its Bluetooth Address (sometimes referred to as MAC address) - By the Manufacturer Specific Data Company ID - By the Device Name The most unique of these parameters is probably the Bluetooth address. In many cases, especially when involving smartphones, the Bluetooth Address is random and changes every 12-15 minutes, making it almost impossible to identify the device. > 💡**Tip:** Generally, we are interested in sensors, beacons, and devices that are not smartphones, in which case the Bluetooth Address is usually fixed. Even in such situations, a more robust method would be to combine two or more of these parameters to get a more accurate match. ## Tips to Make BLE Sniffing Easier ### Add Wireshark Display Columns One way to make finding BLE devices in the capture easier is by adding columns displaying the relevant fields in the packets. For example, if we were interested in seeing the Device Names, we could add the Device Name field as a column. The easiest way to do this is to look for aBLE device that has the device name field in its advertising packet, right-click on the specific field, then click "Apply as Column": ![Applying a Column](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/43eda486-f972-499e-939c-7e41989a70af.png) Now, we should be able to see the Device Name column in the packet capture view: ![Device Name column added to packet capture view](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/63a77ee7-2dd9-4129-ba4d-4e252c0ae7cb.png) You can already see that it's much easier to locate and identify devices with a Device Name once we have this column added! Other useful columns to add (including the packet section it's located in) are: - Manufacturer-Specific Data Company ID (Bluetooth LE Link Layer) - Tx Address Type (Bluetooth LE Link Layer) - Packet Time – start to end (nRF Sniffer for Bluetooth LE) ### Set Wireshark Coloring Rules One other way to make packets stand out is by setting Coloring Rules within Wireshark. A great example of a use case for this is to add the red color to packets that are corrupt and have a bad CRC (whether that's due to transmission error, a noisy environment, or the transmitter being far away from the sniffer). One way to do this is to find a packet with a bad CRC, expand the "nRF Sniffer for Bluetooth LE" section --> Flags --> right-click on the CRC status field --> choose "Colorize with Filter" --> choose the color: ![Colorizing Bad CRC packets](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/3d3c7409-fecf-41aa-b8a5-aa19d15b66e0.png) Once enabled, you can now easily locate the bad CRC packets in the capture view: ![Bad CRC packets colorized with red](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/30ffcd36-89b0-477b-acca-f4ea2c9f1443.png) ### Apply Wireshark Display Filters To filter out nonrelevant BLE devices, we can apply one or more "Wireshark Display Filters." These allow us to focus on the device(s) in question and those that contain the data we're looking for. The format of a Wireshark Display Filter looks like this: `[protocol layer].[filter] [operand] [value]` For example: - `nordic_ble.rssi >= value` - `btle.advertising_header.pdu_type == 0x0` (for showing only connectable advertising packets) - `btle.advertising_address == 06:05:04:03:02:01` There are two common ways to apply a Display Filter: 1\. Finding a packet broadcast by the device we're interested in, selecting the field of interest, right-clicking it, and then clicking "Apply as Filter --> Selected." ![Adding a Display Filter via the Right-Click Menu](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/8bc3b39c-3e09-4cf5-b81f-512b2c372bdd.png) 2\. Adding the filter into the **filter field**. For this method, you will have to know the exact format and filter syntax (Wireshark will also auto-complete and suggest based on the letters you type in the field). ![Adding a Display Filter via the Filters Field](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/acccefce-c6b5-4c77-875e-228d5a7dc7b1.png) > 💡**Note:** You can add multiple Display Filters and apply them. However, keep in mind that this is easier done via the Filters entry field since the right-click/UI method will override any applied Display Filters. Here are a few examples of very useful Display Filters that apply specifically to BLE advertising packets: - `btle.advertising_address == [Bluetooth Device Address]` - `btcommon.eir_ad.entry.device_name == ["DEVICE NAME VALUE”]` - `btle.advertising_header.pdu_type == 0x2` (Non-connectable advertising packets) - `btle.advertising_header.pdu_type == 0x0` (Connectable advertising packets) - `btcommon.eir_ad.entry.company_id == [COMPANY ID]` (filters for a specific Company ID within the Manufacturer-Specific Data field) - `nordic_ble.channel == [37, 38]` (filters for advertising packets sent on channels 37 and 38, excluding channel 39) - `nordic_ble.rssi >= [Minimum RSSI value]` (filters for devices that have an RSSI above a certain threshold) - `nordic_ble.crc.bad == 1` (filters for packets that have a bad CRC) - `nordic_ble.crcok == 1` (filters for packets that have a valid CRC) There are so many other Display Filters that we can only list so many! > 💡**Note:** Wireshark Display Filters are **not** to be confused with Wireshark Capture Filters. Capture Filters are set before beginning a capture and cannot be modified during the capture. In contrast, Display Filters filter out data from the view of the capture and can be removed/changed/added during the capture session. ### Setup Wireshark Profiles Wireshark Profiles are one of the most powerful features of Wireshark. This useful tool allows you to customize the user interface and save as many customizations as you'd like, so you can switch between them for different views and use cases. For example, the UI layout, the displayed columns, and even some UI buttons can be customized for a specific analysis use case, such as for analyzing BLE advertising packets. The Nordic nRF Sniffer software already comes with a Profile for you to use with the sniffer, but it focuses more on BLE connections instead of advertising packets, so it doesn't serve well for this purpose. I've gone ahead and saved you the trouble of customizing the UI with columns, buttons, and a layout that's perfect for analyzing BLE advertising packets. You can download the ZIP package containing the "BLE Advertising Wireshark Profile" at the bottom of the tutorial. Installing a Wireshark Profile is very simple. Here are the steps to do so: - Open Wireshark - In the bottom right-hand corner of the window, right-click on where it says "Profile: ..." and choose "Import" --> "from zip file" - Then navigate to the folder where the Profile Zip file is, select it, and click "Open." - The Profile should now be imported and selected in your window Here's a view of what the UI looks like when installing and selecting the "BLE Advertising Wireshark Profile": ![BLE Advertising Wireshark Profile (Custom)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/fcf66de1-ad32-4616-b3b6-2f7400cc0a57.png) You'll notice the following columns have been included: - Packet No. - Packet Transmit Time - Delta Time from Previous Packet - Source Address - Destination Address - RSSI - Advertising Type - Channel Index - Company ID (from Manufacturer Specific Data field) - Device Name You'll also notice a few custom buttons: - "**Has Device Name**": shows only packets that contain a Device Name - "**Apple Device or iBeacon**": shows only Apple device packets or those that contain iBeacon data - "**Eddystone Beacons":** shows only Eddystone packets - "**Has Manufacturer Specific Data**": shows only packets that have Manufacturer Specific Data present - "**Bad CRC**": shows packets with a bad/invalid CRC - "**Scan Requests/Responses**": shows only Scan Request and Scan Response packets Finally, you'll notice that packets with a bad/invalid CRC will be highlighted in **light red** to make it easier to notice them. So, go ahead and download the Profile using the form below, import it, and start using it today! ## Conclusion In this tutorial, we covered a lot! Learning how to sniff BLE packets is crucial to both understanding BLE and being able to debug communications issues with your BLE system. With this guide, you should be able to get started with learning how to sniff BLE packets and discover the various BLE devices in the environment around you. In future tutorials, we'll cover a lot more including: - Analyzing the timing of BLE advertising packets, such as the Advertising Interval - Advanced Filters, such as for parsing manufacturer-specific data - Reverse-engineering BLE devices and analyzing BLE connections ### When you cannot reproduce it The nRF Sniffer follows one device at a time, so you need to know which device to follow before you start. That is fine on the bench. It is harder when something fails in the field, intermittently, and the capture you need turns out to be the one you did not think to take. If that is where you are, I lend a professional sniffer that watches all channels at once, shipped within the United States, and help you work out what to capture next. [Book a scoping call →](https://calendly.com/novelbits/bluetooth-le-debugging-scoping-call?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=wireshark-guide) [See what a Debug Block includes, and what it costs →](https://novelbits.io/consulting/?utm%5Fsource=novelbits.io&utm%5Fmedium=web&utm%5Fcampaign=debug-block&utm%5Fcontent=wireshark-guide) ### Download the Custom Wireshark Profile Get the **BLE Advertising Wireshark Profile** with custom columns, display filter buttons, and CRC coloring rules. Email Address Send me the Wireshark Profile Check your email! We sent the download link to . No spam. Unsubscribe with one click. ## Resources - [Nordic nRF Sniffer Display Filters](https://www.wireshark.org/docs/dfref/n/nordic%5Fble.html?ref=novelbits.io) - [Bluetooth Low Energy Link Layer Display Filters](https://www.wireshark.org/docs/dfref/b/btle.html?ref=novelbits.io) - [Bluetooth Common Display Filters](https://www.wireshark.org/docs/dfref/b/btcommon.html?ref=novelbits.io) Quick Tip Need to generate test BLE advertising traffic while sniffing? The [BleuIO USB dongle](https://novelbits.io/bleuio/) can act as an advertiser you control via simple AT commands — perfect for generating known advertising packets to verify your Wireshark setup and filters are working correctly. [Learn More About BleuIO →](https://novelbits.io/bleuio/) ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) 📚 **Related guide:** New to Bluetooth LE sniffing? Start with our [Bluetooth LE Sniffer Comparison Guide](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) for an overview of the different sniffer options available. 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE sniffing, debugging, and beyond? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth HID Device Design: Step-by-Step Example Project URL: https://novelbits.io/bluetooth-hid-device-design-example-project/ Last updated: 2026-08-09T05:43:48.000Z In [Bluetooth HID: An Introduction to Human Interface Devices with BLE](https://novelbits.io/bluetooth-hid-devices-an-intro/), we tackled the theory behind the communications of HID Devices with Hosts and how specific standards can simplify the design of new products in this segment. But now, let’s put aside the abstract concepts and focus on the fun part of the development by designing a simple yet fully functioning HID device! 🖱️ ⌨️ Designing a Bluetooth LE HID device requires a combination of expertise, ranging from Product Design to Mechanical, Electronics, and Software Engineering. Let’s start with some basic principles of HID device design. ### Basic principles **Leverage vendor-specific usage table for proprietary messages** One of the great things about HID is that it won’t force the developers to create parallel channels for proprietary data targeting specific Host applications (e.g., a product companion app).You will be able instead to define one or more *Vendor specific* pipes in the Report Map, assigning an arbitrary size (e.g., 20 bytes), and decide at runtime how to fill that data. This means that a custom protocol can be framed within the HID framework and that it can naturally coexist with the rest of the communication meant to be used by any Host. Pretty cool, right? 🔥 **Beware of the resolution assigned to any input fields** The Report Map characteristic defines the range of accepted values precisely for each input. If you assign 8 bits to the description of an axis movement, packing an out-of-range value will lead to inconsistent results!Remember: always sanitize your inputs before using raw data to update a characteristic 🧼 **Make the best use of the information received from the Host** If the Host is correctly using the HID Control Point characteristic, as simple as it may seem, the Device can easily optimize its operations. For instance, it could tune its internal power mode accordingly (saving precious battery 🔋). The same applies to any other data flowing in the Host → Device direction. **Beware of latency and benchmark your target** During active communication, latency, which is the amount of time elapsed from the physical signal to its desired effect (e.g., click on an icon), is affected by many factors. One parameter to remember here is the **connection interval**: the Profile spec states that, after encryption and bonding with the Host, the Device can request the intervals (min and max) that “best suit its use case.”Thus, if you need your Device to be as reactive as possible, always remember to update the min interval to 7.5 ms 🚀 ## Designing a basic input device: HW & SW Requirements Now that we’ve covered some basic principles, we can begin our project! The first requirement, as for any embedded project, is getting the right **Hardware** equipment 🧑‍🔧. I will be using the Nordic nRF52840 DK to develop the application for the example, but any equivalent Nordic kit will do the job. The second need is the choice of the **Software development** environment 🧑‍💻. We could use the classic Nordic SoftDevice architecture (+ nRF5 SDK), but why not opt for the more generic and abstracted Zephyr-based Nordic Connect SDK? A major benefit of this choice is that the application code will be architecture / SoC independent by design so that it will be re-usable (with minimal changes) for other BLE-enabled boards, not necessarily based on the Nordic chips. Last but not least, the project goals are: building a **basic mouse 🖱️**, which can move the cursor across the Host screen (being it a Windows, macOS, or any other HID-ready host) in all four directions, click with two buttons (left and right) and scroll up & down. In case this is the first Nordic Connect SDK (or Zephyr) application you’re writing, we suggest you have a look at [Nordic's DevAcademy course on nRF Connect SDK Fundamentals](https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/?ref=novelbits.io) first so that it will be easier for you to follow and understand the code snippets described. 💡 Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## Registering the GATT Service Ready to jump into code? I really hope you are! The first thing to take care of is registering the GATT Service via the Zephyr Bluetooth API. The most memory-efficient way to achieve this is using Zephyr C macros that statically (at build time) allocate the memory needed to add the Service and its Characteristics & Descriptors into the GATT table. A more versatile way of registering a GATT Service in Zephyr is using a dynamic (runtime) registration by leveraging the dedicated API. ### Static definition & registration A first skeleton describing our service should look like this: ```c /* HID Service Definition */ BT_GATT_SERVICE_DEFINE(simplemouse_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS), … ); ``` At the moment, the Service definition (encapsulated into a hidden variable containing the *simplemouse\_svc* identifier) is just declaring a Primary Service with **HID Service UUID**. Without going into too much detail, implementing the macro BT\_GATT\_SERVICE\_DEFINE will reserve enough memory for the Service by binding the symbol to a specific memory region defined in the linker script, which is scanned at boot time by the Bluetooth subsystem libraries to populate the Attribute Table. We’ll add more entities inside the definition in the following section. ### Runtime registration There may be reasons for an application to dynamically change GATT Services implemented at runtime, for instance, when switching to a specific operational mode. This functionality for Zephyr needs to be explicitly enabled via KConfig: ```kconfig # KConfig … BT_GATT_DYNAMIC_DB=y … ``` In this case, it will be possible at any time to register or unregister the Service: ```c // main.c /* Register the service */ bt_gatt_service_register(&simplemouse_runtime_svc); ... /* system running */ ... /* Unregister the service */ bt_gatt_service_unregister(&simplemouse_runtime_svc); ``` Keep in mind that in this case, possible memory benefits of unregistering a service at runtime are achievable only when using dynamic allocations, which increases the complexity of the application and can be a source of a lot of headaches in the long run. ## Mouse HID Service: Characteristics and configuration Given that we are more interested in the Bluetooth aspect of the project, let’s aim for simplicity and proceed with the static Service definition. This is the list of the Characteristics we’ll need to implement: - *HID Information, HID Control Point,* and *Report Map* as they’re mandatory for any HID Service implementation - *Protocol Mode* and *Boot Mouse Input Report*, as we want to develop a legit HID mouse - 1 x *Input Report* that will be used as a main streaming channel for Device → Host communication We can now, quite literally, “fill the dots” in the code and add the blueprint for the Characteristics needed in the Service: ```c /* HID Service Definition */ BT_GATT_SERVICE_DEFINE(simplemouse_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS), /* Information Characteristic */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, s_read_info, NULL, NULL), /* Control Point Characteristic */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, s_write_ctrl_point, NULL), /* Report Map Characteristic */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, s_read_report_map, NULL, NULL), /* Protocol Mode Characteristic */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, s_read_prot_mode, s_write_prot_mode, NULL), /* Boot Mouse Input Report Characteristic */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_BOOT_MOUSE_IN_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, s_read_report, NULL, (hids_report_info_t *)&mse_boot_input_rep_info), BT_GATT_CCC(s_mse_boot_input_rep_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), /* Mouse Input Report Characteristic (+ descriptor) */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, s_read_report, NULL, (hids_report_info_t *)&mse_input_rep_info), BT_GATT_CCC(s_mse_input_rep_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), BT_GATT_DESCRIPTOR( BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ, s_read_report_desc, NULL, (hids_report_desc_t *)&mse_input_desc), ); ``` Let’s try to dissect the highlights of the code: - For each Characteristic added to the Service we are describing, in order: - Its UUID - Its Properties; expressed as bitflags - Its Permissions; expressed as bitflags - A Read operation callback, if supported by its Properties - A Write operation callback, if supported by its Properties - An optional pointer to user data passed to the operations callbacks - Properties and Permissions of each added Characteristic take into account the functional and security requirements for the HID Profile we highlighted in [Part 1 of this article](https://novelbits.io/bluetooth-hid-devices-an-intro) - Input Reports (Boot and Custom) also include a special descriptor that lets the Client control the Notifications generation (CCCD) - The Mouse Input Report also includes an additional Descriptor helpful to recognize the ID of the HID report and its type (Input, Output, or Feature), as dictated by the HID Service specification (*Report Reference*) ## The *Simplemouse* application: runtime operations ### Connection establishment Even before designing the interactions between the Device and the Host when connected, we’ll need to make sure the BLE Advertising is appropriately configured for any interested Host to detect our mouse when in range. All the details about suggestions and mandatory requirements regarding before & after connection establishment are described in the [HID-over-GATT Profile specification](https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/?ref=novelbits.io). In practice, these are the parameters we are going to use: | **Parameter** | **Value** | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Advertising Data** | **Appearance as a mouse** **Connection flags as Limited DiscoverableList of UUID16 services implemented containing HIDS, BAS, and DIS** | | **Scan Response Data** | **Complete name of the Device** | | **Advertising Interval** | **30 ms to 50 ms** | | **Advertising type (when not bonded)** | **Regular advertising** | | **Advertising type (when bonded)** | **Directed advertising until first timeout, regular advertising afterward** | | **Advertising Timeout** | **180 secs** | | **Connection Parameters** | **For the first 5 seconds after connection, the Device will accept any set of parameters from the Host.** **Afterward**, it will request once to change to its preferred connection parameters: Minimum interval: 7.5 ms, Maximum interval: 22.5 ms, **Peripheral Latency: 10, and Connection Supervision Timeout: 2 secs** | And the code to set them is below (in the `prj.conf` file): ```kconfig # KConfig ... CONFIG_BT_PERIPHERAL=y CONFIG_BT_LIM_ADV_TIMEOUT=180 CONFIG_BT_SMP=y CONFIG_BT_DEVICE_NAME="Simplemouse" # Mouse appearance = 0x352 # (see https://www.bluetooth.com/specifications/assigned-numbers/) CONFIG_BT_DEVICE_APPEARANCE=962 CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6 # 7.5ms CONFIG_BT_PERIPHERAL_PREF_MAX_INT=18 # 22.5ms CONFIG_BT_PERIPHERAL_PREF_LATENCY=10 # 10 cycles CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=200 # 2 secs CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=y ... ``` ```c // main.c #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) #define BT_ADV_INT_MIN 48 /* 0.625ms units --> 30ms */ #define BT_ADV_INT_MAX 80 /* 0.625ms units --> 50ms */ ... /* Advertising Data */ static const struct bt_data ad[] = { /* Appearance */ BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, (CONFIG_BT_DEVICE_APPEARANCE >> 0) & 0xff, (CONFIG_BT_DEVICE_APPEARANCE >> 8) & 0xff), /* Flags */ BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_LIMITED | BT_LE_AD_NO_BREDR)), /* List of UUID16 Services Implemented */ BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_HIDS_VAL), BT_UUID_16_ENCODE(BT_UUID_BAS_VAL), BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)), }; /* Scan Response Data */ static const struct bt_data sd[] = { BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), }; ... int err; struct bt_le_adv_param adv_param; /* Directed advertising if bonding is present and we did not already timed out */ if ((bonded_addr_present) && (!dir_adv_timeout)) { char addr_buf[BT_ADDR_LE_STR_LEN]; adv_param = *BT_LE_ADV_CONN_DIR(&bonded_addr); adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0); if (err) { printk("Directed advertising failed to start\n"); return; } bt_addr_le_to_str(&bonded_addr, addr_buf, BT_ADDR_LE_STR_LEN); printk("Direct advertising to %s started\n", addr_buf); } /* Regular advertising if no bonding is present */ else { adv_param = *BT_LE_ADV_CONN; adv_param.interval_min = BT_ADV_INT_MIN; adv_param.interval_max = BT_ADV_INT_MAX; adv_param.options |= BT_LE_ADV_OPT_ONE_TIME | BT_LE_ADV_OPT_SCANNABLE; err = bt_le_adv_start(&adv_param, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; } printk("Regular advertising started\n"); } ``` Note: for this implementation, we respected all the mandatory requirements and some of the suggested ones; we’ll leave it as an exercise for the reader to find out which other guidelines we may have followed 😄. 💡 **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Input mode selection Provided that, naturally, any general-purpose development kit won’t let us design a real-mouse experience for the user once connected to a Host, we’ll have to find a workaround to test different kinds of inputs with the limited HW capabilities available. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/nrf52840-dk-layout.jpg) **nRF52840 DK Layout (Source: Zephyr Project Documentation)* This is the basic idea behind the system behavior: - **Buttons 1** **& 2** will represent our action inputs, which will result in different reports produced depending on the active *Input Mode*. - **Buttons 3** **& 4** will be just used as *Input Mode* selectors, letting the user scroll a circular list of implemented modes in order to test different kinds of inputs with the action buttons. In other words, pressing on these buttons won’t generate any HID report. See below the list of *Input Modes* we are going to implement: 1. Click (Left & Right) 2. X-Axis Movement (Left & Right) 3. Y-Axis Movement (Up & Down) 4. Vertical Scrolling (Up & Down) The respective onboard LED (1…4) will be set accordingly to the active *Input Mode*. ### Notifications to the Client Upon connection, our Device will just wait for user inputs on the action buttons by periodically monitoring their states: ```c if (INPUT_MODE_CLICK == curr_input_mode) { /* Proceed notifying the new button state only if one of the 2 action buttons did change */ if ((has_changed & KEY_LEFT_UP_MASK) || (has_changed & KEY_RIGHT_DOWN_MASK)) { send_mouse_notification( button_state & (KEY_LEFT_UP_MASK | KEY_RIGHT_DOWN_MASK), 0, 0, 0); } } else if (INPUT_MODE_MOVEX == curr_input_mode) { if (button_state & KEY_LEFT_UP_MASK) { send_mouse_notification(0, -(MOVE_STEP_SIZE), 0, 0); } else if (button_state & KEY_RIGHT_DOWN_MASK) { send_mouse_notification(0, MOVE_STEP_SIZE, 0, 0); } } // Other input modes handled here... ``` The utility *send\_mouse\_notification()* will simply transform the parameters into a data blob to be sent over-the-air, using the *Simplemouse* HID Service public API: ```c static void send_mouse_notification(uint8_t buttons_bitmask, int16_t move_x, int16_t move_y, int8_t scroll_v) { simplemouse_hids_prot_mode_t currProtMode = simplemouse_hids_get_prot_mode(); if (simplemouse_hids_is_mouse_report_writable()) { if (SIMPLEMOUSE_HIDS_PM_REPORT == currProtMode) { simplemouse_hids_report_mouse_t mse_report = { .buttons_bitmask = buttons_bitmask, .move_x_lsb = (uint8_t)move_x, .move_x_msb = (uint8_t)(move_x >> 8) & 0xFF, .move_y_lsb = (uint8_t)move_y, .move_y_msb = (uint8_t)(move_y >> 8) & 0xFF, .scroll_v = scroll_v }; simplemouse_hids_mouse_notify_input( &mse_report, sizeof(simplemouse_hids_report_mouse_t)); } else if (SIMPLEMOUSE_HIDS_PM_BOOT == currProtMode) { simplemouse_hids_report_mouse_boot_t mse_boot_report = { .buttons_bitmask = buttons_bitmask, .move_x = move_x, // implicit cast to 8 bits .move_y = move_y, // implicit cast to 8 bits .scroll_v = scroll_v }; simplemouse_hids_mouse_notify_boot( &mse_boot_report, sizeof(simplemouse_hids_report_mouse_boot_t)); } } } ``` Aside from the Mouse Boot Report, which is by definition a 4-byte packet, the other Input Report defined in our Service shall follow a format dictated by the Report Map: ```c // simplemouse_hids.c /* Report map */ static const uint8_t report_map[] = { /* MOUSE INPUT REPORT MAP */ 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x85, HIDS_REPORT_ID_MOUSE, // Report ID (1) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x95, 0x02, // Report Count (2) 0x75, 0x01, // Report Size (1) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x02, // Usage Maximum (0x02) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap...) 0x95, 0x01, // Report Count (1) 0x75, 0x06, // Report Size (6) 0x81, 0x03, // Input (Cnst, Var, Abs) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x16, 0x00, 0x80, // Logical Minimum (-32768) 0x26, 0xFF, 0x7F, // Logical Maximum (32767) 0x75, 0x10, // Report Size (16) 0x95, 0x02, // Report Count (2) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x81, 0x06, // Input (Data,Var,Rel,No Wrap...) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x09, 0x38, // Usage (Wheel) 0x81, 0x06, // Input (Data,Var,Rel,No Wrap...) 0xC0, // End Collection 0xC0, // End Collection }; // simplemouse_hids_def.h /* Mouse Input Report format is defined according to * the Report Map characteristic: * 8 bits - pressed buttons bitmask (2 LSB used + 6 MSB padding) * 16 bits - x movement * 16 bits - y movement * 8 bits - vertical wheel rotation (device specific) */ typedef struct { uint8_t buttons_bitmask; uint8_t move_x_lsb; uint8_t move_x_msb; uint8_t move_y_lsb; uint8_t move_y_msb; uint8_t scroll_v; } __packed simplemouse_hids_report_mouse_t; ``` ### Write operations on Characteristics handling As we already know, the communication between the Device and the Host is **not** unidirectional: some of the Characteristics are meant to be used as a communication channel in the direction Host → Device. For instance, setting the Protocol Mode is a typical operation that the Host may need to perform. If we zoom in on the Service definition described earlier, we find that we registered a callback to handle this kind of operation: ```c … /* Protocol Mode Characteristic */ BT_GATT_CHARACTERISTIC( BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, s_read_prot_mode, s_write_prot_mode, NULL), … ``` As such, we’ll need to write a robust implementation for *s\_write\_prot\_mode()*: ```c static ssize_t s_write_prot_mode( struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { uint8_t *const prot_mode_ref = (uint8_t *const)&prot_mode; const simplemouse_hids_prot_mode_t newPm = *((const simplemouse_hids_prot_mode_t *)buf); /* Validate flags */ if (!(flags & BT_GATT_WRITE_FLAG_CMD)) { /* Only write without response accepted */ return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } /* Validate length */ if ((offset + len) > sizeof(prot_mode)) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); } /* Validate value received */ if (newPm >= SIMPLEMOUSE_HIDS_PM_N) { return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED); } memcpy(prot_mode_ref + offset, buf, len); return len; } ``` This way, the internal representation of the Protocol Mode is updated (*prot\_mode* variable) in the module implementing the Service, and each new call to *simplemouse\_hids\_get\_prot\_mode()* will return its most updated value. ## A real-life demo ### Development Tips & Tricks The *Simplemouse* application has been developed using the following facilities: - **Visual Studio Code** as the main editor / IDE - **nRF Connect for VS Code Extension Pack** installed locally on the Windows Host - **Nordic Connect SDK 2.0.0** is installed on the Host. Actually, it is fair to say that the *peripheral\_hids\_mouse* sample represented the starting point for our application 😉 The [extensions provided by Nordic](https://marketplace.visualstudio.com/items?itemName=nordic-semiconductor.nrf-connect-extension-pack&ref=novelbits.io) significantly reduce the time spent to get the ball rolling, especially when it comes to writing & browsing the code with Intellisense enabled, inspecting KConfig options, building with different configurations, flashing the binaries on target, and, most of all, debugging! ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/simplemouse-debug.png) **A snapshot of a Simplemouse debugging session* ### *Simplemouse* in action You’ll soon find out that it’s not that hard to test a common HID Device such as a mouse: it’s very likely that any general-purpose computer in your proximity already comes with the needed drivers! In our case, the tests have been carried out on connecting the Nordic DK with a Windows 10 Host. And here we have a full sequence, demonstrating the four different Input Modes available in action just after the connection and pairing are established with the Host: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/simplemouse-demo.gif) ### Further improvements to the application Last but least, here for you some starting points for reflections that may help you design a better version of our Simplemouse or your own BLE product based on Zephyr: - **Notifications Control Flow** Our code is just blindly sending out notifications when new data is ready. However, most HID devices will need to be careful and implement a control flow based on the following: - the size of the internal buffer used by the BT stack to queue notifications and - events confirming that notifications already queued have been sent. - **Synchronization between application and Radio activities** As we know, all BLE communications are based on periodicconnection events that define when the Client and Server are going to send & receive packets. When fine-tuning your application, you will often find out that synchronizing the application activities (sensor sampling, ADC acquisition, algorithms, etc.) with these Radio events is very beneficial from a power consumption and code architecture simplification standpoint. - **(Basic) threads IPC** Zephyr BT Subsystem works by spawning some threads for runtime operations. This means that operations executed inside callbacks are running in the context of one of these computational units. Any data shared between the application threads and BT threads is in danger of becoming a victim of race conditions: beware of these risks when designing the execution flow of your software! - **Event-Driven architecture** Our application monitors the button states using a control-loop approach, that is, by periodically reading their GPIOs. In order to make your device more power efficient, we suggest an event-driven approach, where IRQs can help detect events from the buttons. However, the application can still track time, if needed, by launching dedicated timers. Of course, this will make the execution flow less obvious, but it is the price to pay to increase the CPU idle time, saving battery power. - **BLE connection parameters fine-tuning** The connection parameters used for this application are typical for a general-purpose mouse, but be aware that your HID device may be very different: not every time minimizing latency is important! We suggest that, rather than using default parameters, you reflect on the use cases of your applications and understand if it’s better to prioritize responsiveness or power saving. No one can tell you what’s best unless it is the Marketing Team at your organization speaking with you 📈 ## Conclusion & Resources Thanks for following along with this tutorial! We hope you found it helpful as you dive deeper into Bluetooth HID technology. And if you’re looking for more support, take a look at these resources: - **Comprehensive Resources** \- [The Bluetooth Developer Academy](https://novelbits.io/academy/?utm%5Fsource=blog&utm%5Fmedium=website&utm%5Fcampaign=bluetooth+low+energy+ble+a+complete+guide) - **Blog Article** \- [Bluetooth HID: An Introduction to Human Interface Devices with BLE](https://novelbits.io/bluetooth-hid-devices-an-intro/) - **Official Spec** \- [USB HID](https://www.usb.org/hid?ref=novelbits.io) - **Official Spec** \- [BLE HID-over-GATT Profile](https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/?ref=novelbits.io) - **Official Spec** \- [BLE HID Service](https://www.bluetooth.com/specifications/specs/hid-service-1-0/?ref=novelbits.io) 💡 **Want to get your Bluetooth-connected devices to market faster?** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. --- **About the Author:** *Davide Pollarolo is an Embedded Software Engineer with extensive experience in designing & developing smart devices using Bluetooth Low Energy. He has an MSc in Computer Engineering and has worked in various domains, including robotics, sport & medical wearables, and computer peripherals. Davide is fascinated by Human-Computer Interaction and loves spending his free time exploring new technologies.* Free Download HID Simple Mouse — Complete Source Code Get the full Zephyr RTOS project for the nRF52840 DK, ready to build and flash. Send Me the Code Check your email! We sent the download link to . No spam. Unsubscribe with one click. 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth LE SoC Vendor Comparison Guide URL: https://novelbits.io/ble-soc-vendor-comparison-guide/ Last updated: 2026-08-09T05:23:30.000Z Choosing a BLE SoC is not easy. These days there are a lot of great options on the market, but what I always emphasize to new [BLE](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) developers is: the chipset you choose will very likely dictate the SDK you work with. *And SDKs are not designed equally.* Some SDKs are quite simple to get started with. Others are more complicated. Some SDKs are flexible and allow you to use a variety of toolchains. Others lock you into their own software. You get the idea. In this article, we're going to take a look at nine BLE SoC vendors along with their SDKs and BLE SoCs that I would recommend for beginners. I recommend you use this guide as a jumping-off point to do some more in-depth research on the vendors and chipsets that you're most interested in! Other helpful resources: - [How to Choose a BLE Module](https://novelbits.io/how-to-choose-ble-module-for-your-project/) - [Chipset vs. Module Bluetooth LE Solutions: The Ultimate Guide](https://novelbits.io/chipset-vs-module-bluetooth-le-solutions-the-ultimate-guide/) - [17 Most Popular Bluetooth Low Energy Chipsets Compared](https://novelbits.io/17-most-popular-bluetooth-low-energy-chipsets-compared/) 💡 **Insider Tip:** Want to fast-track your Bluetooth LE development skills? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. Now, let’s start with some background on Bluetooth Low Energy development. ## Bluetooth Low Energy Basics Despite taking many cues from its predecessor, Bluetooth Classic, Bluetooth Low Energy is regarded as a different technology that specifically targets markets where the demand is for ultra-low power rather than high throughput. At its core, Bluetooth Low Energy is a protocol. And just like any other protocol, it acts as a rulebook that devices must adhere to in order to communicate or exchange information. This communication happens between a central device and a peripheral device. BLE communication between two devices will typically consist of: - Advertising by the Peripheral device - Scanning by the Central device - Initiating a connection by the Central device - Discovering a remote database (GATT database) on the Peripheral device - Reading and writing to a remote database (GATT database) To implement these connection steps, you’ll need some software (SDK) and some hardware (chipset and development kit). But, choosing the right tools when getting started can feel overwhelming. Before we get into specific vendors and products, let’s break down some must-know considerations for anyone getting started with BLE development. ## Getting Started with BLE Development When getting started with a new BLE project, or even just learning BLE development in general, it is important to lay out a plan with the necessary steps: - **If you’re starting with a specific BLE project**, you need to take into consideration the requirements for the application. These requirements will help you determine which chipset and development kit are the most appropriate. - **If you’re just wanting to learn BLE development**, you have more flexibility in choosing a chipset and development kit. - Keep in mind that quite a few of the popular BLE features, such as long-range (Coded PHY), extended advertisements, 2M PHY, etc., are **optional per the Bluetooth specification**. This means you must study the chosen chipset's datasheet closely to ensure that the feature of interest is indeed supported by the chosen chipset. For example, the long-range (Coded PHY) mode was introduced in Bluetooth 5.0; however it is an optional feature of the spec, so not every claimed "5.0 certified Bluetooth chipset" actually supports it. - **Once a chipset and development kit are chosen**, the next step would be to learn more about the SDK provided by the chipset vendor, install it on your development machine, and start developing. - The vendor SDK documentation is usually the best place to start along with any provided example applications. - In addition to acquiring a development kit, it’s always a good idea to utilize one of the freely available **mobile BLE Client emulator apps,** such as Nordic’s nRF Connect (iOS, Android), LightBlue (iOS), or BLE Hero (iOS). These apps allow you to communicate, interact, and connect to your development kit when running a BLE Peripheral application. Note: **It’s really important that you consider SDKs, chipsets, and development kits *together* and not independently.** This is because the chipset you choose will dictate your options for SDKs and development kits and vice versa. There are many options on the market, and there’s no “one size fits all” for BLE developers or even beginners. Below we’re going to break down some important specs for top SDKs and SoCs so that you can make the best choice for your project. ## Popular BLE SoC Vendors First and foremost, what are the available SoC options for BLE development? You may have heard of Nordic or Silicon Labs, but there are actually quite a few other SoC vendors who have SDKs and development kits that can work well, depending on your specific needs. We’ll break each down further below, but let’s start with a simple list of the top SoC vendors that have Bluetooth Low Energy chipsets and SDKs available: - Nordic Semiconductor - Silicon Labs (SiLabs) - Texas Instruments (TI) - STMicroelectronics (ST) - Infineon Technologies - NXP Semiconductors - Telink - Renesas - Onsemi Now it’s time to dive a little deeper into each of these vendors’ SDK and SoCs! ## Nordic Semiconductor ### Nordic SDK: [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nrf-connect-sdk?ref=novelbits.io) The nRF Connect SDK is designed to help developers build low-power wireless applications with the nRF52, nRF53, and nRF91 series wireless devices. It is built on the Zephyr RTOS project and provides a modular approach to the SDK and stack. This SDK is not just a Nordic Bluetooth SDK; it integrates with Bluetooth Low Energy and [Bluetooth mesh](https://novelbits.io/bluetooth-mesh-networking-the-ultimate-guide/) protocol stacks along with other protocol stacks such as Thread/Zigbee. | IDE | [Microsoft Visual Studio Code](https://code.visualstudio.com/?ref=novelbits.io) using the [Nordic nRF Connect Extension Pack for VS Code](https://marketplace.visualstudio.com/items?itemName=nordic-semiconductor.nrf-connect-extension-pack&ref=novelbits.io) is recommended\- Includes interface to the compiler and linker\- Includes RTOS-aware debugger\- Provides interface to nRF Connect SDK\- Includes integrated serial terminal | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows, Linux, macOS | | Required Tools | \- Segger JLink\- nRF Util (replaces the archived nRF Command Line Tools; nrfjprog is deprecated) | | Key Features | \- Robust set of resources and videos available to help you get started\- Uses Zephyr RTOS as the foundation, which is 100% open source\- The SDK is hosted publicly on GitHub\- Technically IDE agnostic, although Visual Studio Code is recommended | | Tools Available | \- nRF Connect for Desktop suite\- nRF Sniffer\- nRF Util\- Power consumption measurement tool | ### Recommended Nordic SoC for beginners: [nRF52840](https://www.nordicsemi.com/products/nrf52840?ref=novelbits.io) The nRF52840 is the most advanced chip in the nRF52 series. It has 1 MB of flash memory and 256 KB of RAM. It also supports full-speed 12 Mbps USB, making it a versatile choice for a wide range of applications. ![Nordic nRF52840](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nordic-nrf52840.png) Plus, it’s fully multiprotocol, supporting Bluetooth LE, [Bluetooth mesh](https://novelbits.io/bluetooth-mesh-networking-the-ultimate-guide/), Thread, Zigbee, ANT+, NFC, and 802.15.4\. However, it does not support Bluetooth LE audio and Bluetooth direction-finding features. The nRF52840 has a core ARM-M4 processor that can do complex calculations quickly. This is useful for tasks like digital signal processing or math that require floating-point numbers. Ideal applications of the nRF52840 include: - Gaming controllers - Virtual/ Augmented reality applications - Advanced wearables - Smart city infrastructure - Matter connected home products ## Silicon Labs ### Silicon Labs SDK: [Silicon Labs Bluetooth SDK](https://www.silabs.com/developers/bluetooth-low-energy?ref=novelbits.io) Part of the Silicon Labs Simplicity SDK (SiSDK, which superseded the Gecko SDK for Series 2 and Series 3 parts), the Silicon Labs Bluetooth SDK provides example projects, peripheral drives, the [BLE protocol](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) stack, and the API. The SDK provides a single, hardware-agnostic software stack and API for Bluetooth Low Energy. | IDE | [Silicon Labs Simplicity Studio IDE](https://www.silabs.com/developers/simplicity-studio?ref=novelbits.io) is recommended\- Eclipse-based IDE\- Uses C/C++ Development Tooling (CDT)\- Includes compiler and debugger\- Supports Silicon Labs Secure Vault security software\- Provides access to a full set of tools such as Energy Profiler, Network Analyzer, and GATT Configurator | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows, Linux, macOS*Note: If using Linux or macOS, it is not advised to build with IAR outside of Simplicity Studio* | | Required Tools | \- GCC or IAR compilers\- Segger JLink | | Key Features | \- Simplicity Studio customizes your development environment for you based on your target hardware\- Uses C programming language\- Hardware agnostic | | Tools Available | \- Energy Profiler\- Network Analyzer\- Commander\- GATT Configurator\- Bluetooth Mesh Configurator\- Radio Configurator\- Bluetooth NCP Commander\- Direction Finding Toolsuite | ### Recommended Silicon Labs SoC for beginners - [BG24](https://www.silabs.com/wireless/bluetooth/efr32bg24-series-2-socs?ref=novelbits.io) The EFR32BG24 is a Bluetooth SoC equipped with an advanced 32-bit 78.0 MHz ARM Cortex®-M33 with DSP instruction and a floating-point unit for efficient signal processing. It supports fast communication and is suited for applications that require direction finding, mesh networking, and Bluetooth 5.3 compatibility. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-17.png) This SoC has up to 1.5 MB of flash and 256 KB of RAM, which is enough for complex applications. Target applications for this SoC can be: - Gateways and Hubs - Sensors and switches - Smart door locks - Smart plugs, LED lighting, luminaires - Blood glucose meters and pulse oximeters ## Texas Instruments (TI) ### TI SDK: [TI SimpleLink BLE SDK](https://www.ti.com/tool/SIMPLELINK-CC2640R2-SDK?ref=novelbits.io) The TI SimpleLink BLE SDK includes example applications and documentation designed to help developers who are working on single-mode BLE applications. It includes a protocol stack for developing with Bluetooth 5 (BLE5-Stack) as well as a protocol stack that is memory-optimized for Bluetooth 5.1 applications (BLE-Stack). Both provide support for embedded and network process configurations and work with previous Bluetooth specifications. | IDE | [TI Code Composer Studio™ (CCS) ](https://www.ti.com/tool/CCSTUDIO?ref=novelbits.io#:~:text=Code%20Composer%20Studio%20is%20an,%C2%AE%20and%20macOS%C2%AE%20desktops.)is recommended\- Includes C/C++ compiler\- Includes Resource Explorer with project examples and training\- SysConfig helps configure pins, peripherals, and other components\- EnergyTrace helps optimize for ultra-low-power consumption\- Allows for scripting and automation[IAR Embedded Workbench](https://www.iar.com/products/architectures/arm/iar-embedded-workbench-for-arm/?ref=novelbits.io) is also supported | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Operating Systems supported | Windows, Linux, macOS | | Required Tools | \- TI C Compiler for ARM\- XDCTools | | Key Features | \- Built on top of TI-RTOS framework\- Provides sample applications for all BLE device roles: Central, Peripheral, Broadcaster/Beacon, and Observer\- Code Composer Studio (CCS) provides quick access to training and other resources\- Voice-over-BLE support | | Tools Available | \- Integrated XDS110 USB debugger\- Real-Time Localization Systems (RTLS) toolbox supporting time-of-flight (ToF)\- SimpleLink angle of arrival (AoA) BoosterPack\- SimpleLink CC2640R2 SDK BLE Example Pack that contains additional sample applications such as a glucose sensor | ### Recommended Texas Instruments SoC for beginners - [CC2640R2F](https://www.ti.com/product/CC2640R2F?ref=novelbits.io) The TI SimpleLink CC2640R2F SoC is a Bluetooth Low Energy solution that has a 2.4 GHz RF transceiver, 128 kB programmable memory, and 20 kB of SRAM. It has an ARM Cortex M3 processor that handles the application layer and BLE protocol stack. ![TI CC2640R2F](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/ti-cc2640r2f.png) The CC2640R2F’s sensor block allows for autonomous data acquisition and control, which helps to keep power consumption low. Popular applications of this chipset include: - Fitness tracking - Healthcare monitoring - Smartwatches ## STMicroelectronics ### STMicroelectronics SDK: [STM32CubeWBA](https://www.st.com/en/embedded-software/bluest-sdk.html?ref=novelbits.io) STM32CubeWBA is ST’s embedded software package for the STM32WBA series, containing the HAL and Low-Layer APIs, CMSIS, a file system, an RTOS, and the Bluetooth LE, 802.15.4, Thread and Zigbee stacks, with examples that run on ST boards. (Note: BlueST-SDK, previously listed here, is a phone and gateway side library for Android, iOS and Python, not the embedded SDK.) It allows easy access to the data that is exported by a BLE device using the BlueST protocol. The BlueST protocol itself pre-defines various kinds of data that come from a wide variety of sensor types (environmental, battery, inertial, etc.) and allows the developer to extend support for user-defined data. | IDE | [STM32CubeIDE](https://www.st.com/en/development-tools/stm32cubeide.html?ref=novelbits.io) with STM32CubeMX\- Eclipse-based IDE\- Support for the BlueNRG-LPS, BlueNRG-LP, BlueNRG-1, BlueNRG-2 evaluation platforms\- Includes GCC C/C++ compiler\- Includes GDB-based debugger\- SWD channel support\- No code size limit | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows, Linux, macOS | | Required Tools | \- STM32CubeIDE + STM32CubeMX | | Key Features | \- Multi-platform library (Android/iOS/Python)\- Python release of the BlueST SDK uses bluepy Python library available on Linux to connect to BLE devices\- Sample application available to help you get started\- Includes serial console (stdout/stdin/stderr) over Bluetooth\- Supports data logging in csv | | Tools Available | \- STBLESensor - BLE sensor application for Android and iOS\- STBLEStarNet - BLE start network application for Android and iOS\- STM32Cube function packs for IoT node with BLE connectivity, environmental sensors, motion sensors, digital microphone, and time-of-flight (ToF) sensors | ### Recommended STMicroelectronics SoC for beginners - [BlueNRG-2N](https://www.st.com/en/wireless-connectivity/bluenrg-2n.html?ref=novelbits.io) The BlueNRG-2N is a Bluetooth LE SoC that meets the Bluetooth v5.2 specification. It has a 32-bit Arm Cortex-M0 core and 245 kB of Flash memory. OTA (Over the Air) firmware updates are possible due to the presence of Flash memory. ![ST BlueNRG-2N](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/st-bluenrg-2n.png) The BlueNRG-2N chipset also has 24 kB RAM. This RAM is volatile, which means it loses its contents when the power is turned off. However, the BlueNRG-2N’s RAM retention feature allows two 12 kB banks of RAM to keep their content even when power is turned off. Popular applications of this chipset include: - Smart Watches - Proximity tags - PC peripherals - Remote Controller ## NXP ### NXP SDK: [MCUXpresso SDK](https://mcuxpresso.nxp.com/?ref=novelbits.io) The MCUXpresso SDK includes production-grade software with integrated RTOS (optional), integrated enabling software technologies (stacks and middleware), and reference software. This open-source SDK can be customized based on the NXP development board you’re working with. | IDE | [MCUXpresso IDE](https://mcuxpresso.nxp.com/?ref=novelbits.io)\- Eclipse-based IDE\- Industry-standard GNU toolchain with a choice of libraries\- Integrated GUI Flash Programming Tool\- Integrated configuration tools, including pins, clocks, peripheral and execution tools | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows, Linux, macOS | | Required Tools | \- GNU toolchain for Arm® Cortex® -M with Cmake build system\- IAR Embedded Workbench\- Keil™ MDK-Arm | | Key Features | \- Integrated RTOS (optional)\- Integrated enabling software technologies (stacks and middleware)\- Provides example projects for IAR, KEIL, and GCC with Cmake\- Open-source peripheral drivers | | Tools Available | \- MCUXpresso Secure Provisioning Tool\- MCUXpresso Config Tools | ### Recommended NXP SoC for Beginners - [QN908x](https://www.nxp.com/products/wireless-connectivity/bluetooth-low-energy:BLUETOOTH-LOW-ENERGY-BLE?ref=novelbits.io) The QN908x SoC is a BLE chipset that includes a 32-bit Arm Cortex-M4F running at 32 MHz, 512KB of flash memory, 128 KB of SRAM, and 256 KB of ROM. ![NXP QN908x](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/nxp-qn908x.png) This SoC can be used in applications such as: - Retail Beacons - Human Interface Devices (HID) - Asset Tracking - Remote Controls ## Infineon ### Infineon SDK: [ModusToolbox Software](https://www.infineon.com/cms/en/design-support/tools/sdk/modustoolbox-software/?ref=novelbits.io) The Modus Toolbox Software is an extensible development environment that includes support for many Infineon microcontroller devices, including [AIROC Bluetooth devices](https://www.infineon.com/cms/en/product/wireless-connectivity/?ref=novelbits.io). It is designed to be flexible and allows developers to customize their environment based on the third-party tools they use as well as the applications they are working with. It includes a GNU build system, desktop IDE, and command line interface terminal. | IDE | [Eclipse IDE for Modus Toolbox](https://documentation.infineon.com/html/modustoolbox-software/en/latest/Modustoolbox/IDE%5FUser%5FGuides/Eclipse%5FIDE%5Ffor%5FModusToolbox%5FUser%5FGuide.html?ref=novelbits.io), included within the Modus Toolbox, is recommended\- Uses C/C++ Development Tooling (CDT)\- Uses standard Eclipse menus, toolbars, etc.\- Standard Eclipse Project Explorer, Code Editor, and Console included\- ModusToolbox Perspective provides a “Quick Panel” that adds tabs to the Project Explorer[Microsoft Visual Studio Code](https://code.visualstudio.com/?ref=novelbits.io), [IAR Embedded Workbench](https://www.iar.com/products/architectures/arm/iar-embedded-workbench-for-arm/?ref=novelbits.io), and [Arm µVision](https://developer.arm.com/Tools%20and%20Software/Keil%20MDK?ref=novelbits.io) are also supported | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows, Linux, macOS | | Required Tools | \- GNU, IAR or Arm compiler\- Segger J-Link, Infineon MiniProg4, IAR I-jet, or Arm ULINK debug adapter | | Key Features | \- Includes support for many applications and devices outside of Bluetooth\- Simple starter project examples are provided\- Both low-level peripheral drivers and hardware abstracted APIs are available | | Tools Available | \- Modus-Shell (Windows)\- Device Firmware Update (DFU) Host Tool\- Bluetooth Configurator\- Smart I/O Configurator\- CAPSENSE Configurator\- Library Manager\- Board Support Package (BSP) Assistant | ### Recommended Infineon SoC for Beginners - [AIROC CYW20835](https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-bluetooth-le-bluetooth-multiprotocol/airoc-bluetooth-le/cyw20835/?redirId=199065&ref=novelbits.io) The Infineon AIROC CYW20835 SOC is designed specifically for Bluetooth LE applications and is compliant with Bluetooth 5.2 It has a 96 MHz ARM Cortex M4 microcontroller, flash memory, 384 kB of RAM, and 2048 kB of ROM. ![Infineon AIROC CYW20835](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/infineon-cyw20835.png) This SoC can be used in applications such as: - Home automation - Medical sensors - Keyboards and joysticks - Lighting - Game controllers ## Telink ### Telink SDK: [Multiple Chip-Specific SDKs](http://wiki.telink-semi.cn/wiki/protocols/Bluetooth-LE/?ref=novelbits.io) Telink provides a series of SDKs that are designed to be used for specific applications. The most common two SDKs you may be interested in are the Bluetooth LE Single Connection SDK and Bluetooth LE Multi Connection SDK, but they also offer SDKs for Bluetooth Mesh, Telink Mesh, and Zigbee. | IDE | Telink IDE is recommended\- Built on top of the Eclipse IDE\- Two versions available: IDE for [TLSR8 series chips](http://wiki.telink-semi.cn/wiki/IDE-and-Tools/IDE-for-TLSR8-Chips/?ref=novelbits.io) and [IDE for TLSR9 series chips](http://wiki.telink-semi.cn/wiki/IDE-and-Tools/RISC-V%5FIDE%5Ffor%5FTLSR9%5FChips/?ref=novelbits.io) | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | \- Windows: TLSR8 and TLSR9 \- Linux: TLSR9 | | Required Tools | Telink RISC-V Linux Toolchain (compiler) - if using the TLSR9 series chips on Linux | | Key Features | SDK provides multiple BLE demos | | Tools Available | \- Telink Burning and Debugging Tool (BDT)\- Telink RF Scanner \- Telink Console \- Compiler - built into IDE unless you’re using TLSR9 series chip on Linux | ### Recommended Telink SoC for Beginners - [TLSR827x Series](http://wiki.telink-semi.cn/wiki/chip-series/TLSR827x-Series/?ref=novelbits.io) The Telink TLSR827x series is an ultra low power concurrent multi-protocol SoC built for IoT solutions. It supports Bluetooth LE 5.1, Bluetooth Mesh, Zigbee, Thread, and more. It has a 32-bit MCU running up to 48MHz, stereo audio output, 6-channel PWM, and flexible GPIO interfaces. ![Telink TLSR827x](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/telink-tlsr827x.png) This SoC can be used in applications such as: - Wearable devices - Smart home devices - Smart lighting - Advanced remote controls - HID devices ## Renesas ### Renesas SDK: [Flexible Software Package (FSP)](https://www.renesas.com/us/en/software-tool/flexible-software-package-fsp?ref=novelbits.io#overview) The Renesas Flexible Software Package (FSP) is an open source software package designed to help developers build IoT devices using RTOS, FreeRTOS, and other middleware stacks. It includes HAL drivers for a low footprint, a configurator and code generator, as well as robust application support. | IDE | [e² studio IDE](https://www.renesas.com/us/en/software-tool/e-studio?ref=novelbits.io) is recommended \- Included as part of the FSP\- Provides support with configurators and intelligent code generation\- Uses C/C++ Development Tooling (CDT)\- Can use a Renesas compiler or a third-party compiler\- Supports the development of software for IoT devices to be connectable with Amazon Web Services (AWS) or Microsoft Azure Cloud Computing Service | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows | | Required Tools | Segger J-Link (if not downloaded as part of the SDK) | | Key Features | \- Open software ecosystem provides flexibility to use RTOS, legacy code, or other third party solutions\- Includes CMSIS packs\- Includes tool chain and Segger J-Link drivers\- Source code available through GitHub | | Tools Available | \- QE for BLE: Development Assistance Tool for Bluetooth Low Energy | ### Recommended Renesas SoC for Beginners - [RYZ012x1](https://www.renesas.com/us/en/products/interface-connectivity/wireless-communications/bluetooth-low-energy/ryz012x1-bluetooth-le-module?ref=novelbits.io#overview) The RYZ012x1 is a highly integrated module for Bluetooth LE with a network stack that is executed within the module. The module comes in two versions: with or without a mounted antenna, and it supports a pre-defined serial communication interface, which can help to reduce the learning curve for new BLE developers. ![Renesas RYZ012x1](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/renesas-ryz012x1.png) This SoC can be used in applications such as: - Smart home - Wearables and trackers - Agriculture - Entry-level mass market BLE products ## Onsemi ### Onsemi SDK: [RSL 10 SDK](https://www.onsemi.com/rsl10?ref=novelbits.io) The RSL10 Software Development Kit (SDK) is built to enable development of ultra-low power BLE applications. It provides a set of sample applications to help you get started. The SDK is designed to work on Windows alongside the Onsemi IDE. | IDE | [Onsemi IDE](https://www.onsemi.com/products/wireless-connectivity/wireless-rf-transceivers/rsl10?ref=novelbits.io#overview) is recommended\- Uses C/C++ Development Tooling (CDT)\- Eclipse-based IDE[Keil μVision®](https://developer.arm.com/Tools%20and%20Software/Keil%20MDK?ref=novelbits.io) and [IAR Embedded Work Bench](https://www.iar.com/products/architectures/arm/iar-embedded-workbench-for-arm/?ref=novelbits.io) are also supported | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Operating Systems supported | Windows[Some workaround available](https://www.onsemi.com/forum/t/kb-getting-set-up-with-the-rsl10-sdk-eclipse-ide/175/14?ref=novelbits.io) for Linux and macOS | | Required Tools | Segger J-Link | | Key Features | \- Includes CMIS Pack\- Sample project included\- Includes FOTA (Firmware Over The Air) with Android™ and iOS apps\- Supports FreeRTOS™ | | Tools Available | \- RSL 10 USB Dongle Explorer\- RSL 10 Software Utility Apps\- RSL0 LPDSP Software Package\- BLE Explorer\- RF Tools | ### Recommended Onsemi SoC for Beginners - [RSL10](https://www.onsemi.com/products/wireless-connectivity/wireless-rf-transceivers/rsl10?ref=novelbits.io#evaluation-development-kits) The RSL 10 SoC is designed specifically for ultra-low power BLE wireless applications. It has a dual-core architecture and a 2.4 GHz transceiver which provides support for Bluetooth Low Energy and 2.4 GHz custom protocols. The SoC has a programmable Arm Cortex-M3 processor for clocking speeds up to 48 MHz, 384 kB of flash memory and configurable analog and digital sensor interfaces. ![Onsemi RSL10](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/onsemi-rsl10.png) This SoC can be used in applications such as: - Fitness Trackers/Activity Monitors - Smart Watches - Hearing Aids/Hearables - Heart Rate Monitors - Smart Locks - Connected lighting ## Conclusion The great news is that there is a multitude of (cost-effective) choices on the market for developers getting started with BLE development. However, for many, it can be a difficult choice to find the details online that they need to make an informed decision. I hope you’ve found this guide helpful as you begin to make your own decision! --- 💡 **Insider Tip:** Ready to take your Bluetooth LE development to the next level? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Web Bluetooth: A Getting Started Guide for Developers URL: https://novelbits.io/web-bluetooth-getting-started-guide/ Last updated: 2026-08-09T05:38:26.000Z If you're interested in learning more about how to make use of Web Bluetooth, you're in the right spot. But before we get there, let's take a step back... There is growing support for browser-based applications and operating systems. Web apps, as they are popularly known, are attractive since they can be run from any connected device, e.g., a laptop, a tablet, or a smartphone - without needing native apps for each. Until recently, web apps have been very limited, but with new tech stacks and browser features, they are touted as the future by some. While progressive web apps have made significant feature gains, their ability to communicate with external hardware is extremely limited, if not non-existent. This is especially a major block to their adoption in an IoT world where lots of sensing and monitoring hardware are used. For Bluetooth, and [Bluetooth LE](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) specifically, being by far the most popular wireless communication protocol for IoT devices, it is important for applications to be able to interact with such devices. ## Web Bluetooth Basics **Web Bluetooth** is an attempt to work around this limitation and make it possible for progressive web apps to interact directly with Bluetooth-enabled hardware. Put simply, Web Bluetooth is a set of standardized APIs to enable browser-based interactions with BLE devices. This effectively allows web applications to be much more powerful and sometimes removes an additional layer of native application for Bluetooth hardware communication. While the specs of Web Bluetooth aren’t officially finalized, Google has been a huge supporter of the project from the get-go and offered its partial support in Chrome browsers since 2016\. As of now, amongst the major browsers, Web Bluetooth support is provided in Chrome, Edge, and Opera (Safari being a major browser that is missing from the list). With time, as the specs are finalized, I am convinced that all the browsers will support Web Bluetooth - both on PCs and mobiles - thus enabling highly interactive and seamless progressive web applications. 💡 Want to dive deeper into Web Bluetooth? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. While the support is currently relatively limited, there is still a lot that can be done using Web Bluetooth. In this tutorial, we will be exploring the various methods provided by the Web Bluetooth API to demonstrate their capabilities. We will also look at the current limitations and possible ways of working around them. Specifically, we will be looking at the following: - Scanning for Bluetooth Low Energy peripheral devices - Setting scan filters to find specific remote devices - Connecting to a Bluetooth LE device - Reading device information - Disconnecting from a Bluetooth LE device - Reading a BLE characteristic We will begin by discussing the situational context and work towards creating the scaffolding of a simple web app and creating its views. We will then add communication capability to this web app by using the Web Bluetooth APIs in order to receive and display data from BLE sensors. ## Getting Started with an Example Web Bluetooth Project For the purpose of this tutorial, we will imagine a scenario where multiple athletes are in a practice session, and their health status needs to be monitored remotely. This is to be done by receiving their heart rate and also checking the battery status of the sensors they are wearing. The coaches can type in the name of the athlete they want to monitor, and the app should be able to connect to their sensor and start receiving and displaying the data. ## Prerequisites - Any computer or tablet with a text editor and supported browser. - 1 x BLE Peripheral (we have used 1x nRF52 Development Kit with Nordic HRS example). - Basic understanding of HTML, CSS, and JavaScript. Note: we will be using Bootstrap 5 to develop the user interface, which hugely simplifies the process of adding and aligning various UI components. For this project, I am using: - MacBook Pro 2017 with macOS Big Sur (11.4) - nRF52 Development Kit with Nordic HRS peripheral example - Google Chrome (Version 103.0.5060.53) - Atom (as text editor) ## App Requirements and Prototyping The first thing we need to do is to figure out the look and feel of our HR monitoring web app based on its functional requirements as well as the features we want it to have. The main requirements are listed as follows. - A single-page web app with all the information easily visible. - Ability to enter the name of the device to connect with. - A button to initiate connection or disconnection. - Informational text displaying the connection status of the device. - Show heart rate values in real-time. - Display battery status. Based on these requirements, a simple user interface would look like the sketch below. ![GUI for Web Bluetooth project](https://lh6.googleusercontent.com/ZkCie87VuL9Ia90pWPC697pMharWTaph2RfHEisBbLLf-HNFgUjc2898BWyOl1qJHm2QO6UNVLFlNbnRLUmFgm6vlva80XRwsZ1Gcuaa9jMbUYjy0-tbM0X5Zh9qehGx_g8SivgwulAXTug_aUWGnTPlwr8eGMwB4r3mqB2VRGjkFLpcPeEs6iqDhTtQ-w) The end result of what we are designing today will look like the following image below. ![GUI example](https://lh6.googleusercontent.com/bvcqCHQ4HWYbBje-n-kNqpD44PfprnRRNn_rCPoktXkFo0MrxgkaoBHIx8PozYTIx68ATJTfMAoalR9nk3USv8igBPK8RBNlKoda0WZ4ctAw65QxDgYt5EzQ_Ld1OMHmkeMNRCLeIkdWsIPlcsQOVxrWtcnO5JdKY2eLoU3o18ko-_4un9j5_DahVb9hGg) In the next section, we will start putting together all the components needed to make our user interface look like the image above. ## UI Development Since we are using the Bootstrap framework for our UI Development, the first task is to set it up. The easiest way is to download the [Bootstrap examples](https://getbootstrap.com/docs/5.0/examples/?ref=novelbits.io) compressed file. Once downloaded, unzip it and find the example named starter-template. This contains the files that we will copy over to our project folder shortly. Create a new folder for our project. I am calling it WBHRTrack (which is short for Web Bluetooth HR Track). Inside the folder, create a subfolder called app and copy over the starter template’s HTML and CSS files inside this. At the top level of the WBHRTrack folder, copy over the assets subfolder from the downloaded examples folder. The folder structure should look as shown below. ![folder structure](https://lh5.googleusercontent.com/OBlGYdlSWQgQBxrSnX0PjOmihm2Gs1VrYHuFMd_qt3rOsK3aK7k2ujvbHNRNyFOn_Y2VOLCoc2fp-gwQ20YBU3zby112mqRrg5pI1PW6lgQ6vi5T15V_Khncai2AW6J-OqcWEnC00q3ajG24bc8ZleX4LG134T04rlMpkWI6G7NbWD0_5q6xt6XUSGKVLg) To test that everything works so far, open the index.html file in your browser, and you should see the following page. ![Get started with Boostrap](https://lh4.googleusercontent.com/T_1jD4_Yo_WYbcvqvuAhHNxjyLteN0yoDmbXdvRIOWE7qWJmZoBlugQcJClUlGZPhAKa3Fu0bn4iETG3l0i-efG-vpe7qy3d0DOjfK-MLpaqIILW8wipvdN50VnrKbNFCCAZ1Oge-WT-JR7HNTTAW0p4hFLKORXYN5ugw5wtXySZSJ6usqLb6jmZ3jt5Jw) If you see any formatting issues at this point, make sure your folder structure is correct since we are referring to the assets folder from the index.html file. So far, we haven’t made any changes to the code, but since we want our app to look very different from what is shown in the template, we will now edit the index.html file to suit our requirements. The first thing you might want to change is line 7 so that you are the author of this page. Change the value of the **content** field to your own name. Next, change the title of the web page on line 9 to something more useful. This is the text between the **``** and **``** tags. I have changed it to Web Bluetooth HR Track, so the updated line 9 is as follows: ```html Web Bluetooth HR Track ``` Next, we want to change the top header text (we can leave the Bootstrap logo for now). Change this on line 44 (inside the header tag) to be the following. ```html WBHRTrack ``` Refresh your page, and you should see the following. Our title is right on top in the header. We can leave the Bootstrap logo as it is for now. ![get started with bootstrap](https://lh5.googleusercontent.com/Tna8NbUqdPpnBxOcMElWG1-gk6iIxMyCF86wPtfYjq0uFOvUKSZulkq1e5VaaR0qulCn8_JhA3yp4c6BiTG5pAEIPJcazQkqe474A0UeS3PqqbKO_8YqE_jqNBYSeZspJIZiIlIwyYXUKTxAIVwBOfQrhD5ln_oVsejgAnxlHdKyUWHTUZY3KseCUin3FQ) Next, we can remove the rest of the page's content since we don’t need any of that. We can remove everything between the `
` and `
` tags and fill it up later with our content. Now we can start adding the UI elements to make our web page look like the prototype we created in the previous section. The first thing we want is a form or text box to enter the name of our nearby device, followed by a button to connect to that device. Bootstrap follows a grid system where we add things in rows and columns. For example, if we want to add a form, we will do so in a new row. We want the form to take 10 units (out of 12) of column space and 2 units taken by the button. This is illustrated in the figure below. ![](https://lh6.googleusercontent.com/uxVhiuiaaTM8kZvxaH3f6Ja2HZhtlO8o4ZRomjNDtWkAE_Uf10lIQw4OF7gdz5nydGjdpgs-X5YpooEMylj9KtApBtG89lKUWpv08QCVmB0kMcOVWV0zCKL25U-iu9-KVUFfsWZX5bGUJG3DhF077OqY9FWcL4FtNaXit4Px00jKYEUkwOjxKOj5SUs4iQ) Within the `
` element, we add a new row: ```html
``` Within the row element, we add a column with class col-10 (spanning 10 units) and add our form inside it. We have given it the id deviceNameInput so that we can easily identify it later from our script. ```html
``` On the same row (so part of the same row tag), we add another column with class col-2 that will hold our control button. Bootstrap has different [button styles](https://getbootstrap.com/docs/5.2/components/buttons/?ref=novelbits.io), of which we are using the primary button style with the class name btn-primary. The button id is controlButton (but it can be whatever you want as long as you can identify it later). The column can be added with the code below. ```html
``` This completes our first row. The complete code for the row is as follows. ```html
``` If you save the source file and refresh your browser, you should see the form and button as below. ![](https://lh3.googleusercontent.com/fy45e6yYF8M2ud6apC5BUyqf2mojNBocwvBMQUqjlMBDIncELbFpF2XGqPWTh71q8zYRqrAjq1wl83gFs7B7Z65vwG9hdTqa88ZaKxZmF-uRU8cGHrbfDPRnqZo5VfJDAMmdEcpg1DpNRgsvItnJAWKEgEPpiXsB6SjbYvJv75VLnwmWUasHX2FILH8w2A) Next, we will add our connection status label, which will be on a new row. In this row, we would like the first 3 column units to hold the static text “Connection Status” and the other 9 units for dynamic text indicating the status of the peripheral connection. We will do this with a div unit of class row inside which there will be two other div units of class col-3 and col-9, respectively. ```html
Connection Status
IDLE
``` Note that we are using h5 heading tags for the text. For the second h5 element, we have given it the id connectionStatus and default value of IDLE. When the status changes, we will use this id to update the label. Save and refresh, and you should see this appear on your web page. ![](https://lh3.googleusercontent.com/p2HbUreC6P6SLtq3E6MPaUJteovfLQp4LvmjFDtlTpkOQ3OU4E1Hx5hpkCm-jeGF1yGaAas_OMXeLgXGJggrXfMh_W3ETcVoWkeNCiUtaQI5zPR9FZ88uzdaJu1qoJF3eEXPybHsl6PULXiObtCjgfiWPZSW4EXSmIuSXXRConpQOyrcqbchFglV_prX5Q) As you can see, the label is very close to the form element, so we need a bit of spacing between the two. To add spacing, we add gy-4 class to both columns (gy-\* is used to add vertical gutter, and gx-\* can be used to add horizontal gutters). This would be done as follows. ```html
...
``` And the resultant change is shown in the image below. ![](https://lh5.googleusercontent.com/HJfZHuq829Qv1PlS7Lhkg5WguOpsyX9t4Z4cD1bMYuUiR2E8J3LcO5s4Ih8KEly9z01r3z6Hb6CNUIphb55aC0cA4Uxyhj9kSnQqO9gj7uUZI1m3rw2RHx7gthQmgrWX-kXuGkHvO4Z19mBldltoFsBpykZVw73p6UybqwrBTwLp7RA0DatoUJcqj6oZ7g) Finally, we need to add the last row, which has large icons and text for the heart rate and battery charge. We can add these icons as images, but I will use the amazing resource of icons that is [Font Awesome](https://fontawesome.com/?ref=novelbits.io). Once set up, we can simply add any icon we like by referring to its class name (found on Font Awesome’s website). Setting up Font Awesome is super easy. Go to its [Start](https://fontawesome.com/start?ref=novelbits.io) page, enter your email to register, and receive a unique code. Once you have the code, enter the following script tag with your code just before the end of your head element, i.e., before the line that says ``. ```html ``` Make sure you replace *your-code* with your actual code in the line above. Start a new row, and add two columns of 6 units, each keeping the vertical gutter spacing as gy-4 again. ```html
``` We will now add the icons inside each col-6 div above. To add a *heart* icon, search for heart on Font Awesome’s [online catalog of icons](https://fontawesome.com/icons?ref=novelbits.io). Select the filled heart icon and copy its HTML code from the snippet shown once you click it. Add this snippet to the first col-6 div element. ```html
``` Next, search for battery or charge and find one of the icons to use for the second column. I have used the bolt icon, which is free to use. Add it to the second col-6 div element. ```html
``` Save and refresh your HTML file and you should see icons appear on the next row. ![](https://lh3.googleusercontent.com/syl_vAN9U6epJr5PISKJ29p9PEI7XOuezrl7iaZDsGQxCNrYjz2LnxhhxXhIm3UOEibyi6MQ_WJCizRm3z6oVMjp7NnA3GnoKQZBMxtZi9ea0uxdy4XvRm8RRb7sD72S5OnFiKOOGU8Y5KJA1Zf_ZzVdbz8cOY3PwIz7TYNLBYW5rMZ5PobDlJW-xREIIA) These are quite small, so we need to increase their size. With font awesome, we can increase the size easily by adding the relevant class name to the i tag. For example, to increase the heart icon size by 8x, we simply add the fa-8x class. ```html ``` Add the fa-8x class to both the icons and you should see the size increasing as below. ![](https://lh4.googleusercontent.com/4rQY06uxf75_7fOQHH1hfxFh-Dd2g31JiyJNzUng_VaTD9GHS3HYA6iMVJtcPvKA1D47Nek_h3uL3V0sLvE7LW6KIuVsr7oFe89v0_LFCGIhGzMuzwSnZkv7HZCm1IZ-JQCRdNWl9QQHBYKCkVZjKQ5v5RuWm8EYjfVTDk344_VBK2IFM9uwqisinwFDHA) Next, we want to add the label showing the heart rate and battery charge values underneath the icons. We will do this by adding h4 tags with a unique id for each just below the icons. For the heart rate values, we add the following just below the heart icon. ```html

60 bpm

``` Similarly, for battery percentage, we add the following just below the bolt icon. ```html

100%

``` We also want our text to be centered inside the column, so we add a text-center class to both columns. The complete code for this row is as below. ```html

60 bpm

100%

``` And the resulting UI is shown in the image below. ![](https://lh3.googleusercontent.com/BV7O3CvMMY57A8wg6-b4bIh8hgbzsNo_-xnJDZZ-YJLO1TZXBvmd1UwLjmIhOf8o-JRyMP62QZIAyYoMQe-fVvpxGMw8MdCfcxjPN02WrWuPr05nfZJpRZVrLy5IDG4oVSYEaq-sRxFwZ2_m6zAqU_yqee-mwCuIG5PaMKORbQ9_DwdfODAGj9UMMUz_Nw) Now that our UI is complete, we can move on to setting up Web Bluetooth to receive data from our sensor and update this interface. (Note: We can add colors and stylise the look and feel by modifying the CSS but that is not in scope for this tutorial) ## Initial Web Bluetooth Setup Create an empty new JavaScript file adding it to the app folder. I have named it WBscript.js. Add this js file as the script source in the HTML file just before the end of the body section, on the line before ``. ```html ``` In this JavaScript file, we will get hold of our UI elements like the control button, form, and status label so that we are able to dynamically update or interact with them. We will do this by defining three global constants that will get the element from HTML by using its id. This is done as follows in the JavaScript file. ```javascript const controlButton = document.getElementById("controlButton"); const deviceNameInput = document.getElementById("deviceNameInput"); const connectionStatus = document.getElementById("connectionStatus"); ``` Now that we have a reference to our UI elements, the first thing we would want to do is to make our control button interactive. We will add an event listener to listen for the click events and then perform asynchronous tasks inside this. Add the following to your JavsScript file after the const definitions. ```javascript controlButton.addEventListener("click", BLEManager); ``` Here BLEManager() is an asynchronous function that we now define as follows. ```javascript async function BLEManager() { } ``` Inside this function, we will use the Web Bluetooth API with `await` operator (which can only be used in an `async` function). This way, we will be running an `async` function with a series of statements waiting for one to complete before the other without blocking the execution of any other function of the web app. ## Scanning for a BLE Sensor Scanning for a BLE peripheral is performed using the `navigator.bluetooth.requestDevice()` method for which various options can be defined to filter the device that we are looking for. There are so many different options we can use as our filter criteria, whether it's based on services being exposed by the peripheral, manufacturer data, peripheral name, peripheral name prefix, optional services, etc. Alternatively, a simpler way is to not have any filter and scan for all BLE peripherals in the vicinity. In the BLEManager() function (which is currently empty), add the following code. ```javascript const device = await navigator.bluetooth.requestDevice(); ``` Refresh your web page in the browser and click on the Connect button - without entering any text since we aren’t using that for now. We are only trying to see the BLE peripherals around us. What happens? Nothing. We need to debug what’s happening. Open your developer console. In Chrome, this can be done by going to *Settings->More Tools->Developer Tools,* as shown below. ![web bluetooth debugging](https://lh6.googleusercontent.com/7x2vE81ijKjIw_lzzqwQ7DaS-u45_ayn_jxGzr3XG4HfE3Ovjj4zSQpvDo6xwTtqcjOxNS7QXBfW-0OEy57VdAq-7GY4IS9U9eAfC0Opn_33EX8Luycw9eEdLxp1SBlcYLt0ISWahOqJfe1QXb-bXgXJ7jHaDJgwoByskMEiVpXx2a2QgxVW35eJeMTDcw) In the developer console, you will see an error explaining what went wrong. ![](https://lh3.googleusercontent.com/JKj6Q9FEIr94BIzgMsFhB1z4fw_5Op9rXJiorIVvYXExQk4se1-HAOXAOp0RBpKWrClCdgJ0xf3MPIiMWrWeLjL-GImlUWbK0qNhwM83KVSPnmNaC0IWjRSLiPhWp_K2v64U_kERCS4EHbA4Ab8TqPiiB8tFsFVF_ErPHi63-yuDfYUz06ElOpTSiS2ykQ) In order to scan for all devices, we need to set a certain acceptAllDevices option to be true, which is false by default. Let’s add that to our `requestDevice()` function. ```javascript const device = await navigator.bluetooth.requestDevice({ acceptAllDevices:true }); ``` Save the script and refresh your browser tab, and press the Connect button. If System Bluetooth is off on your device, you will get the following. ![](https://lh6.googleusercontent.com/HV4Bq8Ocmlh56xN5pW2h9MEgSLTZUNX5UWOZSQzjP3r_BnrK3-uJ_sZ2bVmYSQwhZev9NjggX9xuPtDR2Zp5Vm2PPLxmX5MqMtkp0bJJPdihf2vFqWBJcgGmwfL4FfiCD81fUxxqfuzIIZvSWGhkJASqQhTgSyPLUH3EBTX5HsufgdVMJwYY1L7xe3T3IQ) If not, you should see a list of devices around. ![](https://lh3.googleusercontent.com/H8ooEz5M6Dl9QY9yswZMctVhoZ6MdMo6WGKUUduKjhaG-t8auivZfHRmoy7i5lhFlZEVi7FmgGTC4NpOv1wiN3ezXdkKJCwzk8lQb-mhPS-8QVMhvf5mfV7O5c6VUR288u2DWzmOc2FVMMJmU8XwetbBGe7KOLjGTWM4eJ7RyFM3h1hbzS7F8xvZYSNSWQ) In our case, we are looking to find a specific peripheral with the name *Nordic\_HRM*. Let’s create a filter to find that. When we are using a filter, we cannot set acceptAllDevices to true, so we can remove that from our code since it defaults to false anyway. Add the filter as shown below. ```javascript const device = await navigator.bluetooth.requestDevice({ filters: [ {name: deviceNameInput.value } ] }); ``` As you can see, we are fetching the value for `name` from our form, which we defined earlier as a constant named deviceNameInput. For this filter to work, we have to give the exact name of the peripheral we are looking for. In my case, the peripheral name is *Nordic\_HRM*, so I will put that name in the form and click the Connect button. And I should see my peripheral in the chrome prompt. ![](https://lh3.googleusercontent.com/A4aDDbCXgAxcRfIFMqSYBxM-r4ibz1-UrtC1Rr0_Xyz-9nUcS-2zWZCzzP0ZQr695Q0qg2FEBbwgK1GIPNb8jO2vNx-APyI4XyQl1qnwFJoUnDbmS9uojLxLFVFR6D_OKAgivLv2MF1hI2D3AkmiiRfU9pxim3PlXETu35qrQYQhRESK1r_JOTXzQmbQ8Q) If we are unsure of the full name of the peripheral, we can also use namePrefix as part of our filter. We can even use both options, and it will scan for peripherals using an OR condition. That is, all peripherals that match either the namePrefix condition or the name condition will be shown in the list. For example, in the code below, I have hard-coded the namePrefix value and used the name as *Nordic\_HRM* from the form: ```javascript const device = await navigator.bluetooth.requestDevice({ filters: [ {name: deviceNameInput.value }, {namePrefix: 'ai' } ] }); ``` The result is as shown below: ![](https://lh6.googleusercontent.com/bb1y5IdZMOcNZ2gnK12oSyZ4Bg03V440f78ZEH_fNn24sBPD5FIuJZcqfe8IwMWTpNfSdEesuGDw5FgCmeZV9PhZqj43e7nF4iXWqQVcOSphKssHOoAgwHrxjf9zC2ifvjq7Hwp18nRncY-w9bdnnhUhfIVcRSnL_qYl6YfrwjxUKeMl4fcZIdzLfcyQtg) The other options we can use in our filter include services where we can list either short form UUID or the full 128-bit UUID or even descriptors of the known services, e.g., heart\_rate as well as manufacturerData which allows us to filter based on the company identifier. Outside the filter, another option we can use is optionalServices which is different from services. Consider the code snippet below. ```javascript const device = await navigator.bluetooth.requestDevice({ filters: [{ name: deviceNameInput.value, services: ['heart_rate'] }], optionalServices: ['battery_service'] }); ``` This will result in our *Nordic\_HRM* being shown in the filtered list since it has both the heart rate and the battery service. If let’s say, battery service wasn’t available, the peripheral would still be discoverable since heart\_rate is still present and is the required service. **IMPORTANT**: Any service we need access to has to be listed either as part of the services filter or as optionalServices. If, in the above example we don’t mention battery\_service anywhere, then we will not be able to read from it later and will only have access to the heart rate service. Hence it is important to list any service that we need at this point. 💡 Looking for more hands-on guidance? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. You might be wondering what is the point of optionalServices here since we can just list everything as part of the services filter. One common use case is that we can use optionalServices for a general scan with acceptAllDevices option as true and still be able to access relevant services later that we list as part of optionalServices. Other than that, it allows us to form flexible combinations and search for devices that will have certain services and not others. In our case, we know that our peripheral has both the heart rate and battery service so now we can put both of them in the services array and update the code as follows. ```javascript const device = await navigator.bluetooth.requestDevice({ filters: [{ name: deviceNameInput.value, services: ['heart_rate', 'battery_service'] }] }); ``` So now we have figured out how to search for peripherals in different ways. However, our users don’t really know that the search has commenced. Once we hit the Connect button, our status label should update to show that we are searching for the peripheral. To do this, we can simply update the textContent of our label as soon as the button is clicked. Add the following line just before the `requestDevice()` function. ```javascript connectionStatus.textContent = "SEARCHING"; ``` This works well if the user pairs with the peripheral however if the user cancels the dialog that shows the BLE peripherals the status text is still stuck at SEARCHING and there is error in the console . ![](https://lh3.googleusercontent.com/mBPEQQ8Go6Hb0q0RbcofeqE-gAinkyql4e4s3hFl7GP2nyfU5ZKNIaMw0xOrrQizYECAlKhIdc2pkwRhSgHmbc9QSqvVrnmNsnUg24Foo1JmnLHGaKPA0jn31gumItrcovnnIuraA-8JFYJ5oqN6whKZa9sAAYEZjEsxZ7Bbpy8f9jNq6jy-6NiVssee2w) We need to do some error handling here to update the text of the label accordingly. To do this, we will wrap our call to `requestDevice()` in a `try-catch` block. The catch part of this is where we will handle the error, which in this case is updating the text of the label. The complete BLEManager() function at this point will be as shown below: ```javascript async function BLEManager() { connectionStatus.textContent = "SEARCHING"; try { const device = await navigator.bluetooth.requestDevice({ filters: [{ name: deviceNameInput.value, services: ['heart_rate', 'battery_service'] }] }); } catch { connectionStatus.textContent = "CANCELLED"; } } ``` If you save and run now, you will see that the console error disappears, and once you cancel the dialog or move away from the tab, the status will change from SEARCHING to CANCELLED. ![](https://lh4.googleusercontent.com/kUL0HvyM14DpDuNWLTMIagN7thmzx6uWAJh8_aXWKynr0opzuQgvtf4F2CcDL1YKqFJ6gf-wqaIMXXGoouKSn1YLLiUiUQx2ohhK82Qk27na0UaXkB-AEv4WSyw_Xn0MmNgnDUr4rnE1AV0PNMfX9m-kSBzAQrxBUfqjkX1UMXzGpKDNqH9nncJwSnSIJw) We have covered a lot of ground in this section to be able to identify the device we want to connect to and handle the errors that can come about if things go wrong. In the next section we will establish a connection with the BLE peripheral and continue to explore its services and characteristics. ## Establishing a Connection When the dialog appears with a list of peripherals, there are two options given to us: Cancel the dialog or Pair with the selected device. If you select Nordic\_HRM and click on Pair from the list, the peripheral device will continue to advertise as normal. If you search again, the dialog *may* show the device as paired. ![](https://lh6.googleusercontent.com/tZnViwF3DxELow3-BEMh9CKjUyfvc3CQ9JspJrv9qbG4b6fSU3k4lCUvs2pNEOCI95xCb_sr_nXmfEjrHz9hXXztjWntoLMHsvI4hxcqboReTmixOy4oMh6Xa25NoCc0YENOHtY-a53A0YySfp45CzttiqbTyKiucJvgxXurlAl3ySaYF2ckSm8O745ZnA) So what’s happening here? Chrome remembers the peripheral, and since pairing was attempted, it shows the device as already paired. However, we haven’t connected to the peripheral yet despite clicking on the Pair button. In order to connect with a peripheral, two things need to happen: - The user has to explicitly select the peripheral from the list shown in the dialog and click the Pair button. - The selected device must call the connect() function. In the previous section, we used the `requestDevice()` function, which filters and shows the list of devices and then returns the device selected by the user. We aptly called it `device`. To connect to this selected device, we need to call the asynchronous gatt.connect() function: ```javascript const connectedDevice = await device.gatt.connect() ``` Note the use of the await keyword here once again. This is only executed after the earlier function has completed its execution. But what if the earlier function failed and we come directly to this call? We will not have a valid device to connect to, and so this will throw an error. Go ahead and try it out yourself. This is why we will continue adding our code inside the earlier try-catch block ```javascript try { ....... const connectedDevice = await device.gatt.connect() } catch { connectionStatus.textContent = "CONNECTION FAILED" } ``` Note that this call can fail intrinsically if there is a problem connecting to the device or it can fail because we haven’t even found the device we want. So the catch condition can be a bit smarter to detect the reason why it was triggered. We can do something like this: ```javascript if (typeof device !== 'undefined') { connectionStatus.textContent = "CONNECTION FAILED"; } else { connectionStatus.textContent = "CANCELLED"; } ``` While a lot more can be done, this is just an illustration and a reminder to consider the different cases and handle the error appropriately. At this point, the BLEManager() function should look like this: ```javascript async function BLEManager() { connectionStatus.textContent = "SEARCHING"; try { const device = await navigator.bluetooth.requestDevice({ filters: [{ name: deviceNameInput.value, services: ['heart_rate', 'battery_service'] }] }); const connectedDevice = await device.gatt.connect(); connectionStatus.textContent = "CONNECTED"; } catch { if (typeof device !== 'undefined') { connectionStatus.textContent = "CONNECTION FAILED"; } else { connectionStatus.textContent = "CANCELLED" } } } ``` And if you try connecting to the device, you should be able to do that successfully with the label updating to show CONNECTED. ![](https://lh6.googleusercontent.com/QqNKreMzTHdQQRIViigjWnPESjweBF2iAXU7ef0OV84J6LeLk8ovBJAJe32C6YTywvYXv_1i86NnYTRvwUpa6RbljcjzrLT97Z9aj6hdnD9MK5LrqHK1XaD0QWkXuGKQ7EGoXHymxQN1znhz-BvTP4Ojc36iO78koZUtSi4sLPQH1WxWPEjdwUygYPnoOA) ## Discovering Services Now that we have established a successful connection to our peripheral, we need to get its services to be able to discover the characteristics. Remember, we can only work with services that we listed as part of our services filter or optionalServices key when discovering devices. In order to get the service from the server, we use its getPrimaryService() asynchronous method. Secondary services cannot be obtained using this method. We have two primary services that we need: heart\_rate and battery\_service. We can get them as follows once the device is connected. Remember, we are still in the try block and just adding lines after the last status update. ```javascript const batteryService = await connectedDevice.getPrimaryService("battery_service"); const heartRateService = await connectedDevice.getPrimaryService("heart_rate"); ``` At this point, we are not updating the status label, but if you want to see if this has been completed successfully, you can use console.log() and add helpful debug messages that you will see in the console confirming that you have reached this point of your code successfully. ```javascript console.log("Services obtained") ``` Another useful idea is to set up error codes so that you know which Web Bluetooth function has failed and show the correct message to the user in the catch block based on it. For example, we can define a global variable at the top: ```javascript var error_code ``` And then, after each BLE operation, update the value of the error\_code. Subsequently, we can check where the error happens in the catch block of the code, as shown below: ```javascript try { // initialise error_code = 0; // scan for devices (requestDevice) error_code = 1; // connect to specific device error_code = 2; // get primary service error_code = 3; } catch { if (error_code == 0) { // error during scanning } // other conditions } ``` ## Discovering Characteristics Next, we would like to find the characteristics of the heart rate measurement (in the heart rate service) and battery level (in the battery service). This is performed by calling on the getCharacteristic() method on the service. This, like others, is also an asynchronous function, so we use the await keyword. ```javascript const batteryLevelCharacteristic = await batteryService.getCharacteristic("battery_level"); const heartRateCharacteristic = await heartRateService.getCharacteristic("heart_rate_measurement"); ``` Note that we are using the characteristic names here for convenience, but we might just as well use the UUIDs as below. ```javascript const batteryLevelCharacteristic = await batteryService.getCharacteristic(0x2A19); const heartRateCharacteristic = await heartRateService.getCharacteristic(0x2A37); ``` Finally, to get some feedback, we will also print a message on the console log. ```javascript console.log("Characteristics discovered") ``` Save and refresh. You should be able to see the message printed on your console. ## Reading from a Characteristic To demonstrate reading data from a characteristic, we will read data from the battery level characteristic and display the value on the web page. We will do this by calling on the readValue() method of the characteristic. ```javascript const batteryLevel = await batteryLevelCharacteristic.readValue(); ``` We need to interpret this returned value correctly since this is just an array buffer. From the BLE specifications, we know that the battery level characteristic is between 0-100 and is of type Uint8. So we will get this percentage level as below: ```javascript const batteryPercent = batteryLevel.getUint8(0); ``` Once we have this, we can update the textContent of our label. To do this, first, we will define a global const in our script file to get the element with id batteryCharge. ```javascript const batteryCharge = document.getElementById("batteryCharge"); ``` Finally, we will update the textContent of batteryCharge as soon as we get the batteryPercent. Together this operation looks like the following three lines of code. ```javascript const batteryLevel = await batteryLevelCharacteristic.readValue(); const batteryPercent = batteryLevel.getUint8(0); batteryCharge.textContent = batteryPercent.toString() + "%"; ``` Try running this and you should see the battery level updating after connection. ![](https://lh6.googleusercontent.com/GjKHLSmXCU-iLnImmMB1MDVatym4KkrJpQ70httsgp3fu8h29D34BsHaHiELjdGMgWVV5zyzSkDXlzvmo6uZS5UYXyTSiDspmt9n6_XBDK5MuK1g2fqDmDmTp-pE8-cIKo5iA0FgFZ_TgonfGGOQOTj0dejjxQOFqPLkHtGS5L5Co_12OsM9oUA5wRHABw) ## Next Steps If you’ve managed to get this far, congratulations! You have the start of a functional web app that uses the Web Bluetooth API to interact with nearby BLE devices. If you’ve been following along, you have: - Scanned for BLE peripherals - Created filters to find specific BLE peripherals - Connected to a BLE peripheral - Disconnected from a BLE peripheral - Read from a characteristic If you want to keep building this example project, the full project guide is the [***Getting Started with Web Bluetooth course inside the Bluetooth Developer Academy***](https://novelbits.io/academy/?utm%5Fsource=blog&utm%5Fmedium=website&utm%5Fcampaign=bluetooth+low+energy+ble+a+complete+guide). In addition to what we covered in this blog, in the full course, you will learn how to: - Write to a characteristic - Subscribe to notifications - Unsubscribe from notifications - Update the UI based on BLE events (triggered by user gestures or user actions) - Handle errors **Note:** The full course available within the Bluetooth Developer Academy was authored by Anas Imtiaz, Ph.D. ## Final Notes about Web Bluetooth Web Bluetooth is still classified as an experimental API that is in active development. There is a chance of functions and processes changing as the API matures, so keeping up to date with the documentation is highly recommended. Additionally, the support of various API methods may differ across browsers, which is also something to keep in mind while developing web apps with Web Bluetooth. Nevertheless, the support is improving, and with time this is likely to become a standard across all major browsers. 💡 Ready to take your Bluetooth development further? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth HID: An Introduction to Human Interface Devices with Bluetooth LE URL: https://novelbits.io/bluetooth-hid-devices-an-intro/ Last updated: 2026-08-09T05:23:51.000Z **Bluetooth HID** has its roots in another protocol altogether: USB. Before we all had Bluetooth keyboards and mice, engineers were trying to get a hold of the very messy reality that we were facing with no standardization amongst computer peripheral devices. From all the chaos came the **human interface device** protocol that provided a common language for all USB communication. In this article, we will look at how this original HID spec has been extended for use with Bluetooth Low Energy. Let's dive in! ### A brief history of HID device communication For many decades, humans have been working with electronic calculators to tackle complex tasks. One of the first riddles engineers had to solve was developing a means of communication to instruct the machines about the jobs requested and then receive feedback about the results from their metallic "friends." The first step in this process was the invention of input devices, the predecessors of what we now call keyboards, mice, joysticks, and pointing devices. ![human interface devices](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/hid-input-devices.png) **Input Device examples (Source: allresultus.com)* While the first solutions used a mixture of hardcoded (i.e., not customizable) and proprietary protocols in conjunction with dedicated ports (does PS/2 remind you of something? 😬), it soon became clear that there was a need for standardizing the way peripheral devices communicate with the central processing unit (the PC) operating systems. The list of devices that the average person was using every day was growing, and it simply wasn't practical anymore to have proprietary protocols for each type of device on the market. Furthermore, there was a growing need for interoperability between devices from different manufacturers. Something had to change. ![color-coded PS2 connection ports](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/color-coded-ps2-connection-ports.png) **Color-coded PS/2 connection ports (Source: Wikipedia)* In the mid-90s, USB protocols and cables started to appear as they were set to become a universal bus able to connect any peripheral to a personal computer. Within this environment, the USB SIG developed the revolutionary specification of [HID ](https://www.usb.org/hid?ref=novelbits.io) (Human Interface Device) class USB devices, which is a generic framework that could allow input device manufacturers to develop their products ensuring interoperability within different hosts and, most of all, a plug-and-play user experience. This was achieved thanks to the assumption that mainstream OSes already included support for HID and could recognize USB HID devices from the get-go without the need to install specialized device drivers. That has been a fundamental turning point for these types of consumer devices! More recently, a wireless protocol (hint: it has some blue in its logo and name 😉) took hold thanks to the promise of delivering satisfactory performances while removing the hassle of physically connecting cables. Bluetooth has been initially developed to stream audio to headsets and transfer files wirelessly with a PC. However, it became very soon clear that it could also help in getting rid of cables needed for input devices that had to be always connected to desktop computers in offices and at home, often resulting in an unaesthetic messy jungle of wires (say hello to the Bluetooth keyboard!). With the advent of Bluetooth Low Energy around 12 years ago, it was necessary to implement the same protocol using the newer and more power-efficient standard; so here we are, describing the HID Profile for Bluetooth LE, also called HID-over-GATT or the Bluetooth LE HID profile! 💡 **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth Profiles A Bluetooth Profile is a specification describing a particular use case of Bluetooth-based wireless communication between devices. In order to use Bluetooth (Classic and Low Energy), a device must be compatible with the subset of device Profiles that implement its capabilities. It is worth noting that Bluetooth LE profiles don't map to any part of a Bluetooth LE stack implementation, in contrast to Services, Characteristics, Descriptors, GAP functionalities, etc. They are instead just behavioral specifications covering common scenarios and including capabilities requirements/recommendations for the peer devices involved and security restrictions, if any. For instance: the **Heart Rate Profile** includes the **Heart Rate Service** and **Device Information Service**. This means that a device streaming Heart Rate values will also need to expose information about the Manufacturer, its Serial Number, and more to be qualified as a Bluetooth Heart Rate sensor device. HID-class devices compliant with the official Bluetooth LE Profile make no exception: for instance, its Bluetooth HID Service requirements are listed in Table 3.1 of the specification: ![Bluetooth HID device service requirements](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hid-table-3-1.png) ### The Importance of the Bluetooth HID Specification HID has been developed to standardize communication: a Bluetooth HID Device and an HID Host device exchange data within a well-defined framework. The specification is also extensible and versatile, covering a wide range of products. This means that manufacturers can develop different kinds of devices, making sure that: - Interoperability with any legit HID Host is preserved - The performance of competitors' HID Devices can be easily compared using generic Host drivers - Any proprietary/device-specific information can still be transmitted using dedicated vendor-specific "pipes" (more on that later…) - No matter the physical link used (USB, Bluetooth Classic, Bluetooth LE,...), the plug-and-play experience for the user is always preserved ## Bluetooth LE HID Profile components The official Profile specification is downloadable [here](https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/?ref=novelbits.io). The document outlines the supported roles when establishing HID bi-directional communication over Bluetooth LE: - Bluetooth HID Device (pointing device, Bluetooth keyboard, game controller, …) - Boot Host - Report Host The two kinds of Hosts differ in the way they'll need to interpret the data received from the connected Devices: in Boot mode, no HID parser is needed, and a fixed data format is used, supporting keyboards and mice exclusively; if Report mode is instead enabled, the Host is required to *decode* payloads to interpret them correctly. **NOTE**: Boot mode represents some sort of retro-compatibility feature with respect to the old-fashioned PS/2-based protocol, which supported only fixed data format from the Devices; it is also very useful if a Device needs to connect with a Host when no OS has booted, such as if only the BIOS is running. ![HID services and profile roles](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hid-services-roles.png) **Relationships between Services and the Profile roles (Source: Bluetooth SIG)* As we already know, the mandatory Services to be implemented for Bluetooth HID Devices are HID, Battery, and Device Information (note: for DI, only a single instance is allowed!). The Host shall instead support the Scan Client role of the Scan Parameters Profile, but given that Scan Parameters Service is optional for the Device, we'll ignore this detail. On the Device side, a set of recommendations on the configuration of each of the Services is described; for instance, the payload sent with Advertising packets should contain some specific information in order to enhance the user experience and ensure a prompt discovery by scanning Hosts in range. The specification document also describes the GATT procedures that the Host will need to support to interact with the Device: for instance, the requirements for the *Discovery* of Services and Characteristics slightly differ between Boot and Report mode. Some suggestions (aka the "*should*" terminology in the spec) or hard requirements (aka "*shall*" terminology) are also listed regarding the specific Device-Host interaction on the Characteristics themselves (e.g., the expected behavior of Battery Level) and on connection establishment procedures, being started by the Device or the Host. This is where suggestions about Advertising and Scanning parameters are described. If we reflect on this for a second, this is exactly what we expect from this specification: punctual and precise guidelines that help standardize the behavior of similar devices produced by different manufacturers but competing in the same market! Last but not least, a few words on security: to be compliant, a Bluetooth LE HID Device shall protect all supported Characteristics with **LE Security Mode 1, Level 2, or 3**. This means encryption is mandatory for any kind of Characteristics interaction between peers. ## Insights into the Bluetooth HID GATT Service It should be clear by now that the Bluetooth HID GATT Service represents the backbone of the communication between compliant Hosts and Devices. If a device utilizes the HID GATT service, it can be referred to as a Bluetooth Low Energy-GATT-compliant HID device. The specification has been modeled after the original USB HID approach but adapted to a different underlying protocol. Let's start by listing out the main characteristics involved, as they are described in the official spec: ![HID service characteristics](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hid-service-chars.png) The first thing that catches the eye is that many of the characteristics within this Service are optional or at least configurable, which is exactly what makes it so flexible! Now, before getting into the juicy details of the main characteristics, let's spend a few words about the least important: - The **HID Information** characteristic simply reports some static HID Device attributes related to the behavior of the Devices in some conditions (e.g., advertising if already bonded but not connected, …). - The **HID Control Point** characteristic can be used by the Host device to flag that it is entering a particular state. At the time being, only *Suspend* and *Exit Suspend* are supported. ### Protocol Mode: A Safety Switch This characteristic is used to read or set the current mode of operation of HID Service. Only two values are currently supported, as stated in the spec: ![HID protocol modes](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/hid-protocol-modes.png) In practice, this means that: - If the value is **0**, Boot Procol Mode is active, and the Device will send and receive data through the Boot Input/Output characteristics (available for keyboards and mice only). - If the value is **1**, Report Protocol mode is active, and the Device will send and receive data via standard Input/Output reports characteristics. - Upon each connection establishment, Protocol Mode is reset to the default (Report). It is now evident why more than one operation mode exists: a less capable Host device can always force a basic level of communication to work using a fixed format, regardless of the complexity of the peer Device. 💡 **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Reports: Input, Output, and Feature Three different kinds of reports characteristics can be implemented: - An **Input Report** is used to transmit data from the Device → Host direction. - An **Output Report** is used to transmit data from the Host → Device direction. - A **Feature Report** is used to set/get properties (configurations, states …) in both directions. In a single Service implementation, multiple reports characteristics of each kind can be implemented. The number of reports present and their data format is regulated by the Report Map. ### Report Map: the encoding/decoding trace The Report Map characteristic plays a major role in the success of the Bluetooth HID protocol. Its value is constant, and a single instance is allowed for a given Service implementation on the Device. The Map is nothing but a single descriptor defining how the data prepared by the Device is packed into the Input Reports and how the data received from the Host, if any, is expected to be formatted into the Output Reports. The format of the characteristic value is fully inherited by the USB HID Class specification, tracing the *HID Descriptor*. As an example, have a look at a Report Map for a basic mouse: ```c static const uint8_t report_map[] = { 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 0x09, 0x02, /* Usage (Mouse) */ 0xA1, 0x01, /* Collection (Application) */ 0x09, 0x01, /* Usage (Pointer) */ 0xA1, 0x00, /* Collection (Physical) */ // Define 3 buttons data format (1 bit for each button) 0x05, 0x09, /* Usage Page (Button) */ 0x19, 0x01, /* Usage Minimum (0x01) */ 0x29, 0x03, /* Usage Maximum (0x03) */ 0x15, 0x00, /* Logical Minimum (0) */ 0x25, 0x01, /* Logical Maximum (1) */ 0x95, 0x03, /* Report Count (3) */ 0x75, 0x01, /* Report Size (1) */ 0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,...) */ // 5 bits padding needed after the 3 bits for buttons 0x95, 0x01, /* Report Count (1) */ 0x75, 0x05, /* Report Size (5) */ 0x81, 0x03, /* Input (Const,Var,Abs,No Wrap,Linear,...) */ // Define the motion sensor data format (8 bits for each axis) 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 0x09, 0x30, /* Usage (X) */ 0x09, 0x31, /* Usage (Y) */ 0x15, 0x81, /* Logical Minimum (129) */ 0x25, 0x7F, /* Logical Maximum (127) */ 0x75, 0x08, /* Report Size (8) */ 0x95, 0x02, /* Report Count (2) */ 0x81, 0x06, /* Input (Data,Var,Rel,No Wrap,Linear,...) */ 0xC0, /* End Collection */ 0xC0, /* End Collection */ }; // With the above Report Map, the mouse input report sent over-the-air will // look like: struct mouse_report_t { uint8_t buttons; // Use only 3LSBits int8_t x; int8_t y; } ``` *Snippet from hog.c (Zephyr RTOS source code -* [*https://github.com/zephyrproject-rtos*](https://github.com/zephyrproject-rtos?ref=novelbits.io)*)* ### Useful tools As we've seen, a significant portion of the HID Service specification is inherited from the USB HID Class, especially when it comes to en/decoding the Report Map characteristic. Don't worry if you are not familiar with that terminology! Luckily, tools can automate generating or decoding a valid Map without you knowing all the quirks of the USB spec. Usually, it's a good idea to start with the working example of a descriptor and then gradually modify it according to your product needs. Check out the tools below; all freely available online, that may come in handy along the way: - [HID Descriptor Tool](https://www.usb.org/document-library/hid-descriptor-tool?ref=novelbits.io) The official (and a bit dated…) USB HID tool that lets you edit, create and validate HID Report Descriptors. - [USB Descriptor and Request Parser](https://eleccelerator.com/usbdescreqparser/?ref=novelbits.io) An online tool that's able to parse HID Descriptors, providing some insights about their structure. - [Waratah](https://github.com/microsoft/hidtools?ref=novelbits.io) It is the newest of the tools I've found, directly maintained by Microsoft. It offers the use of a meta-language to easily design descriptors and generate the right blob in code - quite remarkable! 💡 ## Conclusion - Working with Bluetooth HID While the roots of HID are in USB, today developers are making use of it to implement Bluetooth LE device connections. And that's exactly what we looked at in today's article. If you're ready to tackle a more hands-on Bluetooth HID project, head over to [**Bluetooth HID Device Design: Step-by-Step Example Project.**](https://novelbits.io/bluetooth-hid-device-design-example-project) As you expand your knowledge of Bluetooth LE HID, I recommend you bookmark this article along with these other helpful resources: - ***Comprehensive Resources*** \- [The Bluetooth Developer Academy](https://novelbits.io/academy/?utm%5Fsource=blog&utm%5Fmedium=website&utm%5Fcampaign=bluetooth+low+energy+ble+a+complete+guide) - **Blog Article* \-* [Bluetooth HID Device Design: Step-by-Step Example Project](https://novelbits.io/bluetooth-hid-device-design-example-project) - **Official Spec* \-* [USB HID official specs](https://www.usb.org/hid?ref=novelbits.io) - **Official Spec* \-* [Bluetooth LE HID-over-GATT Profile spec](https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/?ref=novelbits.io) - **Official Spec* \-* [Bluetooth LE HID Service spec](https://www.bluetooth.com/specifications/specs/hid-service-1-0/?ref=novelbits.io) Free Download HID Simple Mouse — Complete Source Code Get the full Zephyr RTOS project for the nRF52840 DK so you can flash and study a working Bluetooth LE HID Mouse implementation. The Report Map and HID Service code are ready to build, run, and adapt. Send Me the Code Check your email! We sent the download link to . No spam. Unsubscribe with one click. 💡 ****Want to get your Bluetooth-connected devices to market faster? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up.** --- ![Davide Pollarolo](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/davide-profile-picture-1.png) **About the Author:** *Davide Pollarolo is an Embedded Software Engineer with extensive experience in designing & developing smart devices using Bluetooth Low Energy. He has an MSc in Computer Engineering and has worked in various domains, including robotics, sport & medical wearables, and computer peripherals. Davide is fascinated by Human-Computer Interaction and loves spending his free time snorkeling in the Mediterranean* 🌊 *or hiking in the Alps* 🏔 --- ### Bluetooth Mesh Networking: The Ultimate Guide URL: https://novelbits.io/bluetooth-mesh-networking-the-ultimate-guide/ Last updated: 2026-08-09T05:24:15.000Z The Bluetooth Low Energy (LE) standard has been around for over a decade, but it wasn't until 2017 that the Bluetooth SIG released the [Bluetooth mesh standard](https://www.bluetooth.com/specifications/mesh-specifications?ref=novelbits.io). Competing with other mesh-capable standards like Zigbee and Thread, Bluetooth mesh is designed to enable applications within the IoT by, for the first time, allowing for many-to-many communication over Bluetooth LE. A few things to know: - **The Bluetooth SIG refers to the standard as Bluetooth mesh** (with a lower-case “m” in the word “mesh”). - **The standard is not part of the Core Bluetooth standard** (rather it's defined in its own separate set of specifications). - That said, **Bluetooth mesh builds on top of BLE** and utilizes many of the concepts in BLE. - **Bluetooth mesh utilizes only the advertising/scanning states of BLE devices.** This means that devices that are part of a Bluetooth mesh network must relay information to each other via advertising packets, which are received by the other devices via scanning. - Bluetooth mesh supports all versions of BLE (going back to Bluetooth version 4.0, which is the first version of the Bluetooth specification that included BLE). - **Bluetooth mesh does not support Bluetooth 5 features** such as advertising extensions and the long-range mode (coded PHY), as of October 2022. - The maximum number of nodes within a Bluetooth mesh network (defined in version 1.0 of the specification) is **32,767 nodes**. - The maximum hops a message can travel within a Bluetooth mesh network (defined in version 1.0 of the specification) is **127 hops**. ## What is Bluetooth mesh networking? The Bluetooth mesh specification was released in July of 2017 with the goal of increasing the range of Bluetooth networks and adding support for more industrial applications that utilize Bluetooth LE. Earlier versions of Bluetooth supported two different topologies: - **One-to-one**: when two BLE devices are connected. - **One-to-many**: when BLE devices operate exclusively in the Broadcast state, such as [Beacons](https://novelbits.io/what-is-a-beacon-guide-to-bluetooth-beacon-technology/). BLE mesh introduced a new topology for BLE: **many-to-many.** This is generally referred to as **mesh topology,** where many mesh devices can communicate with many other mesh devices within the same network using mesh nodes. This essentially creates large-scale device networks (think hundreds, if not thousands, of devices) that can be used for a variety of IoT applications. ![Bluetooth mesh network in a cityscape](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bluetooth-mesh-network-1-jpeg.jpg) ## Benefits of Bluetooth mesh The main benefits of the Bluetooth mesh standard are: - **Built on top of BLE:** Bluetooth mesh uses the same protocol stack as BLE. Smart devices with Bluetooth 4.0 or later (like many smartphones today) can utilize Bluetooth mesh technology directly. - **Global interoperability:** devices and products from different manufacturers are guaranteed to interoperate as long as they are Bluetooth mesh certified according to the standard. - **Scalability:** one of the main goals of Bluetooth mesh was to be scalable and be able to support a large number of participating nodes within a single network. Bluetooth mesh supports up to 32,767 elements (if each node has only one element, this makes this value the maximum number of devices per mesh network). - **Reliability:** another goal was to make the standard reliable and be able to handle lost and/or corrupt messages. - **Security:** security in Bluetooth mesh is mandatory to implement. This is compared to BLE where it’s optional and left to the developer to decide whether to implement or not in their application. ## BLE mesh vs other wireless mesh specifications (like Zigbee) There are a few differences between the BLE mesh protocol and other mesh networks out there like Thread, Zigbee and Z-Wave. Some of the important ones are: - **Bluetooth mesh does not use the Internet Protocol (IP)** — instead, it builds on top of BLE. - **Bluetooth mesh uses a managed flooding** technique compared to[routing techniques](https://en.wikipedia.org/wiki/Wireless%5Fmesh%5Fnetwork?ref=novelbits.io#Routing%5Fprotocols) that other protocols use. - **Bluetooth mesh has more robust security protocols** than others like Zigbee. - **Bluetooth mesh is still primarily used for building automation applications**, such as automating smart home devices and lighting systems, while other protocols like Zigbee are more widely used for things like asset tracking and industrial automation. ![Bluetooth mesh lighting example](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/meshnetwork-6-resized-1-jpeg.jpg) ## Bluetooth mesh networking - must-know concepts To understand how Bluetooth mesh operates, there are a few (or maybe more than a few!) concepts you need to know: - **Mesh nodes:** A mesh node is a device that has joined a Bluetooth mesh network. Devices that are not part of the network are called unprovisioned devices. Once an unprovisioned device gets provisioned, it joins the network and becomes a node. - **Elements:** A node may contain multiple parts which can be controlled independently. For example, a light fixture may contain multiple light bulbs which can be turned on/off independently. These different parts of a single node are referred to as elements. - **Models:** A model defines some or all functionality of a given element. There are three categories of models: server model, client model, and control model. - **States:** Elements can be in various conditions, represented by state values. For example, on and off are states of a lightbulb within a light fixture. A change from one state to another is called a **state transition**. This can be instantaneous, or it can occur over time after what’s called a transition period. When a state change occurs, it is likely to cause a change in the behavior of an element. - Properties: Properties add some context to a state value. For example, defining that a temperature value is an outdoor or indoor temperature. There are two types of properties: manufacturer property, which provides read-only access, and **admin property,** which provides read-write access. - **Scenes:** A scene is a stored collection of states and is identified by a 16-bit number which is unique within the mesh network. Scenes allow triggering one action to set multiple states of different nodes. They can be triggered on-demand or at a specified time. - **Messages:** Messages are the mechanism by which operations on nodes are invoked. If a node needs to report its status, it also sends it via a message. A given message type represents an operation on a state or collection of multiple state values. - **Addresses:** Messages in a Bluetooth mesh network must be sent to and from an address. 💡 **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## How does Bluetooth mesh communication work? The way messages are exchanged in a Bluetooth mesh network is via the publish-subscribe pattern. **Publishing** is the act of sending a message. **Subscribing** is a configuration used to allow select messages to be sent to specific addresses for processing. Typically, messages are addressed to group or virtual addresses. ### Types of Bluetooth mesh messages There are three types of messages in Bluetooth mesh, each of which is defined by a unique opcode (operation code): - **A GET message**: a message to request the state from one or more nodes. - **A SET message**: a message to change the value of a given state. - **A STATUS message**: A status message is used in different scenarios: - In response to a GET message, containing the state value. - In response to an acknowledged SET message. - Sent independently of any message to report the element’s status. One example is a message that’s triggered by a timer running on the element sending this message. Some messages require an acknowledgment message to be sent by the receiver of the original message. An acknowledgment message serves two purposes: - Confirmation of receipt of the message. - Return of data related to the message received. If a response to the message is not received by the sender, or an unexpected response is received, the sender may resend the message. Multiple acknowledged messages received by a node do not affect the behavior (it’s as if the message was received once). ### Managed flooding Many mesh networks use routing mechanisms to relay messages across the network. The other extreme is to flood the network with the messages being relayed without consideration of the optimal routes these messages need to take to reach their prospective destinations. Bluetooth mesh uses a technique that’s a compromise of both of these techniques. This technique is referred to as **managed flooding**. Managed flooding relies on broadcasting messages to all nodes within range of the sender node, with a few added optimizations: - **Messages have a TTL assigned** **TTL** stands for **time-to-live**, which limits the number of hops a message can take across multiple nodes within the mesh network. A value of **zero** indicates that a message *has* not been relayed and *should* not be relayed. This means that a node can send a message to other nodes which are in its direct radio range and indicate to the receiving node(s) that the message should not be relayed. If a message is sent with a **TTL ≥ 2**, then each time it is relayed, the TTL value gets decremented. A TTL value of **1** means that the message may have been relayed at least once, but that it should not be relayed again. - **Messages are cached** **Message caching** is required by all nodes and requires that messages received that already exist in the cache get immediately discarded. - **Heartbeat messages are sent periodically** **Heartbeat messages** are used to indicate to other nodes that the sender is alive and active within the network. - **Friendship** **Friendship** refers to the relationship between two nodes. These two node types are: - A **low-power node**, or **LPN**, conserves power and is not able to receive mesh messages all the time. This node spends most of its time with the radio turned off. - A live-powered node called the **friend node,** which can serve as a proxy for the LPN. The friend node caches messages for the LPN to save power, so that the LPN can stay asleep most of the time and only wake up occasionally. When the LPN wakes up, it polls the friend node to read the cached messages and sends any messages it needs to send to the mesh network. ## Types of nodes All types of nodes can send and receive mesh messages. However, optional features give particular nodes special capabilities. Here are the different types of nodes with optional features enabled: - Relay nodes - Proxy nodes - Friend nodes - Low power nodes ![Relay Node](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/mesh-relay-node.png) *Relay node* A node may support none, some, or all of these optional features, which may be enabled or disabled at any time. For example, a single node may have the features of a **relay node**, **proxy node**, and **friend node**, all at the same time. ### Relay nodes A **relay node** is one that supports the relay feature. This means it can retransmit messages that are broadcast by other nodes. This enables extending the reach of these messages and allows them to traverse the entire network beyond the reach of the original transmitting node. ### Proxy nodes To allow communication with a mesh network from a non-mesh-supported BLE device, a special type of node called a **proxy node** can be utilized. A proxy node acts as an intermediary and utilizes GATT operations to allow other nodes outside of the mesh network to interface and interact with the network. ![Proxy Node](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/mesh-proxy-node.png) *Proxy node* The protocol used in this case is called the **proxy protocol**, which is intended to be used with a connection-enabled device (using GATT). The protocol is built on top of GATT and allows a device to read and write proxy protocol PDUs from GATT characteristics exposed by the proxy node. The proxy node performs the translation between proxy protocol PDUs and mesh PDUs. For example, this allows a smartphone that does *not* implement the Bluetooth mesh protocol to interact with a mesh network via a proxy device through GATT operations. ### Friend Nodes and Low Power Nodes A **friend node** and a **low-power** node (LPN) are closely related to each other. In fact, in order for a low-power node to participate in a Bluetooth mesh network, it requires a *friendship* relationship with another node, called the **friend node**. Here are how these two types of nodes work together: ![Friend nodes and low power nodes](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/friend-node.png) *Friend nodes and low-power nodes* - Low-power nodes usually have limited power supply, such as batteries, so they need to conserve energy by keeping the radio off as much as possible. - Low-power nodes may be concerned with sending messages more than receiving them. Take, for example, a temperature sensor powered by a coin cell battery. It may need to send the temperature reading once per minute whenever that reading is above or below a set limit. If the user decides to change the threshold limit, then that gets sent in a message to the temperature sensor. In order for the sensor to not miss this threshold configuration message, it needs to be on all the time, meaning it will consume a lot of power. - To solve the problem mentioned in the previous point, the concept of a friend node is introduced. A friend node lets the low-power node stay asleep longer. - Friend nodes make this possible by caching messages that are destined for the low-power node. The low-power node, at its control, wakes up and polls the friend node for these cached messages. When it polls for the messages, it also sends any messages it needs to relay to the network to its friend node. - The relationship between a friend node and a low-power node is known as “friendship.” - Friendship is key to allowing power-constrained nodes to participate in a mesh network while keeping their power consumption optimized. 💡 **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## Bluetooth mesh example Here’s an example of a mesh network in a home that’s composed of 6 light switches and 9 light bulbs. The network utilizes the publish-subscribe method to allow nodes to send messages to each other. ![Publish-subscribe in Bluetooth mesh lighting control system](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bluetooth-mesh-publish-subscribe.png) *Publish-subscribe in Bluetooth mesh lighting control system (Source: “Bluetooth Mesh – An Introduction for Developers”)* Nodes may subscribe to multiple addresses. An example of this is light #3 in the above figure, which is subscribed to both the *kitchen* and the *dining room* group addresses. Also, multiple nodes may publish to the same address, such as switches #5 and #6 in this example. These two switches control the same group of lights located in the garden. The benefit of using group or virtual addresses is that adding or removing nodes does not require the reconfiguration of nodes. ## Bluetooth mesh architecture Bluetooth mesh builds on top of Bluetooth LE. It specifically utilizes the advertising state of BLE devices. Devices within a Bluetooth mesh network do not connect to each other as traditional BLE devices do. Rather, they use advertising and scanning states to relay messages to each other. There is one exception to this in a special device that can be part of the mesh network, the proxy node (which we covered in the previous section on “Node Types”). ![Bluetooth Mesh Architecture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/mesh-architecture.png) *Bluetooth mesh architecture* Here’s a description for each of the layers within the architecture of Bluetooth mesh (starting with the bottom layer): 1. **Bluetooth Low Energy layer** As we mentioned earlier, Bluetooth mesh builds on top of Bluetooth LE, so it requires a full BLE stack to be running on the device. It utilizes the advertising and scanning states for sending and receiving messages between devices within the mesh network. It also supports the connected state and GATT for the **proxy nodes**. 2. **Bearer layer** The **bearer layer** defines how the different mesh packets (Protocol Data Units or PDUs) are handled. There are two types of Bluetooth mesh bearers: - Advertising bearer: this bearer utilizes the advertising and scanning states of BLE devices. - GATT bearer: this bearer utilizes the connection state of BLE devices. It allows non-mesh supporting devices to interact with the mesh network via GATT operations. This is accomplished via the proxy node. 3. **Lower transport layer** This layer handles two main tasks: - Segmentation of packets from the layer above (upper transport layer) - Reassembly of packets from the layer below (bearer layer) 4. **Upper transport layer** This layer is Responsible for the following functionalities: - Encryption - Decryption - Authentication - Transport control messages (heartbeat, friendship, etc.) 5. **Access layer** This layer defines how the application uses the upper transport layer. It handles the following tasks: - Application data format - Encryption and decryption - Data verification 6. **Foundation Models layer** This layer is concerned with network configuration and network management models. 7. Models layer This layer addresses the implementation of **models**, including behaviors, messages, states, and state bindings. ## The provisioning process The **provisioning process** is one of the most important concepts in Bluetooth mesh. It is used for adding devices to the mesh network. A device that gets added to the network is called a **node**, and the device used to add a node to the network is called the **provisioner** (usually a tablet, smartphone, or PC). This process involves five steps: ### Step 1: Beaconing Step 1 involves what’s called **beaconing**, where the unprovisioned device announces its availability to be provisioned by sending the **mesh beacon** advertisements in the advertisement packets. This is a new type of advertisement data type introduced in the Bluetooth mesh standard. A common way to trigger this process is via a defined sequence of button presses on the unprovisioned device. ### Step 2: Invitation When the provisioner discovers the unprovisioned device via the beacons that were sent, it sends an **invitation** to this unprovisioned device. This uses a new type of PDU introduced in Bluetooth mesh called the **provisioning invite PDU**. The unprovisioned device then responds with information about its capabilities in a **provisioning capabilities PDU**, which includes: - The number of elements the device supports. - The set of security algorithms supported. - The availability of its public key using an **Out-of-Band (OOB)** technology. - The ability of this device to output a value to the user. - The ability of this device to allow a value to be input by the user. ![Provisioning Invite step](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/mesh-provisioning-invite.png) *Provisioning invite step* ### Step 3: Public key exchange Security in Bluetooth mesh involves the use of a combination of symmetric and asymmetric keys, such as the Elliptic-curve Diffie-Hellman (ECDH) algorithm. In ECDH, public keys are exchanged between the provisioner and the device to be provisioned. This is done either directly over BLE or via an **out-of-band (OOB)** channel. ![Public Key Exchange step](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/mesh-public-key-exchange.png) *Public key exchange step* ### Step 4: Authentication The next step is to **authenticate** the unprovisioned device. This usually requires an action by the user to interact with both the provisioner and the unprovisioned device. The authentication method depends on the capabilities of both devices used. In one case, called the **output OOB**, the unprovisioned device could output a random single- or multiple-digit number to the user in some form, such as blinking an LED a number of times. That number is then input into the provisioning device via some input method. Other cases include an **input OOB**, where the number is generated by the provisioner and entered into the unprovisioned device, a **static OOB**, or **no OOB** at all. Regardless of the authentication method used, the authentication also includes a confirmation value generation step and a confirmation check step. ![Authentication step](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/mesh-authentication.png) *Authentication step* ### Step 5: Provisioning data distribution After authentication is complete, each device derives a **session key** using its private key, and the public key is sent to it from the other device. The session key is then used to secure the connection for the exchange of additional **provisioning data**, including the **network key (NetKey)**, a **device key**, a security parameter known as the **IV index**, and a **unicast address** which is assigned to the provisioned device by the provisioner. After this step, the unprovisioned device becomes known as a **node**. ## How is security handled in Bluetooth mesh? The first important note regarding security in Bluetooth mesh is that it is *mandatory*. This is compared to BLE, where it’s optional and left to the developer to decide whether to include it or not. Here are some of the basics of security in Bluetooth mesh: - All mesh messages are encrypted and authenticated - Network security, application security, and device security are all handled independently. - Security keys can be changed during the life of the mesh network Due to the separation of security between the network, application, and device levels, there are three types of security keys (each addressing a specific concern): - **Network key (NetKey)** Possession of this shared key makes the device part of the network (also known as a node). There are two keys derived from the NetKey: the **network encryption key** and the **privacy key**. Possession of the NetKey allows a node to decrypt and authenticate up to the **network layer**, allowing the relay of messages but no application data decryption. - **Application Key (AppKey)** This is a key that’s shared between a subset of nodes within a mesh network, normally those that participate in a common application. For example, a lighting system AppKey would be shared between light switches and light bulbs, but not with a thermostat or a motion sensor. An AppKey is used to decrypt and authenticate messages at the application level, but it is only valid within one mesh network, not across multiple networks. - **Device Key (DevKey)** This is a device-specific key that’s used during the provisioning process for securing communication between the unprovisioned device and the provisioner. ### Node removal One major concern with a mesh network is gaining access to a network via a discarded or removed device that used to be part of the network. This can be accomplished via gaining physical access to the keys stored within the device (often referred to as a **trash can attack**). In order to protect against such an attack, Bluetooth mesh defines a procedure for the removal of a node where the device is added to a blacklist and the keys are refreshed. This process distributes new network keys, application keys, and other relevant data to all nodes except those in the blacklist. ### Privacy Another concern is **privacy**. The way privacy is addressed in Bluetooth mesh is via the use of a **privacy key** that’s used to obfuscate the message header. The privacy key is derived from the network key (NetKey). For example, the source address could be obfuscated to prevent tracking of a device via its address. ### Replay attacks The last security topic we want to cover is **replay attacks**. A replay attack is when one or more messages are stored and replayed later by a malicious device. Bluetooth mesh provides protection against replay attacks by: - Utilizing a **sequence number (SEQ)**. Elements increment the SEQ value every time they publish a message. A node, receiving a message from an element that contains an SEQ value that’s less than or equal to the one in the last valid message, will discard it (since it is likely that it relates to a replay attack). - Using an incrementing **IV index**, which is an additional value that also gets validated when a message is received. ## Conclusion While some may say that Bluetooth mesh has had a slow adoption rate, there’s still real potential for it to enable IoT applications in the near future. In this post, we covered a lot, and there's still so much more to learn about Bluetooth mesh. Look for a series of upcoming posts covering more of the implementation aspects of the technology, where we build out both a Bluetooth mesh light bulb and a light switch. 💡 **Insider Tip:** Want to get your Bluetooth-connected devices to market faster? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### What is a Bluetooth Beacon? iBeacon, Eddystone, and Use Cases URL: https://novelbits.io/what-is-a-beacon-guide-to-bluetooth-beacon-technology/ Last updated: 2026-08-09T05:26:48.000Z Bluetooth beacons are alive and well due to their low cost and widespread usage in commercial spaces like retail stores and logistics. The technology itself has been around for a while but gained widespread awareness when Apple released its iBeacon protocol in 2013\. Since then, adoption has increased as businesses and developers come up with creative ways to use the technology. Whether you're a consumer looking to understand how these little devices work or a Bluetooth developer looking to dive into the technical specs, *you'll find what you need in this article.* ## What is a beacon? **Bluetooth beacons** are small wireless, usually battery-powered devices that transmit data at regular intervals using Bluetooth Low Energy (BLE).This mini-radio transmission device can be ‘discovered' and seen by all BLE scanners within a certain radius. The Bluetooth beacon, however, cannot ‘see' anyone back. It doesn't require an Internet connection and acts as a broadcaster within a short-range radius. The receiving device, such as a BLE-enabled smartphone, often acts as an intermediary device that uses the information from the beacon to transfer it somewhere or do something with it. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83573d5c4a.jpg) Bluetooth beacons enable the connection between the physical and digital world by creating a communication bridge between enabled devices and the person carrying them. In doing so, Bluetooth Low Energy beacons allow businesses to automate certain processes and enhance experience-based actions and interactions. ## Beacon technology: a brief history The original Bluetooth technology was originally created by Dr. Nils Rydebeck and Dr. Johan Ullman in 1989. Since then, Bluetooth has gone through many iterations to include more features, increased speed, and bandwidth. The Bluetooth specification is managed by the [Bluetooth SIG](https://www.bluetooth.com/?ref=novelbits.io), which released corresponding Versions 2.0 and 3.0\. These versions required a two-way connection to work — meaning that devices are required to actively connect with one another through pairing. In 2010, **Bluetooth Low Energy (in version 4.0)** was released and allowed for one-way communication (Hint: this is what enabled beacon technology!). This meant that devices could be configured to only transmit and aren’t required to listen, thus reducing power consumption significantly in the process. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a8357436260.jpg) On June 10th, 2013, Apple introduced **iBeacon** as part of iOS 7 at the World Wide Developer Conference (WWDC 2013). iBeacon is a protocol standard that enables mobile apps to listen for signals from beacons in the physical world and respond accordingly. This led to the growth and adoption of **Bluetooth beacon technology**. By 2014, over 50 of the top 100 US retailers began to test beacon technology in their shops for contextual advertising and behavioral data gathering. Around this time, Google also launched the Physical Web, which is a Chrome browser-based beacon scanner. The idea behind this is that unlike iBeacon, which required an app, Google's Physical Web will allow a user through Google's Chrome web browser to accept the URL and see the web pages with the associated spaces. However, it should be noted that Physical Web was discontinued in 2018 and is no longer supported. In 2016, Google announced the **Eddystone-EID standard**. This standard is similar to Apple's iBeacon protocol but with additional features to include encrypted identifiers, telemetry data, and more. More recently, we have seen a wide range of beacon applications from asset tracking to proximity marketing - more to come on that later! ## Beacon technology - an overview So how do beacons work? In this section, we’ll cover an overview of everything you need to know to understand how **BLE beacons** work - and how you might be able to make use of them yourself. ### How do beacons communicate? Bluetooth beacons work by transmitting packets of data that are picked up by a compatible receiving device via radio waves. These packets of data are either self-contained or are triggers to events on the receiving device, such as push notifications, app actions, and prompts. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83574606d8.jpg) BLE uses the same spectrum range as Bluetooth Classic (2.400–2.4835 GHz ISM band) but on a different set of channels. BLE has 3 primary advertising channels. This makes it faster for devices to connect and reduces a listening device's scanning time. To prevent narrowband interference problems, BLE uses adaptive frequency hopping mechanisms via digital modulation techniques or direct-sequence spread spectrum to counteract. ### What's the transmission range of a beacon? A **Bluetooth beacon** has a theoretical maximum radius distance of less than 100m. The actual range and response time depend on the beacon itself and what process it has been programmed to do. BLE is mostly used in short-range applications (using the standard 1M PHY). **Most Bluetooth beacons can reliably transmit up to approximately 30 meters without any physical obstructions.** A typical operating range is around 2 to 5 meters, depending on the transmit power. The higher the range, the higher the battery consumption. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83574bf261.jpg) *Example of a Bluetooth Classic connection* ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a8357520ca7.jpg) *Example of a Bluetooth beacon* In the case of smart devices like a phone, the acceptance of a BLE broadcasting signal is often enabled through an app that allows for automated scanning to occur. ### The hardware inside beacon devices Inside a beacon, you will find a small microprocessor, a radio, and a small battery (typically a lithium-ion battery). This extremely limited hardware makes beacon devices very cost-effective and easy to maintain. ### Do beacons use Classic Bluetooth (BR/EDR) or Bluetooth Low Energy (BLE)? Bluetooth beacons use Bluetooth LE due to their fundamental need for one-way communication. On the other hand, Bluetooth Classic (BR/EDR) isn't feasible for beacon applications because it requires two-way communication. This is an important distinction. Despite Bluetooth Classic and Bluetooth Low Energy sounding similar, they are two distinct protocols that are incompatible. Because beacons utilize BLE, you will sometimes hear a beacon referred to as a "BLE beacon." ### Beacon standards - iBeacon, Eddystone, AltBeacon There are three main beacon standards: 1\. **iBeacon standard:** A protocol developed by Apple in 2013 and introduced at the Apple Worldwide Developers Conference. Being the first official beacon standard, there is widespread acceptance by developers and hardware support. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83578ea9f1.png) *The iBeacon Packet Format* While iBeacon is only officially supported by iOS, APIs exist for Android applications to scan for iBeacon broadcasts. To do this, a user must have an app installed that’s developed to find the beacon and do something with it. 💡 **Learn More:** [Implementing Bluetooth Beacons (iBeacons) nRF52 Use Case](https://novelbits.io/eddystone-beacons-zephyr-nrf52/) 2\. **Eddystone standard**: ABluetooth Low Energy data format that was released in 2015 by Google. It is an open protocol that is open-source and cross-platform, supporting both iOS and Android. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83579170af.png) *The Eddystone beacon packet format* Unlike iBeacon, Eddystone only supports one main basic interaction — the “Eddystone discovery,” which is a similar concept to iBeacon’s ranging. However, Eddystone also added multiple types of data (called *frames*) that include much more information than what’s in the iBeacon protocol. For example, battery voltage reading, temperature, advertising count, and more. 3\. **AltBeacon standard**: Not as popular as iBeacon and Eddystone, this is an open specification that was developed by [Radius Networks](https://www.flybuy.com/?ref=novelbits.io). It was developed to provide a free, vendor-agnostic, open-source beacon standard. ### Mobile support (Android and iOS) for beacons Support for the beacon standards differs somewhat between iOS and Android mobile device operating systems. This is partly due to the fact that Apple owns and manages the iBeacon standard. On iOS, you’ll find built-in support for iBeacon, but Eddystone is not natively supported. To use Eddystone, you’ll need to use Core Bluetooth APIs, and you will still encounter some limitations. On Android, there is no longer any special treatment for Eddystone beacons. iBeacons and Eddystone beacons are treated just like any other BLE device. I recommend using an open-source library such as Radius Networks' [Android Beacon library](https://altbeacon.github.io/android-beacon-library/index.html?ref=novelbits.io). ## iBeacon vs Eddystone: a quick comparison Before we get into the broader pros and cons of beacon technology, let's pin down the practical differences between the two formats most often discussed. If you're evaluating beacons for a project today, this is the comparison you actually need. | | iBeacon | Eddystone | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Maker** | Apple | Google | | **Released** | 2013 | 2015 | | **Status** | Active, still maintained | Google deprecated the Eddystone services and tooling in 2022 (still works, but no longer recommended for new deployments) | | **Identifier model** | Single 128-bit UUID + 16-bit Major + 16-bit Minor | Multiple frame types (see below) | | **Frame types** | One: a fixed advertising payload structure | Four: UID (identifier), URL (broadcasts a web URL directly), TLM (telemetry like battery, temperature), EID (ephemeral, rotating identifiers for privacy) | | **Open standard?** | Proprietary to Apple, but the wire format is well-documented and widely reverse-engineered | Yes, open-source spec on GitHub | | **iOS support** | First-class, including background ranging APIs | Limited; iOS sees Eddystone beacons but doesn't have the same dedicated APIs as for iBeacon | | **Android support** | Yes (via standard BLE scanning + manual frame parsing) | First-class historically; still works on Android today | | **Best for** | Apps that need to wake up the user's iPhone when entering a region, or that need region-monitoring while the app is backgrounded | Use cases where you want to broadcast a URL directly (no app needed) or rotate identifiers for privacy | For new projects in 2026, the practical pick is usually iBeacon — not because it's technically superior, but because Eddystone's deprecation by Google means there's no clear momentum behind it. That said, if your use case specifically benefits from one of Eddystone's frame types (broadcasting a URL without requiring an app, for example), it's still a valid choice; the protocol itself works fine on the air. The frame-format details and the underlying Bluetooth LE advertising mechanics are the same for both — both are just specific ways of structuring the payload inside a standard Bluetooth LE advertising packet. The difference is in what the payload says and how mobile OSes interpret it. ## The advantages of Bluetooth beacons **BLE beacons** provide many benefits to both developers and consumers. A few of the most important include: - **Low cost**. Because of their design, beacons are cheap to build. This makes them easy for developers to work with as well as practical for a variety of industries to purchase at scale. - **Easy to install**. Beacons are purposely designed to be small and simple to install in a variety of contexts. There are many types of beacons available that are built for specific applications, such as being mounted to a wall. - **Low maintenance**. Due to the low power consumption, beacons have great battery life. Many Bluetooth beacons can last up to 3 years without a battery replacement. - **Receiving device flexibility**. While the beacons don't listen for a response, the receiving device can perform actions based on the beacon's instructions. This includes, and is not limited to, things like check-ins on social media, location-based actions, push notifications, or sending data via the user's Internet connection. ## Disadvantages of Bluetooth beacons On the flip side, there are some downsides to beacons. A couple I find the most important to consider are: - **They don't work by themselves**.A beacon is one part of a system. By this, I mean that the entire setup relies on users carrying a compatible device (in most cases). - **Functionality is limited by receiving device**.Bluetooth beacon triggers can also be limited by the quality of the receiving device's connection to the Internet. Sometimes, a roadblock can be as simple as a user needing to accept consent requirements when automatically logging into Wi-Fi hotspots first. ## How are beacons being used? (real applications) Bluetooth beacons were originally seen as an opportunity to offer users customized retail-related things like discounts and purchase suggestions. Its real-life applications, however, have extended beyond just retail. Here are a few examples of how Bluetooth beacons are currently being used: ### Key finders and tags The popular Tile key finder tag started as a Kickstarter that raised over $2.6 million through preorders sold direction to 50,000 backers. **Tile is a Bluetooth beacon that lets users find the attached item**, such as your keys or wallet, all through an app on your phone. Other similar products include Chipolo, TrackR, Orbit, and Mynt. ### Indoor Navigation Disneyland Resort uses Bluetooth beacons to help guests navigate and use the theme parks and its resorts. This allows users to use an interactive map with relevant and real-time offerings that a physical map cannot replicate. When the app is downloaded and BLE access is granted on the user’s phone, **the visitor’s time at the theme park is customized based on personal preferences and any additional data** given to Disneyland. Many airports, museums, sports stadiums, and shopping malls also utilize Bluetooth beacons for this same purpose. ### Enabled experience San Franciso’s Asian Art Museum currently employs Bluetooth beacons as part of an enhanced visitor experience by offering exhibit information based on where they are standing in the Museum. With over 18,000 pieces, the Asian Art Museum contains one of the largest Asian art collections in the world. **Bluetooth beacons have been used to enhance the overall experience of a visitor** by giving them immediate access without additional hardware or physical informational devices that are usually costly or oversized. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835788d2bf.png) *Event experience enabled by Bluetooth beacon technology* ### Asset tracking In some systems, the receiver is instead a fixed device installed in a facility, and the beacons are mobile. One example of this is an asset tracking system with a fixed locator device. In this situation, the beacons are attached to assets to track their location within a facility. ## Summary Bluetooth beacons have had an interesting recent history, but with new creative uses for the technology popping up constantly, Bluetooth beacons aren’t going anywhere. Bluetooth beacons' **low energy consumption** makes them highly desirable from a maintenance perspective. Their **low cost** makes them highly desirable for long-term and mass implementations. Their **decade worth of history**, support, and development by major tech companies make the technology reliable with future growth, stability, and support. 💡 **Insider Tip:** Want to dive deeper into Bluetooth beacon technology and implementation? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. 💡 **Insider Tip:** Want to dive deeper into Bluetooth beacon technology and implementation? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### 7 Cool Projects You Can Build with the InPlay NanoBeacon™ IN100 URL: https://novelbits.io/in100-inplay-bluetooth-beacon-seven-cool-projects/ Last updated: 2026-08-09T05:44:12.000Z **This article is sponsored by [InPlay, Inc](https://inplay-tech.com/?ref=novelbits.io). However, the opinions expressed by the author about the InPlay IN100 SoC are his own and were not influenced by the sponsor.** A few weeks ago, I published an article and video covering the world's first **programming-free** Bluetooth beacon development platform. You can check out the abovementioned post [here](https://novelbits.io/inplay-nanobeacon-in100-programming-free-bluetooth-beacon/). If you're unfamiliar with InPlay and their latest NanoBeacon™ family of chipsets (including the IN100), it's an innovative company focused on providing an **easy-to-use**, **ultra-low cost**, **and ultra-low power** solution for Active RFID and wireless sensor solutions. I also recommend you check out my Hackster.io project on getting started with the IN100: The IN100 is the first of the NanoBeacon™ family of chipsets primarily focused on ultra-low cost and ultra-low power with a minimal physical footprint (as small as 2.5x2.5 mm). Other solutions in the market might focus on both low-power and low-cost. But, all of these other solutions require a high upfront investment cost: **firmware development**. The IN100 requires no programming at all and minimal knowledge of the Bluetooth Low Energy protocol. This is achieved via a companion desktop application called the NanoBeacon™ Config Tool. This application now supports all major platforms: macOS, Linux, and Windows, and allows you to configure and flash your IN100 in a matter of minutes without writing a single line of code. This is a significant breakthrough in the field of IoT development, whether that's for industrial, commercial, or even consumer applications. Ideal target solutions include active RFID, asset tracking, and wireless sensors. ## The challenge with the current IoT market There are many problems with the current IoT market. This includes many obstacles that entrepreneurs, innovators, and especially hobbyists face when looking to add wireless connectivity to their products. This applies to even the simplest applications, like a wireless sensor or a beacon tag! Let's discuss the different challenges and difficulties in the current IoT market, learn how the InPlay NanoBeacon™ SoCs help us overcome these challenges, and finally, go over some really cool projects that you can build with the InPlay IN100. Here are the three prominent challenges in the IoT market today: 1. **Complexity and barrier of entry**: Wireless technology can be daunting to a newcomer or a non-technical person. Most people don’t know where to start when adding wireless connectivity to their products. 2. **Cost**: Firmware development is very expensive 💰 and adding wireless technology to a product increases its BOM cost in a non-insignificant way 3. **Time**: The length of time to design a wireless connected product is long Wouldn’t it be nice if there was a solution to all these problems? Well, I’m here to tell you that there is! ## How the InPlay IN100 solves today's IoT market challenges InPlay’s unique NanoBeacon family of SoCs was designed from the ground up to address each and every one of these challenges. How does it address them, you ask? Let’s take a look! 1. **Complexity and barrier of entry**: Innovators coming from the sensors world or RFID field may not know where to start and how to add wireless connectivity to their products. They might be afraid of the unknowns and the complexities associated with wireless protocols (from Bluetooth LE to WiFi to ZigBee, you name it!). With the InPlay IN100, a Bluetooth Low Energy chipset and the first of the NanoBeacon family, you don’t need to know much about Bluetooth LE or even wireless technologies in general. And the things you need to know are covered in video tutorials available on the InPlay website. This can help you get started with minimal to zero knowledge of Bluetooth LE. 2. ****Cost:** The IN100 was designed to be 100% programming-free. That means you can go from designing your product to shipping it to customers without writing a single line of code and without spending thousands of dollars $$ on firmware development. The IN100 was also designed to be ultra-low cost. We’re talking **under $1** for a fully packaged certified Bluetooth beacon tag (excluding external peripherals). This makes the IN100 an ideal choice for cost-sensitive applications such as Active RFID and wireless sensor applications., 3. **Time**: The NanoBeacon™ Config Tool application allows you to configure and design your IN100-based application in hours! ... instead of the weeks- and months-long process that comes with firmware development. ## Seven practical IN100 projects Here are seven cool projects that you can build today using the IN100\. Each of these takes only hours or even minutes to configure and design using the NanoBeacon™ Config Tool. ### 1\. Wireless Weather Station (I2C sensors) ![Wireless weather station project icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/weather-station-e1662948409923.png) Whether it's temperature, humidity, air quality, or air pressure, nowadays, you can find a digital sensor for almost any sensing application you can think of. With the IN100, you have many options when connecting peripherals. You can configure the device to advertise the values captured from multiple connected peripherals in a single advertising packet. It supports interfacing with both simple GPIO and I2C sensors. Alternatively, you can configure it to act as if it's three independent devices, each with its own: advertising packet containing readings from a specific GPIO-connected sensor, a different device name, and even a different Bluetooth address. For example, you could include the temperature in one advertising set with the device name "Temperature," the humidity in another advertising set with the device name "Humidity," and air pressure in the final advertising set with the device name "Air Pressure." Examples of sensors you could incorporate into such as system include: - **Sensirion SHT40** (Temperature and Humidity) - I2C. You could use a breakout board for easy integration and testing. One such example is [Adafruit's breakout board for this sensor](https://www.adafruit.com/product/4885?ref=novelbits.io). - **Bosch BME680** (Temperature, Humidity, Pressure, and Gas) - I2C You could use a breakout board for easy integration and testing. One such example is [Adafruit's breakout board for this sensor](https://www.adafruit.com/product/3660?ref=novelbits.io). ### **2\. Plant Watering Monitoring System (Analog sensors)** ![Plant watering monitoring system project icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/soil-analysis-e1662991498861.png) In addition to digital input, the IN100 also supports interfacing with analog sensors via the built-in ADC. It features four ADC channels available on GPIO pins: ![IN100 ADC channels and their respective GPIO pins](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/adc-channels.png) ADC Channels and their respective GPIOs The internal ADC has **11 bits** referenced by an internal **0.8 Volt bandgap reference**. This means we have ADC values ranging from **0 – 2047**, and the analog input signal range is from **0 – 2\*ReferenceVoltage** (up to 1.6 Volts). If you'd like to get started with an example project for measuring soil moisture using an analog such as the [DFRobot Soil Moisture sensor](https://www.dfrobot.com/product-2054.html?ref=novelbits.io), then check out my recent Hackster.io project: This is just a simple example project that you can use as a starting point to add your own sensors and peripherals and customize its advertising behavior and data. ### 3\. Smoke Detector ![CO2 smoke detector](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/co2-sensor.png) Say that you want to build your own smoke detector to detect when smoke or even flammable gas is in the area and notify you when this occurs, then you can simply use a sensor such as the [MQ-2 sensor from Winsen](https://www.winsen-sensor.com/sensors/combustible-sensor/mq2.html?ref=novelbits.io). [MQ2 Sensor from Sparkfun](https://www.sparkfun.com/smoke-sensor-mq-2.html?ref=novelbits.io) and its [breakout board](https://www.sparkfun.com/gas-and-smoke-analog-sensor-breakout-board-mq-2.html?ref=novelbits.io). ![MQ-2 sensor and breakout board from Sparkfun](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-18.png) MQ-2 Sensor and breakout board from Sparkfun The sensor can be interfaced with using I2C, which is simple to do via the InPlay NanoBeacon™ Config Tool. ### 4\. Key Finder (Bluetooth Beacon) ![Key finder Bluetooth beacon project icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/key-tag.png) For simple applications such as item finding, one implementation would be to utilize an iBeacon or Eddystone advertising device (Bluetooth beacon). The InPlay IN100 not only supports **Eddystone** and **iBeacon** formats, but it can also be configured to advertise your own **custom beacon/data format**. Once you have the IN100 configured with the chosen advertising data format, you could utilize the RSSI of the advertising packets to determine the proximity of the item the IN100 is attached to. 💡**Tip:** The IN100 also supports including Constant Tone Extension (CTE) data in the advertising data, part of the Direction Finding feature introduced in Bluetooth version 5.1\. However, note that it is limited to using the Legacy Advertising data format, so your scanner will need to support parsing the CTE data in Legacy Advertising packets (vs. Extended Advertising packets). ### 5\. Mailbox Delivery Notification System ![Mailbox delivery notification system project icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/mail-box.png) Want to minimize your trips to the mailbox? Tired of not knowing when the mail was actually delivered? With a simple sensor such as the STMicroelectronics LIS3DH attached to your mailbox cover, you can detect when the cover has been open/closed. For this project, you could utilize a breakout board such as [this one from Adafruit:](https://www.adafruit.com/product/2809?ref=novelbits.io) ![Adafruit LIS3DH Triple-Axis Accelerometer ](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-8.png) Adafruit LIS3DH Triple-Axis Accelerometer (+-2g/4g/8g/16g) The sensor supports an I2C interface, which the IN100 supports, so it would be a matter of simply interpreting the sensor data and detecting when the cover is in the open vs. closed state. To understand how to work with the acceleration data, you can refer to [ST's App Note](https://www.st.com/resource/en/application%5Fnote/an3308-lis3dh-mems-digital-output-motion-sensor-ultralowpower-highperformance-3axis-nano-accelerometer-stmicroelectronics.pdf?ref=novelbits.io). ### 6\. Water Leak Detector ![Water leak detector project icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/leak-detector.png) Another really useful application that you can build with the IN100 is a water leak detector. A simple sensor like this one from Adafruit would do the job. It simply detects when water is present on the sensor and outputs a high signal. ![Simple Water Sensor (Adafruit)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-7.png) Simple Water Sensor (Adafruit) We can connect it to one of the GPIOs on the IN100 and either include the GPIO status in the advertising data or, better yet, configure a triggered advertising set that only gets broadcast when the GPIO is high. The IN100 has such low power consumption that one of its customers and partners, [Aquasensing](https://www.aquasensing.com/?ref=novelbits.io), has built a water leak detector device that is **100% battery-free**! ![Aquasensing Water Leak Detector](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-09-13-at-9-36-43-am.png) Aquasensing Water Leak Detector ### 7\. Loud Noise Detector ![Loud noise detector project icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/noise.png) Our final example of a project you can build using the IN100 is a loud noise detector. Whether that's for detecting a glass-break noise, a loud siren, or even gunshots, you can use a sensor like the [KY-37 sound detection module](https://electropeak.com/sound-sensor-ky-037?ref=novelbits.io): ![KY-037 Electret Microphone Audio Sensor Module package](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-4-4.png) KY-037 Electret Microphone Audio Sensor Module package The sensor module has two output options, an analog and a digital output. And you can use either with the IN100 since it supports GPIO and has an internal ADC for reading analog signals. ## Summary - InPlay IN100 As you can see, the sky is the limit with the applications you can build with the IN100! and best of all, you don't need to write a single line of code! To summarize, some of the pros of using the IN100 include: - 100% Programming-free - Ultra-low power – pairs well with energy-harvesting solutions - Ultra-low cost – under $1 for a fully-packaged, certified beacon (no peripherals) - Minimal footprint – 2.5 mm x 2.5 mm - Supports long-range (Coded PHY) mode – using Legacy Advertising events - Supports Direction Finding feature from Bluetooth 5.1 – using Legacy Advertising events Do you have an interesting application you would like to build with the IN100? Would you like to see detailed instructions for building one of the projects we listed? Let me know by sending me a message [here](https://novelbits.io/contact/). 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth Low Energy (BLE): A Complete Guide URL: https://novelbits.io/bluetooth-low-energy-ble-complete-guide/ Last updated: 2026-05-01T15:53:19.000Z The Internet of Things (IoT) has been a buzzword for decades, but today this market is far from theoretical. There are over [10 billion](https://dataprot.net/statistics/iot-statistics/?ref=novelbits.io) active IoT devices globally, and one of the key technologies enabling this market growth is Bluetooth Low Energy (BLE). Introduced in 2010, this flexible protocol provides wireless connection for many of IoT’s most critical applications. Its focus on operating with ultra-low power allows it to be used across industries such as consumer electronics, healthcare, and logistics. In this article, we’ll equip you with all of the basics of BLE, so you can jumpstart your next BLE development project and get a piece of the massive [$384 billion-dollar IoT market](https://www.marketsandmarkets.com/Market-Reports/internet-of-things-market-573.html?ref=novelbits.io#:~:text=%5B275%20Pages%20Report%5D%20The%20IoT,16.7%25%20from%202021%20to%202026.). Free 12-Day Email Course Learn Bluetooth LE in 12 Days A free crash course delivered to your inbox. One lesson per day — just the fundamentals you need to start building. Start the Free Course Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ## The Origins of Bluetooth The Bluetooth Specification has been around since the 90s. The original intent was to design a protocol that would take the place of cables for transmitting data between devices over short distances. Today, this is still its primary use case. Bluetooth is a short-range wireless technology that operates in the unlicensed 2.4 GHz ISM to transmit data and build personal area networks (PANs). Most of us probably have a handful of Bluetooth devices within grabbing distance right now: cell phones, laptops, headphones, and speakers. In fact, in 2021, there were over [4.7 billion Bluetooth devices](https://www.statista.com/statistics/1220933/global-bluetooth-device-shipment-forecast/?ref=novelbits.io#:~:text=Annual%20Bluetooth%20device%20shipments%20worldwide%20stood%20at%204.7%20billion%20units%20in%202021.) shipped globally. **Bluetooth is one of the most widely used technologies in the world.** Most people on the street would know what Bluetooth is - at least at a high level. But behind the scenes, it’s a relatively complex technology standard managed by a group known as the [Bluetooth Special Interest Group (SIG)](https://www.bluetooth.com/about-us/?ref=novelbits.io). Over the years, the Bluetooth SIG has released different versions of the Bluetooth Specification. The most popular protocols in the spec are **Bluetooth Classic** and **Bluetooth Low Energy**. Up until 2010, the focus was on enhancing Bluetooth Classic. But in 2010, the Bluetooth SIG released v4.0\. This version took a different direction than the previous versions by adding a new protocol: Bluetooth Low Energy (BLE). ## What is Bluetooth Low Energy (BLE)? Despite taking many cues from its predecessor, Bluetooth Classic, Bluetooth Low Energy is regarded as a different technology that specifically targets markets where the demand is for ultra-low power rather than high throughput. Data communication with an LE radio happens in short bursts that do not need to be very frequent. A typical LE use case would include periodically turning on the radio, transferring or receiving a few bytes or kilobytes of data, and then turning off and going back to sleep. This contrasts with Bluetooth Classic use cases where the radio is not turned off, like maintaining a connection for a lengthy period of time to guarantee the least latency when a call comes in, or use cases like the exchange of a large file. ## Bluetooth Classic vs. Bluetooth Low Energy (LE) While Bluetooth Classic and Bluetooth Low Energy protocols share many similarities, such as both being protocols covered by the Bluetooth Specification and both operating within the 2.4 GHz ISM band, they are two distinct, incompatible protocols. Bluetooth Classic is designed to handle a lot of data, but it also consumes power quickly. Think about transmitting music from your phone to Bluetooth headphones. That is a traditional use case for Bluetooth Classic. ![bluetooth classic vs bluetooth low energy (ble)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/ble-guide-stack.png) Bluetooth Low Energy vs. Bluetooth Classic BLE, on the other hand, is designed for applications that don’t require handling a lot of data but do require really good battery life. Think about a sensor in a temperature-controlled warehouse that you want to set and forget for months or even years. BLE would be a better fit for that kind of application. While there is more technical nuance to the two protocols, at a high level, the difference between Bluetooth Classic and Bluetooth Low Energy comes down to differences in power consumption and data throughput. ## Advantages of BLE By now, you understand that BLE was developed with a particular market in mind: that of devices that require low power and small data transmission. To help meet this market’s demand, Bluetooth Low Energy provides an array of advantages for both developers and end consumers of BLE devices. Let’s look at a few of the most valuable advantages of BLE: ![advantages of bluetooth low energy (ble)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/advantages-of-ble-1.png) Advantages of Bluetooth Low Energy ### **Low power consumption** Even when compared to other low-power technologies. BLE achieves optimized and low power consumption by keeping the radio off as much as possible and sending small amounts of data at low transfer speeds. **Low cost of entry into development** BLE modules and chipsets are low-cost when compared to other similar technologies. This is a result of the increased adoption rate and competition in the marketplace. ### **Open access to documentation** With most other wireless protocols and technologies, you would have to become a member of the official group or consortium for that standard to access the specification. Becoming a member of those groups can cost a significant amount (up to thousands of dollars annually). With BLE, the major version (4.0, 4.1, 4.2, 5.0, 5.1, 5.2, 5.3, etc.) specification documents are available to download from the Bluetooth.com website for free. ### **Prevalence in smartphones** This is probably the biggest advantage BLE has over its competitors, such as ZigBee, Z-Wave, and Thread. The vast majority of people in the world own a smartphone, and almost all of those smartphones have BLE hardware inside. This gives developers a much larger potential user base for their applications. ## Limitations of BLE As a developer, understanding the limitations of a particular technology is just as important as understanding its advantages. In this way, you can determine if a particular technology is a good fit for your application or not. Let’s look at a few of the most important limitations of BLE. ![Limitations of BLE](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/limitations-of-ble.png) Limitations of Bluetooth Low Energy ### **Data Throughput** The data throughput of BLE is limited by the physical radio data rate, which is the rate at which the radio transmits data. This rate depends on the Bluetooth version used. For Bluetooth versions earlier than 5.0, the rate is fixed at 1 Mbps. For Bluetooth 5.0 and later, however, the rate varies depending on the mode, and PHY (discussed later in the Physical Layer section) used. The rate can be at 1 Mbps like earlier versions or 2 Mbps when utilizing the high-speed feature. When utilizing the long-range feature, the rate drops to either 500 or 125 Kbps. At the application layer and for the end-user, the data rate is much lower than the radio data rate. ### **Range** BLE was designed for short-range applications; hence, its range of operation is limited. There are a few factors that limit the range of BLE, including: - It operates in the 2.4 GHz ISM spectrum, which is greatly affected by obstacles that exist all around us, such as metal objects, walls, and water (especially human bodies). - Performance and design of the antenna of the BLE device. - The physical enclosure of the Bluetooth Low Energy device affects the antenna performance, especially if it is an internal antenna. - Device orientation – effectively relates to the positioning of the antenna (e.g., in smartphones). ### **Gateway Requirement for Internet Connectivity** To transfer data from a BLE-only device to the Internet, another BLE device that has an IP connection is needed to receive this data and then, in turn, relay it to another IP device (or to the internet). ## BLE Applications When it was released in 2010, the BLE protocol primarily focused on the Internet of Things (IoT) applications where small amounts of data are transferred at lower speeds. Over the last decade, BLE has been used in various applications, from consumer devices to industrial manufacturing. Let’s take a look at a few of the most common applications we see today: - **Home automation:** Much of the home automation market is, in part, enabled by the use of Bluetooth LE. BLE technology enables devices like smart lights, smart thermostats, smart locks, and sensors that detect smoke or an ajar window. - **Fitness tracking:** Many of us have smartwatches or Fitbits that track our heart rate, steps, and more. These health and activity tracking devices communicate with apps on our phones using BLE. These short bursts of data at close range are a perfect candidate for BLE technology. ![ble-enabled fitness tracker](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/ble-guide-gap.png) - **Audio devices:** We’re all familiar with Bluetooth headphones, but typically these devices utilize Bluetooth Classic. One of the latest developments in Bluetooth Low Energyis LE Audio. This new standard offers several advantages over traditional Bluetooth, including improved audio quality, lower power consumption, and support for hearing aids. - **Contact tracing:** Smart contact tracing systems are starting to emerge to help prevent the spread of infectious diseases. Instead of manually reporting data that can be used to identify those who have been in close contact with an infected person, BLE-enabled contact tracing allows for continuous scanning of [BLE “tags”](https://kontakt.io/what-is-bluetooth-contact-tracing/?ref=novelbits.io) or [smartphones](https://www.apple.com/newsroom/2020/04/apple-and-google-partner-on-covid-19-contact-tracing-technology/?ref=novelbits.io) to anonymously track human touchpoints. - **Item finding tags:** An increase in travel chaos has had some people adding [AirTags](https://www.apple.com/airtag/?ref=novelbits.io) or [Tiles](https://www.thetileapp.com/en-us/?ref=novelbits.io) to their luggage in case it gets lost. These BLE-enabled precision tracking devices can be used for more than just luggage, though. You can pop one on anything you think you might lose, like a bicycle or your car keys, and track its location via a smartphone app. - **Targeted ads:** Imagine being at the clothing store and getting a push notification for a coupon delivered to your phone for the very store you’re in. These types of personalized, location-based ads are exactly what [advertisers and store owners can deliver](https://www.mokoblue.com/about-bluetooth-advertising/?ref=novelbits.io). This is thanks to enhancements found in Bluetooth 5.0 along with Bluetooth Beacons’ broadcasting technology. - **Inventory management:** Warehouse managers are starting to use BLE solutions to track temperature and humidity on sensitive shipments, detect drops for fragile items, and even map out the most optimal storage locations for assets within a warehouse. There is significant potential in this area to combine artificial intelligence and BLE to provide a truly smart logistics chain. ## BLE and the Internet of Things (IoT) While IoT technology has been around for some time, in recent years, it’s been gaining some serious traction. This traction means there’s also been an uptick in confusing explanations of what IoT is exactly.So, let’s break it down. The Internet of Things is the network of billions of devices - “things” - that are connected wirelessly to exchange data over the internet. IoT technology helps to connect things like thermostats, smart lights, people with embedded medical devices, animals with implanted trackers, and cars with driver-assist sensors. Any person, animal, or man-made object can become a “thing” in IoT. This means IoT is essentially connecting people, processes, and systems. ![bluetooth and the internet of things (IoT)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/ble-guide-gatt.png) To make all of these connections possible, IoT relies on wireless technologies. ZigBee, Bluetooth Classic, and WiFi can all be used to connect devices wirelessly. However, BLE is often viewed as the most optimal technology for IoT applications because of two main reasons: 1. ***Low power consumption.*** Many IoT devices are battery-powered and need to last in the field for a very long time. For example, it would simply be impractical to regularly replace the batteries in hundreds of sensors in a warehouse environment. 2. ***The type of data being exchanged.*** BLE is optimized to transmit a small amount of data. This works great for IoT devices like sensors that just need to transfer state data. Free 12-Day Email Course Learn Bluetooth LE in 12 Days A free crash course delivered to your inbox. One lesson per day — just the fundamentals you need to start building. Start the Free Course Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ## BLE Beacons Bluetooth beacons are small and wireless battery-powered transmitters that use BLE protocol for transmission. The special thing about beacons is that they usually work in one direction. They broadcast to nearby Bluetooth Low Energy devices, but they do not receive data. BLE beacons do not require an internet connection to do this broadcasting. Typically this would look like a single beacon broadcasting data to smart devices (cell phones, smart watches, etc.) nearby. Currently, smartphone support for Bluetooth beacons is lacking, so real-world implementations are minimal. In the future, we will likely see beacons being used for things like proximity marketing, indoor navigation, and asset tracking in the logistics industry. ## BLE Development Basics The Bluetooth Low Energy protocol is not straightforward to learn, even if you’re a seasoned developer. To get you started on your BLE development journey, we’re going to break down the Bluetooth LE protocol architecture at a high level and each of the BLE protocol layers. ### Bluetooth LE Protocol Architecture Bluetooth Low Energy is a [communications protocol](https://novelbits.io/communications-protocols-and-why-we-need-them/). And just like any other protocol, it acts as a rulebook that devices must adhere to in order to communicate or exchange information. It’s important to understand that a protocol's general functionality is broken down into smaller protocols, each of which is responsible for a very specialized role. These smaller protocols are packaged into a layered architecture called a protocol stack or protocol suite. The Bluetooth protocol stack is broadly broken down into three primary components or subsystems: **application, host, and controller.** Inside each of these blocks are distinct layers. ![Bluetooth protocol stack](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/ble-guide-security.png) ### BLE Protocol Layers If you are a developer looking to develop BLE applications, you won’t have to worry much about the layers below the Security Manager and Attribute Protocol layers. But it might still be helpful to have some context about these layers. Let’s take a look. #### The Physical Layer The physical layer (PHY) refers to the physical radio used for communication and for modulating/demodulating the data. It operates in the ISM band (2.4 GHz spectrum). #### The Link Layer The Link Layer is the layer that interfaces with the Physical Layer (Radio) and provides the higher levels an abstraction and a way to interact with the radio (through an intermediary level called the HCI layer which we’ll discuss shortly). It is responsible for managing the state of the radio as well as the timing requirements for adhering to the Bluetooth Low Energy specification. #### The Host Controller Interface (HCI) The (HCI) layer is a standard protocol defined by the Bluetooth specification that allows the Host layer to communicate with the Controller layer. These layers could exist on separate chips, or they could exist on the same chip. #### The Logical Link Control and Adaptation Protocol (L2CAP) The L2CAP layer acts as a protocol multiplexing layer. It takes multiple protocols from the upper layers and places them in standard BLE packets. These packets are then passed down to the lower layers beneath it. #### Attribute Protocol (ATT) The Attribute Protocol (ATT) defines how a server exposes its data to a client and how this data is structured. #### Generic Attribute Profile (GATT) The Generic Attribute Profile (GATT) defines the format of the data exposed by a BLE device. It also defines the procedures needed to access the data exposed by a device. There are two Roles within GATT: Server and Client. The **Server** is the device that exposes the data it controls or contains and possibly some other aspects of its behavior that other devices may be able to control. A **Client**, on the other hand, is the device that interfaces with the Server with the purpose of reading the Server’s exposed data and/or controlling the Server’s behavior. Keep in mind that a Bluetooth LE device can act as the Server and a Client at the same time. To understand the GATT, you need to understand Services and Characteristics. **Services** are a grouping of one or more Attributes (a generic term for any type of data exposed by the server). It’s meant to group together related Attributes that satisfy a specific functionality on the Server. For example, the SIG-adopted Battery Service contains one Characteristic called the Battery Level. A **Characteristic** is always part of a Service, representing a piece of information/data that a Server wants to expose to a client. For example, the Battery Level Characteristic represents the remaining power level of a battery in a device that can be read by a Client. In BLE, there are six types of operations on Characteristics: 1. Commands 2. Requests 3. Responses 4. Notifications 5. Indications 6. Confirmations ### Generic Access Profile (GAP) The GAP provides a framework that defines how BLE devices interact with each other. This includes: - Roles of BLE devices - Advertisements (Broadcasting, Discovery, Advertisement parameters, Advertisement data) - Connection establishment (initiating connections, accepting connections, Connection parameters) - Security The different roles of a Bluetooth LE device are: - Broadcaster: a device that sends out Advertisements and does not receive packets or allow Connections from others. - Observer: a device that listens to others sending out Advertising Packets but does not initiate a Connection with an Advertising device. - Central: a device that discovers and listens to other devices that are advertising. A Central also has the capability of connecting to an Advertising device. - Peripheral: a device that Advertises and accepts Connections from Central devices. Keep in mind that a single device may operate in multiple Roles at the same time. For example, your smartphone can operate in the Central role when communicating with your smartwatch and also act in the Peripheral role while communicating with a PC. ## How to Learn More About BLE? We’ve only scratched the surface of the BLE technology. If you’re looking to dive a little deeper or just stay up-to-date on the latest in Bluetooth, there are numerous free and low-cost resources available. Some of our top tips are: **Get your hands on a development kit.** This is one of the best ways to put knowledge into practice. Some of the best are: - [Nordic Semiconductor nRF5340 DK](https://www.nordicsemi.com/Products/Development-hardware/nrf5340-dk?ref=novelbits.io) - [Nordic Semiconductor nRF52840 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK?ref=novelbits.io) - [Silicon Labs xG24-DK2601B](https://www.silabs.com/development-tools/wireless/efr32xg24-dev-kit?tab=overview&ref=novelbits.io) - [TI LAUNCHXL-CC2640R2](https://www.ti.com/tool/LAUNCHXL-CC2640R2?ref=novelbits.io) - [ESPRESSIF ESP32-C3 DevKit](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html?ref=novelbits.io). **Use a** [**Bluetooth sniffer.**](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) - Pick up an [nRF52840 Dongle ](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle?ref=novelbits.io)and download the [Bluetooth LE packet sniffer software](https://www.nordicsemi.com/Products/Development-tools/nrf-sniffer-for-bluetooth-le?ref=novelbits.io). - Watch video tutorials on how to use a BLE sniffer - Run some live sniffing of connections and advertisements to get a real feel and visual of what the packets look like **Subscribe to industry newsletters:** - [Novel Bits weekly Bluetooth & UWB Newsletter](https://novelbits.io/blog/) - **Read official spec docs.** While not the easiest to digest, every Bluetooth developer should have a copy of the latest official Bluetooth. - **Join the Developer Academy.** If you’re looking to get expert help to accelerate your Bluetooth LE product development, the [Bluetooth Developer Academy](https://novelbits.io/academy). Continue Your Journey Dive deeper into specific Bluetooth LE topics [ **GATT Services & Characteristics** Design custom services and characteristics ](https://novelbits.io/bluetooth-gatt-services-characteristics/) [ **How BLE Advertisements Work** Channels, PDU types, and advertising data ](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/) [ **BLE Sniffer Comparison Guide** Find the right sniffer for your needs ](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) [ **nRF52840 Wireshark Guide** Capture and analyze BLE packets step by step ](https://novelbits.io/nordic-ble-sniffer-guide-using-nrf52840-wireshark/) [ **BLE Advertisement Builder Tool** — Build and decode ad packets visually → ](https://novelbits.io/ble-advertisement-builder/) ## Frequently Asked Questions What is the difference between Bluetooth Classic and Bluetooth LE? Bluetooth Classic is designed for continuous, high-throughput data streaming (audio, file transfer). Bluetooth LE is optimized for intermittent, low-power data exchange — short bursts of data with long sleep periods. They use different radio modulation, different protocol stacks, and serve different use cases. Most modern devices support both. How far can Bluetooth LE reach? In typical indoor conditions, Bluetooth LE range is 10-30 meters. With Bluetooth 5.0's Coded PHY (long range feature), range can extend to 200+ meters line-of-sight. Actual range depends on transmit power, antenna design, environment (walls, interference), and receiver sensitivity. What is GATT in Bluetooth LE? GATT (Generic Attribute Profile) defines how two connected Bluetooth LE devices exchange data. It organizes data into services and characteristics — a service groups related data, and a characteristic holds the actual value. For example, a Heart Rate Service contains a Heart Rate Measurement characteristic. Is Bluetooth LE the same as Bluetooth 5.0? No. Bluetooth LE is a protocol type (alongside Bluetooth Classic). Bluetooth 5.0 is a specification version. Bluetooth LE was introduced in the Bluetooth 4.0 specification (2010) and has been enhanced in every version since. Bluetooth 5.0 added features like 2M PHY (faster data rate), Coded PHY (longer range), and extended advertising. What are common Bluetooth LE applications? Bluetooth LE powers a wide range of IoT applications: fitness trackers and smartwatches, medical devices (glucose monitors, pulse oximeters), smart home sensors (temperature, door locks), asset tracking beacons, proximity detection, audio (LE Audio/Auracast), and industrial monitoring systems. Free 12-Day Email Course Learn Bluetooth LE in 12 Days A free crash course delivered to your inbox. One lesson per day — just the fundamentals you need to start building. Start the Free Course Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ## Summary - Bluetooth Low Energy (BLE) Let’s take a look at the highlights of what we covered in this BLE Guide: - Bluetooth Low Energy was released in 2010 as part of version 4.0 of the Bluetooth Spec. - BLE is a separate protocol from Bluetooth (also known as Bluetooth Classic). The two protocols are not compatible. - BLE is designed for applications that demand ultra-low power but do not require the transmission of large amounts of data. - The Bluetooth protocol stack is broken into three primary subsystems: application, host, and controller. - As a developer, you must understand how the GATT and GAP protocol layers of BLE function. - If you’re a developer looking to dive deeper into the BLE protocol, we recommend you pick up a BLE book, get your hands on a development kit, and start getting plugged into industry resources. ### How to Choose a Bluetooth LE Module for Your Project URL: https://novelbits.io/how-to-choose-ble-module-for-your-project/ Last updated: 2026-08-09T05:25:07.000Z If you're looking for a way to add Bluetooth LE connectivity to your project, you have many options. So how do you know which module is right for you? We’ll help you understand the options available and make the best decision for your needs. ## **How to select a Bluetooth LE module** There are a few key considerations to keep in mind when selecting a Bluetooth LE module. These include: 1. Does the module support the Bluetooth LE features that your project requires? 2. Is it multi-protocol capable if your project requires a multi-radio system? 3. Antenna type, certification, and compliance? 4. The module's core, interfaces, operating temperature, RF performance? 5. Is the module vendor reputable; In terms of both support and quality? 6. OTA (over-the-air) updates support? 7. Power consumption? ![Trade-off during selection of Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/trade-off-of-selecting-module.png) *Trade-off during the selection of a Bluetooth LE module* ### **Bluetooth LE support:** If your application needs a higher transmission throughput, then look for modules that support 2M PHY or advertisement packet extension. For longer ranges, then modules that support LE Coded PHY. For indoor location & positioning and tracking applications, you'll want a module that supports Angle of Arrival (AoA) or Angle of Departure (AoD) mechanisms. The list can go on and on, but the main criteria should be the features required by your application. ### **Multi-protocol capability:** Are you working on a project that requires multiple radios? If yes, you should look for modules with built-in support for multiple protocols. For example, if your project uses both Zigbee and Bluetooth LE, you'll want to find a module that can support both protocols. This will save you the hassle of having to design and build two separate radio systems. Usually, the module will contain only a single radio chipset, so support for both protocols will be done in a time-plexed manner. Make sure you keep that in mind since it could impose some new limitations and capabilities for each of the supported protocols. ### **Antenna type, certification, and compliance:** The next thing to consider is the type of antenna that is used by the module. The antennas for Bluetooth modules are mainly classified into two types - omnidirectional antenna and directional antenna: - An omnidirectional antenna radiates the signals to a 360-degree area to maximize the coverage rate. - Directional antennas focus the radio signals in a particular direction. The type of antenna you need will depend on your application requirements. For example, if your device is used in various orientations, you may have to attempt omnidirectional coverage with a module that uses an omnidirectional antenna. And if your product is enclosed in solid metal, and its antenna needs to radiate away from the enclosure, not into it, then a directional antenna is required. In terms of certification & compliance, many module manufacturers market their products as pre-certified or tested. This is good news for non-traditional RF manufacturers who want to integrate the wireless module into their products but lack the RF development experience. ### **Core, interfaces, operating temperature, and RF performance:** The core is the microprocessor, a.k.a brain, of the module, and it decides the module's processing capabilities. Another important factor is the module's interfaces. How the module connects to the peripherals outside itself is crucial in determining compatibility. Choose a module with enough processing power for your application. Additionally, the module’s operating temperature should be able to work in the same temperature range as your product. Lastly, a module with high RF sensitivity and output power gives you a better link budget and caters to more range without needing an external amplifier. Keep your product's needs in mind, and the onus to finding the right module will be much simpler. ### **Reputable Bluetooth LE module vendor:** You should always pick a module vendor with a good reputation and strong technical support structure. They will help you get your product into the market quickly while providing quality modules that are up-to-date in terms of security features, SDKs, etc. ### **OTA updates:** OTA (over-the-air) updates are an important feature for commercial and industrial applications. If your product is going to be deployed in the field, you'll want a module that has OTA support so you can update the firmware, fix bugs, and add new features wirelessly promptly. OTA updates reduce the need for costly downtime and technical visits. ### **Power consumption:** Power consumption is important when it comes to Bluetooth LE products. This is because most of these products use current-constrained power sources, like lithium-ion coin cell batteries. ![Current draw graph of a Bluetooth LE device](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/current-cycle-of-a-bluetooth-peripheral.jpg) *The current consumption level on the y-axis; Time on the x-axis* The module's CPU and the radio will be some of the most power-hungry components in your product. When it comes to how much power a module uses while in transmit, receive, and sleep modes, you should select one with the most power-saving design to cater to the expected battery life of your product. ### **Other parameters:** There are many other factors you'll want to think about, and these include the packaging dimensions, automatic sleep/activation, development tools, and price. ## **Common Bluetooth LE Modules** Some of the popular Bluetooth LE modules are listed below. This is not an exhaustive list, but it should give you a good starting point in your search for the right module for your project. 💡 **Note:** Click on each table to view it in fullscreen mode. ### **1\. Nordic Semiconductor** ![Nordic Semiconductor modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nordic-semi-ble-modules.png) *[BL5340](https://www.lairdconnect.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl5340-series-multi-core-bluetooth-52-802154-nfc-modules?ref=novelbits.io)*, [BT8*40/F/E/X/XE*](https://www.fanstel.com/bt840?ref=novelbits.io)*, [Nina-B40](https://www.u-blox.com/en/product/nina-b40-series-open-cpu?ref=novelbits.io)* ### **2\. Silicon Labs** ![Silicon Labs Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/silicon-labs-ble-modules.png) *[BGM210P](https://www.silabs.com/documents/public/data-sheets/bgm210p-datasheet.pdf?ref=novelbits.io), [BGM220P](https://www.silabs.com/documents/public/data-sheets/bgm220p-datasheet.pdf?ref=novelbits.io), [BGM210L](https://www.silabs.com/documents/public/data-sheets/bgm210l-datasheet.pdf?ref=novelbits.io), [BGM111](https://www.silabs.com/documents/public/data-sheets/BGM111%5Fdatasheet.pdf?ref=novelbits.io), [Lyra S](https://www.lairdconnect.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/lyra-series-bluetooth-53-modules?ref=novelbits.io)* ### **3\. Renesas Semiconductor (Dialog Semiconductor)** ![Renesas Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/renesas-ble-modules.png) *[RYZ012](https://www.renesas.com/us/en/document/dst/ryz012-datasheet?ref=novelbits.io), [RX23W](https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rx23w-32-bit-microcontrollers-and-module-bluetooth-5-iot-endpoint-devices-system-control-and-wireless?ref=novelbits.io)* ### **4\. STMicroelectronics** ![STMicroelectronics Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/stm-ble-modules.png) *[BlueNRG-M2](https://www.st.com/en/wireless-connectivity/bluenrg-m2.html?ref=novelbits.io), [STM32WB5MMG](https://www.st.com/en/microcontrollers-microprocessors/stm32wb5mmg.html?ref=novelbits.io)* ### **5\. Texas Instruments (TI)** ![Texas Instruments (TI) Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ti-ble-modules.png) *[CC2652RSIP](https://www.ti.com/product/CC2652RSIP?ref=novelbits.io), [CC2652PSIP](https://www.ti.com/product/CC2652PSIP?ref=novelbits.io), [CC2651R3SIPA](https://www.ti.com/product/CC2651R3SIPA?ref=novelbits.io)* ### 6\. NXP ![NXP Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nxp-ble-modules.png) *[AW-XM458](https://www.azurewave.com/wireless-modules-nxp.html?ref=novelbits.io), [Type 1ZM](https://www.murata.com/en-sg/products/connectivitymodule/wi-fi-bluetooth/overview/lineup/type1zm?ref=novelbits.io), [MAYA-W1](https://www.u-blox.com/en/product/maya-w1-series?ref=novelbits.io), [Summit SOM 8M Plus](https://www.lairdconnect.com/wireless-modules/system-on-module/summit-som-8m-plus-system-module-wifi-5-bluetooth-53?ref=novelbits.io)* ### 7\. Infineon (Cypress) ![Infineon's Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-08-24-at-9-01-23-pm.png) *[CYBLE-0130XX-00](https://www.mouser.com/pdfdocs/CYBLE-0130XX-00%5FEZ-BLE%5FWICED%5FMODULE.pdf?ref=novelbits.io), [CYBLE-3X307X-02](https://www.infineon.com/dgdl/Infineon-CYBLE-343072-02%5FCYBLE-333073-02%5FCYBLE-333074-02%5FAIROC%5FBluetooth%5FLE%5Fmodule-AdditionalTechnicalInformation-v01%5F00-EN.pdf?fileId=8ac78c8c7d718a49017d9a4f3ee63c2d&ref=novelbits.io), [CYBLE-416045-02](https://www.infineon.com/dgdl/Infineon-CYBLE-416045-02-DataSheet-v02%5F00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee63f136e57&ref=novelbits.io), [CYBLE-224116-01](https://www.infineon.com/dgdl/Infineon-CYBLE-224116-01%5FEZ-BLE%5FCREATOR%5FXT%5FXR%5FMODULE-DataSheet-v09%5F00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee3077369fc&ref=novelbits.io)* ### 8\. Espressif (ESP32) ![Espressif (ESP32) Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/esp32-ble-modules.png) [*NINA-W15* S*eries*](https://www.u-blox.com/en/product/nina-w15-series-u-connect?ref=novelbits.io)*, [ESP32-WROOM-32E](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32e%5Fesp32-wroom-32ue%5Fdatasheet%5Fen.pdf?ref=novelbits.io), [ESP32-C3-MINI-1](https://www.espressif.com/sites/default/files/documentation/esp32-c3-mini-1%5Fdatasheet%5Fen.pdf?ref=novelbits.io)* ### 9\. Qualcomm ![Qualcomm Bluetooth LE modules](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/qualcomm-ble-modules.png) *[BLE24V1,](https://developer.qualcomm.com/sites/default/files/ble024%5Fuser%5Fmanual%5Fv1.2.pdf?ref=novelbits.io) [LM930](https://www.lm-technologies.com/lm%5Fdownloads/LM930%5FDATASHEET.pdf?ref=novelbits.io)* ## **Let's Recap** So, what's the best Bluetooth LE module for your project? It depends mostly on your application needs and budget. If you are looking for a more feature-rich module, the higher the price tag will be. If you need a module with a good range, then you'll have to make sure it has high sensitivity and output power. And finally, always select a reputable vendor with good technical support. Are you camping between a Bluetooth Module vs. a Bluetooth LE SoC? Check out our [Chipset vs. Module Bluetooth LE Solutions guide](https://novelbits.io/chipset-vs-module-bluetooth-le-solutions-the-ultimate-guide/) to help you decide**.** 💡 **Insider Tip:** Choosing the right Bluetooth LE module is just the beginning. Want to learn how to develop firmware for your chosen module? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### The Ultimate Guide to Getting Started with Android Bluetooth LE Development URL: https://novelbits.io/getting-started-android-bluetooth-le-development/ Last updated: 2026-08-09T05:24:55.000Z 💡 **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## Introduction Android development can be a daunting topic on its own merit but throw in Bluetooth Low Energy, and you might be tempted to switch to iOS. But in all seriousness, Bluetooth Low Energy development on Android can be painful and extremely error-prone without the right guidance. With the right guidance, it is possible to build robust Bluetooth Low Energy applications on Android and enjoy it! Android provides a plethora of options for performing Bluetooth Low Energy scans. Properly configuring and understanding the available options is the only way to leverage them effectively. In addition to an overwhelming number of Bluetooth Low Energy scan options, Android also requires user permissions that vary among API versions making permission management an additional chore. Again, with the right guidance, it’s possible to deal with these Android eccentricities and enjoy working with Bluetooth Low Energy. In this article, we will cover all of the steps required to set up an Android application to begin scanning for Bluetooth Low Energy devices. We will not be covering any User Interface specific implementation in this tutorial to focus on the most important aspects of Bluetooth Low Energy development on Android. In this tutorial, we will cover the following topics: - [Project setup and overview of Android Studio debugging and logging](#setup) - [Configuring and requesting required user permissions](#required%5Fpermissions) - [Introduction to SharedFlows and StateFlows from the Coroutines Framework](#flow%5Fconcepts) - [Bluetooth radio state monitoring](#blemanager) - [Bluetooth Low Energy scan configuration](#scan%5Fsettings) - [Android Scanning Limitations](#scan%5Flimitations) - [Callback-based Bluetooth Low Energy Scanning](#callback%5Fscanning) - [PendingIntent-based Bluetooth Low Energy scanning](#pendingintent%5Fscanning) - [Summary: Callback vs. PendingIntent based scanning](#scan%5Foptions%5Fsummary) - [Logging Scan Results](#logging%5Fscan%5Fresults) - [Summary and Next Steps](#summary) ## Prerequisites - Mac running macOS 11 or later or Windows computer running Windows 10 or later - Android Studio Bumblebee \[[Download here](https://developer.android.com/studio?ref=novelbits.io)\] - An Android mobile device running Android 10 or later - Familiarity with Kotlin is helpful but not required - Familiarity with Asynchronous programming - Basic understanding of Android development For the steps laid out in this article, we'll be using the following: - MacBook Pro 2021 with macOS Monterey - Android Studio Bumblebee 2021.1.1 Patch 2 - Google Pixel 3A with Android 11 ## Android Studio Project Setup ⚠️ **NOTE:** If, at any point, Android Studio asks you to upgrade the Gradle version, please ignore this and do not upgrade. If you upgrade the Gradle, it may break other dependencies. Open Android Studio and select -> New Project. Select “Empty Activity” for the project type then click “Next.” ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c6d41a74.png) Update the project details to match the following image. Make sure the “Name” and “Package name” match exactly as shown; later portions of the project will depend on the naming used here. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c6f161ce.png) ## Android Studio Overview A full introduction to Android Studio is outside the scope of this tutorial. We will review the key functionalities that will be used in the context of this tutorial. ### Device selection After you have plugged your development device into the computer you will be using for this tutorial; you should be able to select it from the drop-down menu in the top right portion of the toolbar. It may take a couple of minutes for Android Studio to finish setting up the new project, so you may not be able to access all of the options in the toolbar until that finishes (progress shown in the taskbar at the bottom of the screen in Android Studio). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c70c2faa.png) If you do not see your device under the drop-down menu, ensure you have enabled developer mode and USB debugging. ### Run vs. Debug There are two options for loading the application onto your mobile device, Run and Debug. The Run option is represented by the Play button in the toolbar. The debug option is represented by the Bug button in the toolbar. Breakpoints will not work if the Run option is used; you must use the Debug option. ### Logging Console logs will be printed in the Logcat tab in the bottom toolbar in Android Studio. Make sure to select your connected device from the first dropdown on the left, the application from the second drop-down, and “Show only selected application” from the dropdown on the far right. If you do not select “Show only selected application,” you will see logs for all Android processes making it difficult to find what you are logging from the application. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c7211107.png) ## API Support Level In production apps, it’s good practice to support a minimum of the three most recent major OS release versions. Android’s latest production release is Android 12 so we are going to configure our project to support a minimum of Android 9\. We configure this by setting the minimum SDK version defined in **BLEScanner/app/build.gradle**. Each Android OS version has a corresponding SDK version. This can be a little confusing, but it’s very easy to figure out the SDK version for a specific Android version with a quick google search. In the case of Android 9, the corresponding SDK version is 26\. Update the build.gradle file located at BLEScanner/app/build.gradle to match the following: ```kotlin plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { compileSdk 32 defaultConfig { applicationId "com.novelbits.blescannertest" minSdk 26 targetSdk 32 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.6.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' } ``` ## Required Permissions ### Explanation of required permissions Android requires a combination of user permissions to perform a Bluetooth scan, and several permissions depend on the Android SDK version. - **BLUETOOTH**: is necessary to perform any Bluetooth classic or BLE communication, such as requesting a connection, accepting a connection, and transferring data. - **BLUETOOTH\_ADMIN**: If you want your app to initiate device discovery or manipulate Bluetooth settings The Bluetooth and Bluetooth Admin permissions were required up to Android 12, SDK Version 30\. We need to make sure to request these permissions only when the device running the application is Android 12 or earlier. - **BLUETOOTH\_SCAN**: If your app looks for Bluetooth devices, such as BLE peripherals. - **ACCESS\_FINE\_LOCATION**: this is necessary because, on Android 11 and lower, a Bluetooth scan could potentially be used to gather information about the user's location. For Android 11 and greater, this is only needed if your application relies on Bluetooth scan results to derive location. If not, then add the “usesPermissionFlags” to the SCAN permission in your manifest, as shown below: ```kotlin ``` **NOTE:** Including this will result in some BLE beacons, such as iBeacons, being filtered from scan results. Additionally, this is only available in Android 12 (SDK 31) and later. - **ACCESS\_COARSE\_LOCATION**: If your app targets Android 9 (API level 28) or lower, you can declare this instead of ACCESS\_FINE\_LOCATION ### Configuring Permissions In Android, any permissions that will be requested from the user need to be included in the Android manifest. Open the AndroidManifest.xml file and add the permissions shown below. Note how BLUETOOTH, BLUETOOTH\_ADMIN, and ACCESS\_COARSE\_LOCATION all include a max SDK version. ```markup ``` ### Requesting User Permissions Android also requires permissions to be requested from the user during application run-time. Make sure your current view perspective is set to **Project**. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c7368895.png) Add a new folder and name it permissions. Right-click, select “New,” then select “Package.” ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c747fd11.png) ![Graphical user interface, text, application, website Description automatically generated](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c75a5719.png) Create a new **Kotlin Class/File** called **PermissionManager**, and select **Object** as the type. We will be following the built-in Kotlin singleton pattern. Declare the PermissionManager as an Object. Add a new constant for TAG at the top of the file that will be used for logging. ```kotlin object PermissionManager { // Tag used in our console logs private const val TAG = "PermissionManager" } ``` We need to keep track of the required permissions for our applications and the permissions that need to be requested. This will allow us to request only the permissions that have not yet been granted by the user. Declare two new variables at the top, inside the PermissionManager object, permissionsRequired and permissionsToRequest. Additionally, inside the **PermissionManager** object, add a public variable named **permissionsGranted** with public get and private set properties. Add a private **\_permissionsGranted** variable to act as the property backing for the publicly accessible permissionsGranted variable. ```kotlin // Public access to permissions var permissionsGranted: Boolean = false get() = _permissionsGranted private set // Indicate whether all permissions have been granted private var _permissionsGranted: Boolean = false // Permissions required & Permissions we will prompt the user for this lifecycle private val permissionsRequired: MutableList = buildPermissionsList() private val permissionsToAsk: MutableList = arrayListOf() ``` Now define a function inside the **PermissionManager** object to populate the permissionsRequired list called **buildPermissionsList**. We need to add the appropriate permissions to ask based on the Android SDK Version. Android SDK 28 and lower - BLUETOOTH - BLUETOOTH\_ADMIN - ACCESS\_COARSE\_LOCATION Android SDK 30 and lower - BLUETOOTH - BLUETOOTH\_ADMIN - ACESSS\_FINE\_LOCATION Android SDK 31 and greater - BLUETOOTH\_SCAN - ACCESS\_FINE\_LOCATION ```kotlin /** * Add all permissions your app requires * @return MutableList of permissions */ private fun buildPermissionsList(): MutableList { val permissionsList = mutableListOf() if (Build.VERSION.SDK_INT <= 28) { permissionsList.add(Manifest.permission.BLUETOOTH) permissionsList.add(Manifest.permission.BLUETOOTH_ADMIN) permissionsList.add(Manifest.permission.ACCESS_COARSE_LOCATION) } else if (Build.VERSION.SDK_INT <= 30) { permissionsList.add(Manifest.permission.BLUETOOTH) permissionsList.add(Manifest.permission.BLUETOOTH_ADMIN) permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION) } else if (Build.VERSION.SDK_INT >= 31) { permissionsList.add(Manifest.permission.BLUETOOTH_SCAN) permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION) } return permissionsList } ``` Add another function, called **askPermissions** that takes an Android Activity as an argument. The activity reference will be needed when requesting permissions. Inside of the **askPermissions** function, add code to iterate through the required permissions and check which permissions have not been granted, and add those permissions to our permsissionsToRequest array. ```kotlin /** * Ask user permissions for all required permissions within this object * onRequestPermissionResult will be called once all permissions have been granted or dismissed * @param activity activity */ fun askPermissions(activity: Activity) { // Create permissionsToAsk list based off if permission has been granted already permissionsRequired.forEach { permission -> if (ContextCompat.checkSelfPermission( activity.applicationContext, permission ) != PackageManager.PERMISSION_GRANTED ) { // Add to permissionsToAsk list permissionsToAsk.add(permission) } } } ``` Make sure to import Manifest and Build at the top of PermissionManager as shown: ```kotlin import android.Manifest import android.os.Build ``` Add a new constant at the top inside of **PermissionManager** called **requestCode** and set it to 1\. This value will be provided when we request the permissions so that we can match the value returned in the callback we are going to add. ```kotlin // Request Code to be used with permissions request val requestCode = 1 ``` Next, we need to request the permissions included in the permissionsToRequest array we just populated (shown under the **// Request each permission** comment below). ```kotlin /** * Ask user permissions for all required permissions within this object * onRequestPermissionResult will be called once all permissions have been granted or dismissed * @param activity activity */ fun askPermissions(activity: Activity) { // Create permissionsToAsk list based off if permission has been granted already permissionsRequired.forEach { permission -> if (ContextCompat.checkSelfPermission( activity.applicationContext, permission ) != PackageManager.PERMISSION_GRANTED ) { // Add to permissionsToAsk list permissionsToAsk.add(permission) } } // Request each permission if (permissionsToAsk.size > 0) { ActivityCompat.requestPermissions( activity, permissionsToAsk.toTypedArray(), requestCode ) } else { permissionsGranted = true } } ``` Make sure to add the following imports at the top of PermissionManager. ```kotlin import android.app.Activity import android.content.pm.PackageManager import androidx.core.content.ContextCompat import androidx.core.app.ActivityCompat ``` The permissions must be requested from an Activity so we need to make it possible to route the permissions request result callback to the permissionsManager. Add a new function inside the **PermissionManager** called **onRequestPermissionResult** that takes the parameters shown below. Inside onRequestPermissionResult we first need to verify that the request code matches the value we provided in the request. Next, we need to verify that all the requested permissions were granted by the user. We can do this easily using the `any` function. The function accepts a predicate that checks if the given condition is true for any of the items in the array. ```kotlin /** * Receives callback ONCE with array of permissions and results * Called from overridden OnRequestPermissionResult from Activity */ fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { // Make sure the request code matches if (this.requestCode == requestCode){ // Check if any of the permissions were not granted _permissionsGranted = grantResults.any{ it == PackageManager.PERMISSION_DENIED } } } ``` Inside the **MainActivity**, override the **onRequestPermissionResult** function. Inside the function make a call to onRequestPermissionResult in the PermissionManager object. Now the permissions request result can be handled by the PermissionManager. ```kotlin override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult( requestCode, permissions, grantResults) PermissionManager.onRequestPermissionsResult( requestCode, permissions, grantResults) } ``` We need to invoke request permissions from the **MainActivity**. First, make sure to import the correct dependency. Add a call to PermissionManager.askPermissions inside of the onCreate function. Now, permissions will be requested when the app starts but only permissions that have not already been granted will be requested. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) PermissionManager.askPermissions(this) } ``` Go ahead and run the app on a device and make sure the appropriate permissions are requested from the user. Requesting user permissions is only required one time. If you want to see which permissions have been granted or denied, you can long-press on the app and then select “App info” and then select “Permissions.” ## Flow Concepts ### Coroutines Asynchronous programming is an important part of Android development in general and an especially important part of working with Bluetooth Low Energy. In Kotlin, we use Coroutines for building logic to deal with asynchronous events. A Coroutine is an instance of an asynchronous block of code, i.e. a piece of code that we can invoke and completion can be expected at a later time. An in-depth Coroutines tutorial is outside the scope of this tutorial. A complete Coroutines introduction along with examples can be found at [https://kotlinlang.org/docs/coroutines-guide.html](https://kotlinlang.org/docs/coroutines-guide.html?ref=novelbits.io). ### CoroutineScope In many cases, we will have several coroutines in a class that will need to be canceled together. CoroutineScope enables us to attach all our coroutines to a single cancellable scope rather than needing to cancel each coroutine individually. We will typically define a CoroutineScope at the top of Classes that will rely on Coroutines. ### Flows In Coroutines, we can use Flows to emit “flows” of data sequentially through a single entry point. A Flow is analogous to a pipe for data. For example, you could use a flow to provide real-time updates from a database. StateFlows and SharedFlows are included with the Flows API that allows up to emit state and value updates to multiple receivers. We will rely heavily on both StateFlows and SharedFlows in this tutorial. ### StateFlows A StateFlow is an observable state holder. StateFlows hold a state-value and emit state-value changes to observers. StateFlows are useful when we need to provide an observable state on a class. For example, if we had a Flashlight class, it would be useful to provide an observable power state. Other classes would be able to check the current power state if needed and also be able to observe power state changes. ### SharedFlows SharedFlows are similar to StateFlows except that they do not store state so observers would only receive emitted data but would not be able to access a current value. SharedFlows are useful when we need to emit values that are only meaningful at the time they are emitted. For example, if we were taking a measurement from an accelerometer once per second and emitting the measured value, the value would only be valid at the moment the measurement was taken. So there would be no need to make that value available after it was emitted. ### Coroutine Dependencies We need to add the appropriate dependencies in our project for Coroutines. Add the dependencies shown below in the BLEScanner/app/build.gradle file. ```kotlin dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0" } ``` Let’s update our **PermissionsManager** to leverage **StateFlows** so that we can provide an asynchronous observable property. Add both **MutableStateFlow** and **StateFlow** as dependencies at the top of the file. ```kotlin import android.Manifest import android.app.Activity import android.content.pm.PackageManager import android.os.Build import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow ``` This will allow us to perform an action when permissions have been granted without polling for changes in permissions. Replace the following code that we defined towards the top of **PermssionManager**, ```kotlin // Public access to permissions var permissionsGranted: Boolean = false get() = _permissionsGranted private set // Indicate whether all permissions have been granted private var _permissionsGranted: Boolean = false ``` with the code shown below: ```kotlin private var _permissionsGranted = MutableStateFlow(false) var permissionsGranted: StateFlow = _permissionsGranted ``` The new variable types, MutableStateFlow and StateFlow, may show up as red if the correct imports were not already added. If you hover over each of the variable types that are shown in red, you will be presented with a popup providing you the option to import the correct dependencies. Mouseover and select import for both MutableStateFlow and StateFlow. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c76adbfe.png) Lastly, we need to update the code that sets the “\_permissionsGranted” variable inside of the “onRequestPermissionsResult” function in addition to inside of “askPermissions” function. Replace the following code: (Inside askPermissions function) ```kotlin // Request each permission if (permissionsToAsk.size > 0) { ActivityCompat.requestPermissions( activity, permissionsToAsk.toTypedArray(), requestCode ) } else { permissionsGranted = true } ``` (Inside onRequestPermissions function) ```kotlin // Make sure the request code matches if (this.requestCode == requestCode){ // Check if any of the permissions were not granted _permissionsGranted = grantResults.any { it == PackageManager.PERMISSION_DENIED } } ``` with the code shown below: (Inside askPermissions function) ```kotlin // Request each permission if (permissionsToAsk.size > 0) { ActivityCompat.requestPermissions( activity, permissionsToAsk.toTypedArray(), requestCode ) } else { _permissionsGranted.value = true } ``` (Inside onRequestPermissions function) ```kotlin // Make sure the request code matches if (this.requestCode == requestCode){ // Check if any of the permissions were not granted _permissionsGranted.value = grantResults.any { it == PackageManager.PERMISSION_DENIED } } ``` Notice that we are now setting the value property of **\_permissionsGranted**. ## BLEManager Class ### Bluetooth Manager Add a new folder (package) called model and then add a file inside the model folder and select **Class** and name the file **BLEManager**. The BLEManager will be responsible for managing all BLE-related activities. In this tutorial, we will add scanning functionality to the BLEManager. ![Graphical user interface, text, application Description automatically generated](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c77876a3.png) Add a constant of type **Context** inside the **BLEManager** constructor. Context will be needed to access an instance of BluetoothManager. Also, go ahead and add a new constant for TAG at the top that will be used for logging. ```kotlin class BLEManager(val context: Context) { private val TAG = "BLEManager" } ``` There are several Android Bluetooth components we will be working with. - **BluetoothManager**: “High-level manager used to obtain an instance of a [BluetoothAdapter](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter?ref=novelbits.io) and to conduct overall Bluetooth Management.” - **BluetoothAdapter**: “Represents the local Bluetooth adapter (Bluetooth radio). The BluetoothAdapter is the entry-point for all Bluetooth interaction. Using this, you can discover other Bluetooth devices, query a list of bonded (paired) devices, instantiate a BluetoothDevice using a known MAC address, and create a BluetoothServerSocket to listen for communications from other devices. Fundamentally, this is your starting point for all Bluetooth actions.” - **BluetoothLEScanner**: “This class provides methods to perform scan-related operations for Bluetooth LE devices. An application can scan for a particular type of Bluetooth LE devices using [ScanFilter](https://developer.android.com/reference/android/bluetooth/le/ScanFilter?ref=novelbits.io). It can also request different types of callbacks for delivering the result.” Inside the newly created BLEManager file, we need to declare a few variables. To perform BLE scanning, we will need an instance of BluetoothManager, a reference to the BluetoothAdapter owned by BluetoothManager, and a reference to the BluetoothLEScanner owned by BluetoothAdapter. Let’s declare each of these with lazy initializers. Using a Lazy initializer means that the variable will not be initialized until accessed. This is convenient for scenarios where we want to assign something to a variable that won’t be available until run-time. Instead of making the variable nullable and assigning its value during the initialization of the class, we can use lazy initialization. ```kotlin private val bluetoothManager = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager) private val bluetoothAdapter: BluetoothAdapter by lazy { bluetoothManager.adapter } private val bluetoothLeScanner: BluetoothLeScanner by lazy { bluetoothAdapter.bluetoothLeScanner } ``` In order to perform any Bluetooth actions, we need to ensure that Bluetooth is enabled and turned on. First, declare a constant named “REQUEST\_BT\_ENABLE” at the top, inside BLEManager, just below the “TAG” declaration. Assign it a value of 3\. Android Studio may give you a warning for the naming format. You can ignore the warning. ```kotlin private val TAG = "BLEManager" private val REQUEST_ENABLE_BT = 3 ``` Add an initializer to our BLEManager and add logic to check if Bluetooth is enabled and, if not, request that the user enable it. ```kotlin init { if (!bluetoothAdapter.isEnabled){ val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) (context as Activity).startActivityForResult( enableBtIntent, REQUEST_ENABLE_BT) } } ``` ### Bluetooth Adapter State #### Explanation of need for observing adapter state As mentioned above, the Bluetooth Adapter represents the Bluetooth radio. It’s important for the application to track Bluetooth adapter state changes. If the adapter is off, it won’t be possible to perform any Bluetooth-related operations. The possible Bluetooth adapter states are: - **BluetoothAdapter.STATE\_OFF**: “Indicates the local Bluetooth adapter is off.” - **BluetoothAdapter.STATE\_TURNING\_ON**: “Indicates the local Bluetooth adapter is turning on. However, local clients should wait for STATE\_ON before attempting to use the adapter.” - BluetoothAdapter.STATE\_ON: “Indicates the local Bluetooth adapter is on and ready for use.” - **BluetoothAdapter.STATE\_TURNING\_OFF**: “Indicates the local Bluetooth adapter is turning off. Local clients should immediately attempt graceful disconnection of any remote links.” #### Bluetooth Adapter state intent filter, Bluetooth adapter state observer Let’s add a function inside of BLEManager and call it “setupBluetoothAdapterStateHandler” where we can set up the code to track the Bluetooth adapter state. At the top of the function, we need to declare a broadcast receiver object named “bluetoothAdapterStateReciever.” This broadcast receiver will receive Bluetooth adapter state changes. Leave the broadcast receiver object empty, and we will come back to add code later. ```kotlin private fun setupBluetoothAdapterStateHandler() { val bluetoothAdapterStateReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { } } } ``` Below the broadcast receiver and inside setupBluetoothAdapterStateHandler, declare a constant called filter and set it equal to an intent filter initialized with BluetoothAdapter.ACTION\_STATE\_CHANGED. Next, we need to register our broadcast receiver object to be called when any broadcast intent matches the filter we have specified, in this case, when there is a BluetoothAdapter state change. ```kotlin val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) (context as Activity).registerReceiver(bluetoothAdapterStateReceiver, filter) ``` Now that we’ve registered the broadcast receiver let’s go back and add our code to receive Bluetooth adapter state changes. Inside the broadcast receiver, override the onRecieve function. Declare a const and assign the intent action to it. Next, add logic to verify the action matches BluetoothAdapter.ACTION\_STATE\_CHANGED. ```kotlin val bluetoothAdapterStateReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // Verify the action matches what we are looking for if (intent.action == BluetoothAdapter.ACTION_STATE_CHANGED) { } } } ``` The ACTION\_STATE\_CHANGE intent always contains extra fields EXTRA\_STATE and EXTRA\_PREVIOUS\_STATE, and we can obtain those values by calling getIntExtra on the intent. Declare and assign two new constants and set them equal to the EXTRA\_STATE and EXTRA\_PREVIOUS\_STATE. Finally, add a switch to determine the current adapter state. Later on, in this tutorial, we will use previousState. ```kotlin override fun onReceive(context: Context, intent: Intent) { // Verify the action matches what we are looking for if (intent.action == BluetoothAdapter.ACTION_STATE_CHANGED) { val previousState = intent.getIntExtra( BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.ERROR ) val currentState = intent.getIntExtra( BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR ) when (currentState) { BluetoothAdapter.STATE_OFF -> Log.d(TAG, "BluetoothAdapter State: Off") BluetoothAdapter.STATE_TURNING_OFF -> Log.d(TAG, "BluetoothAdapter State: Turning off") BluetoothAdapter.STATE_ON -> Log.d(TAG, "BluetoothAdapter State: On") BluetoothAdapter.STATE_TURNING_ON -> Log.d(TAG, "BluetoothAdapter State: Turning on") } } } ``` Inside of the **BLEManager initializer**, add a call to the “setupBluetoothAdapterStateHandler” function prior to the code that checks if the Bluetooth adapter is enabled. ```kotlin init { setupBluetoothAdapterStateHandler() if (!bluetoothAdapter.isEnabled){ val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) (context as Activity).startActivityForResult( enableBtIntent, REQUEST_ENABLE_BT) } } ``` We need to add an instance of BLEManager to our app. For now, let's add an instance inside of the onCreate function inside the MainActivity. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) PermissionManager.askPermissions(this) val bleManager = BLEManager(this) } ``` Import BLEManager at the top of the MainActivity file. ```kotlin import com.novelbits.blescannertest.model.BLEManager ``` Run the app and confirm you see the adapter state logs in the console when you toggle the Bluetooth on and off. ![Graphical user interface, text Description automatically generated](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c788b298.png) ### Scan Configuration Android provides many settings to tailor Bluetooth scanning to fit your application needs. **Callback Type:** configure whether a callback is triggered for every advertisement from a single device and whether to trigger a callback when advertisements are no longer received from a previously discovered device. - [CALLBACK\_TYPE\_ALL\_MATCHES](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#CALLBACK%5FTYPE%5FALL%5FMATCHES): “Trigger a callback for every Bluetooth advertisement found that matches the filter criteria. If no filter is active, all advertisement packets are reported.” - [CALLBACK\_TYPE\_FIRST\_MATCH](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#CALLBACK%5FTYPE%5FFIRST%5FMATCH): “A result callback is only triggered for the first advertisement packet received that matches the filter criteria.” - [CALLBACK\_TYPE\_MATCH\_LOST](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#CALLBACK%5FTYPE%5FMATCH%5FLOST): “Receive a callback when advertisements are no longer received from a device that has been previously reported by a first match callback.” Configuring the callback type to include all matches would be important for monitoring dynamic advertisement data or signal strength, for example. - **Legacy:** restrict scan results to only include legacy-type advertisements. Bluetooth Version 5.0 introduced a new feature called Extended Advertisements that enables devices to advertise more data than was allowed with Legacy Advertisements. When building an application that will only interact with devices utilizing Legacy Advertisements, it’s possible to restrict scanning to only return Legacy Advertisements. **Match Mode:** configure how quickly ScanFilter matches should be reported - [MATCH\_MODE\_AGGRESSIVE](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#MATCH%5FMODE%5FAGGRESSIVE): “In Aggressive mode, hw will determine a match sooner even with feeble signal strength and few number of sightings/match in a duration.” - [MATCH\_MODE\_STICKY](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#MATCH%5FMODE%5FSTICKY): “For sticky mode, a higher threshold of signal strength and sightings is required before reporting by hw” Setting the match mode to sticky would be useful to reduce the number of matches reported that may be out of stable connection range. **Number of Matches:** configure the number of advertisements to report for devices matching a specific ScanFilter - [MATCH\_NUM\_FEW\_ADVERTISEMENT](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#MATCH%5FNUM%5FFEW%5FADVERTISEMENT): “Match few advertisements per filter, depends on current capability and availability of the resources in hw” - [MATCH\_NUM\_MAX\_ADVERTISEMENT](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#MATCH%5FNUM%5FMAX%5FADVERTISEMENT): “Match as many advertisements per filter as hw could allow, depends on current capability and availability of the resources in hw” - [MATCH\_NUM\_ONE\_ADVERTISEMENT](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#MATCH%5FNUM%5FONE%5FADVERTISEMENT): “Match one advertisement per filter” Limiting the number of advertisements reported for each ScanFilter match may help reduce CPU usage. If the advertisement data is not dynamic, there may be no benefit in receiving multiple advertisements for each device. **Physical Layer:** “Set the Physical Layer to use during this scan.” - [PHY\_LE\_ALL\_SUPPORTED](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#PHY%5FLE%5FALL%5FSUPPORTED): “Use all supported PHYs for scanning. This will check the controller capabilities and start the scan on 1Mbit and LE Coded PHYs if supported, or on the 1Mbit PHY only.” - PHY\_LE\_1M: “Use only 1M PHY for scanning.” - PHY\_LE\_CODED: “Use only LE Coded PHY for scanning.” In the case of Extended Advertisements supported with Bluetooth 5.0, we can restrict scanning to the 1M PHY or allow advertisements to be scanned on both the 1M and LE Coded PHYs. - **Report Delay:** “Set report delay timestamp for Bluetooth LE scan. If set to 0, you will be notified of scan results immediately. If > 0, scan results are queued up and delivered after the requested delay or 5000 milliseconds (whichever is higher). Note scan results may be delivered sooner if the internal buffers fill up.” It may be beneficial in some applications to process bulk scan results at regular intervals rather than asynchronously as they are received. **Scan Mode:** configure the scan prioritization - [SCAN\_MODE\_BALANCED](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#SCAN%5FMODE%5FBALANCED): “Perform Bluetooth LE scan in balanced power mode. Scan results are returned at a rate that provides a good trade-off between scan frequency and power consumption.” - SCAN\_MODE\_LOW\_LATENCY: “Scan using highest duty cycle. It’s recommended to only use this mode when the application is running in the foreground.” - SCAN\_MODE\_LOW\_POWER: “Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the least power. This mode is enforced if the scanning application is not in the foreground.” - [SCAN\_MODE\_OPPORTUNISTIC](https://developer.android.com/reference/android/bluetooth/le/ScanSettings?ref=novelbits.io#SCAN%5FMODE%5FOPPORTUNISTIC): “A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for other scan results without starting BLE scans themselves.” NOTE: Opportunistic scan mode allows an application to intercept scan results from scans that were started by other applications or by the Android OS. Scan mode provides an opportunity to optimize for battery consumption or reduced latency. Define a ScanSettings constant at the top of BLEManager using a lazy initializer. The Android SDK provides a ScanSettings builder that makes configuring ScanSettings easy. Inside the lazy initializer for scanSettings, add a call to the ScanSettings builder. Configure each available setting as shown, or feel free to test out different options. This is typically not necessary as many of the defaults will suffice, but all are included here for reference. ```kotlin private val scanSettings: ScanSettings by lazy { ScanSettings.Builder() .setCallbackType(CALLBACK_TYPE_ALL_MATCHES) .setLegacy(false) .setMatchMode(MATCH_MODE_AGGRESSIVE) .setNumOfMatches(MATCH_NUM_MAX_ADVERTISEMENT) .setPhy(PHY_LE_ALL_SUPPORTED) .setReportDelay(0) .setScanMode(SCAN_MODE_LOW_LATENCY) .build() } ``` ## Scanning ### Android Scanning Limitations Android includes a few restrictions related to BLE scanning that are important but not well known. - Android rate limits the number of start scan calls to 5 within a time interval of 30 seconds. If that value is exceeded, there will be a one-minute timeout before being able to start scanning again. - Scans timeout out after 30 minutes, so need to be restarted if the goal is to scan continuously. ### Starting a Scan Android provides two different options for receiving scan results during a Bluetooth scan. #### Option 1: Scan results received by Callback In order to receive scan results via Callback, we first need to define a ScanCallback object. Inside BLEManager, below the “setupBluetoothAdapterStateHandler,” define a new constant called leScanCallback of type ScanCallback using a lazy initializer. ```kotlin private val leScanCallback: ScanCallback by lazy { object: ScanCallback() { } } ``` Now, inside the ScanCallback we need to override two methods, onScanResult and onScanFailed. Add console logs in both overridden functions to verify things are working when we run the app later. ```kotlin private val leScanCallback: ScanCallback by lazy { object: ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult?) { super.onScanResult(callbackType, result) Log.d(TAG, "BLE Scan Result") } override fun onScanFailed(errorCode: Int) { super.onScanFailed(errorCode) Log.d(TAG, "BLE Scan Failed with ErrorCode: $errorCode") } } } ``` Next, add a function below leScanCallback called startScanning. Now add a call to start a scan and pass in the scanSettings, scanFilters, and the leScanCallback we just defined. We also need to make sure that the correct permissions have been granted before starting a scan. Make sure to add a check as shown. Android will include a warning for the start scan call indicating the check needs to be performed. ```kotlin fun startScanning(){ if (PermissionManager.permissionsGranted.value) { bluetoothLeScanner .startScan( scanFilters, scanSettings, this.leScanCallback) } } ``` We need to add a call to start scanning. Normally, we would set this up differently but since this is only for demonstration, we are going to invoke a call to start scanning from the main activity. We need to wait for permissions to be granted before we attempt a scan. In the Coroutines section, we set up the PermissionsManager to make this possible. We need to declare and define a CoroutineScope where we will observe the permssionsGranted StateFlow on PermissionManager. Inside of the MainActivity towards the top, declare a new constant called scope. ```kotlin val scope = CoroutineScope(Dispatchers.IO) ``` On the line below bleManager inside of the onCreate function in the MainActivity, launch a new Coroutine using the scope we just defined and observe the permissionsGranted StateFlow property of PermissionManager. If permissions have been granted, start scanning. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) PermissionManager.askPermissions(this) val bleManager = BLEManager(this) scope.launch { PermissionManager.permissionsGranted.collect{ permissionsGranted -> if (permissionsGranted) { bleManager.startScanning() } } } } ``` Run the application and confirm scan results are being received by the callback. ![Graphical user interface, text Description automatically generated](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c7a02853.png) #### Option 2: Scan results delivered via a PendingIntent Option 2 requires significantly more work to set up than option one. First, we set up an Intent, an IntentFilter, and a PendingIntent. At the top of the BLEManager, below the bluetoothLeScanner declaration, add each as shown below. ```kotlin val ACTION = "BluetoothDevice.ACTION_FOUND" val FLAGS = PendingIntent.FLAG_UPDATE_CURRENT val intent = Intent(context, LEScanBroadcastReceiver::class.java).setAction(ACTION) val intentFilter = IntentFilter(BluetoothDevice.ACTION_FOUND) val pendingIntent = PendingIntent.getBroadcast(this.context, -1, intent,FLAGS) ``` Next, we need to set up a broadcast receiver. Add a new class declaration above BLEManager named LEScanResultBroadcastReciever that extends BroadcastReciever. Add a TAG at the top for logging and override the onRecieve method. Inside of the onRecieve function, add logic to verify the intent action matches BluetoothDevice.ACTION\_FOUND. Finally, we need to grab the scan result from the intent. ```kotlin class LEScanBroadcastReceiver: BroadcastReceiver() { private val TAG = "LEScanBroadcastReciever" override fun onReceive(context: Context?, intent: Intent?) { val action = intent?.action val EXTRA = BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT if (action == "BluetoothDevice.ACTION_FOUND"){ val scanResult = intent.getParcelableArrayListExtra(EXTRA) Log.d(TAG, "Scan Result: ${scanResult}") } } } ``` Now we need to initialize an instance of LEBroadcastReciever inside BLEManager and register it with the intentFilter. Add a call to registerReciever inside the init function and pass the LEBroadcastReciever instance and the intentFilter. ```kotlin private val leScanBroadcastReceiver: LEScanBroadcastReceiver = LEScanBroadcastReceiver() init { setupBluetoothAdapterStateHandler() (context as Activity).registerReceiver(leScanBroadcastReceiver, intentFilter) if (!bluetoothAdapter.isEnabled){ val enableBtInt = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) (context as Activity).startActivityForResult(enableBtInt, REQUEST_ENABLE_BT) } } ``` Finally, we need to register the receiver and intent filter in the Android Manifest inside of the application tag as shown below. ```markup ``` Update the startScan call in BLEManager to pass the pending intent instead of the leScanResultCallback. ```kotlin fun startScanning(){ bluetoothLeScanner .startScan( scanFilters, scanSettings, this.pendingIntent) } ``` Run the app and make sure you see the expected output in the console. ![Graphical user interface, text Description automatically generated](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c7b46158.png) ### Scan Options Summary #### Option 1: Callback-Based Scan #### *Pros:* - Simple setup - Scan results are returned as ScanResult objects; no need to interact with intents to unwrap data - Supported on older versions of Android #### *Cons:* - Background scan is limited to 10 minutes without adding a Foreground Service to keep the app running in the background - Not possible to re-launch the application from the scan result event #### Option 2: PendingIntent Based Scan #### *Pros:* - Scan results delivered in the background without the need to add a Foreground Service - Ability to re-launch the application on scan result event #### *Cons:* - A complicated setup, requires a much larger effort - Higher power consumption - Only supported Android 8 and later ## Logging and Interacting with Scan Results Let’s go back to the onScanResult function defined in BLEManager inside of the leScanCallback and update the console log to include all the data included in each of the scan results. Android provides the manufacturer data as a SparseArray, so we will add a function to convert it to a hex byte array. Add the function shown inside BLEManager. ```kotlin private fun toString(array: SparseArray?): String? { if (array == null) { return "null" } if (array.size() == 0) { return "" } val buffer = StringBuilder() for (i in 0 until array.size()) { buffer.append( String.format("%02x", array.keyAt(i))) val a = array.valueAt(i) a?.let { it.forEach { byte -> buffer.append(String.format("%02x", byte)) } } } return buffer.toString() } ``` We also need to format the raw advertisement data into a hex string as shown so that it’s readable. ```kotlin private val leScanCallback: ScanCallback by lazy { object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult?) { super.onScanResult(callbackType, result) val record = result?.scanRecord Log.d(TAG, """ BLE ScanResult Periodic Advertising Interval: ${result?.periodicAdvertisingInterval} Primary Phy: ${result?.primaryPhy} RSSI: ${result?.rssi} Secondary PHY: ${result?.secondaryPhy} Timestamp: ${result?.timestampNanos} TX Power: ${ if (result?.txPower == TX_POWER_NOT_PRESENT) "NOT PRESENT" else result?.txPower} Connectable: ${result?.isConnectable} Legacy: ${result?.isLegacy} """.trimIndent()) var rawAdvBytes: String = "" record?.bytes?.let { bytes -> for (b in bytes){ rawAdvBytes += String.format("%02x", b) } } var manufactureDataBytes: String = "" toString(record?.manufacturerSpecificData)?.let { manufactureDataBytes = it } Log.d(TAG, """ BLE ScanRecord Advertisement Raw Bytes: $rawAdvBytes Advertisement Flags: ${record?.advertiseFlags} Device Name: ${record?.deviceName} Manufacturer Specific Data: $manufactureDataBytes Service Data: ${record?.serviceData} Service Solicitation UUIDs: ${record?.serviceSolicitationUuids} Service UUIDs: ${record?.serviceUuids} """.trimIndent()) } override fun onScanFailed(errorCode: Int) { super.onScanFailed(errorCode) Log.d(TAG, "BLE Scan Failed with ErrorCode: $errorCode") } } } ``` Verify you see the expected console output: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/img_62f95c7c8d7b8.png) ## Summary & Next Steps In this tutorial, we covered everything required to get an Android application set up with the correct permissions and begin scanning for Bluetooth Low Energy devices. --- 💡 **Insider Tip:** Want access to the full source code of this tutorial and parts 2 and 3 of the "Getting Started with Android Bluetooth LE Development" course series? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. **Getting Started with Android Bluetooth LE Development - Part 2** covers: - The steps needed to properly manage connections and disconnections with Bluetooth Low Energy devices from an Android application - nRF52 Development Kit Setup: Nordic\_Blinky example - Updating ScanFilters to filter for Nordic\_Blinky example - Building a Class to represent the development kit running the Nordic\_Blinky example - Building reliable logic to track discovered and connected devices - Building a ListView with Jetpack Compose to display discovered and connected devices - The most common connection error in Android and how to avoid it **Getting Started with Android Bluetooth LE Development - Part 3** covers: - Modifying the NordicBlinky example to require pairing and bonding - Importance of tracking and observing bond state for devices that require bonding - Initiating GATT discovery and building a model to encapsulate characteristic references - Requesting a larger MTU - GATT Operations - Using Flows to make characteristic data updates observable - Abstracting GATT operations - Importance of synchronous GATT operations - Building a GATT queue to ensure GATT operations happen synchronously - Updating the app to support multiple views with a Navigation controller - Building a new view to display NordicBlinky states and control the LED ### Tutorial: How To Design A Bluetooth LE GATT Server For Your Application URL: https://novelbits.io/design-bluetooth-low-energy-gatt-server-database/ Last updated: 2026-04-26T17:49:02.000Z If you want to learn how to create a GATT server and load it with some attributes, then you might find this tutorial helpful. The process of creating a GATT server is not as daunting or complicated, that is, once you break it down into easy steps. What You Will Need: - Read the [ATT Protocol layer and GATT Profile post](https://novelbits.io/bluetooth-le-att-gatt-explained-connection-oriented-communication/) - Silab's Configurator tool (within [Simplicity Studio](https://www.silabs.com/developers/simplicity-studio?ref=novelbits.io)) This is a simple, straightforward guide that will hopefully demystify the process and make it easy to follow. Before we begin, there are a few things we need to go over again: - What is a GATT server? - Attributes - Organizing data in a hierarchical model - services and characteristics - UUIDs ## **GATT Servers & GATT Clients?** When two connected devices exchange data using Bluetooth Low Energy (LE) technology, they follow a client-server architecture, where one device has the data or resource and the other device requests it. The device with the data is called the **GATT server,** while the one requesting it is known as the **GATT client.** So, to an extent, designing a GATT server is similar to designing a database. And to do so, we need to understand three things: 1. The format in which each piece of data is stored, 2. How groups of data are organized, and 3. The different ways the data can be accessed. **Let's begin with the format.** ## **Attribute** The GATT Server uses the **Attribute data structure** to store its data. This data structure has four fields: - Handle - UUID (Attribute Type) - Value - Permissions So, every data entry stored in our GATT server (a.k.a database) must have these four fields. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image.png) Source: Bluetooth Core Specification document - **Handle**: is just an index number used by the GATT server to identify each entry, so it can be easily updated, deleted, or modified if needed. - **UUID:** a type field that tells us what type of data is stored in the value field. \[refer to the [post about UUIDs](https://novelbits.io/uuid-for-custom-services-and-characteristics/)\] - **Value:** is the actual application data we want to store. - **Permissions:** This indicates if the data can be read, written, both, or none. Security requirements are also listed for each type of operation. Now that we know how a single piece of data is stored, let's move on and see how groups of this data are organized in our GATT server. ## **Hierarchical Model** The GATT server organizes its database using a hierarchical model. There are four levels in this hierarchical model: - Level 0 or the root is called the *profile* - Children of the profile are named services (level 1) - Children of services are named characteristics (level 2) - Children of characteristics are named values and descriptors (level 3) Let's quickly go over each level: - **Profile:** a template that defines how the data should be organized and the behavior of the client and server implementing the profile. It's almost like the table of contents of our GATT server database but also defines the behavioral guidelines of a device implementing the profile. - **Services**: contain all of the characteristics associated with specific functionality. - **Characteristics:** each contains a single piece of application data that we actually want to store along with its descriptors or metadata. These are the characteristic value and descriptor, respectively. The GATT server's database stores the following levels of the hierarchy framework: - Service - Characteristics - Properties - Value - One or more descriptors (attributes that describe the characteristic value. E.g., unit, user description, etc.) \[optional\] The GATT server will store data for each of these levels in the following manner: ![GATT Hierarchy](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1.png) Source: Bluetooth Core Specification document When we look at the database, we can see that a characteristic value below a service holds the value related to the functionality that the service provides. Furthermore, the characteristic descriptors that appear beneath a characteristic value describe the value... This is how the hierarchical model assists us in organizing our GATT data. ## **UUIDs** As previously stated, the attribute data structure is used to store all data in a GATT server. One of the fields in that data structure is the UUID. This means that each of the GATT attributes you intend to store (service, characteristic declaration, characteristic properties, and characteristic value) must have a unique identifier (UUID). **How do we assign UUIDs to these data types?** It depends if the UUID is for a custom service/characteristic or if it's for one of the Bluetooth SIG Adopted Profiles. If it's for a custom service or characteristic, you can use any UUID you want as long as it doesn't conflict with the Bluetooth SIG's Adopted UUIDs. To learn more about generating your own custom UUID(s), refer to our previous post [here](https://novelbits.io/uuid-for-custom-services-and-characteristics/). However, if it is for a Bluetooth SIG Adopted Profile service/characteristic, you must use the UUID that the Bluetooth SIG has already assigned. A list of these UUIDs can be found [here](https://www.bluetooth.com/specifications/assigned-numbers/?ref=novelbits.io). 💡 **Tip:** In general, you don’t have to worry about assigning the UUIDs for the descriptors and properties. These are usually automatically assigned by the Bluetooth LE stack in use on a certain platform. **Enough with the long-winded introduction; let's get into the tutorial!** ## **Four Steps To Designing Your GATT Server** Now that we understand how a GATT server stores data and the different ways to access that data, we can start creating our own GATT server. The first step is identifying which profile you want to use (application use-case). This will determine the services and characteristics. Instead of creating a "Hello World"-style application that simply shows you that we can dump some information on the screen, in this tutorial, we will take an example application that does something useful. **Real-World Application - “Bluetooth Weather Station”** Let's say we want to create a weather station that uses Bluetooth Low Energy (LE) to interact with a smartphone. The weather station will have some sensors to measure the temperature, humidity, and pressure. It will also have an LCD screen so we can see the current readings without having to pull out our phone. **Step 1**: **Describe what your application will do.** The data flow for this weather station application will look like this: The weather station will take readings from the sensors and store them, and therefore it will act as the GATT server. The smartphone will then connect to the weather station and read the values of the characteristics, which represent the sensor readings. The phone can also subscribe to notifications so that it gets alerted whenever a new sensor reading is taken. Now that we know what our application will do, we can start creating the GATT server. **Step 2: Define Your Characteristic Values, Permissions, and Descriptors** In this step, ask yourself these questions: - What different application data points do I want my GATT server to store, share, or be controlled? - How do I want other devices to interact with this data? Read-only? Writeable? Notifiable? Indicatable? 💡 **Tip:** the main difference between Notifications and Indications is that indications require the application layer to acknowledge their receipt by sending a confirmation message. In contrast, notifications do not require a confirmation. - What security permissions do I want to set on this data? (e.g., authorized writes, encrypted reads/writes, etc.) - Do I need descriptors for my data? For example, a user description descriptor? The answer to these questions will help you define your characteristic values, permissions, and characteristic descriptors. **In our weather station example, we need the following data:** - **Temperature** readings in **Celsius** \- Readable, Notifiable - **Humidity** readings in **relative percentages** \- Readable, Notifiable - **Barometric** **pressure** in **hPa** \- Readable, Notifiable - LCD screen text - Writable, Readable - Battery level - Readable These data will be the different characteristic values stored in our weather station GATT server. We also want to allow any device to connect to our weather station, so we won't set any security requirements. **We also need the following descriptors:** - **Characteristic User Description** \- for example, for the LCD screen text, we can give it a friendly name like "LCD Screen" – same for the other characteristics (”Temperature” for the temperature characteristic, etc.) - **Client Characteristic Configuration Descriptor (CCCD)** \- This is a special descriptor that allows a GATT client to subscribe/unsubscribe to notifications and indications for a specific characteristic. For the temperature, humidity, and pressure readings so that the phone can subscribe to notifications. This allows a GATT Client to avoid polling the characteristic value of interest and getting “notified” when a new value is available, thus reducing the power consumption and bandwidth usage. These descriptors will be the characteristic descriptors stored in our weather station GATT server. The following table summarizes the information that we want to store on our GATT server and the permissions that we want to give for each: - **User Description**: UTF-8 string to describe the Characteristic Value for a better user experience - **UUID**: Standard/Adopted UUIDs are defined in [https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit UUID Numbers Document.pdf](https://www.bluetooth.com/specifications/assigned-numbers/?ref=novelbits.io) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-08-08-at-10-09-07-pm.png) **Step 3: Build up the hierarchy by forming services** Now that you have defined your characteristic values, permissions, and characteristic descriptors, you can start creating your GATT service by grouping your characteristics together. Ask yourself these questions: - Do all my characteristics belong to the same service (functionality), or can they be grouped into multiple services? - If there are multiple services, which ones should I consider as my primary services? In our weather station example, we will be creating three services called: - "**Weather Station**" service (custom) - “**LCD Screen**” service (custom) - “**Battery Level**” service (SIG-Adopted) The "Weather Station" service will group together the temperature, humidity, and pressure readings. This is because they all relate to the weather parameters. The battery level and LCD screen readings will each have their own service since they don't relate to each other. **Step 4: Decide on your UUIDs** Now that you have decided on your services and characteristics, you need to give each of them a unique identifier called a UUID. There are two ways to generate a UUID: - Use a pre-defined UUID - e.g., the 16-bit (or 32-bit – not common) Bluetooth SIG assigned UUIDs for officially adopted services and characteristics - Generate a random UUID (128-bit) - e.g., using a Universally Unique Identifier (UUID) generator for custom services and characteristics \[see the [previous post on choosing your UUIDs](https://novelbits.io/uuid-for-custom-services-and-characteristics/)\] Ask yourself these questions: - Which amongst my services are already predefined by the SIG so I can re-use their UUIDs? (Public services and characteristics) - How will I generate UUIDs for my custom services and characteristics? In our weather station example, we will generate random UUIDs for our **“weather station”** service and characteristics and the **“LCD screen”** service and characteristic using SiLab's UUID Configurator Tool. These two are our custom services. And, since the battery level service is already an officially adopted one, we will use one of the 16-bit Bluetooth SIG assigned UUIDs for it. We also do not have to create UUIDs for the Descriptors (User Description, CCCD, etc.); those have UUIDs that the SIG defines in the specifications (see *Vol 3, Part G, Section 3.3.3 of the Bluetooth Core Specification document)*. What’s cool is that by using Silicon Labs’ GATT Configurator Tool, we don’t even have to worry about generating any custom UUIDs or assigning the correct UUIDs for the adopted services and characteristics. It all gets handled automatically for us. The following table shows the UUIDs that we have generated for our weather station application using the GATT Configurator Tool: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-4.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-08-08-at-10-06-16-pm.png) ## **Demo: Create your GATT database using Silicon Labs' GATT Configurator Tool \[Simplicity Studio\]** The GATT Configurator Tool is a GUI tool that allows you to create and edit your GATT database files when developing on Silicon Labs' chipsets/development kits/modules. Here's a video tutorial showing how it's done: ## **Let's Recap!** In this tutorial, we learned: - All about the most important attributes used in Bluetooth LE: Profiles, Services, Characteristics, and Descriptors. - That these attributes are structured hierarchically on the GATT Server, in such a way that's very similar to a database. - How to design the GATT Server for a custom device, in four steps. Finally, we showcased and example of how to configure your GATT server using the Silicon Labs GATT Configurator Tool that's included part of [Simplicity Studio (v5)](https://www.silabs.com/developers/simplicity-studio?ref=novelbits.io). ### Bluetooth ATT and GATT Explained (Connection-Oriented Communication) URL: https://novelbits.io/bluetooth-le-att-gatt-explained-connection-oriented-communication/ Last updated: 2026-04-08T18:05:16.000Z In our previous post, we introduced some of the [layers](https://novelbits.io/bluetooth-low-energy-protocol-stack-layers/) of the [Bluetooth Low Energy](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/)[ protocol stack](https://novelbits.io/protocol-stacks-layered-architecture/). Today, we will take a closer look at the ATT (Attribute) protocol and GATT (Generic Attribute Profile), two important [protocol](https://novelbits.io/communications-protocols-and-why-we-need-them/) layers that allow data transfer during a connection-oriented communication mode. If you are looking to transfer data between connected devices using LE, understanding the technical jargon around ATT & GATT is essential! So let's get started... ## Quick Primer: How Devices Connect Using The GAP Layer For Bluetooth LE-enabled devices to transmit data between each other, they must first form a communication channel. How this channel is formed and maintained is the responsibility of the GAP (Generic Access Profile). The Generic Access Profile instructs that for two devices to connect and communicate, one must take the role of Central, and one must take the role of Peripheral. The Central is typically a powerful device like a smartphone, while the Peripheral is often something that requires less power, like a fitness tracker. And the journey to establishing a connection between the two starts like this: ### **Step 1:** When the device that wants to assume the peripheral role is ready to connect, it must enter the advertising state and begin announcing its presence by using its LE radio to broadcast advertising packets on the three primary advertising channels: 37, 38, and 39. ![Advertising Events](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/1.png) *Broadcasting Advertisement packets on the primary channels* **Note**: *Advertisement packets (PDUs) can also be sent on secondary advertisement channels (data channels) in Bluetooth 5 (or later), but they *always* start with advertising on the primary channels first. For the sake of simplicity, we'll focus on the primary advertising channels for the time being; alternatively, you can read a post we wrote about* [*Bluetooth 5's features*](https://novelbits.io/bluetooth-5-advertisements/)*.* ### **Step 2:** A device that wants to assume the Central GAP role must transition into a scanning state and listen on these three channels for an advertising packet. ![Scanning Event](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/scanning-event-1-1.png) *Listening for packets on the primary channels* When the scanning interval coincides with an advertising event, something magical happens: the central device discovers the peripheral device! ### **Step 3:** When an advertising packet is detected, the next step is for the Central to initiate a connection to the Peripheral by sending a **Connection request packet.** Between the two GAP roles, the device that supports the central GAP role is in charge of managing the connection and has the final say in the connection parameters. We won't delve much into these connection parameters, but some of them include: - **Connection Interval** \- to specify how much time elapses between connection events - **Peripheral Latency** \- to specify how many connection events can be skipped by the peripheral device - **Channel Map** \- to specify which of the 37 available data channels will be used for transmission. The Central device decides on these parameters and bundles them up into a connection request packet that it sends to the peripheral. After this act**, we say the connection is created.** Then, the central device will then send a data packet to the peripheral device after a time interval known as a connection interval. If the peripheral device receives the data packet and responds by sending one back to the central device, **the connection is now considered to be established.** ![A smartwatch is establishing a connection with a ](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/connection-establishment-2-1.png) *Connection creation and connection establishment* ### **Step 4: Viola! We have a connection.** After establishing a connection, devices can have a persistent and synchronized bi-directional data transfer. So, how exactly is this data transfer accomplished? How do devices talk to each other after they've established a connection? This is where ATT & GATT play a vital role. ## Attribute Protocol (ATT) - Roles First, the ATT Protocol defines roles. And, yes, with each role comes specific responsibilities. The roles defined by ATT are based on a client-server architecture, similar to the one used by the world wide web, where a device that is a provider of a resource or service is called a *server*, and the *client* is the consumer or requester of that resource or service. - **Server** \- The server acts as a database and stores data that can be read or written by the client. E.g., a fitness tracker will store the latest heart rate value. - **Client -** which is the device that requests the data from the server. E.g., a smartphone connected to a fitness tracker. Now, don't fall into the assumption that a device that supports a GAP Central role will automatically assume the Client ATT role, and the device that supports a GAP Peripheral role will automatically assume the Server ATT role. No, this isn't always the case. The server and client ATT roles are independent of the GAP roles and can be played by any device at any time. So, both devices in a connection can act as either a server or a client, depending on the context of the data being transferred. To further understand this concept, let's take a look at an example from [Android's Bluetooth guide](https://developer.android.com/guide/topics/connectivity/bluetooth/ble-overview?ref=novelbits.io): Imagine you have an Android smartphone that is connected to your fitness tracker. When the tracker wants to report data to the phone, then it acts as the server, and the phone acts as the client. In this case, the tracker provides data (such as heart rate or steps taken) to the phone. An example of when the phone acts as the server is for a SIG-adopted service called the *Current Time Service*. In this case, the phone will expose the current time information for the peripheral (e.g., tracker) to read and obtain. Since the phone usually has an internet connection and can synchronize its clock to an accurate reference, it can easily provide this information to other devices that do not have access to the internet; the fitness tracker in this scenario. ## Attribute Protocol (ATT) - Server Role and Attributes As previously stated, the server device functions as a database to store the data that it needs to share with the client device. For proper functionality, the server, like any other database, requires: - A standard method to store and organize the data, and - Standard mechanisms to access the data. **It is the responsibility of the ATT protocol to provide means for the server device to store data in a format that can be read and written by the client, as well as to provide mechanisms for the client to access, write, and read that data.** ### Attributes The ATT protocol defines a data structure called an attribute as a standard method for effectively organizing the data stored, accessed, and updated on the server. The attribute data structure has four fields: Handle UUID Value Permissions Attribute data structure - **An Attribute Handle** \- This is a unique unsigned 16-bit identifier that is used by the client to reference an attribute on the server. It makes the attribute "addressable," and it does not change during a single connection. - **An Attribute Type (UUID)** \- This is a globally unique 2-byte or 16-byte UUID identifier that defines the type and meaning of the specific data stored in the attribute's value field. There are two types of UUIDs: Service UUID and Characteristic UUID. - **An Attribute Value** \- This is the actual data being stored. For example, the heart rate sensor reading value or temperature reading from a temperature sensor. - **An Attribute Permissions Field** \- It specifies the various methods that can be used to access the attribute value, as well as the security level required to access the attribute value. For example, an attribute may require no permissions to read but may require authentication to modify (write to) it. **On the server, data is organized as a table of attributes:** Handle 0001 Attribute 0002 Attribute 0005 Attribute ●●● FFFE Attribute FFFF Attribute A table of Attributes in a Server's database All attributes of an LE server are stored in its database by increasing the attribute handle value. A successive attribute doesn't need to have the next integer handle value, and there can be gaps between handle values as long as they are in increasing order. ### Attribute Access Methods The ATT protocol also defines methods by which attributes can be read or written. The methods depend on whether it is the client or the server who initiates the attribute access procedure. In the case where the client initiates attribute access, two operations are defined - **The read and write operation.** They are pretty self-explanatory, but to recap: ![Client device performing a write and read ATT access method](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/write-and-read-operation-1-1.png) *Write and Read ATT-defined access methods* The **Read operation** is used by the client to read the value of an attribute from the server. The server responds with the value of the attribute. The **Write operation** is used by the client to write the value of an attribute on the server. The server responds with a status indicating if the write was successful or not. On the other hand, in the case where the server initiates access, two operations are defined: **Notification** and **Indication** operations**.** ![Notification and Indication ATT-defined access methods](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/notification-and-indication-operations-1-1.png) *Notification and Indication ATT-defined access methods* The **Notification** operation is used by the server to send an updated value of an attribute to the client every time it changes. The client does not respond to this operation. The **Indication** operation is similar to the notification operation, but the client has to send back a response with an acknowledgment status indicating whether or not it has correctly received the value. ### Attribute Access Permissions Access permissions, like file permissions, determine whether a client can read or write (or both) an attribute value. Each attribute can be assigned one of the following access levels: - **None** \- A client can neither read nor write the attribute. - **Readable** \- A client can read the attribute. - **Writable** \- A client can write the attribute. - **Readable and writable** \- The client can read and write the attribute. Regarding security requirements, the attribute types and handles are public information, but the value field and permissions are not. As a result, in order for the client to access these two private fields, the server may require the following: - Authentication to read or write - Authorization to read or write - Encryption and pairing to read or write ## A Hierarchical Database Model A hierarchical database model is a data model in which data is not organized sequentially but rather in a non-linear format to demonstrate the data's hierarchical relationship. This model uses a tree-like pattern to represent data. This type of data model organizes data in a way that makes it faster to access and uses less memory. [Scaler Topics'](https://www.scaler.com/topics/non-linear-data-structure/?ref=novelbits.io) example is arguably the best way to explain a hierarchical database model: Assume John and Sarah are high school students. Their teacher assigned them to provide a detailed list of the names of the Faculties in their year, as well as their departments. John decides to create a table that includes each person's name, department, and designations. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-5-3.png) *Source: Scaler Topics* Sarah, on the other hand, decides to draw a tree diagram showing all of the faculties and their designations: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-6-2.png) *Source: Scaler Topics* **Q. Who do you believe will receive a higher grade in their assessment?** Sarah! She created a hierarchical database model, which allowed her to more easily visualize the structure of the data and understand the relationships between the different elements (faculty members). The hierarchical model is an efficient way to organize data. As you can see, it efficiently organizes data into a hierarchy. This makes it easy to visualize the structure and relationship of the data elements. **ATT Server (A.K.A database)** As previously stated, the ATT protocol stores data as attributes in a table in a linear manner by sequentially increasing the handle number of the attribute. But what if we want to indicate a relationship between the data stored on the server? Just like Sarah did in the previous example. And, by relationship, we mean the one similar to a file and folder relationship found in a computer disk drive, where we intuitively understand that files in the same folder are related. This would make it easy to navigate through a complex database. Wouldn't you agree? **The GATT layer is in charge of defining a hierarchical data structure that demonstrates the relationship or connection between the data stored in an ATT server.** Let's take a look at how the GATT protocol layer is used to establish this relationship. ## GATT (Generic Attribute Profile) The GATT protocol layer defines a framework in which the resources (data) on a server's database can be organized to show a hierarchical relationship. The GATT layer defines a 4-level tree-like framework: - The root node is named the **profile**. (level 0) - Children of the profile are named **services.** (level 1) - Children of services are named **characteristics.** (level 2) - And characteristics can be defined by a single **value** and 0-n **descriptors** (level 3) Let's illustrate this in the image below: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/gatt-profile-1.png) *Hierarchical Relationship of data* ### 1\. Characteristic A characteristic is a basic storage unit where the application data is "written" into and "read" from. It is analogous to a file on a computer disc drive. We know that files are where all programs and data are written into or read from. Every Characteristic is defined by : - Value - Descriptor (optional) **Characteristic Value** \- The actual application data stored. **Descriptors**\- A descriptor is optional information that tells you more about a characteristic's value. This might include a human-readable description, an acceptable range for the characteristic's value, or a unit of measure that is specific to the characteristic's value. A very popular descriptor is the **Client Characteristic Configuration Descriptor (CCCD).** CCCD is used to enable or disable indications or notifications from a GATT server. By enabling notifications or indications on a particular characteristic, the client can be notified or receive updates whenever the characteristic value changes on the server. Let's look at a fitness tracker with a[ GATT Heart Rate Profile ](https://www.bluetooth.com/specifications/specs/heart-rate-profile-1-0/?ref=novelbits.io)to see how the hierarchical relationship works. According to the Heart Rate GATT profile, a device implementing it will contain: - Heart rate measurement characteristic (mandatory) - Body measurement characteristic (optional) - Device information characteristic (optional) **The heart rate characteristic is defined by:** - **Heart rate value-** this is the actual heart rate sensor data. - **Characteristic configuration descriptor-** this is for notification purposes so the client can be notified of changes to the heart rate value. **The body measurement characteristic is defined by:** - **Body measurement value**\- this is used to describe the location of the body where the device is to be worn. **The Device information characteristic is defined by:** - **Manufacturer name string**\- This is the name of the device's manufacturer. ### 2\. Services Services are primarily used for organization purposes rather than storage. They are analogous to folders or drawers. Just like a folder houses related files, a service contains related characteristics. For our fitness tracker example, its services will be: - **Heart rate service-** This service includes the heart rate characteristic \[heart rate value + Characteristic configuration descriptor\]. - **Body measurement service-** This service includes the body measurement characteristic. - **Device information service-** This service includes the device information characteristic. ### 3\. Profile On top of the hierarchy are the profiles, which contain services for a particular use case that the server supports. Some services are optional, while others are required, but every device that conforms to a specific profile must implement all mandatory services (and characteristics). This is done to ensure that devices that support the same GATT profile can communicate with one another (interoperability). For example, when a fitness tracker from manufacturer X claims to support the Heart Rate GATT profile. Then it's expected that : - It will 100% contain the Heart Rate service - It will 100% contain the Heart rate measurement characteristics. This standardized way of organizing data has many benefits: - **Data is easy to find** \- When we know the structure of how the data is organized, client devices can quickly discover the services offered by the server and determine whether or not the services are relevant. - **Data is easy to share**\- When everyone agrees on how the data should be structured, it becomes much easier to exchange that data between devices. - **Promotes interoperability**\- When devices use the same profile, they can be sure that they will be able to communicate with each other. In our fitness tracker example, its Heart rate profile contains the following services: - Heart rate service (mandatory) - Body measurement service (optional) - Device information service (mandatory) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/heart-rate-profile-1.png) *Hierarchical relationship of data in a Heart Rate Profile* ## The GATT Profile Builds On The Functionality Of The ATT Protocol The GATT layer lies above the ATT (Attribute Protocol) layer in the Bluetooth Low Energy protocol stack. It reuses many of the concepts and functionality of the ATT layer. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/application-4-2-2.png) *ATT and GATT in the Bluetooth protocol stack* ### 1\. GATT Reuses The ATT Client-server Architecture: GATT layer uses the ATT client-server architecture. In this architecture, devices play either the role of a GATT client or a GATT server. - GATT Server- This stores and sends requested data to the GATT client. - GATT Client- A device that wants to access data on the GATT server. It is also used to discover all the primary services and characteristics offered by a GATT server. In general, communication between the GATT client and the GATT server begins with the GATT client performing a service and characteristic discovery to find out: what services are offered by the GATT server and what characteristics are associated with each service. ![GATT Client and GATT server](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Notification-and-Indication-Operations-1920--C3-97-1080px-1-1-1.png) *Service discovery is always before Attribute access methods* After the discovery process is complete, the GATT client can then read or write the values of certain characteristics that it is interested in or configure notifications to be sent by the GATT server whenever the value of characteristic changes. ### 2\. GATT Reuses The ATT Attribute Data Structure GATT uses the Attribute data structure to store services and characteristics. ![Attribute's table](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/attributes-table-2-1.png) *GATT Attributes stored in the Server's Attribute Table* Each service and characteristic, therefore, have a: - **UUID** \- This is a unique identifier that differentiates it from other services or characteristics, and it is stored in the attribute's type field. For officially adopted Bluetooth LE services and characteristics, the UUID has a length of 16 bits. [Custom services](https://novelbits.io/bluetooth-gatt-services-characteristics/) have a UUID length of 128 bits. - **Value-** This is data or metadata stored in the Attribute value field. - **Permissions-** This defines what operations are allowed on the data (read, write, etc.) and security settings. These are stored in the Attribute permissions field. ### 3\. GATT Uses ATT PDUs The GATT layer uses ATT requests and responses to: ![Attribute Protocol PDU](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/attribute-protocol-pdu-1-1-1.png) *Attribute Protocol PDU* - Read and write data on the GATT server - Discover all the primary services offered by a GATT server - Subscribe or unsubscribe to notifications/indications from the GATT server. ## Summary In this post, we took a closer look at the ATT and GATT Protocol layers to help us develop applications that take advantage of connection-oriented communication. Simply put: - The ATT protocol is responsible for managing data storage between devices. It provides a means for the server device to store data in a format (Attribute data structure) that the client can read and write, as well as provide mechanisms for the client to access, write, and read that data ( Access methods and permissions). - The GATT layer defines a hierarchical data structure that aids in demonstrating the (relationship) connections between various types of server-stored data ( GATT Profile) 💡 **Insider Tip:** Want to take your Bluetooth Low Energy knowledge to the next level? The [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) gives you access to comprehensive courses covering ATT, GATT, and much more with hands-on implementation guides. ### The Bluetooth Low Energy Protocol Stack: Understanding the Layers URL: https://novelbits.io/bluetooth-low-energy-protocol-stack-layers/ Last updated: 2026-05-01T15:53:28.000Z Do you want to know how the Bluetooth Low Energy Protocol Stack works? You've come to the right place. The first step in understanding how the LE Stack functions is to recall what [a protocol](https://novelbits.io/communications-protocols-and-why-we-need-them/) and [protocol stack](https://novelbits.io/protocol-stacks-layered-architecture/) are. A protocol is a rulebook that devices must adhere to in order to communicate or exchange information. So, **what is the Bluetooth LE Protocol?** The same thing. A rulebook that has to be followed by devices that use the standardized [Bluetooth Low Energy](https://www.youtube.com/watch?v=JSQhRyTKnW4&ref=novelbits.io) technology for communication purposes. Second, picture a rulebook divided into several chapters. The general functionality of a protocol is also divided into smaller protocols, each of which is in charge of a particularly specific task. These smaller protocols are packaged into a layered architecture called a protocol stack or protocol suite. So, what is a **Bluetooth LE Protocol Stack?** The same thing. A package of smaller protocols, where each focuses on a specific role. These smaller protocols are packaged into layers that work together to provide the overall functionality of the Bluetooth Low Energy Protocol. The knowledge of these two concepts—**protocol and protocol stack**—clears up the mystery and gives you some idea of what to expect while learning about the Bluetooth Low Energy protocol stack. Gear up, and let's get started with our exploration of the Bluetooth LE protocol stack. ## **Break It Down: Subsystems of the LE Protocol Stack** The Bluetooth Low Energy protocol stack is broadly broken down into three primary components or subsystems. These are the **application, host, and controller** blocks. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18df9b62b6.jpg) ### **1\. Application** This is software that acts as a man-machine interface by bundling together the entire functionality of Bluetooth LE protocol in a fashion that is accessible to the user. ### **2\. Host** The host is typically a software stack made up of the **topmost layers of the LE stack** as well as what are known as **profiles**. A profile offers details on how each protocol in the stack should communicate with one another and work together for a certain usage model. LE Profiles act as a commander by directing the soldiers (the layers of the protocol stack) in a specific enemy's direction (specific usage model). ### **3\. Controller** The controller is a subsystem that consists of the **lower layer protocols in the LE stack.** The LE controller also consists of a physical radio that can generate and receive radio waves in the 2.4 GHz band, encode the RF signals with data (GFSK modulation) and radiate the signals through an antenna. It should be able to receive RF waves as well as understand how these signals can be interpreted as data packets with information within them. ## **Host, Controller, Host Controller Interface (HCI)** The HCI is an **optional** part of the stack. It provides a standardized communication interface between the host and the controller. ![Host Controller Interface](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18dfae5b8e.jpg) *Host Controller Interface* If it is omitted, it means in such a device, the functionality of a host and a controller will be implemented by the same processor. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18dfc1a4b2.jpg) *Source: Inside Bluetooth Low Energy* If it is included, then it allows a device to implement the Bluetooth LE functionality using a host from one vendor and a controller from another vendor (on different chipsets). For example, a [**Bluetooth USB dongle**](https://plugable.com/products/usb-bt4le?ref=novelbits.io) **attached to a PC**. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18dfcf3eb8.jpg) *Source: Inside Bluetooth low Energy* Another example is a **smartwatch.** ![Bluetooth LE smartwatch](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18dfde40d8.jpg) ## **Open It Up: The Protocol Layers in the LE Subsystems** The host and the controller subsystems house different protocol layers. Do you want to take a look? ![Bluetooth LE Protocol Stack](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/protocol-stack-7.jpg) *Bluetooth LE Protocol Stack* ## **Casting (Different Communication Styles)** In computer networking, casting is the process of sending data from one device to another. Just as there are many possible ways we humans can communicate with each other, so too are there several types of casting that can take place between devices in a network. For example, if I want only to have **one-to-one communication** with one specific person in my contacts, I would send them a direct message on WhatsApp. However, if I want to send a message to all my contacts, I would **broadcast** the message on my WhatsApp status. And if I want to send a message to a **specific group** of people called " serious engineers," I would create a Whatsapp group and add only those people whom I want to communicate with. Similarly, Bluetooth LE Protocol allows devices to exchange messages in different styles: - **Unicast Communication (one-to-one)** - **Broadcast Communication (one-to-many)** In a one-to-one communication style, there is a dedicated link (connection) between two devices, and data can flow in both directions. An example of this would be sending an "open the door" command from your smartphone to your [Tesla's ](https://novelbits.io/tesla-passive-keyless-entry-system-hacked/)door lock via Bluetooth LE and receiving a "door open" status notification back in return. In this type of communication, one device must initially start or stop the connection, and the other device is said to "accept" the connection. On the other hand, there is the one-to-many communication style. Here, a device can share (broadcast) its data with others without being connected to them. In Bluetooth LE, sharing data without connecting to others first is referred to as **advertising,** and searching (listening) for advertised data is referred to as **scanning.** Even in this communication style, the devices involved have roles. One device is tasked with **advertising**, while the other is tasked with **scanning.** An example of this would be [beacons](https://novelbits.io/blog/) in a retail store broadcasting their data, which in this case may be marketing notifications, to any LE-enabled smartphone in range. The beacon is the advertiser and the smartphone is the observer who is scanning. There is also a many-to-many communication style. But we won't get into that topic for now. **The main thing to bear in mind from this is that in each type of communication style, each device involved has a specific role to play in order for the exchange to be successful**. ## **The GAP, Link Layer & Physical Layer** Let's start with the GAP. ### **1\. GAP** GAP stands for **Generic Access Profile.** The Generic Access Profile is responsible for defining devices' roles in Bluetooth LE communication, among other things. There are four device roles defined by the GAP: - Broadcaster - Observer - Peripheral - Central In a **connection-less communication( broadcasting), where the exchange of data between devices occurs without first establishing a connection**, the Bluetooth LE devices involved take on the roles of **Broadcaster and Observer.** A broadcaster is expected to share the information, and an Observer is expected to be listening for such information. In a **connection-oriented communication (unicast),** **where data is only exchanged after a connection has been established between two devices,** the Bluetooth LE devices involved take on the roles of **Peripheral and Central.** The first step of a connection-oriented communication is **device discovery**. Here the peripheral device is expected to be **announcing its presence by advertising,** while the Central device is expected to be **looking for such announcements by scanning** and then sending a **connection indication** to the peripheral device. Once a connection is established, data can flow in both directions between the two devices. **The GAP roles essentially outline the tasks you can anticipate from a device during a Bluetooth LE communication transaction.** Just as you cannot expect a banana to grow on a mango tree, you cannot anticipate that a central device will announce its presence through advertising. That's the job of a peripheral device. In summary, one can say that the Generic *Access* Profile gives us *access* to the link layer state machine. Hold on, what's a link layer state machine? I am glad you asked. ### **2\. The Link Layer** The Link layer is the second lowest protocol in the Bluetooth Low Energy protocol stack. It's responsible for managing the state of the LE radio, among other things. To do this, the Link layer relies on a state machine. So, what's a state machine? In short, it's a model that defines how a system should behave under certain conditions. Let's take H2O, for example. H2O can exist in **3 different states** easily observable in nature: solid (ice), liquid (water), and gaseous (steam, fog, clouds). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18e003525c.jpg) The behavior of H2O varies in each of these states. When water is liquid, it flows; when it is solid, it is frozen. And the means of forcing transitions between the three states is also well-defined. Similar to this, the link layer provides seven different states for a Bluetooth LE radio. The LE radio acts differently in each state. In this post, we'll focus on 5 of the seven states. These are: - Standby state - Advertising state - Scanning state - Initiating state - Connection state ![Link Layer State Machine](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18e015e670.png) *Source: [Intro to Bluetooth Low Energy](https://www.novelbits.io/introduction-to-bluetooth-low-energy-book?ref=novelbits.io)* In a **standby state**, the LE radio is not doing much. It's neither sending nor receiving any packets. It is idle. The LE radio can enter the standby state from any of the other six states. In an **advertising state**, the LE radio is broadcasting advertisement packets that can be received by any LE-enabled device in range. The advertisement packets broadcast the device's presence and share information about it with other devices in the vicinity. In a **scanning state**, the LE radio is looking (listening) for packets that are being broadcasted by other LE-enabled devices in range. In an **initiating state,** the LE radio is attempting to establish a connection with another LE-enabled device. The LE radio can enter the initiating state from the standby state. In a **connection state,** the LE radio is connected to another LE-enabled device, and data can be exchanged between the two devices. Now let's link these radio states with the GAP roles. ![Connection-less and Connection-oriented communication styles](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/protocol-stack-6.jpg) *Connection-less and Connection-oriented communication styles* (the intermediate Standby state has been omitted for simplification) For a device that has a **broadcaster role**, its radio can be in the following states: **standby and advertising.** For a device that is an **observer**, its radio can be in the following states: **standby and scanning.** For a device that has a **peripheral role**, its radio can be in the following states: **standby, advertising, and connection states.** And for a device that has taken the **central role,** its radio can be in the following states: **standby, scanning, initiating, and connection states.** Based on a device's GAP role, its radio is expected to be in certain link layer states. And finally, let's discuss the Physical layer. ### **3\. Physical layer** The physical layer (PHY) is the lowest layer of the Bluetooth LE protocol stack. It relates to the physical method used to transmit the information, which in this case is the use of RF waves for transmitting and receiving raw bits over the air. The PHY defines how these bits are modulated onto an RF carrier wave, as well as how this RF carrier wave is transmitted and received by the radio hardware. A Bluetooth LE radio hardware must operate in the **ISM band (2.4 GHz spectrum),** which is segmented into **40 RF channels**, each separated by **2 MHz (center-to-center)**, as shown in the following figure: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62d18e03b721b.png) *Source: [Intro to Bluetooth Low Energy](https://www.novelbits.io/introduction-to-bluetooth-low-energy-book?ref=novelbits.io)* Some of the other rules that an LE radio must obey are: - It should use the **Gaussian Frequency Shift Keying (GFKS)** as a modulation scheme. - It should use **Frequency Hopping Spread Spectrum (FHSS)**, which allows the two communicating devices to switch to randomly (agreed-on) selected frequencies for exchanging data. This greatly improves reliability and allows the devices to avoid frequency channels that may be congested and used by other devices in the surrounding environment. - The **transmit power levels** are: Minimum: 0.01 mW (-20 dBm), and Maximum: 100mW (+20 dBm) for version >= 5, 10mW (+10 dBm) for version <= 4.2 - The allowed **data rates** are 1 Mbps for an LE 1M PHY radio, 2 Mbps for an LE 2M PHY radio, and 500 kbps or 125 kbps for an LE Coded PHY radio. ## **Summary** As mentioned, the smaller protocols (layers) in a protocol stack work together for the ultimate functionality of a communication protocol. In this post, we demonstrated how the GAP layer, link layer, and PHY layer each have unique responsibilities while cooperating as a whole. - The PHY radio is in charge of exploiting RF waves to transmit and receive raw bits of data. - The link layer controls the state of the PHY radio based on the GAP role of the device. However, the GAP does more than just define roles. There is more to the PHY layer than what we have covered here, and there is more to the link layer than the link layer state machine. Free 12-Day Email Course Learn Bluetooth LE in 12 Days A free crash course delivered to your inbox. One lesson per day — just the fundamentals you need to start building. Start the Free Course Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. 💡 **Insider Tip:** Want the full learning experience of the Bluetooth Low Energy stack? Join the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) to get instant access to the Core Foundations Course and comprehensive guides on every layer of the protocol stack. ### What is a Protocol Stack? And Why is it Layered? URL: https://novelbits.io/protocol-stacks-layered-architecture/ Last updated: 2026-08-09T05:26:17.000Z [Protocol](https://novelbits.io/communications-protocols-and-why-we-need-them/) stacks are important for a variety of reasons. But what are they, exactly? Protocol stacks are a layered collection of protocols that work together to provide communication services. Each protocol in the stack is responsible for a specific task, and by layering them, we can create a more robust and reliable system. By the end of this article, you should have a **better understanding of what a protocol stack is** and **the design methodology behind it.** --- ## Layered Architecture The layered architecture pattern, often known as the "n-tier" architecture design, is a common technique for reducing complexity across numerous disciplines. A structure is divided into parts that work together. Each part has a special job to do. The parts are arranged in layers, one on top of the other. ### A simple example is the airline system: An airplane system is a good analogy to use because computer networking is a lot like air travel: In an airplane, a passenger is being "shipped" from source to destination the same way that in a computer network a message is being shipped from one device to another. An airline system is a complex system and its functionality, believe it or not, is organized in layers, very much like the Bluetooth LE Protocol stack or any other stack. Think for a minute about a series of steps you take when you fly on an airline. First, you purchase your ticket, check your bags, go to the gate, and eventually get loaded onto the plane. The plane takes off and is routed to its destination. After your plane lands, you deplane at the gate and claim your bags. If the trip was bad, you complain about the flight to the ticket agent. Behind these actions is a structure. A layered structure. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/layered-architecture-of-airline-functionality_auto_x2-1-1024x346-1.jpg) The layering of airline functionality. Source: Computer Networking A Top-down Approach Featuring the Internet The first layer is the **customer service layer** whichdeals with tickets. The second layer is the **baggage handling layer** where you check your bags at the departure airport and where your bags are unloaded and you claim them at the arrival airport. The third layer is the **gate layer** which deals with loading you onto the plane and unloading you from it. The fourth layer is the **runway layer** which the plane uses to take off and land. The final layer is the **air traffic control layer** which makes sure that planes stay separated in the sky and that they take the correct routes. This is a very simplified view of how an airline system works but it serves to illustrate the point that complex systems are organized in layers. Now let's discuss the key benefits of layered architecture. ### Key features that make this design favored across multiple fields are: - Abstraction - Separation of concerns - Layers of isolation ### 1\. Abstraction It is possible for different parts of a system to have zero knowledge about one another at the implementation level, but still, be able to interact with each other. Based on this, abstraction is the idea of hiding the implementation details of a layer and only sharing functionality with the layer it has to interface with. **It is the separation of what a layer does from how it does it.** By keeping the details of how a layer works hidden, other layers can easily interact with it. They only need to know what that layer does and they can interface with it when they need that specific functionality. They do not need to worry about how the task is performed. ### 2\. Separation of concerns It is the idea that each layer should only be responsible for one thing and should not contain rules that deal with other things. Separation of concerns makes an application simpler by breaking it down into smaller, more manageable parts. Each part does one thing, and they work together to create a whole. It abides by the divide-and-conquer strategy which is a very effective way to reduce complexity. ### 3\. Layers of Isolation It is the idea that each layer should be an island unto itself, receiving input and sending output as required. It shouldn't be influenced by anything happening outside of itself. Each layer should be self-contained. Individual layers cannot see beyond the immediate layer with which they are interacting, and have no knowledge or care about what happens beyond. Isolation is a good thing as it allows changes made in one layer of the architecture to generally not impact or affect components in other layers. It also makes it easier to test and debug an application because each layer can be tested independently. **The above features: Abstraction, Separation of concerns, and Layers of isolation are what make the layered architecture appealing for Protocol stacks** --- ## A Protocol Stack **A protocol stack or protocol suite is the architecture of a protocol that follows the layered architecture design principle.** The functionality of the whole protocol is broken down into component protocols that are separately managed and can be treated and designed mostly independently from one another. A protocol stack typically contains a set of protocols where each protocol in the stack performs a specific task and is responsible for a well-defined function. The protocols are often referred to as layers with each layer providing services to the layer above it and receiving services from the layer below it. ### **A typical protocol stack will be structured in an n-tier architecture pattern like this:** ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/User-A-15--C3-97-7cm-15--C3-97-10cm-1-1_auto_x2-1-768x562-1.jpg) Protocol Stack Architecture ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/bluetooth-le-protocol-stack-1-1-274x300-1.jpg) Bluetooth Low Energy Protocol Stack As shown in the image above (*Protocol Stack Architecture*), a protocol stack is created by dividing a protocol into n-multiple layers. In each layer, two entities communicate with each other using the appropriate protocol for that layer. They do this by exchanging data units through a channel that connects them. Each of the protocols fulfills a portion of the overall Protocol's functionality. ### **Peer-to-Peer Protocol** Protocols in a protocol stack are said to be peer-to-peer protocols. This means that the protocol operates between two entities that are peers, at each layer. For example, a protocol entity in the nth layer can only exchange data units with its peer entity at the same level, according to the protocol of that layer. ### **Virtual Channels + 1 Real channel** As can be seen in the image below (*Application Data Transfer through a Protocol Stack*), the protocol entities in the lowest level communicate with each other using a real channel. This channel is also called a physical channel. The channels of the higher layers are virtual channels. Since the higher layer's channels are virtual, their messages ([PDUs](https://en.wikipedia.org/wiki/Protocol%5Fdata%5Funit?ref=novelbits.io)) must be transferred from a higher layer to the one beneath it until the PDUs reach the physical layer. The physical layer will then be able to transmit the messages through the real/physical channel. --- ## User Data Transfer Through A Protocol Stack ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/application-data-transfer-1_auto_x2-2-1-1024x683-1.jpg) Application Data Transfer through a Protocol Stack The highest layer in the protocol stack is called the application layer because it interacts with the user, while the lowest layer is called the physical layer because it has a real channel as opposed to virtual channels used by higher layers. ### **The journey of the user data from device A to device B begins as follows:** 1\. The user of device A(also called an initiator) uses the application on that device to ask then-th layer protocol entityto transfer data to the application at the recipient side. **2.** The n-th layer protocol entity adds its control information (PCI) to the data and passes the n-PDU message to the next layer down. **3.** The (n-1)th layer entity executes a similar action... **4.** Data that were generated by the application at the initiator side are thus passed down from one layer to the next lower layer, while each layer adds its own control information to the data. **5.** When the data and control information added by all the layers reach the physical layer, it is all transferred through the physical channel to the recipient side. **6.** On the recipient side, data flows up from one layer to the next higher layer. The protocol entity in each layer analyzes control information that was generated by its peer at the transmitting side. If everything goes well, the protocol entity passes user data it sees to the entity in the next higher layer. **7.** This process is repeated until the data originally sent by the initiating application arrives at the application on the recipient side. --- ## Let's Recap! In this article, we learned about: 1\. The key features of a layered architecture 2\. The definition of a Protocol Stack 3\. Why protocols in a protocol stack are said to be peer-to-peer protocols. 4\. The protocol stack has virtual channels + 1 real channel 5\. How data is transferred through a protocol stack from the initiating application to the recipient one. 💡 **Insider Tip:** Want to understand protocol stacks in action with Bluetooth Low Energy? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Communications Protocols And Why We Need Them URL: https://novelbits.io/communications-protocols-and-why-we-need-them/ Last updated: 2026-08-09T05:24:31.000Z A **communications protocol** is a "*set of rules that must be obeyed by all users in a device network*." This is a very grand definition, but it is also very dry. It does not tell us very much. **What do protocols exactly do? Why do we need them?** In this article, we will explore the answers to these two questions. ## What is a Protocol? The communication between any two devices can take place only if they are compatible in their connectivity, in terms of hardware and software. This compatibility is achieved through the use of a **protocol**. Communication protocols are in short, *a set of rules that communication entities must follow in order to exchange information*. Protocols are just agreed-upon ways to ensure that two/more communication entities connected together can recognize, and talk to each other. Come to think of it, protocols used in any network technology, including Bluetooth LE, are a lot like traffic rules we all observe in our daily lives. For example, when driving a car toward a busy intersection, we know what to do by observing the protocol displayed by the traffic light. If the light is green, we go. And if it's red, we stop. In rare instances when we encounter an intersection with no traffic lights or signs, there is general confusion among drivers about which car should go next because there is no protocol/consensus to follow. Any driver might just go, and then another driver might think he has the right of way and go as well, leading to a collision. Without generally accepted protocols, a network would not work properly because hardware manufacturers and software developers would all be doing things their own way. This would result in proprietary products being unable to communicate with each when connected together. ## Protocols Can Be Open or Proprietary Open Protocols are protocols that are available for any system to use, and anyone to implement without having to pay a license fee. They are usually developed through a collaborative process such as a standards body or an open-source project. They aim to create interoperability to allow diverse devices to work together. Notable examples of open protocols are the [TCP/IP suite](https://docs.oracle.com/cd/E18752%5F01/html/816-4554/ipov-6.html?ref=novelbits.io) and [Bluetooth LE](https://novelbits.io/how-bluetooth-low-energy-works-21-interesting-facts/). In contrast, proprietary protocols are owned by a particular company and can only be used by licensing from that company. They are vendor lock-in, typically closed and tightly controlled. This gives the owner of the protocol an advantage in the market, as they can control who has access to the technology and how it is used. However, it also means proprietary protocols are often less flexible and adaptable than open protocols. In addition, because they are not publicly available, it can be difficult for independent researchers to assess their security and privacy implications. ## Main Points That Protocols Address Adding networking capabilities to an embedded system is not a trivial task. Why? Because it entails sending data from a protected environment (a device) over a hostile medium (the outside world), and interacting with a hostile remote system that may not care what condition your device is in, and may be running at a different clock or time frame. Now, protocols come to the rescue by providing a set of ground rules or common denominators that both systems can agree upon and use to communicate with each other. **Here are some of the main points that a protocol addresses:** ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/protocols-vs-problems.jpg) ### **1\. Line Level Compatibility** One of the challenges in data communications is that different pieces of equipment use different voltages to represent 1s and 0s. For example, some devices use -5 volts to represent a 1, while others use +5 volts. This can create potential problems when connecting devices together, as a -5 volt signal may be interpreted as a 0 by a device that is expecting a +5 volt signal. To avoid these conflicts, devices must be designed to be line-level compatible, which means that they can translate between the various voltage levels, in order to communicate with other devices. While this may seem like a relatively simple concept, it is one of the biggest headaches in ensuring smooth and reliable data communication. Without proper standards, it is almost impossible to meet. ### **2\. Timing Relationships** A second important aspect that protocols must take into account is the timing relationships between devices. The data level transitions are determined by a clock at the sender ( source). The receiver usually has no access to this clock. As a result, the relative timing of the signals has to be recovered/ regenerated at the receiver to accurately determine the beginning and the end of the message. Protocols must, therefore, define how the receiver can reconstruct the original clock signal from the data signal in order to correctly interpret the timing relationships. This process is called Clock Recovery. ### **3\. Time Management of Multiple Users** Another big issue that protocols must contend with is the time management of multiple users. Remember, in a network, there can be many devices sending and receiving data at the same time. The protocols have to ensure that all these devices have fair access to the medium through which they are communicating and that no individual user dominates the medium for an excessively long period of time. ### **4\. Error Control or Effects of Noise on the line** A fourth important consideration is the effects of noise on the line. In any practical communication system, there will always be some background noise present on the line, which can potentially corrupt or destroy the data being transmitted. The job of the protocols is to provide mechanisms to detect and/or correct these errors so that the data is received in its original form. ### **5\. Security** With the increase in IoT hacking, security has become a major concern for embedded systems. A protocol must have provisions for [security](https://novelbits.io/bluetooth-address-privacy-ble/) so that the data being transmitted cannot be accessed by unauthorized persons. ### **6\. Power Control** If everyone were to transmit at the power above the maximum required for a satisfactory level of performance, it would create a lot of interference in the shared RF spectrum, and no one would be able to communicate properly. It is the task of a communication protocol that uses the RF spectrum to make sure that each transmitter only transmits at the power required to cover the desired distance and no more. This allows others to use the same or nearby frequencies without interference. ### **7\. RF Band Planning (Channel Spacing & Bandwidth)** For a protocol that uses the RF spectrum( e.g Bluetooth LE), two important things are considered: *how much space there is between channels*, and *how much bandwidth each channel can use.* Every communication protocol must use the correct amount of channel spacing and bandwidth for the RF Frequency band it will use. If it does not, then the systems that rely on the protocol will not work properly and could cause interference for other users of the RF spectrum. ### **8\. Message Formatting** Another thing that a protocol must define is the message format. This includes the message structure and the sequencing of messages. The message structure is the way in which the data is arranged within the message. For example, a message may have a header followed by a payload and then a checksum. The sequencing of messages is the order in which they are sent. For example, one message may need to be sent before another message in order to establish a connection. Take a look at how [Bluetooth LE structures its packets and how it sequences them.](https://novelbits.io/deep-dive-ble-packets-events/) ### **9\. Techniques to Combat Reliability Issues** Communication is said to be reliable if the information sent is information received. But since the mediums used are often not 100% reliable, techniques must be used to combat the unreliability. In the case of Bluetooth LE, some techniques include using a spread spectrum, RSSI as a link quality estimator, and a good modulation scheme (GFSK), among others. ## Continue Learning Now that you understand what communication protocols are and why they matter, here are some guides to go deeper: - [The Complete Guide to Bluetooth Low Energy](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) — a comprehensive overview of one of the most widely used communication protocols in IoT. - [Bluetooth LE Protocol Stack Layers](https://novelbits.io/bluetooth-low-energy-protocol-stack-layers/) — see how Bluetooth LE implements each of the protocol concerns discussed above. - [GATT Services and Characteristics](https://novelbits.io/bluetooth-gatt-services-characteristics/) — how Bluetooth LE handles data exchange at the application layer. - [Choosing the Right Wireless Technology](https://novelbits.io/choosing-wireless-technology/) — compare Bluetooth LE, WiFi, Zigbee, Thread, and more for your next project. ## Let's Recap! In this article, we learned about: - What communication protocols are - The importance of protocols There are many different communication protocols, but they are all striving to accomplish the same thing - to be a common language between devices. And though the goal is the same, they may go about it in different ways, with different priorities. 💡 **Insider Tip:** Want to learn more about communication protocols used in IoT and embedded systems? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Chipset vs Module Bluetooth LE Solutions: The Ultimate Guide URL: https://novelbits.io/chipset-vs-module-bluetooth-le-solutions-the-ultimate-guide/ Last updated: 2026-08-09T05:24:23.000Z Whether you're creating a new Bluetooth Low Energy (LE) product or updating an existing one, deciding whether to go with a chipset vs. a module is a very important decision. What's the difference between the two? And which one is best for you? **Summary Answer:** - SoC chipset is an IC that integrates a programmable processor, memory, and other essential peripherals onto a single silicon chip. - A SiP module is an IC package that contains multiple ICs. An SoC is included inside this package. - The primary difference between the two is that in an SoC, we group heterogeneous components onto a single chip; In a SiP, we group heterogeneous ICs onto a single package. - SiPs allow for the easy addition of analog and RF features to digital CMOS, which may offer cost and performance benefits. - Although SoC designs are typically smaller and less expensive to produce, design costs may be greater, and time-to-market is typically slower. - Build or buy? Depending on the anticipated unit volumes, time to market urgency, risk tolerance, and available resources for each Bluetooth LE product, either approach may be appropriate. Let's unpackage the summary answer. Shall we? ## SoC vs. SiP Module: The Basics ### 1\. SoC A system-on-chip, or SoC, is an integrated circuit that contains most of the essential components of a complete system on a single chip. It is the realization of a system’s entire functionality in a single IC. ![General architecture of an embedded core-based system-on-chip (SoC)](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-9.png) The general architecture of embedded core-based system-on-chip (SoC). Source: [ResearchGate](https://www.researchgate.net/figure/General-architecture-of-embedded-core-based-system-on-chip-SoC%5Ffig1%5F257943815?ref=novelbits.io) SoCs contain most of the essential blocks a system needs to function. A typical SoC contains one or more general-purpose processors, one or more DSP processors, embedded memory, a protocol block, controllers for external memories, and various interface support circuitry. Although an SoC does include a lot of things. There are some things it doesn't have. These include interface blocks that can't be made with CMOS- or CMOS-compatible technologies. This includes interface blocks for displays, keypads, batteries, and more. The Bluetooth LE market is rife with SoCs, which are utilized extensively. Check out the [most popular SoCs on the market](https://novelbits.io/17-most-popular-bluetooth-low-energy-chipsets-compared/). ### 2\. SiP Modules A [system-in-package](https://www.sciencedirect.com/topics/engineering/system-in-package?ref=novelbits.io), or SiP, is a group of integrated circuits (ICs) with different functionalities, and passive and active components, enclosed in a single housing that acts as a system or subsystem. ![Example system-in-package (SiP) with stacked dies](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-4-5.png) Example SiP Packaging. Source: SiP and Module These ICs (the largest ICs manufacturable at the highest yield and hence lowest cost) are usually connected using wire bonding or flip-chip technology. One of the most significant advances observed in SiP is the ability to stack dies vertically 3D or horizontally, side-by-side, allowing the provision of multiple dies in a single package. This allows for a smaller form factor and higher density packaging. Additionally, SiP offers more design freedom because it allows designers to combine numerous semiconductor technologies and reuse intellectual property from various sources, allowing them to overcome integration challenges without sacrificing chip technologies. Another rising trend in SiP is integrating different types of devices such as passive and active components inside substrates. For example, [Silabs' BGM220S SiP modules ](https://www.silabs.com/documents/public/data-sheets/bgm220s-datasheet.pdf?ref=novelbits.io)have an [antenna integration within the SiP module substrate.](https://www.silabs.com/whitepapers/miniaturizing-iot-designs?ref=novelbits.io) ## Antenna Integration The IoT industry is booming and one of the most frequently asked questions about Bluetooth LE-enabled IoT devices is their: - size, - radio performance, - and pricing. Ideally, engineers would want to build LE products with components as small and as cheap as feasible, with excellent RF performance. Because necessity is the mother of invention, silicon manufacturing processes were improved to allow the integration of the MCU(Microcontroller Unit) and RF frontend into system-on-chip (SoC) configurations. This creates small-sized wireless MCU required by the IoT applications where space is premium. However, the [bottleneck for a real wireless SoC is the realization of an on-chip antenna (OCA)](https://repository.kaust.edu.sa/handle/10754/667094?ref=novelbits.io). The last challenge is antenna integration, which is not trivial. Therefore, most available Bluetooth LE SoCs solutions are [SoC transceiver designs.](https://www.ezurio.com/resources/white-papers/soc-vs-sdr-for-wireless-product-design?ref=novelbits.io) The RF transceiver is integrated into the chip, but the antenna is left for customers to sort out. **A person designing a Bluetooth LE product will face two choices: Build or Buy. Either purchasing an SoC and an external chip antenna and then integrating the two on their own (building) or buying a SiP module that has already integrated the SoC with the chip antenna.** ## Choice A: Using a Bluetooth LE SoC On The Product Printed Circuit Board SoC designs are smaller and less expensive to produce. But they do have more design costs because trying to put an SoC and chip antenna together on the same product printed circuit board (PCB) is difficult. But how hard can it be? To create an SoC with an antenna matched for the actual end-application design, an experienced designer must answer some complex questions about the antenna, such as what type of antenna to use, the appropriate selection of packaging material to prevent antenna detuning, the position of the antenna in the design, PCB size, clearance areas and more. The optimization of antenna performance and the SoC RF layout requires an understanding of the difficult RF design rules and the use of expensive equipment, software, and facilities to debug RF designs. On top of all that are regulatory approvals and wireless standard certifications. Wireless SoCs do not carry product-type approvals or pre-certifications. Therefore you will have to go through the entire approval and certification process on your own before commercialization. ### Hidden Costs Associated with Choosing a Bluetooth LE SoC For this design route, there are some hidden costs that you need to consider. #### **1\. Pricing Trends** When buying components, you, as an individual customer, will have less pricing power than module vendors. This is because the latter aggregate the volume from many customers, giving them more negotiating clout. So if you are building just a few LE products, procuring all the components needed to put the SoC on the board can be a little bit more costly. #### **2\. Supply Chain Overheads** When using a module, you would only need one supplier to manage - the module vendor. But with an SoC, you need to manage the SoC vendor, as well as all the other component vendors. These multiple suppliers have different lead times, product longevity, and other factors. All these together into a common supply chain require more resources to manage. If you want to learn more about the hidden costs in SoC design-based products, read this [white paper from Silicon Labs](https://www.silabs.com/documents/public/white-papers/six-hidden-costs-in-a-wireless-soc-design.pdf?ref=novelbits.io). It provides an insightful look at these costs. ## Choice B: Using A Pre-Certified Bluetooth LE SiP Module In Your Design A SiP module is a complete system in a package, integrating an SoC with one or more passive and active devices such as an antenna, filters, and power amplifiers (PA) into a single package. The antenna size and position are optimized to work with the electronics inside the package, and modules come with well-documented layout guidelines for maximum RF performance. Consequently, the complexity of RF design is eliminated. Modules offer plug-and-play solutions that can easily be integrated into LE products. Additionally, with modules, getting RF regulatory approvals and wireless standard certifications is the job of the module manufacturer. So, you don't have to worry about any of that. Counterpole to the above advantages is that a SiP module costs more and is typically larger (in size) than its SoC equivalent. ## Bluetooth LE SoC vs. SiP Module: Which is right for you? Build or Buy? Depending on the anticipated unit volumes, time to market urgency, risk tolerance, and available resources for each Bluetooth LE product, either approach may be appropriate. ### 1\. Example Use Cases when a SiP Module is a Better Strategy than an SoC: Oftentimes, the decision of whether to use a SiP module or an SoC can be boiled down to a question of cost. However, as Omer Sheena from Dialog (now Renesas) pointed out, the choice also depends on strategy and business needs. Below are examples of two use-case scenarios where the benefits of a SiP module justify the additional expense. #### **A. When Time to Market (TTM) is more important** TTM or time-to-market is the amount of time it takes from when a product idea is conceived to when it is available for consumers to purchase. A SiP module is usually preferred over an SoC when TTM is more important. This could be the case if: - Your product is seasonal - The goal is to be 1st in the market with novel features - Last generation products are declining, and you are using the new product to reinvigorate demand. ![Chart showing how time-to-market delays reduce peak sales and total revenue](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-7.png) How Time to Market affects Sales. Source: Dialog Semiconductors (now Renesas) With an SoC, you would have to worry about antenna design, regulatory approval, and wireless certification. These are all time-consuming tasks that can push back your TTM and can therefore cause you to lose certain months in the market. Every day the product is not on the market is a day of lost revenue. So, is TTM critical for you? Can you handle the market late entry cost? Can you handle the reduced peak? #### **B. When the main electronics board is used for both LE devices and non-LE devices** Let's take the example of a "dumb" plug v1\. and and "Smart" plug v2. Assume the "smart" plug uses the LE for connectivity and also that both devices use the same main electronics board. The only difference between them is that one has an LE connectivity option and another doesn't. In such circumstances, a module is usually ideal since it provides a plug-and-play solution that allows you to reuse the main electronics board across both product lines without starting from scratch as you would if you used an SoC. ### 2\. Module Vs. SoC Consideration Table | You might want to consider an SoC when | You might want to consider a SiP Module when | | ------------------------------------------------------------------------ | -------------------------------------------------------------------- | | It is important to have the lowest possible BOM. | Fast time to market is very important | | You have RF Engineers on staff | You have limited RF Engineering on staff | | You own RF lab equipment and tools | You have limited RF lab equipment or tools | | There is ample time for prototypes to optimize antenna | There is no appetite for RF design risk on TTM | | You have experts and/or budget for wireless standards compliance testing | You have limited experience in wireless standards compliance testing | | You have experts and/or budget for regulatory approvals | You have limited experience with regulatory approvals | SoC vs. Module Considerations. Source:[ Silicon labs](https://www.slideshare.net/siliconlabs/choosing-between-a-wireless-module-and-a-wireless-soc?ref=novelbits.io) ## Steps For Making a Module Vs. SoC Cost and Break-Even Analysis How do you run a cost analysis to see which option makes sense for your business? Let's review the steps needed to do a module vs. SoC cost and break-even analysis. #### **1\. Step One: Understand and Estimate the Cost** Find the price of buying the required SiP modules. Estimate the overall cost of building a module in-house. Your overall cost of building a module in-house should reflect an estimate of: - The component cost of SoC - Test and RF Engineering costs, samples, lab equipment, etc. - Certification costs - Supply-chain overhead #### **2\. Step Two: Estimate the number of LE product units you expect to sell** Research and identify the total available market (TAM) size and expected growth, and then roughly estimate the number of LE product units you expect to produce and sell. #### **3\. Step Three: Use the Cost per Unit formula** A cost per unit volume (CUV) is the total cost of a product or service divided by the total quantity of that product or service sold/made. This metric is often used in business to track the efficiency of production. The goal is to have a low CUV so that you can pass on the savings to the customer and entice more customers to buy (or take home more money if you’re able to sell your product at a premium). Calculate your CUV and create an excel graph with the number of units you expect to produce and sell on the x-axis and their associated cost per unit on the y-axis. You will get something that looks like this: ![Graph comparing cost per unit volume for SoC vs module at different production volumes](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-8.png) CUV vs. Product Volume. Source: Dialog Semiconductors (now Renesas) For this particular example, for 25,000 units, it makes more sense to use a module over an SoC. At 190,000 units ( break-even) point, it doesn't matter if you use an SoC or a module because the price is almost the same. But you can see that with a volume beyond 250,000 units, using an SoC starts to get cheaper than buying a SiP module. So generally, the best option changes with the volume of products you intend to sell. ## Conclusion In the end, it’s important to weigh all of the factors involved to make the best decision for your product. Luckily, most SoC or module vendors have a sales and support team that can help you with the decision-making process and can give you more insights into what to expect in terms of cost, schedule, and product quality. 💡 **Insider Tip:** Want to dive deeper into choosing the right Bluetooth LE hardware for your product? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### 17 Most Popular Bluetooth Low Energy Chipsets Compared URL: https://novelbits.io/17-most-popular-bluetooth-low-energy-chipsets-compared/ Last updated: 2026-08-09T05:23:19.000Z According to Pareto's 80/20 rule, roughly 80% of the results come from 20% of the efforts. There are probably over a hundred of BLE System-on-Chips (SoCs) in the market, but most come from only a handful of manufacturers. So, who are the top players in the BLE chipset industry? The most popular [Bluetooth LE](https://novelbits.io/bluetooth-low-energy-ble-complete-guide/) SoCs are : **1\. Nordic Semiconductor (nRF52840, nRF52832, nRF51822, nRF52811, nRF52810, nRF52833, nRF5340, nRF52805)** **2\. Dialog Semiconductor ( DA14683, DA14585)** **3\. Texas Instruments ( TI CC2541,TI CC2540)** **4\. STMicroelectronics ( BlueNRG-2N)** **5\. Silabs (EFR32BG13, EFR32BG22)** **6\. NXP Semiconductors (QN908x)** **7\. Qualcomm (CSR102x)** We found this list of Bluetooth LE SoCs by doing a Google search using the Surfer Keyword Tool. We looked for the SoCs that were being searched for the most in 2022\. We assume that the more often an SoC is being searched for, the more popular it must be. We bet you've skimmed through the list and been disappointed to see that it doesn't contain some of the most recent SoCs. Though newer chipsets have better features than their predecessors, popularity is a slow acclivity. It takes time to percolate through the market. Enough with the long intro; let's move on to what a System on Chip (SoC) is, shall we? ## **What is an SoC?** It is an integrated circuit (IC) that combines all the components of a computer or other electronic system into a single chip. It's called a system on-chip because it includes everything from the central processing unit (CPU) to peripherals, memory, and input/output (I/O) ports into a single die. In short, it is a complete system on a single chip. ![System on Chip (SoC) diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93e0a02e.jpg) The main benefits of using an SoC over traditional discrete components are increased reliability, smaller form factor, and lower power consumption. Now that we know what an SoC is, let's discuss the most popular BLE SoCs on the market. **Disclaimer: Pricing links point to distributor pages where you can find the latest pricing. Note that volume pricing may vary across the different chipsets listed.** ## **1\. Nordic Semiconductor - nRF52840** The nRF52840 is the most advanced chip in the nRF52 series. It has 1 MB of flash memory and 256 KB of RAM. It also supports full-speed 12 Mbps USB, making it a versatile choice for a wide range of applications. ![Nordic nRF52840 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93e3e983.png) Plus, it's fully multiprotocol, supporting Bluetooth LE, [Bluetooth mesh](https://novelbits.io/bluetooth-mesh-networking-the-ultimate-guide/), Thread, Zigbee, ANT+, NFC, and 802.15.4\. However, it does not support Bluetooth LE audio and Bluetooth direction-finding features. The nRF52840 has a core ARM-M4 processor that can do complex calculations quickly. This is useful for tasks like digital signal processing or math that require floating-point numbers. Ideal applications of the nRF52840 include: - Gaming controllers - Virtual/ Augmented reality applications - Advanced wearables - Smart city infrastructure - Matter connected home products ## **2\. Nordic Semiconductor - nRF52832** The Nordic Semiconductor nRF52832 is a powerful, general-purpose 32-pin GPIO SoC. It is considered a subset of the nRF52810 and nRF52805 SoCs and therefore packs a considerable punch. ![Nordic nRF52832 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93e5f002.png) The nRF52840 is similar to the nRF52832\. They both have an Arm Cortex-M4 with FPU. This allows them to do complex tasks. The nRF52832 also supports Bluetooth LE, Bluetooth Mesh, NFC, ANT, and 2.4 GHz proprietary protocols. However, it does not support ZigBee, Thread, or Matter protocols along with Bluetooth LE audio and Bluetooth direction-finding features. The nRF52832 has less memory support than the nRF52840\. The nRF52832 supports 512/256 KB Flash and 64/32 KB RAM. Despite this, the nRF52832 is still a powerful chipset that can be used for a variety of purposes, including: - Beacons - PC peripherals such as wireless keyboards and mice - Advanced wearables - Sensor Networks - Toys ## **3\. Nordic Semiconductor - nRF51822** The Nordic Semiconductor nRF51822 is a low-cost Bluetooth chip that can be used for many purposes. It has a 32-bit ARM Cortex M0 processor and 31 configurable GPIO pins. ![Nordic nRF51822 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93e82aac.png) Even though the nRF51822 has less program memory and RAM than other SoCs, it can still support Bluetooth LE and Bluetooth Mesh. The nRF51822 is used in a variety of applications, including: - Proximity sensors - Sports and fitness trackers - Hearing aids - Remote controls - Toys ## **4\. Nordic Semiconductor - nRF52811** The Nordic Semiconductor nRF52811 is the fourth member of the nRF52 Series and is packed with features, including Bluetooth long-range, and protocol support (for 802.15.4, Thread, ZigBee). It also has a direction-finding feature and it has better Rx sensitivity than other chips in the nRF52 series. ![Nordic nRF52811 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93ea7d09.png) Direction-finding enables positioning solutions to rely not just on the received signal strength indicator (RSSI) but also on the direction of a signal. Direction-finding is based on the principle of triangulation, whereby the position of a point can be determined based on the angles between three other points. In the case of BLE, the three points are typically the transmitting device, the receiving device, and a reference device. By measuring the angles between these three points, it is possible to calculate the position of the transmitting device with a high degree of accuracy. With the direction-finding feature, the nRF52811 is ideal for use in applications like: - Asset tracking - Indoor navigation - A transmitter in both AoA( Angle of Arrival) and AoD (Angle of Departure) mode - Real-time locating systems - Beacons ## **5\. Nordic Semiconductor -nRF52810** It is one of the tiniest SoCs available, along with the nRF52811 and nRF52805\. It is a flash-based SOC like all members of the nRF52 series and as such supports[ over-the-air firmware upgrades](https://novelbits.io/ota-device-firmware-update-part-1/) (OTA DFU). This allows for software updates on the field. ![Nordic nRF52810 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93eccd4e.png) Let me remind you what "flash-based SoC'' means: A flash-based SoC is one in which the program code is stored in flash memory. Flash memory is a type of non-volatile memory that can be erased and rewritten. This is opposed to a mask ROM-based SOC, in which the program code is hardwired into the chip during manufacture and cannot be changed thereafter. The main advantage of a flash-based SOC is that it allows for data logging and updates to the program code after the chip has been manufactured. This is especially important in the case of BLE chips, as the Bluetooth SIG regularly updates the specification to add new features and fix bugs. The nRF52810 is used in a variety of applications including: - Beacons - Fitness sensors - Logistics and tagging - Disposable medical sensors - Toys ## **6\. Nordic Semiconductor -nRF52833** The nRF52833's most appealing feature is its Bluetooth radio direction finding ability, which is certified to work at temperatures as low as -40 °C and up to 105 °C. So, if your application requires operation at either end of the temperature range, this will be able to do so. ![Nordic nRF52833 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93f01262.png) The possible applications of the nRF52833 include: - Professional lighting - Industrial - Advanced wearables - Gaming - Smart home - Asset tracking and RTLS ## **7\. Nordic Semiconductor -nRF5340** The nRF5340 is the world's first wireless chip with two Arm® Cortex®-M33 processors. One processor is used to manage networks and the other processor is used to run applications. This chipset has features like USB, Bluetooth 5.3, up to 105 °C operating temperature, and 1 MB Flash + 512 KB RAM. ![Nordic nRF5340 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93f25a37.png) It also has an 8 KB 2-way set associative cache which is used to speed up data access in the SoC. It's like having a personal data center that stores recently accessed data only without any servers. How does it work? When data is accessed by the application processor, it is first checked in the cache. If it's available, the data is transferred to the application processor from the cache at high speed. If the data is not available in the cache, it is fetched from main memory and stored in the cache for future access. The nRF5340 ca be used in a wide variety of applications including: - LE Audio - Professional lighting - Industrial - Medical - Asset tracking ## **8\. Nordic Semiconductor - nRF52805** The nRF52805 is a really small chip, only 2.48 x 2.46 mm WLCSP ( Wafer level Chip Scale Package). ![Nordic nRF52805 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93f507eb.png) Typically, small SoC designs require a four-layer PCB, but the nRF52805 is built with only two PCB layers. This is ideal for cost-constrained applications since the more layers, the more expensive it gets. The nRF52805 is used in applications like: - Styluses - Presenters - Disposable medical sensors - Beacons ## **Which Nordic SoC is Right for You? A Comprehensive Table Guide** ### 1\. Supported Bluetooth Features | | **nRF52840** | **nRF52832** | **nRF52822** | **nRF52811** | **nRF52810** | **nRF52833** | **nRF5340** | **nRF52805** | | --------------------------- | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ----------- | ------------ | | Bluetooth 4.0 | X | X | X | X | X | X | X | X | | Bluetooth 5.3 | X | X | | X | X | X | X | X | | Bluetooth 2 Mbps | X | X | | X | X | X | X | X | | Bluetooth Long Range | X | | | X | | X | X | | | Bluetooth Direction Finding | | | | X | | X | X | | | Bluetooth LE Audio | | | | | | | X | | | Bluetooth Mesh | X | X | | | | X | X | | | Thread | X | | | X | | X | X | | | ZigBee | X | | | X | | X | X | | | Matter | X | | | | | | X | | ### **2\. Hardware Key Features** | **SoC** | **Core** | **Memory** | **Price** | | ---------------- | ------------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | **1\. nRF52840** | 64 MHz Arm Cortex-M4 with FPU | 1 MB Flash + 256 KB RAM | [↗](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52840-QIAA-R/7725407?ref=novelbits.io) | | **2\. nRF52832** | 64 MHz Arm Cortex-M4 with FPU | 512/256 KB Flash + 64/32 KB RAM | [↗](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52832-QFAB-R/6051565?ref=novelbits.io) | | **3\. nRF51822** | 32-bit ARM Cortex-M0 | 256/128 KB Flash + 32/16 KB RAM | [↗](https://www.aliexpress.com/wholesale?catId=0&initiative%5Fid=SB%5F20220612220848&SearchText=+nRF51822&ref=novelbits.io) | | **4\. nRF52811** | 64 MHz Arm Cortex-M4 | 192 KB Flash + 24 KB RAM | [↗](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52811-QFAA-R/9922503?ref=novelbits.io) | | **5\. nRF52810** | 64 MHz Arm Cortex-M4 | 192 KB Flash + 24 KB RAM | [↗](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52810-QFAA-R/7725406?ref=novelbits.io) | | **6\. nRF52833** | 64 MHz Arm Cortex-M4 with FPU | 512 KB Flash + 128 KB RAM | [↗](https://www.digikey.com/en/products/detail/nordic-semiconductor-asa/NRF52833-QIAA-R/10501333?ref=novelbits.io) | | **7\. nRF5340** | 128/64 MHz Arm Cortex-M33 (dual-core) | 1 MB + 256 KB Flash; 512 KB + 64 KB RAM | [↗](https://www.mouser.com/ProductDetail/Nordic-Semiconductor/nRF5340-CLAA-R?qs=81r%252BiQLm7BTUbHQUWWib8A%3D%3D&ref=novelbits.io) | | **8\. nRF52805** | 64 MHz Arm Cortex-M4 | 192 KB Flash + 24 KB RAM | [↗](https://octopart.com/nrf52805-caaa-r7-nordic+semiconductor-106710796?ref=novelbits.io) | ## **9\. Dialog Semiconductor - DA14683** The DA14683 is a flexible System-on-Chip based on an ARM® Cortex®-M0 CPU running at 96MHz. ![Dialog Semiconductor DA14683 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93f7d02e.png) It is mostly marked for its enhanced security features such as secure booting. Secure booting is a process of authenticating a system's firmware and bootloader before execution. This ensures that only authorized software can run on the system, preventing malicious code from running. Secure booting is especially important in embedded systems, which are often used in industry critical applications where security is paramount. Other applications that frequently use the DA14683 include: - Virtual reality remotes - Human Interface devices - Wearables ## **10\. Dialog Semiconductor - DA14585** The DA14585 is a low-power System-on-Chip based on an ARM® Cortex®-M0 CPU running at 16MHz. It also has an extra dedicated AES-128 bit encryption processor and a link layer processor as well. ![Dialog Semiconductor DA14585 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93fa7709.png) This chip supports all Bluetooth developments up to Bluetooth 5\. It has 96kB of RAM and 64kB of One-Time Programmable (OTP) memory. It also offers a very fast boot time (<50ms) and can support up to 8 BLE connections. This processor can be used by itself as a standalone application processor or as a data pump part of a larger system. Other applications that frequently use the DA14585 include: - Beacons - Voice-controlled remote controls - Smoke alarms - Human Interface devices ## **11\. Texas Instrument - TI CC2541** The Texas Instrument CC2541, is a power-optimized system-on-chip (SoC) solution for both Bluetooth low energy and proprietary 2.4-GHz applications. ![Texas Instruments CC2541 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93fcf295.png) The CC2541 is built around an 8051 MCU, along with 128/256 KB flash memory and 8-KB RAM. Security features include cryptographic acceleration, debug security, device identity, and software IP protection. With its low power consumption and small form factor, the CC2541 is ideal for a wide range of wireless applications including : - Human-Interface Devices (Keyboard, Mouse, Remote Control) - Mobile phone accessories - Sports and fitness sensors ## **12\. Texas Instrument - TI CC2540** The Texas Instruments CC2540 is a cost-effective, low-power, system-on-chip (SoC) solution for Bluetooth low energy applications. It is built around an 8051 MCU, 128 / 256 KB in-system programmable flash memory, and 8KB SRAM. ![Texas Instruments CC2540 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a93fcf295-1.png) The main disadvantage of this chipset is that it is a legacy BLE chipset, meaning it does not support LE Secure Connections. This can be a problem for applications that require the highest levels of security that can be provided for in Elliptical Curve Diffie-Hellman (ECDH) key exchange used in LE Secure Connections. Despite this setback, the CC2540 is still widely used in a variety of applications, such as: - BLE wireless mouses and keyboards - Remote controls - USB Dongles ## **13\. STMicroelectronics ( BlueNRG-2N)** The BlueNRG-2N is a Bluetooth LE SoC that meets the Bluetooth v5.2 specification. It has a 32-bit Arm Cortex-M0 core and 245 kB of Flash memory. OTA (Over the Air) firmware updates are possible due to the presence of Flash memory. ![STMicroelectronics BlueNRG-2N SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a94002925.png) The BlueNRG-2N chipset also has a 24 kB RAM. This RAM is volatile, which means it loses its contents when the power is turned off. However, the BlueNRG-2N's RAM retention feature allows two 12 kB banks of RAM to keep their content even when power is turned off. Popular applications of this chipset include: - Smart Watches - Proximity tags - PC peripherals - Remote Controller ## **14\. SiLabs - EFR32BG13** The EFR32BG13 is a powerful and versatile Bluetooth LE SoC that supports all optional Bluetooth 5 features, including long-range and 2M PHYs. It also includes the option to add multiprotocol sub-GHz and 2.4 GHz support, making it ideal for proprietary protocols, wireless M-BUS, and Low Power Wide Area Network applications. ![Silicon Labs EFR32BG13 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a94035180.png) Based on a 32-bit ARM® Cortex®-M4 core, the EFR32BG13 offers up to 512 kB of programmable Flash memory and 64 kB SRAM, making it a great choice for - Human Interface Devices, - Commercial and Retail Lighting and Sensing, - Metering applications. ## **15\. SiLabs - EFR32BG22** The EFR32BG22 is a Bluetooth SoC equipped with an advanced 32-bit ARM Cortex-M33 CPU running at 76.8 MHz. It supports fast communication and is suited for applications that require direction finding, mesh networking, and Bluetooth 5.3 compatibility. ![Silicon Labs EFR32BG22 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a94063c26.png) This SoC has up to 512 KB of flash and 32 KB of RAM, which is enough for complex applications. Target applications for this SOc can be: - Asset Tags and Beacons - Indoor navigation - Smart door locks - Bluetooth mesh low-power nodes ## **16\. NXP Semiconductors - QN908x** The QN908x SoC is a BLE chipset that includes a 32-bit Arm Cortex-M4F running at 32 MHz, 512KB of flash memory, 128 KB of SRAM, and 256 KB of ROM. ![NXP QN908x SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a9408f86b.png) This SoC can be used in applications such as: - Retail Beacons - Human Interface Devices (HID) - Asset Tracking - Remote Controls ## **17\. Qualcomm -CSR1020** The Qualcomm CSR1020 SoC is a low-power, high-performance System-on-Chip that can support Bluetooth v5.0, Bluetooth mesh, and CSR Mesh applications. It incorporates a 16-bit RISC core running on a maximum speed of 16 MHz. ![Qualcomm CSR1020 SoC](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62b3a940b50ea.png) In terms of memory, it has an internal mask ROM of 192 KB, internal data RAM of 16 KB, Code RAM of 64 KB, OTP of 60 KB, and MTP of 256 KB. It does not support on-chip flash memory but can be interfaced with an external SPI flash memory of up to 16 MB. The device is ideal for applications such as: - Human Interface Devices (HID) - Sports and fitness sensors - Camera controls - Proximity tags ## **Which BLE SoC is Right for You? A Comprehensive Table Guide** | **SoC** | **Core** | **Memory** | **Price** | | ------------------- | -------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **9\. DA14683** | 94 MHz Arm Cortex-M0 | 128 MB ROM + 128 KB RAM + 16 KB Cache | [↗](https://www.digikey.com/en/products/detail/dialog-semiconductor-gmbh/DA14683-00000U2/8666199?ref=novelbits.io) | | **10\. DA14585** | 16 MHz ARM Cortex-M0 | 128 KB ROM + 64 KB OTP + 96 KB RAM | [↗](https://www.digikey.com/en/products/detail/dialog-semiconductor-gmbh/DA14585-00000AT2/6817036?ref=novelbits.io) | | **11\. TI CC2541** | 8-bit 8051 | 128/256 KB Flash + 8 KB RAM | [↗](https://www.digikey.com/en/products/detail/texas-instruments/CC2541F256RHAT/3182054?ref=novelbits.io) | | **12\. TI CC2540** | 8-bit 8051 | 128/256 KB Flash + 8 KB RAM | [↗](https://www.ti.com/product/CC2540/part-details/CC2540F128RHAT?ref=novelbits.io) | | **13\. BlueNRG-2N** | 32-bit ARM Cortex-M0 | 256 KB Flash + 24 KB RAM | [↗](https://www.digikey.com/en/products/category/rf-if-and-rfid/37?Enterprise=44&Vendor=497&WT.z%5Fcid=sp%5F497%5F0928%5Fbuynow&lang=en&s=N4IgTCBcDaIEIBkCqBRAcgJQOIFowGYAWEAXQF8g&ref=novelbits.io) | | **14\. EFR32BG13** | 40 MHz ARM Cortex-M4F with FPU | 512 KB Flash + 64 KB RAM | [↗](https://www.mouser.com/ProductDetail/Silicon-Labs/EFR32BG13P632F512GM48-DR?qs=EBDBlbfErPz%2F9lJ7SrSejA%3D%3D&ref=novelbits.io) | | **15\. EFR32BG22** | 76.8 MHz ARM Cortex-M33 with FPU | 512 KB Flash + 32 KB RAM | [↗](https://www.mouser.com/ProductDetail/Silicon-Labs/EFR32BG22C224F512GN32-CR?qs=zhx2xqPtQQwytWxp95uUrg%3D%3D&ref=novelbits.io) | | **16\. QN908x** | 32 MHz ARM Cortex-M4F with FPU | 512 KB Flash + 128 KB RAM | [↗](https://www.digikey.com/en/products/detail/nxp-semiconductors/QN9080DHNE/8344054?WT.z%5Fcid=sp%5F568%5Fbuynow&ref=novelbits.io) | | **17\. CSR1020** | 16-bit RISC MCU | 192 KB ROM + 80 KB RAM + 60 KB OTP | \- | ## **Conclusion** There are many different BLE chipsets on the market today that offer a variety of features and capabilities. When choosing a BLE chipset for your application, it is important to consider the specific needs of your project to select the best possible solution. In this article, we have compared 17 of the most common Bluetooth Low Energy SoCs. **There are recent releases like** [**nRF5340 from Nordic**](https://www.nordicsemi.com/Products/nRF5340?ref=novelbits.io)**,**[ **BlueNRG-LP from STMicroelectronics**](https://www.st.com/en/wireless-connectivity/bluenrg-lp.html?ref=novelbits.io)**, the** [**CC2652R7 from Texas Instruments**](https://www.ti.com/product/CC2652R7?ref=novelbits.io)**,** [**DA1469x family from Dialog Semiconductor**](https://www.renesas.com/in/en/blogs/dialog-smartbond-da1469x-introducing-our-most-advanced-bluetooth-low-energy-product-family?ref=novelbits.io)**,** [**EFR32BG24**](https://www.silabs.com/wireless/bluetooth/efr32bg24-series-2-socs?ref=novelbits.io)[ from Silicon Labs](https://www.silabs.com/wireless/bluetooth/efr32bg24-series-2-socs?ref=novelbits.io), **and** [**TLSR 921x from Telink**](https://www.telink-semi.com/?ref=novelbits.io)[**.**](https://www.telink-semi.com/?ref=novelbits.io) **These newer chipsets offer improved performance, lower power consumption, and more features than their predecessors and they are definitel**y on the path to becoming the most popular Bluetooth LE SoCs in the market. 💡 **Insider Tip:** Want to go deeper into Bluetooth LE development on these chipsets? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### How Fast is Bluetooth 5? Real Throughput, PHY, DLE & MTU Tuning URL: https://novelbits.io/bluetooth-5-speed-maximum-throughput/ Last updated: 2026-08-09T05:23:35.000Z I've received a lot of questions over the years since Bluetooth 5 was released about how the "2x speed" actually works and what to expect in terms of realistic speeds (as opposed to theoretical speeds). So, in this post, I'm going to break it all down for you. We'll cover: - What's the practical throughput to expect from Bluetooth LE? - Bluetooth 5's new 2M PHY for data transfer - What are the factors that impact/determine data throughput? - How do you calculate your application data throughput? - How do you maximize your data throughput? - Testing, measuring, and calculating data throughput using two nRF52 series development kits ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ## Key things to know about Bluetooth 5 speeds Before we dive in too deep, let's get a few things straight: - **The Bluetooth 5 “2x speed” feature may require a hardware/stack update** so older devices/chips/modules may not support it (refer to your chipset's datasheet). It is also important to note that in order to achieve this higher throughput you will need each of the two Bluetooth devices communicating with each other to support the new LE 2M PHY (which makes it possible to transfer data at this higher rate). - **The new LE 2M PHY, as well as the original LE 1M PHY, are both called Uncoded PHYs** since they use a 1-symbol representation per bit of data (in comparison to the new LE Coded PHY which uses a 2-symbol or 8-symbol representation per bit of data). - **When utilizing the higher-speed PHY, you actually achieve lower power consumption** (given that you transfer the same amount of data). This is because the radio-on time is reduced without the transmit power being increased. This in turn also improves coexistence with other wireless technologies within the 2.4 GHz spectrum (also due to the reduced radio-on time). ## Why is it impossible to achieve theoretical Bluetooth speeds? First, we need to understand that **the speeds advertised are only theoretical and are cut down when it comes down to application data throughput.** The data rates of 1 Mbps (LE 1M PHY), 2 Mbps (LE 2M PHY), 125 kbps, and 500 kbps (both using the LE Coded PHY with S=8 and S=2, respectively) are the rates at which the radio transmits data, but this is not achievable for the application throughput due to the following reasons: - Limit on the number of packets per connection interval - Inter Frame Space (IFS) delay between packets (150 us) - Empty packets are required to be sent from a device even if no data is available for transmission - Packet overhead - not all bytes in a packet are used for payload In order to better understand these factors and understand what impacts application throughput, we have to take a deeper look at the packet format. The following figure shows what LE 1M PHY and 2M PHY data packets look like: ![LE Uncoded Packet format diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/le-uncoded-packet-format-1-e1504168301565.png) The part we’re interested in (and the one that really defines the application data) is the **ATT Payload**. As you can see from the figure, there are a number of overhead bytes that are used by each layer in Bluetooth Low Energy. - In 4.0 and 4.1, the maximum ATT Payload is 20 bytes. - In 4.2 and 5.0, a new feature called Data Length Extensions (DLE) allows the ATT Payload to hold up to 244 bytes of data. ### Bluetooth 5 speed: 2x speed utilizing the new 2M PHY It is useful to understand the limitations of using the new LE 2M PHY in Bluetooth 5: - Cannot be used to transmit the primary advertisements (on the primary channels). - Can be used for the secondary “auxiliary packets” sent on the same channels as the data packets (37 channels: 0-36). *To learn more about primary and secondary advertisements, refer to my previous blog post:* [**Bluetooth 5 Advertisements: Everything you need to know**](https://novelbits.io/bluetooth-5-advertisements/)*.* - LE 1M is mandatory, whereas LE 2M is optional. So, not all chipsets claiming Bluetooth 5 support can necessarily handle the higher throughput. - Advertisements and discovery can occur on the LE 1M PHY, and then connections occur on the secondary advertisement channel using the LE 2M PHY Transfer of application data from one device to another usually happens during a connection between the two Bluetooth devices. The connected devices can negotiate the use of a different PHY via the **PHY Update Procedure**. It can be initiated by either Peripheral or Central after a connection is established, but the Central will ultimately make the final decision on which PHYs are used for each direction (based on the Peripheral's request and the PHYs the Central supports). ![LE PHY Update Procedure sequence diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/phy-update-procedure-e1504123921450.png) ## Factors that impact/determine the data throughput for Bluetooth devices There are a few factors that impact the data throughput of a Bluetooth Low Energy application. The most common are: - PHY being used (LE 1M vs. LE 2M vs. LE Coded (S=2 or S=8)) - Connection interval - Maximum number of packets per connection interval - ATT Maximum Transmission Unit (ATT MTU) - Data Length Extension (DLE) - Operation type: Write with response vs. Write without response, Indications vs. Notifications - Inter Frame Space (IFS): time gap between consequent packets (150 us) - Transmission of empty packets - Packet overhead - not all bytes, in a packet, are used for the application payload Let’s go over each of these in more detail. ### PHY There are basically three PHYs in Bluetooth 5: the original 1 Mbps PHY, the new 2 Mbps, and the Coded PHY (with S=2, or S=8 configuration). The PHY used will directly impact the maximum data throughput you can achieve since it determines the actual raw data rate at which packets are sent over the air. ### Connection Interval & max packets per connection event The connection interval effectively determines how many packets can be sent during one connection event. The higher the value, the more packets can be sent in one connection event (up to a certain limit for some devices). *Learn more about connection intervals:* [*Bluetooth LE connection intervals and events*](https://novelbits.io/ble-connection-intervals/) However, the number of packets per connection event depends on the device and Bluetooth Low Energy stack so it is limited and differs between devices and stack versions on a specific device. This value also depends on the operation of the device, so the radio may have to attend to other events and the number of packets sent per connection events may not reach the max allowed by the stack. For example, the number differs between iOS and Android and also changes depending on the version of the OS running on the device. Sometimes it is useful to dynamically update the connection parameters based on the use case. However, keep in mind that it is up to the Central to accept these recommendations or update the parameters to accommodate them. ### Data Length Extensions (DLE) This feature allows the packet size to hold a larger amount of payload (Up to 251 bytes vs. 27 when disabled). This feature was introduced in version 4.2 of the Bluetooth Core specification. ### ATT Maximum Transmission Unit (ATT MTU) ATT MTU Determines the max amount of data that can be handled by the transmitter and receiver and which they can hold in their buffers. The MTU value affects the amount of overhead data (specifically the ATT header which is 3 bytes). The minimum ATT MTU allowed is 27 bytes. This allows a max of 20 bytes of ATT payload (3 bytes are used for the ATT header, and 4 bytes for the L2CAP header). There is no limit per the spec on how high the MTU value can be, but the specific stack in use may have its own limitations. Typical values are in the range of 512 bytes. For example, if you enable DLE then you can transfer up to 251 - 4 = 247 bytes (after deducting the L2CAP Header size). After taking into account the ATT header (3 bytes), we are left with 244 bytes for the actual ATT payload data. If the MTU is at least 247 bytes then the MTU will fit into one single packet. If the MTU is greater than 247 bytes and the data is also larger than that, then the ATT payload will span multiple packets causing the throughput to go down (because of the packet overhead and timing in between the packets). The effective MTU gets determined by the minimum value of ATT MTU that the client and server support. For example, if a client supports an ATT MTU of 100 bytes and the server responds that it supports an ATT MTU of 150 bytes, then the client will decide that the ATT MTU to be used for the connection from thereon is 100 bytes. ### Operation type: Write with response vs. write without response, Indications vs. Notifications If high throughput is desired then we can use Write without response or Notifications to transfer the data from the client to the server and from the server to the client. These operations remove the need for the other device to acknowledge receipt of the data at the application layer and respond before the next block of data can be sent. ### Inter Frame Space (IFS): time delay between consecutive packets (150 us) From the Bluetooth specification: ### Transmission of empty packets If the device receiving data has no data to send back, it still needs to send an empty packet as per the Bluetooth specification. ### Packet overhead As we saw in the packet format figure, the packet includes some overhead data that doesn't count toward your application data (ATT data). Basically, these bytes will consume part of your transfer data rate while not accounting for any bytes being sent as part of your application data. ## Calculating your application data throughput The big question is: **how do we calculate our application throughput?** As we mentioned before, there are a few variables that impact the data throughput: - Bluetooth version & PHY used - DLE: Data Length Extensions - enabled or not - ATT MTU value - Connection interval - Maximum number of packets per connection event - Operation (writes with responses vs. writes without responses, and notification vs. indication) - Inter Frame Space (IFS): 150 microseconds The Bluetooth version and PHY determine the raw data transfer rate. For example, if we are using Bluetooth version 4.2 and the LE 1M PHY, then the transfer rate is at 1 Mbps. If on the other hand, we are using the Bluetooth 5 LE Coded PHY with S=8, then the data rate goes down to 125 kbps. The DLE, ATT MTU, connection interval, the maximum number of packets per connection interval, Operation, and IFS all determine the portion of the on-radio time that's utilized for actual data transfer. The packet format plays a big role in how much of the data being transferred is your actual application data. The LE 1M PHY and LE 2M PHY both have a similar packet format. The LE Coded PHY has a significantly different packet format, so we'll be looking at these two cases separately. ### LE 1M PHY and LE 2M PHY calculation Referring back to the packet format for LE Uncoded PHYs: ![LE Uncoded Packet format diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/le-uncoded-packet-format-1-e1504168301565-1.png) The amount of overhead for each PHY is slightly different. The Preamble is 1 byte in the case of the 1M PHY and 2 bytes in the case of the 2M PHY. The MIC field is an optional field that is used only for encrypted connections. For simplicity, we will only consider unencrypted connections - for the encrypted case, it simply adds 4 bytes of overhead. For LE Coded PHYs, the packet format looks like this (from the Bluetooth Core spec Vol 6, Part B, Section 2.2): ![LE Coded PHY Packet Format Diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/le-coded-phy-packet-format-e1504163429980.png) #### Steps for calculating the throughput (in Mbps): For sake of simplicity, we assume the following: - Encryption is NOT enabled (the MIC field is not included in the packet) - We are interested in the throughput for one direction (e.g. Central to Peripheral), so we assume the other direction only transfers empty packets - Writes without responses (which would help in maximizing the throughput when transferring large amounts of data ##### Steps: **Step 1*: Determine the PHY being used and note down the rate of raw data transfer* E.g. for 1M PHY → 1 Mbps, for Coded PHY and S=8 → 125 kbps **Step 2:** *Determine the time it takes to send one data packet and the empty packet from the receiver.* ![connection interval packet diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/connection-interval-packets-1-e1504157824666.png) The time during which one data packet can be sent will include the following: **Data\_Packet\_Time = Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS.** An empty packet transmission time can be calculated as follows: **Time to transmit empty packet = empty packet size / raw data rate** An empty packet will contain the following fields: Preamble + Access Address + LL Header + CRC. For 1M PHY, Preamble will be 1 byte, and so the total size of the empty packet = 1 + 4 + 2 + 3 bytes = 10 bytes = **80 bits.** (for 2M PHY, the size of an empty packet will be **88 bits** since the Premable is 2 bytes instead of 1 byte). Based on this, the time to transmit an empty 1M PHY packet will be: **Time to transmit empty packet** \= empty packet size / raw data rate = 80 bits / 1 Megabits per second = **80 microseconds** A data packet will contain all fields listed in the packet format diagram with the exception of the MIC field (encryption disabled). **Time to transmit data packet = data packet size / raw data rate** If we have DLE enabled and the ATT MTU is equal to the maximum bytes allowed in one packet: 247 bytes, then we can calculate the **data packet size** as: **Data packet size** \= 1 + 4 + 2 + 4 + 247 + 3 bytes = 265 bytes = 265 x 8 bits = 2120 bits Time to transmit data packet = 2088 bits / 1 Mbps = **2,120 microseconds** **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 80 + 2 x 150 + 2120 = **2,500 microseconds** For comparison, in the case of 2M PHY, it would be: **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 88/2 + 2 x 150 + (2 + 4 + 2 + 4 + 247 + 3) x 8/2 = **1,392 microseconds** When DLE is enabled and the ATT MTU is set to less than 247, we end up with more overhead (since now data larger than the ATT MTU gets split up into more packets). For example, say we have the ATT MTU set to 158, then in order to transfer 244 bytes of application data, we will need two packets instead of one, causing the throughput to go down due to the increased byte overhead as well as the increased IFS between the packets. In another scenario, we could have DLE disabled (Payload size up to 27 bytes) and the ATT MTU greater than 27 bytes. Here, this will also result in more packets needing to be sent for the same amount of data, causing the throughput to go down. Note: The same method for calculating the data and empty packet sizes that we used above can be used for the LE Coded PHY. **Step 3:** *Figure out how many packets can be transmitted during one connection interval* This calculation is not always purely mathematical - you will need to take into account the limitations of the stack and device being used. iOS and Android have maximums that change with OS version, so it's not always easy to figure out. That being said, on an MCU, the vendor's SDK usually lists the maximum in their documentation. It's also helpful to do a trial and error and figure out what your specific device supports. Once you've figured out the maximum, you can calculate the maximum theoretical number of packets that would fit within a connection interval of choice. For example, if we had a connection interval of 7.5 milliseconds (the lowest permitted by the spec), then for our example above (using 1M PHY, DLE enabled): **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\], where \[ \] rounds to the highest whole number (integer) **Maximum # of data packets per connection interval** \= \[7.5 x 1,000 microseconds / 2,468 microsecs\] = 3 packets Usually, this number is not realistic as there are timing delays between packets being sent on consecutive connection events. So, for our example, we will go with 2 packets instead of 3. **Step 4:** Once we've figured out the maximum # of data packets that can be transferred per connection interval, we can calculate the data throughput: **Data throughput = data per connection interval ÷ connection interval** \= (No. of data packets per connection interval x Data size per packet) ÷ connection interval **\= 2 x 244 x 8 bits / 7.5 milliseconds** \= 520,533 bits/sec \~= **508 kbps** ## Testing and calculating data throughput between two nRF52 development kits In this section, we will run multiple tests of data transfer, calculate the throughput using the procedure we described earlier, and then compare them with the measured throughput reported by the application running on the development boards. The tests are run based on the demo app provided by Nordic Semiconductor and featured in this blog post: [Throughput and long-range demo.](https://devzone.nordicsemi.com/blogs/1078/throughput-and-long-range-demo/?ref=novelbits.io) The source code for the example can be found on the GitHub page [here](https://github.com/NordicSemiconductor/nrf528xx-ble-throughput-demo?ref=novelbits.io). ### Case 1 (PHY: 1 Mbps, ATT MTU = 23 bytes, DLE: enabled, Connection interval: 7.5 millisecs) #### Data throughput reported by firmware: #### Calculated data throughput: With the MTU set to 23 bytes, DLE does not really affect the data throughput and packet sizes. **Time to transmit data packet** \= data packet size / raw data rate = 1 + 4 + 2 + 4 + 23 + 3 bytes / 1 Mbps= 37 x 8 bits / 1 Mbps = 296 microsecs **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 80 + 150 + 296 + 150 microsecs = 676 microsecs **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\] = \[7.5 millisecs / 676 microsecs\] = \[11.09\] = 11 packets **Total data transferred per connection interval** \= 11 x 20 bytes = 11 x 20 x 8 bits = 1,760 bits **Data throughput** \= Total data transferred per connection interval/connection interval = 1760 bits / 7.5 millisecs = **234.67 Kbits/s** As we can see, the calculated value and measured value are pretty close. ### Case 2 (PHY: 2 Mbps, ATT MTU = 23 bytes, DLE: enabled, Connection interval: 7.5 millisecs) #### Data throughput reported by firmware: #### Calculated data throughput: **Time to transmit data packet** \= data packet size / raw data rate = 2 + 4 + 2 + 4 + 23 + 3 bytes / 2 Mbps= 38 x 8 bits / 2 Mbps = 152 microsecs **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 44 + 150 + 152 + 150 microsecs = 496 microsecs **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\] = \[7.5 millisecs / 512 microsecs\] = \[15.12\] = 15 packets **Total data transferred per connection interval** \= 15 x 20 bytes = 15 x 20 x 8 bits = 2400 bits **Data throughput** \= Total data transferred per connection interval/connection interval = 2400 bits / 7.5 millisecs = **320 Kbits/s** As we can see, the calculated value and measured value are pretty close. ### Case 3 (PHY: 1 Mbps, ATT MTU = 158 bytes, DLE: enabled, Connection interval: 7.5 millisecs) #### Data throughput reported by firmware: #### Calculated data throughput: **Time to transmit data packet** \= data packet size / raw data rate = 1 + 4 + 2 + 4 + 158 + 3 bytes / 1 Mbps= 172 x 8 bits / 1 Mbps = 1376 microsecs **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 80 + 150 + 1376 + 150 microsecs = 1756 microsecs **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\] = \[7.5 millisecs / 1756 microsecs\] = \[4.27\] = 4 packets **Total data transferred per connection interval** \= 4 x 155 bytes = 4 x 155 x 8 bits = 4960 bits **Data throughput** \= Total data transferred per connection interval/connection interval = 4960 bits / 7.5 millisecs = **661.33 Kbits/s** ### Case 4 (PHY: 2 Mbps, ATT MTU = 247 bytes, DLE: enabled, Connection interval: 7.5 millisecs) #### Data throughput reported by firmware: #### Calculated data throughput: **Time to transmit data packet** \= data packet size / raw data rate = 2 + 4 + 2 + 4 + 247 + 3 bytes / 2 Mbps= 262 x 8 bits / 2 Mbps = 1048 microsecs **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 44 + 150 + 1048 + 150 microsecs = 1392 microsecs **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\] = \[7.5 millisecs / 1392 microsecs\] = \[5.39\] = 5 packets **Total data transferred per connection interval** \= 5 x 244 bytes = 5 x 244 x 8 bits = 9760 bits **Data throughput** \= Total data transferred per connection interval/connection interval = 9760 bits / 7.5 millisecs = **1301.33 Kbits/s** **Important Note:* In the last two cases, the number of packets per connection interval is small and any difference between what we calculate and what is measured will have a big impact on actual data throughput.* *For example, if the number of packets per connection interval ends up being 4 instead of 5 inCase #4, the calculated throughput becomes 1,041.1 Kbps instead of 1,301.33 Kbps (which is a big difference and could explain the discrepancy in numbers here).* ### Case 5 (PHY: 2 Mbps, ATT MTU = 247 bytes, DLE: enabled, Connection interval: 50 millisecs) #### Data throughput reported by firmware: #### Calculated data throughput: **Time to transmit data packet** \= data packet size / raw data rate = 2 + 4 + 2 + 4 + 247 + 3 bytes / 2 Mbps= 262 x 8 bits / 2 Mbps = 1048 microsecs **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 44 + 150 + 1048 + 150 microsecs = 1392 microsecs **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\] = \[50 millisecs / 1392 microsecs\] = \[35.92\] = 35 packets **Total data transferred per connection interval** \= 36 x 244 bytes = 35 x 244 x 8 bits = 68320 bits **Data throughput** \= Total data transferred per connection interval/connection interval = 70272 bits / 50 millisecs = **1366.4 Kbits/s** ### Case 6 (PHY: 2 Mbps, ATT MTU = 247 bytes, DLE: enabled, Connection interval: 400 millisecs) #### Data throughput reported by firmware: #### Calculated data throughput: **Time to transmit data packet** \= data packet size / raw data rate = 2 + 4 + 2 + 4 + 247 + 3 bytes / 2 Mbps= 262 x 8 bits / 2 Mbps = 1048 microsecs **Data\_Packet\_Time** \= Time to transmit empty packet + IFS + Time to transmit the actual data packet + IFS = 44 + 150 + 1048 + 150 microsecs = 1392 microsecs **Maximum # of data packets per connection interval** \= \[connection interval / Data\_Packet\_Time\] = \[400 millisecs / 1392 microsecs\] = \[287.36\] = 287 packets **Total data transferred per connection interval** \= 287 x 244 bytes = 287 x 244 x 8 bits = 560224 bits **Data throughput** \= Total data transferred per connection interval/connection interval =560224 bits / 400 millisecs = **1400.56 Kbits/s** ## Optimizing for maximum Bluetooth device data throughput Based on the factors we went over, we can note the following when optimizing for high data throughput: - *Always enable DLE* Obviously, if you're using Bluetooth v4.1 or earlier, this is not a valid option. In general, however, make sure you enabled DLE to maximize your packet-to-application data efficiency - *Use LE 2M PHY* If you know that the devices on both ends support Bluetooth 5, then utilizing the LE 2M PHY is one of the best ways to maximize your application data throughput. Using the LE 2M PHY will also help your device have low power consumption (and therefore, a longer battery life!), so you hit two birds with one stone! - *Use Notifications and Writes without Responses* Utilizing these will help remove any unnecessary packets being transmitted (compared to Indications and normal Writes (with responses) which require the receiving end to acknowledge each packet received). - *Choose an ATT MTU value of at least greater than 247 bytes* This will minimize any overhead in packet bytes. - *Choose a connection interval that allows for the maximum # of packets per connection interval* But keep in mind that the connection interval affects power consumption. The shorter the interval, the more power your device will consume because of the increased radio-on time.You also want to make sure you don't choose an interval that's too high, otherwise, it'll compromise the user experience (higher connection interval results in higher latency).One last thing to make sure you account for is any limitations of the devices in your system in terms of the maximum number of packets per connection interval supported. ## Summary & closing The calculated values we listed above are still theoretical and may not align with the measured data throughput in practice and real-life environments, but they still are a good starting point and give a good indication of what to expect (at least for a maximum). Interference and transmission/reception errors also affect data throughput (retries, data loss, and closing of connection events result in lower throughput). These can be caused by the presence of other devices utilizing the same 2.4 GHz band as Bluetooth Low Energy, longer distance between devices, the existence of obstacles between devices, and more... ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE data throughput, PHY selection, and connection parameter optimization? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## References/Credits - [Nordic Throughput and long-range demo](https://devzone.nordicsemi.com/blogs/1078/throughput-and-long-range-demo/?ref=novelbits.io) - [Maximizing BLE Throughput on iOS and Android](https://punchthrough.com/blog/posts/maximizing-ble-throughput-on-ios-and-android?ref=novelbits.io) - [Maximizing BLE Throughput Part 2: Use Larger ATT MTU](https://punchthrough.com/blog/posts/maximizing-ble-throughput-part-2-use-larger-att-mtu?ref=novelbits.io) - Question: [How do I calculate throughput for a BLE link?](https://devzone.nordicsemi.com/question/3440/how-do-i-calculate-throughput-for-a-ble-link/?ref=novelbits.io) - Question: [How to calculate effective throughput in nRF52](https://devzone.nordicsemi.com/question/110538/how-to-calculate-effective-throughput-in-nrf52/?ref=novelbits.io) ### How a Group of Researchers Hacked Tesla's Passive Keyless Entry System URL: https://novelbits.io/tesla-passive-keyless-entry-system-hacked/ Last updated: 2026-08-09T05:26:37.000Z Bluetooth Low Energy Passive keyless entry (PKE) systems, which allow drivers to open car doors without having to fumble for their keys are becoming increasingly popular. However, new research has shown that these systems may be vulnerable to link-layer relay attacks. **A team of researchers from NCC Group detailed how they were able to successfully carry out such an attack against a Tesla Model 3\. Even worse, the attack tool they developed can conduct a relay attack with an added latency that is within the range of the normal GATT response timing variation, making it difficult to detect that the attack is in progress.** So, how does the attack work? Is your PKE system safe? How does the Bluetooth LE proximity-based authentication fail? Let's take a closer look. ## **How Does A Bluetooth LE Passive Keyless Entry Work?** To understand how the attack works, we need to first understand how a Bluetooth LE PKE system works. A PKE system is a system that automatically unlocks and locks your car when you are near it with an authorized phone or key fob. The system is called "passive" because it does not require any user action. With this system, the driver can lock/unlock the car doors and start/stop the engine without needing to do anything manually, either with a key fob or a mechanical key. The nitty-gritty of how a PKE system works is as follows: ![Flow diagram of a Bluetooth LE passive keyless entry system](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a837036defc.jpg) Flow diagram of Bluetooth LE PKE system A typical PKE system uses two devices: a registered mobile device that acts as a key and a vehicle-mounted receiver, both implementing the Bluetooth LE proximity GATT profile. The Bluetooth LE proximity profile, as defined in its [official specification](https://www.bluetooth.com/specifications/specs/proximity-profile-1-0-1/?ref=novelbits.io), describes what happens when a device moves away from a peer device or what happens when two devices come closer together. In a PKE system, the vehicle acts as a proximity monitor and performs a periodic discovery scan for a mobile device. Upon detecting a known mobile device (i.e a mobile device whose MAC address is white-listed), the vehicle verifies that the RSSI value received from the mobile device is within an acceptable range. RSSI is a received signal strength indication and is a measure of the strength of the radio signal received by the receiver. If the RSSI value is within an acceptable range, then it can be concluded that the user carrying the authorized mobile phone or key fob is in close proximity to the car and therefore, can be authenticated. Generally, Bluetooth LE authentication is a challenge-response operation based on the security tokens shared when the two peer devices are initially paired. Finally, after the completion of authentication, the vehicle maintains a connection with the mobile phone and monitors the RSSI value of the connection. Based on the RSSI value, the vehicle can infer if the user is nearby or not and therefore lock/unlock the vehicle doors and start/stop the car as required. In basic terms, the RSSI value is used to authenticate the presence of the user. So far, everything sounds like it works well. But where does the Bluetooth LE proximity-based authentication fail? ### **How does the Bluetooth LE proximity-based authentication fail** A common problem with proximity authentication using Bluetooth LE is that the RSSI value isn't a very reliable way to determine if someone is close by. The RSSI value and MAC address are values that come from a layer below layer 2 on the OSI model. This means that they can be measured regardless of the connection status. They are not protected by the authentication, confidentiality, and integrity guarantee that the link layer provides via pairing. | Property | Secure? | Authenticity | Confidentiality | Integrity | | ----------- | ------- | ------------ | --------------- | --------- | | MAC Address | No | ✘ | ✘ | ✘ | | RSSI | No | ✘ | ✘ | ✘ | **Untrusted Properties of a Bluetooth LE connection** The MAC address and the RSSI value are therefore untrusted properties of a Bluetooth LE connection, as we've discussed in our [previous article on the topic](https://novelbits.io/how-to-protect-the-privacy-of-your-bluetooth-low-energy-device/). They are insecure and can be easily collected and forged by an attacker in a relay attack. ## **Understanding A Relay Attack** A relay attack is a well-known attack used to target communication systems. In a basic relay attack, messages are relayed from one location to another to make one entity appear closer to another. Normally, the attack does not need to interpret nor modify the message signal. It just introduces a delay. ![Simplified diagram of a Bluetooth LE relay attack on passive keyless entry](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83703cefb1.jpg) A simplified view of the attack relaying Bluetooth LE signal In a Bluetooth LE context, a relay attack can be performed by an attacker who uses one device that is in close proximity to both the victim (i.e the user) and another device close to the intended receiver (i.e the car). The attacker collects the MAC address of the victim's mobile device and modifies the RSSI value to whatever is required to make it appear close to the car, and then relays these two values to the car. If there is no link-layer encryption employed between the Bluetooth LE connection of the victim and the car, then the attacker can also easily carry out a relay attack of GATT requests and responses. When the car receives the modified RSSI values, it is tricked into thinking that the authorized user is in close proximity, even though they might be far away. This corresponds to a scenario where an authorized phone is in the owner's pocket in the supermarket and the car is in the supermarket's parking lot. If successful, the attacker can gain access to the victim's car without needing the victim's key fob or phone. ### **Mitigating Relay Attacks On PKE Systems** The possibility of relay attacks against Bluetooth LE proximity authentication is a problem that has been known for a long time, but [researchers](https://www.ndss-symposium.org/wp-content/uploads/2017/09/franc.pdf?ref=novelbits.io) have discovered that the Bluetooth specification doesn't have a secure way of verifying devices are near each other. As previously stated, RSSI is an insecure property that can be easily [sniffed](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) and modified by an attacker. One approach to mitigate relay attacks is Elliptic Curve Diffie-Hellman (ECDH) key exchange during the initial pairing process. This protects the devices' GATT characteristics from unauthorized reads and writes. A second approach exploits the known flaw of relay attacks which is that they introduce latency in the communication. Here, developers impose strict GATT response time limits. If the time exceeds a certain threshold, this indicates that the devices might not be in close proximity and the connection should be aborted. Other systems try to block signal amplification relay attacks through various localization techniques like triangulation. But most localization techniques require specialized hardware which is not always available. Even though we have come up with some solutions, there is a new type of relay attack that can get around the existing protections. ## **The Dangerous Relay Attack That Can Unlock Your Tesla** The NCC Research Group has developed a new type of Bluetooth LE attack that operates at the link layer and is therefore capable of relaying encrypted messages. The [NCC Research Group's tool](https://web.archive.org/web/20231231020619/https://research.nccgroup.com/2022/05/15/technical-advisory-tesla-ble-phone-as-a-key-passive-entry-vulnerable-to-relay-attacks/) can forward link-layer responses within a single connection event, and introduces as little as 8 ms of round-trip latency beyond normal operation. However, since real Bluetooth LE devices commonly require multiple connection events to respond to GATT requests or notifications and have inherent variability in their response timing, the latency introduced by this relay attack is well within the range of normal response timing variation for real Bluetooth LE devices. The relay attack shown in the video below can bypass latency bounding and encryption security measures that are in place to protect Tesla's Model 3 vehicles from being unlocked and driven without the authorized mobile device or key fob being nearby. Because normal response time or successful communication over an encrypted link layer cannot be used to tell if a relay attack is happening, conventional mitigations against relay attacks do not work against these link-layer relay attacks. ## **Recommendation** Science is all about problem-solving. It's the process of finding out what is causing a problem and then figuring out how to fix it. It, therefore, is no surprise that the researchers who created a tool to launch relay attacks on Bluetooth LE PKE systems have issued a few recommendations to reduce the opportunities for such attacks. They recommend: - When the mobile device has been stationary for more than a minute, the passive entry functionality should be disabled in the mobile app. - The mobile application should report the mobile device's last known location during authentication with the vehicle. - Developers should move towards Time-of-Flight as a proximity measurement over RSSI. We hope that these findings will prompt car manufacturers to revisit the security of their PKE systems and find ways to better protect their customers against these types of attacks. ## References - [Technical Advisory - Bluetooth LE Proximity Authentication Vulnerable to Relay Attacks (NCC Group)](https://web.archive.org/web/20250112194426/https://research.nccgroup.com/2022/05/15/technical-advisory-ble-proximity-authentication-vulnerable-to-relay-attacks/) - [Technical Advisory - Tesla Bluetooth LE Phone-as-a-Key Passive Entry Vulnerable to Relay Attacks (NCC Group)](https://web.archive.org/web/20231231020619/https://research.nccgroup.com/2022/05/15/technical-advisory-tesla-ble-phone-as-a-key-passive-entry-vulnerable-to-relay-attacks/) 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE security topics like relay attacks, pairing, and encryption? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### How to Protect the Privacy of Your Bluetooth Low Energy Device URL: https://novelbits.io/how-to-protect-the-privacy-of-your-bluetooth-low-energy-device/ Last updated: 2026-08-09T05:25:11.000Z There are several ways to secure Bluetooth LE device communications. One way is to randomize the MAC address of the device. This is an effective way to thwart passive tracking and device spoofing attacks. If you are developing a Bluetooth LE device, make sure to implement MAC address randomization in conjunction with other security measures, such as the passkey entry or numeric comparison LE secure connections' pairing methods, to provide the best security for your device and its data. ## **The Problem With The Static Bluetooth MAC Address** The Bluetooth MAC address is a unique identifier assigned to each Bluetooth device. This 48-bit MAC address is typically assigned by the manufacturer and is hard-coded into the device hardware. So it never changes. This is the first problem. This static Bluetooth LE MAC address is included in the advertisement packets of the device and is how other devices know how to connect to it. Remember that advertisement packets are not encrypted. They are always sent in the clear plaintext and can be easily monitored by anyone within range. This is the second problem. These two problems make it possible for someone to passively track a Bluetooth LE device by monitoring the advertisement packets and looking for the static MAC address. For example, consider a scenario where you are using a Bluetooth LE-enabled fitness tracker. The fitness tracker continuously broadcasts advertisement packets as it looks to announce its presence for a connection to the smartphone. These packets include the static MAC address of the device. An attacker could use a [sniffer to monitor the advertisement packets](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) and record the MAC addresses of devices in range. Later, when you walk by the same location, the attacker sees the same MAC address in the sniffer logs, they would know that it is likely the same device (i.e. the fitness tracker) and therefore you. The attacker is using the static MAC address to track the location of the device over time. This is how passive tracking works. The example we just shared was actually discovered by a group of researchers in this recent [study](https://dl.acm.org/doi/pdf/10.1145/2873587.2873594?casa%5Ftoken=dzmvSSIX-FQAAAAA:0LTB4uo%5Fgr8-XtwnHJOOk1HYsSRwwaRWL-0E8ar-vXH8HXnp1%5FUZpBWAIEuJLeT7eIMafdcwi%5FF2Ql8&ref=novelbits.io). User tracking by monitoring the device's static Bluetooth LE address is feasible. How can we mitigate this problem? I am glad you asked. ## **The Solution: Bluetooth MAC Address Randomization** MAC address randomization is a process of generating MAC addresses that cannot be traced back to a specific device. MAC addresses are randomly generated and changed periodically, making it difficult for someone to track down a specific device. The Bluetooth specification includes a feature known as [Bluetooth LE Privacy](https://www.bluetooth.com/blog/bluetooth-technology-protecting-your-privacy/?ref=novelbits.io), which causes the MAC address within the advertising packets to be replaced with a random number. This number changes periodically at intervals determined by the manufacturer, although the specification recommends that these intervals should be less than 15 minutes. MAC address randomization helps prevent third-party observers from tracking your device. By randomly generating a MAC address, it appears as though multiple devices are being used, rather than just one. This makes it difficult to track an individual based on their MAC address. As a result, MAC address randomization disguises a device's identity and provides an additional layer of privacy and security for users. ## **Implementing MAC Address Randomization** To implement MAC address randomization in Bluetooth LE, we have to use the random private address instead of the public address or the random static address. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836cb18e15.jpg) Why should Bluetooth LE device developers stay away from public addresses? The public address is the MAC address that is bought from the IEEE and is used as the device's identity. The public address does not change. **What's wrong with that?** The problem is that the public address can be sniffed and used to track the device. Also, it is possible to infer the identity of the manufacturer through the public address. This could be useful for an attacker who wants to target a particular manufacturer's devices. Random static addresses, on the other hand, are generated randomly, but they stay the same over time. They do not change during the power cycle of the device. So while they are not as easy to track as public addresses, they are still static and can be used to track a device's location over time. The only way to truly prevent tracking is to use a random private address. There are two types of random private addresses you can choose from during device development: resolvable private addresses and non-resolvable private addresses. You can find more information about the [different Bluetooth LE device addresses](https://novelbits.io/bluetooth-address-privacy-ble/) in our previous post. ### **1\. Resolvable Private Addresses (RPA)** A resolvable private address is generated randomly, so an attacker cannot trace it back to a particular manufacturer. It is also not static, so it cannot be used to track a device's location over time. The benefits of using an RPA are not just limited to its ability to hide the device's real address. It is resolvable. Your device can broadcast random RPA MAC addresses to other devices. If these devices are paired with or explicitly trusted by your device, they will be able to resolve the MAC addresses into your device's real MAC address. The way that RPAs are resolved is through the use of an Identity Resolving Key (IRK). A device using RPA generates the IRK and distributes it to trusted devices during paring. ### **2\. Non-Resolvable Private Addresses (NRPA)** A non-resolvable private address is also generated randomly and cannot be traced back to a specific manufacturer. It is also not static, so it cannot be used to track a device's location over time. The benefits of using an NRPA are that it is truly private and cannot be resolved by any other devices, even if they are paired with or explicitly trusted by your device. It always hides the real address of the device. ## **Conclusion** MAC address randomization is becoming more and more important as the number of Bluetooth-enabled devices increases. If you’re not already using it, we urge you to start implementing it on your devices as soon as possible. Not only will this keep your device safe from eavesdropping and tracking, but it will also help to ensure that your customers’ data remains confidential. 💡 **Insider Tip:** Want to master Bluetooth LE security and privacy features? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Native vs. Cross-Platform Bluetooth LE Mobile Apps URL: https://novelbits.io/native-vs-cross-platform-bluetooth-low-energy-mobile-app-platforms/ Last updated: 2026-08-09T05:25:42.000Z If you're building a mobile app that communicates with a Bluetooth Low Energy device, one of the first big decisions you'll face is this: should you go native (Swift for iOS, Kotlin for Android) or use a cross-platform framework like Flutter or React Native? It's a decision that seems straightforward on the surface — write once, run everywhere sounds great, right? But when Bluetooth LE is involved, the answer gets a lot more nuanced. **A note on this post:** Much of the insight here comes from a discussion thread in the [Bluetooth Developer Academy](https://novelbits.io/academy/) community forums, where experienced Bluetooth LE app developers — including professionals in mobile development, medical devices, and security — shared their real-world perspectives on this topic. I've organized and expanded on their insights here, combined with my own experience. The opinions and recommendations don't necessarily reflect my own views in every case, but I think they represent a well-rounded and practical take on the subject. In this post, we'll cover: - The key factors that should drive your native vs. cross-platform decision - When cross-platform frameworks work well for Bluetooth LE apps - When you should absolutely go native - How Flutter and React Native compare for Bluetooth LE development - Security and regulatory considerations (especially for medical devices) - A practical decision framework to help you choose ## The Real Question: How Complex Is Your Bluetooth LE Usage? Let's get straight to the heart of the matter. The single biggest factor in this decision isn't your team's language preference or your timeline — it's **how your app uses Bluetooth LE**. There are three questions you should ask yourself before anything else: 1. **Is this a "quick check" app?** — Does the user open the app occasionally to take a reading (like a blood pressure measurement) or toggle something on/off? If so, a cross-platform framework with a generic Bluetooth LE plugin can work just fine. 2. **Does the app need a persistent background connection?** — If your app needs to maintain a Bluetooth LE connection even when it's in the background, you're going to run into platform-specific behavior that cross-platform frameworks don't always handle well. 3. **Is the communication complex or time-critical?** — If you're streaming data, transferring files, or need to connect and transmit within a tight time window, the overhead and limitations of third-party Bluetooth LE libraries become much more apparent. If you answered "yes" to question 1 and "no" to questions 2 and 3, cross-platform is probably fine. For anything beyond that, let's just say things start to get complicated. ## When Cross-Platform Works for Bluetooth LE Apps Let's be clear — I'm not saying cross-platform frameworks can never work for Bluetooth LE apps. They absolutely can, under the right conditions. Here's when they tend to work well: - **Simple, infrequent connections** — reading a sensor value, toggling a switch, or fetching a status update - **Low throughput requirements** — the data exchange is small and doesn't need to happen quickly - **No background processing** — the user opens the app, interacts with the device, and closes the app - **Prototyping and proof of concept** — when getting something to market fast matters more than a polished user experience In these scenarios, you get the main benefit of cross-platform development: **shared UI code and business logic** across iOS and Android. The Bluetooth LE interaction is a small part of the overall app, and the generic plugins handle it adequately. I've seen some genuinely good cross-platform apps that use Bluetooth LE for these kinds of simple interactions. The GUI can look and feel native, and you do save development time on the non-Bluetooth parts of the app. ## When You Should Go Native Now, let's talk about the scenarios where I'd strongly recommend going 100% native. In my experience, once your app's Bluetooth LE requirements go beyond simple read/write operations, native development becomes not just preferable — it becomes practically necessary. Let's go through the key scenarios: ### OTA Device Firmware Updates (DFU) This is a big one. If your app needs to perform over-the-air device firmware updates (OTA DFU), I'd seriously reconsider using a cross-platform framework. OTA DFU involves streaming firmware files over Bluetooth LE, managing connection stability during a process that can take several minutes, and handling error recovery if something goes wrong mid-transfer. Most chipset vendors (like [Nordic Semiconductor](https://www.nordicsemi.com/?ref=novelbits.io)) provide native iOS and Android SDKs specifically for their DFU process. These SDKs are well-tested, handle edge cases, and are maintained by the vendor. Trying to replicate this in a cross-platform framework is error-prone — and if the DFU fails, you could potentially brick a customer's device. The practical compromise I've seen work well is a **hybrid approach**: use a cross-platform framework for the UI and general app logic, but write native plugins (in Swift and Kotlin) for the Bluetooth LE communication and DFU. You expose a simple API over the framework's bridge — for example, just passing a firmware filename that the native code loads and sends to the device. It works, but at some point you have to ask yourself: if you're writing native Bluetooth LE code anyway, what are you really gaining from the cross-platform layer? ### Persistent Background Connections Both iOS and Android handle background Bluetooth LE differently, and the platform-specific behavior can be difficult to manage through a cross-platform abstraction. iOS is particularly restrictive about what apps can do in the background, and getting background Bluetooth LE to work reliably requires using the native CoreBluetooth APIs correctly. ### High Throughput or Complex Communication If your device and app have a lot of back-and-forth communication, use complex data structures, or stream data (for example, real-time sensor data or log transfers), the overhead of routing everything through a JavaScript or Dart bridge adds latency and reduces reliability. For these use cases, working directly with the native Bluetooth LE APIs gives you much better control over connection parameters, MTU negotiation, and data throughput. ### Platform-Specific Bluetooth LE Features When you're pushing the limits of what Bluetooth LE can do — for example, using features that were introduced in Bluetooth 5.0 or later, or leveraging platform-specific optimizations — you'll often find that third-party libraries simply don't expose those capabilities. The native APIs (CoreBluetooth on iOS, the Android Bluetooth LE API) are always the first to support new features. ## Flutter vs. React Native for Bluetooth LE Development If you've decided that a cross-platform approach makes sense for your use case, the next question is usually: Flutter or React Native? Based on what I've seen from developers in the Bluetooth LE space, **Flutter has a clear edge over React Native for Bluetooth LE development**. Here's why: ### Bluetooth LE Plugin Stability The Flutter Bluetooth LE plugins — specifically [flutter\_blue\_plus](https://github.com/chipweinberger/flutter%5Fblue%5Fplus?ref=novelbits.io) (the actively maintained successor to flutter\_blue) and [flutter\_reactive\_ble](https://github.com/PhilipsHue/flutter%5Freactive%5Fble?ref=novelbits.io) — are generally considered more stable than their React Native counterparts ([react-native-ble-plx](https://github.com/dotintent/react-native-ble-plx?ref=novelbits.io) and [react-native-ble-manager](https://github.com/innoveit/react-native-ble-manager?ref=novelbits.io)). Developers I've spoken with consistently report fewer issues with the Flutter plugins for basic Bluetooth LE operations. Between the two Flutter packages, flutter\_blue\_plus has stronger community adoption and more active maintenance. Both offer similar feature sets, so either is a reasonable choice — but I'd lean toward flutter\_blue\_plus given its larger community. ### Community and Ecosystem Flutter's community support for Bluetooth LE development has been growing steadily, and the quality of documentation and examples is improving. React Native's Bluetooth LE ecosystem, while functional, hasn't kept pace in the same way. ### The Same Caveat Applies Regardless of which framework you choose, the same principle applies: for simple Bluetooth LE interactions, the cross-platform plugins work fine. For complex operations like OTA DFU, you'll still need to drop down to native code. The Flutter teams I've talked to follow exactly this pattern — they use the Flutter plugins for basic Bluetooth LE communication and write native plugins for DFU and other advanced operations. ## Security and Regulatory Considerations Let's talk about something that often gets overlooked in this decision: security. This is especially relevant if you're building apps in regulated industries like **medical devices**. Here's the fundamental concern with cross-platform frameworks from a security perspective: when you're working one abstraction layer above the native code, you have **limited visibility into what's happening underneath**. You're trusting that the third-party Bluetooth LE library handles encryption, key management, and connection security correctly — but you have no easy way to verify this or fix it if it doesn't. For a general consumer app, this might be an acceptable trade-off. But for medical devices, where cybersecurity is a regulatory requirement and patient safety is at stake, it adds a layer of risk that's hard to justify. As one medical device security expert from our developer community put it: > If you are working one additional level from the "real" code, then you have no idea what good or bad practices are being created under the 'covers'. And if they are there, there is nothing you can do to fix it short of creating a bunch of native code wrappers — and by then the question is: why did I use this framework? There are additional practical concerns for regulated industries: - **Vendor support** — If you're building native iOS apps, Apple will actually help you with issues through their paid developer program. There's no equivalent support channel for React Native or Flutter issues on iOS. - **Bug fix timelines** — When a security vulnerability is discovered in the underlying Bluetooth stack (which happens — think Android 12's Bluetooth LE connection issues), native developers can update immediately. Cross-platform developers have to wait for the third-party library maintainers to update, which introduces delays. - **Audit trail** — Regulatory compliance (FDA, IEC 62443, etc.) requires demonstrating control over your software components. An additional cross-platform layer adds complexity to your software bill of materials (SBOM) and makes audits more involved. That said, I should mention that some medical device organizations do use Flutter or React Native for their Bluetooth LE apps. It's not unheard of. But it adds complexity to an already complex and regulated software development process, and the primary driver is usually cost — the belief that maintaining one codebase is cheaper than two. In practice, that cost saving often evaporates once you start writing native wrappers for the critical Bluetooth LE functionality. ## A Practical Decision Framework Let's bring all of this together. Here's a decision framework I recommend when choosing between native and cross-platform for Bluetooth LE apps: | Factor | Cross-Platform OK | Go Native | | --------------------------- | -------------------------------------- | ---------------------------------------- | | **Connection type** | Brief, foreground only | Persistent or background | | **Data throughput** | Low, infrequent reads/writes | Streaming, file transfer, high-frequency | | **OTA DFU needed?** | No | Yes | | **Regulatory requirements** | None or minimal | Medical, industrial, safety-critical | | **Time criticality** | Relaxed timing | Tight connection/transmission windows | | **Team expertise** | JS/Dart only, can't learn Swift/Kotlin | Has or can acquire native skills | | **Primary goal** | Prototype / MVP / proof of concept | Production-quality, long-term product | If most of your answers land in the "Cross-Platform OK" column, a framework like Flutter (with flutter\_blue\_plus) is a reasonable choice. If you have even two or three answers in the "Go Native" column, I'd recommend going native — or at minimum, using the hybrid approach where your Bluetooth LE layer is native and only the UI is cross-platform. ## My Recommendation Here's my honest take: **for anything beyond a simple "quick check" Bluetooth LE app, I recommend going native**. Swift for iOS, Kotlin for Android. Yes, it means maintaining two codebases. Yes, it's more expensive upfront. But in my experience, you end up saving time and headaches in the long run — especially when you need to debug connection issues, implement DFU, handle background Bluetooth LE, or meet security requirements. If your team really can't do native development and cross-platform is the only option, go with Flutter over React Native. The Bluetooth LE plugin ecosystem is more stable, the community support is stronger, and Flutter's rendering engine gives you better UI consistency across platforms. And if you do go the cross-platform route, plan from day one to write native plugins for anything beyond basic Bluetooth LE read/write operations. Don't wait until you're deep into development to discover that the generic plugin can't handle your DFU flow or background reconnection logic. The most important thing is to make this decision with eyes wide open. Understand the trade-offs, be honest about your app's Bluetooth LE requirements, and choose accordingly. ## Summary In this post, we covered the key considerations for choosing between native and cross-platform development for Bluetooth LE mobile apps. Here are the main takeaways: - **The complexity of your Bluetooth LE usage** is the single biggest factor — simple, infrequent connections can work cross-platform; anything more complex warrants native development - **OTA DFU** is a particularly strong argument for native development, since chipset vendor SDKs (like Nordic's) are far more reliable than cross-platform alternatives - **Flutter is the better choice** over React Native if you do go cross-platform, with flutter\_blue\_plus being the recommended Bluetooth LE plugin - **Security and regulatory concerns** favor native development, especially in medical device and other regulated industries - **The hybrid approach** (cross-platform UI + native Bluetooth LE plugins) is a viable middle ground, but adds its own complexity - **Vendor support matters** — Apple supports native iOS developers directly; there's no equivalent for cross-platform frameworks You should now have a much clearer picture of the trade-offs involved and be able to make a more confident decision for your next Bluetooth LE app project. It's not always an easy choice, but understanding these factors upfront will save you from painful surprises down the road. 💡 **Insider Tip:** Want to go deeper into Bluetooth LE mobile development? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### The World's First Programming-Free Bluetooth Beacon Platform URL: https://novelbits.io/inplay-nanobeacon-in100-programming-free-bluetooth-beacon/ Last updated: 2026-08-09T05:25:23.000Z **This article/video is sponsored by InPlay, Inc. However, the opinions expressed by the author are his own and were not influenced by the sponsor.** ## Introduction In some cases, you may want to build a very simple Bluetooth Low Energy device that sends out sensor data like a temperature reading or the state of a particular GPIO input ... or maybe you just want to quickly create a Bluetooth Low Energy device that sends out an ID so you can identify it by a scanner device ... or maybe you just want to build a Bluetooth beacon that simply advertises a chunk of data for testing purposes. Traditionally, in order to accomplish any of the above tasks, you'd have to: - Know how to develop firmware or mobile app development - Understand how Bluetooth Low Energy works - Learn the APIs provided by your selected Bluetooth Low Energy platform/development kit Getting to the level of knowledge and experience required to achieve these skills takes a long time (weeks, months, and sometimes even years!). If you've ever worked on a Bluetooth LE project from scratch, no matter how simple the end product is, then you'll know that there are some frustrating and not-so-trivial obstacles that need to be overcome just to get started with any traditional Bluetooth Low Energy development kit. This is what a company called [InPlay, Inc](https://inplay-tech.com/?ref=novelbits.io). set on a mission to eliminate with their recently released **NanoBeacon™ IN100 platform** \[[Press Release](https://www.prnewswire.com/news-releases/inplay-launches-worlds-smallest-and-software-programming-free-bluetooth-low-energy-soc-301158837.html?ref=novelbits.io)\]. The way they accomplished this is by developing a chipset (the NanoBeacon™ IN100) that requires: 1. **No software programming** 2. **Minimal knowledge** of how Bluetooth Low Energy technology works All this while creating an **ultra-low-power** and **ultra-low-cost** offering that many other vendors have not been able to achieve. We are talking **under $1** for an end-product Bluetooth beacon device (no external peripherals involved)! In today's post and video (below), I'll be covering: - A high-level overview of the NanoBeacon™ IN100 evaluation kit including the different technical specs and features of the IN100 chipset. - An overview of the NanoBeacon™ Config Tool, which is the PC software that is used to configure the device. - A walkthrough of a demo showing how you can use this platform to create a Bluetooth beacon in a matter of minutes (iBeacon, Eddystone, custom format). Before we get into the details of the platform and the tutorial, let's give a short intro and background on the company InPlay Inc. ## Who is InPlay Inc.? ![InPlay Inc. logo](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/inplaylogo.png) InPlay Inc. is a group of semiconductor industry veterans with a proven track record of delivering innovative mixed-signal/RF wireless communication SoCs. InPlay began in 2017 with a focus on enabling extremely fast communication between hosts and many sensors. They accomplish this via an innovative protocol designed into the hardware. It is designed with scalability, low latency, and ultra-low power in mind. As a result, the SwiftRadio ™ product lines (IN600 and IN300) are available in the market today. The NanoBeacon IN100 is a new product line from InPlay available to the market since Q4 of 2021 that aims to enable the next generation of active RFID applications and wireless sensors. NanoBeacon was architected with **ease of use**, **low-cost**, **minimal physical size**, and **long battery life** as the main objectives. ## The NanoBeacon™ IN100 SoC The promise of the IN100 is this: #### To allow any product creator to easily build their own wireless applications without worrying about learning the complex Bluetooth protocol stack and embedded software development. The package is also physically minimal, as small as 2.5mm x 2.5mm. The way it works is by using a companion desktop application called the **NanoBeacon™ Config Tool** to connect to a **programming board** via UART over USB, which is then connected to the **beacon tag**. ![InPlay NanoBeacon Config Tool desktop application](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nanobeacon-config-tool-hero-1.png) The InPlay NanoBeacon™ Config Tool Once connected, the user can configure the tag with their own advertising data and in different formats (up to three distinct formats) and then test out the different configurations. Once the testing phase is complete, the user can then flash the configuration to IN100's One-Time Programming (OTP) memory, disconnect the tag, insert a tiny coin-cell battery (CR1220) and it is ready to go. The tag includes a couple of internal sensor interfaces: a **temperature sensor** and **battery voltage measurement**. The IN100 also supports a few external interfaces including UART, I2C, GPIO, pulse counter, and ADC. Here's what the evaluation kit and programmer board look like: ![NanoBeacon IN100 evaluation kit with programmer board and tag](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-19.png) Evaluation kit: programmer board + IN100 tag Some of the key features of the IN100 chipset are: - Bluetooth 5.3 compliant - iBeacon, Eddystone, and custom advertising data format options - Ultra-low power consumption: - Avg. **1.4uA @ 10s** as advertising interval - Avg. **650nA @ 1min** as advertising interval - Sleep mode **< 650 nA** with 32 kHz RC ON - Enhanced security: - AES-128 based authentication - AES-128 based encryption - Privacy protection: resolvable private address - Anti-Cloning: time-varying advertising payload - 1-wire bus for I/O and space-constrained applications - Built-in ultra-low leakage load switches - Wide operating voltage range (suitable for all types of batteries): **1.1V\~3.6V** The IN100 SoC is available in DFN8 (2.5mmx2.5mm) and QFN20 (3mmx3mm) package configurations. Here are a few images of the evaluation kit (packaging, programming board, and battery-powered tags): ## Hardware and Software Requirements To get started with developing with the platform, you will need the following: - The NanoBeacon™ IN100 Evaluation Kit (includes one programming board and three tags) – can be purchased from DigiKey [here](https://www.digikey.com/en/products/detail/inplay-inc/IN1BN-DKC0-100-C0/15652914?ref=novelbits.io). - A Windows PC, but you could also run it within Windows in a Virtual Machine (e.g. VirtualBox, Parallels, etc.) - The NanoBeacon™ Config Tool application; can be downloaded from [here](https://inplay-tech.com/nanobeacon-config-tool?ref=novelbits.io). - A USB Micro-B to USB A cable (used to connect the programming board to the PC): ![Micro USB Cable USB 2.0 A-Male to Micro B Cable Fast Charging Cord High Speed USB Durable Android Charger Cable (3 Pack, 8.5in) - Walmart.com - Walmart.com](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/75ba39ac-c186-47bf-b8c2-2e8d995b0b99_1-0a00efff174c44bda6011a9ea8117ae8.jpg) - A CR1220 3 Volt battery (to power the tag after programming the OTP and separating it from the programming board): ![Panasonic CR-1220EL - Size: CR1220 - 3V - Lithium Power ✓](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/cr1220_single_battery-3674.jpg) - A Bluetooth Low Energy scanner application (mobile or PC-based). Examples of this include [BLE Hero app](https://apps.apple.com/us/app/ble-hero/id1013013325?ref=novelbits.io) for iOS, Nordic nRF Connect ([iOS](https://apps.apple.com/us/app/nrf-connect-for-mobile/id1054362403?ref=novelbits.io), [Android](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=en%5FUS&gl=US&ref=novelbits.io), [Desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop/download?ref=novelbits.io)). ## Demo and Overview Check out the [YouTube video above](https://youtu.be/m3FmiPxdmQg?ref=novelbits.io) for a full demo showcasing how to configure and test out the IN100 to broadcast: 1. Apple's iBeacon format 2. Google's Eddystone format 3. Your own custom beacon data format ## Summary & Conclusion As we've seen from the tutorial and demo, programming a beacon application using the NanoBeacon IN100 platform is very simple and straightforward and can be done in a matter of minutes, instead of weeks and months as is the case with most other Bluetooth Low Energy development platforms. Be sure to check out the InPlay, Inc. official website for more information on the NanoBeacon™ IN100 and their other products: [**Visit InPlay Inc.'s Official Website**](https://www.inplay-tech.com/?ref=novelbits.io) 💡 **Insider Tip:** Interested in learning more about Bluetooth LE beacons, advertising, and building your own beacon applications? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Introducing the Nordic nRF5340 LE Audio Development Kit URL: https://novelbits.io/nordic-nrf5340-le-audio-development-kit/ Last updated: 2026-08-09T05:43:33.000Z ## Introduction In this post and video, we cover the newest development kit from Nordic Semiconductor: the nRF5340 LE Audio development kit, which was released in May 2022\. You can learn more about the development kit [here](https://www.nordicsemi.com/Products/Development-hardware/nRF5340-Audio-DK?ref=novelbits.io). LE Audio represents the next generation of Bluetooth audio! ![Diagram comparing Bluetooth Classic Audio and Bluetooth LE Audio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/audio-classic-le-1.png) Source: [Bluetooth SIG](https://www.bluetooth.com/learn-about-bluetooth/feature-enhancements/le-audio/?ref=novelbits.io) It requires support for an optional feature that was introduced in [Bluetooth version 5.2 called LE Isochronous Channels (ISOC)](https://novelbits.io/bluetooth-version-5-2-le-audio/). Some of the most prominent use cases include: - Broadcast & audio sharing – location-based or personal - Location-based: broadcasts available in certain locations such as Public Announcement (PA) systems in airports - Personal-based: broadcasts set up by individuals for sharing audio with friends and family for example - Standardization of Bluetooth audio for hearing aids and migrating from using the dated telecoil systems - Multi-stream audio: support for multiple independent and synchronized audio streams to one or more devices It also offers a much more flexible foundation and framework for developing audio applications and achieves lower power consumption, which is a really big deal especially for reducing the physical size of devices or for increased battery life. ## Applications Examples of applications: - PA Announcements airports - Movie theaters - Conferences and venues - multi-language streams and allowing hearing-impaired attendees to listen directly to the audio source through their LE Audio compatible hearing aid - Museums - TV screens in gyms and public areas - True Wireless Stereo (independent streams sent to independent earbuds). Even though it exists today in some products, LE Audio will standardize it and allow you to use devices from different manufacturers thanks to interoperability. Along with the new LE Audio specs and profiles, a new more efficient [audio codec named LC3](https://www.bluetooth.com/blog/a-technical-overview-of-lc3/?ref=novelbits.io) was introduced. It achieves higher quality audio at the same data rate or even slightly higher quality at lower data rates than SBC and is mandatory for all LE Audio devices. ## Mode of Operation LE Audio operates in two modes: - **Connected Isochronous Stream (CIS)** - Require a connection between the devices - A limited number of connected devices - Provides higher reliability - More efficient utilization of the spectrum (retransmissions only occur based on feedback from the receivers) - Support for bidirectional audio streams (earbud + mic) - **Broadcast Isochronous Streams** - An unlimited number of receivers can tune into the broadcast streams - Inefficient use of the spectrum since the broadcaster may decide to include retransmissions even if the receiver is able to receive all the audio packets (due to the fact that no feedback from the receiver to the transmitter) - Can be either open or secured LE Audio is still in the very early stages, so you can expect that devices will continue to support Classic Audio and over time will transition to using LE Audio instead. ## Nordic nRF5340 LE Audio Development Kit Be sure to watch the video above to learn more about the newly released nRF5340 LE Audio development kit and a demo of both Broadcast Isochronous Streams (BIS) and Connected Isochronous Streams (CIS). 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Implementing Nordic nRF52 OTA DFU over Bluetooth LE - Part 4 URL: https://novelbits.io/nrf52-ota-dfu-ble-part-4/ Last updated: 2026-04-08T17:51:21.000Z ⚠️ **Note:** This tutorial uses the Nordic nRF5 SDK, which has been superseded by the nRF Connect SDK (based on Zephyr RTOS). The concepts covered here are still applicable to Bluetooth LE development, but the code examples may not compile with current toolchains. For up-to-date implementation guidance, check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io). In a few previous posts ([Part 1](https://novelbits.io/ota-device-firmware-update-part-1/), [Part 2](https://novelbits.io/ota-device-firmware-update-part-2/), and [Part 3](https://novelbits.io/ota-device-firmware-update-part-3/)), we covered the basics of designing a secure Over-the-Air Device Firmware Update (OTA DFU) process, an overview of the Nordic nRF52 OTA DFU process, as well as testing out one of the DFU examples included in the nRF5 SDK. In this tutorial, we will be going over the complete steps of how to integrate the **Nordic Buttonless DFU** into our own application to enable OTA DFU functionality and be able to update the device in the field over Bluetooth Low Energy. ## Prerequisites: There are a few required hardware and software elements for our tutorial: ### Hardware Requirements - **A development PC** (Windows, macOS, or Linux) – for building the bootloader and application, and generating cryptographic keys. - **One nRF52-based development kit** – used as the DFU target (**Note:** we’ll be using an nRF52840 DK as our target device). - **A mobile phone** (iOS or Android) – used as the DFU controller (alternatively, you could use a second nRF52 DK along with your development PC and use the Bluetooth Low Energy app within nRF Connect for Desktop) ### Software Requirements - [**nRF5 SDK (version 17.1.0)**](https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download?ref=novelbits.io#infotabs) – download and unzip the SDK to a folder of your choice. - [**Segger Embedded Studio**](https://www.segger.com/downloads/embedded-studio?ref=novelbits.io) – download and install to your PC. - [**nRF Command Line Tools (nrfjprog)**](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download?ref=novelbits.io) – download and install to your PC. - [**nrfutil (Python dependent)**](https://infocenter.nordicsemi.com/topic/ug%5Fnrfutil/UG/nrfutil/nrfutil%5Finstalling.html?ref=novelbits.io) – needed for generating the cryptography keys and the DFU packages. - If you are using a DK other than the nRF52840, then you may need to [install micro-ecc](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv17.1.0/lib%5Fcrypto%5Fbackend%5Fmicro%5Fecc.html?ref=novelbits.io#lib%5Fcrypto%5Fbackend%5Fmicro%5Fecc%5Finstall). On nRF52840, you can use the CC310 crypto engine which is hardware supported by this DK. - **nRF Connect for Mobile** ([iOS](https://apps.apple.com/us/app/nrf-connect/id1054362403?ref=novelbits.io), or [Android](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=en%5FUS&ref=novelbits.io)) or [**nRF Connect for Desktop**](https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-desktop/Download?ref=novelbits.io#infotabs) if you’re using a PC as the DFU controller. You may also use nrfutil connected via a second nRF52 DK to act as the DFU controller to the target device (refer to [the documentation here](https://infocenter.nordicsemi.com/topic/ug%5Fnrfutil/UG/nrfutil/nrfutil%5Fdfu%5Fble.html?ref=novelbits.io)). Once you have all these requirements satisfied, you can follow along with the steps laid out next. ## 1\. Adding the Buttonless DFU service and functionality to an nRF52 example Our first step is to add the Buttonless DFU service to our application. We'll be using the `ble_app_blinky` example within the nRF5 SDK (v 17.1.0). We'll be using the *Unbonded* version of the *Buttonless DFU* implementation. The Nordic [**Buttonless DFU**](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv17.1.0/service%5Fdfu.html?ref=novelbits.io) functionality allows the device to expose the DFU GATT Service alongside your application’s GATT Services and be able to go into DFU mode from within the Application running on your device, instead of requiring bootup into DFU mode (via physical button presses). In Segger Embedded Studio, open the example's SES Project Solution located at `/examples/ble_peripheral/ble_app_blinky/pca11056/s140/ses/ble_app_blinky_pca10056_s140.emProject`. You can also make a copy of the example before making any changes if you want to preserve the original example. Then make sure that you can build it successfully. **Note**: If you are using a newer version of Segger Embedded Studio (I believe > V6.0), you may encounter the following error when building the solution: "*`__vfprintf.h`: No such file or directory*". To fix this, simply remove the file `SEGGER_RTT_Syscalls_SES.c` (under the nRF\_Segger\_RTT folder) from the Project and rebuild. ![ble_app_blinky successful build in Segger Embedded Studio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-01-at-2-23-10-am.png) ble\_app\_blinky successful build We'll first need to add a few files to the project. We can create a new folder within the project to host these files: - `/components/ble/ble_services/ble_dfu/ble_dfu_bonded.c` - `/components/ble/ble_services/ble_dfu/ble_dfu_unbonded.c` - `/components/ble/ble_services/ble_dfu/ble_dfu.c` - `/components/libraries/bootloader/dfu/nrf_dfu_svci.c` ![nRF_BLE_DFU files added to Segger Embedded Studio project](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-01-at-2-29-35-am.png) nRF\_BLE\_DFU files Then we'll have to add a few DFU preprocessor definitions. To do this, right-click on the Project in the Project Explorer window → Click Options → Choose the "Common" configuration → click on "Preprocessor" → "Preprocessor Definitions" and add the following: - `BL_SETTINGS_ACCESS_ONLY` (limits access to the Bootloader settings to access-only since we'll be generating the Bootloader settings and writing them along with the Bootloader, SoftDevice, and Application). - `NRF_DFU_TRANSPORT_BLE = 1` ![DFU Preprocessor definitions in Segger Embedded Studio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-07-at-8-47-35-pm.png) DFU Preprocessor definitions Next we'll add a few include folders that host the header files needed for DFU: - `/components/libraries/bootloader` - `/components/libraries/bootloader/dfu` - `/components/libraries/bootloader/ble_dfu` ![Include folders for DFU header files in Segger Embedded Studio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-07-at-8-57-20-pm.png) Before we move on, let's make sure the application builds successfully: ![Successful build after adding DFU files](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-01-at-2-38-33-am.png) Successful build Next, we'll be modifying/enabling some of the definitions in `sdk_config.h`: - `#define BLE_DFU_ENABLED 1` - `#define NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY 1` - `#define NRF_SDH_BLE_SERVICE_CHANGED 1` Then we'll be adding/modifying some code in `main.c`: Add `#includes` for the following: ```c // DFU-related #includes #include "nrf_power.h" #include "nrf_dfu_ble_svci_bond_sharing.h" #include "nrf_svci_async_function.h" #include "nrf_svci_async_handler.h" #include "ble_dfu.h" #include "nrf_bootloader_info.h" ``` Add the following three functions (taken from the DFU Buttonless example `ble_app_buttonless_dfu` within the nRF5 SDK): `app_shutdown_handler()` ```c /**@brief Handler for shutdown preparation. * * @details During shutdown procedures, this function will be called at a 1 second interval * untill the function returns true. When the function returns true, it means that the * app is ready to reset to DFU mode. * * @param[in] event Power manager event. * * @retval True if shutdown is allowed by this power manager handler, otherwise false. */ static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event) { switch (event) { case NRF_PWR_MGMT_EVT_PREPARE_DFU: NRF_LOG_INFO("Power management wants to reset to DFU mode."); // YOUR_JOB: Get ready to reset into DFU mode // // If you aren't finished with any ongoing tasks, return "false" to // signal to the system that reset is impossible at this stage. // // Here is an example using a variable to delay resetting the device. // // if (!m_ready_for_reset) // { // return false; // } // else //{ // // // Device ready to enter // uint32_t err_code; // err_code = sd_softdevice_disable(); // APP_ERROR_CHECK(err_code); // err_code = app_timer_stop_all(); // APP_ERROR_CHECK(err_code); // } break; default: // YOUR_JOB: Implement any of the other events available from the power management module: // -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF // -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP // -NRF_PWR_MGMT_EVT_PREPARE_RESET return true; } NRF_LOG_INFO("Power management allowed to reset to DFU mode."); return true; } ``` `buttonless_dfu_sdh_state_observer()` ```c /**@brief Register application shutdown handler with priority 0. */ NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0); static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void * p_context) { if (state == NRF_SDH_EVT_STATE_DISABLED) { // Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot. nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC); //Go to system off. nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF); } } ``` `ble_dfu_buttonless_evt_handler()` ```c /* nrf_sdh state observer. */ NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) = { .handler = buttonless_dfu_sdh_state_observer, }; static void ble_dfu_buttonless_evt_handler(ble_dfu_buttonless_evt_type_t event) { ret_code_t err_code; switch (event) { case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE: NRF_LOG_INFO("Device is preparing to enter bootloader mode\r\n"); break; case BLE_DFU_EVT_BOOTLOADER_ENTER: NRF_LOG_INFO("Device will enter bootloader mode\r\n"); break; case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED: NRF_LOG_ERROR("Device failed to enter bootloader mode\r\n"); break; default: NRF_LOG_INFO("Unknown event from ble_dfu.\r\n"); break; } } ``` Add the following highlighted lines to `services_init()`: ```c /**@brief Function for initializing services that will be used by the application. */ static void services_init(void) { ret_code_t err_code; ble_lbs_init_t init = { 0 }; nrf_ble_qwr_init_t qwr_init = { 0 }; // Initialize Queued Write Module. qwr_init.error_handler = nrf_qwr_error_handler; err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); APP_ERROR_CHECK(err_code); // Initialize LBS. init.led_write_handler = led_write_handler; err_code = ble_lbs_init(&m_lbs, &init); APP_ERROR_CHECK(err_code); // Initialize the DFU service ble_dfu_buttonless_init_t dfus_init = { .evt_handler = ble_dfu_buttonless_evt_handler }; err_code = ble_dfu_buttonless_init(&dfus_init); APP_ERROR_CHECK(err_code); } ``` Add the following highlighted lines to `main()`: ```c /**@brief Function for application main entry. */ int main(void) { ret_code_t err_code; // Initialize. log_init(); // Initialize the async SVCI interface to bootloader before any interrupts are enabled. err_code = ble_dfu_buttonless_async_svci_init(); APP_ERROR_CHECK(err_code); leds_init(); timers_init(); buttons_init(); power_management_init(); ble_stack_init(); gap_params_init(); gatt_init(); services_init(); advertising_init(); conn_params_init(); // Start execution. NRF_LOG_INFO("Blinky example started."); advertising_start(); // Enter main loop. for (;;) { idle_state_handle(); } } ``` ## 2\. Generating the private-public key pair used for signing the firmware image For this type of modified application in which we combined the DFU service, we can't simply program the application and softdevice from SES and call it a day! Instead, we have to create a special firmware hex image file and then flash it to the DK. Let's first create a folder to host all the contents and files needed for our DFU process. We'll call it `dfu_images`. To create a private-public key pair to be used for signing/validating the firmware image, we run the following command in the dfu folder we initially created: ```bash nrfutil keys generate private.key ``` This will generate the key pair. **Note:** It's important to make sure the `private.key` file is secured and kept in a safe location not accessible by any unauthorized third parties. `nrfutil` also provides a handy command to generate the public key source file that we can copy/paste into the bootloader project before building the bootloader. The command is as follows: ```bash nrfutil keys display --key pk --format code private.key --out_file public_key.c ``` Once completed, we can view the contents of `public_key.c`: ![Contents of generated public_key.c file](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-02-at-12-15-51-am.png) public\_key.c Now we are ready to integrate this into the bootloader and build it. Open the SES Project for the bootloader located at `/examples/dfu/secure_bootloader/pca10056_s140_ble/ses/secure_bootloader_ble_s140_pca10056.emProject`. ![Secure Bluetooth LE bootloader SES project with modified public key](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-02-at-12-22-33-am.png) Secure BLE bootloader SES project with a modified public key In the project, open the file `dfu_public_key.c` and replace its contents with the contents of the file we generated above, `public_key.c`. Now, build the bootloader solution and copy the file located at `/examples/dfu/secure_bootloader/pca10056_s140_ble/ses/Output/Release/Exe/secure_bootloader_ble_s140_pca10056.hex` to the dfu folder we created. Ok, that's it in terms of source code modifications! ## 3\. Creating the firmware image for the application Now, let's go through the steps needed to create our firmware hex image file: 1\. Copy the build output hex file from the modified ble\_app\_blinky application to the above-created folder. The file should be located at `/examples/ble_peripheral/ble_app_blinky/pca10056/s140/ses/Output//Exe/ble_app_blinky_pca10056_s140.hex` 2\. Run the following command to generate a DFU Settings Page based on our application hex file ```bash nrfutil settings generate --family NRF52840 --application ble_app_blinky_pca10056_s140.hex --application-version 1 --bootloader-version 1 --bl-settings-version 2 bl_settings.hex ``` The output should look something like this: ``` Note: Generating a DFU settings page with backup page included. This is only required for bootloaders from nRF5 SDK 15.1 and newer. If you want to skip backup page generation, use --no-backup option. Generated Bootloader DFU settings .hex file and stored it in: bl_settings.hex Bootloader DFU Settings: * File: bl_settings.hex * Family: NRF52840 * Start Address: 0x000FF000 * CRC: 0xDA1BB4E9 * Settings Version: 0x00000002 (2) * App Version: 0x00000001 (1) * Bootloader Version: 0x00000001 (1) * Bank Layout: 0x00000000 * Current Bank: 0x00000000 * Application Size: 0x0000DFC8 (57288 bytes) * Application CRC: 0x342C1D00 * Bank0 Bank Code: 0x00000001 * Softdevice Size: 0x00000000 (0 bytes) * Boot Validation CRC: 0x8C7C8FF7 * SD Boot Validation Type: 0x00000000 (0) * App Boot Validation Type: 0x00000001 (1) ``` Now, let's merge the Bootloader Settings, the Bootloader itself, the Softdevice, and the application. The Softdevice is located at `/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex` (your Softdevice version may differ). The command to run for merging is: ```bash mergehex --merge bl_settings.hex secure_bootloader_ble_s140_pca10056.hex s140_nrf52_7.2.0_softdevice.hex ble_app_blinky_pca10056_s140.hex --output bl_sd_settings_app.hex ``` The output will look something like this: ``` Parsing input files. Merging file "bl_settings.hex" into output. Merging file "secure_bootloader_ble_s140_pca10056.hex" into output. Merging file "s140_nrf52_7.2.0_softdevice.hex" into output. Merging file "ble_app_blinky_pca10056_s140.hex" into output. Storing merged file. ``` ## 4\. Flashing the custom hex image to the development kit The next and final step to run our application on the DK is to flash it. Run the following commands from the DFU folder that you created in Step 1. ```bash nrfjprog --recover nrfjprog -f nrf52 --program bl_sd_settings_app.hex --verify nrfjprog --reset ``` Here's the output from running the commands on my end: ![Terminal output from flashing hex firmware image with nrfjprog](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-01-at-3-46-08-am.png) Flashing hex firmware image Let's double-check that the application is running fine by connecting to the serial port. In my case, I'm using an app called **Serial** on macOS (other alternatives include PuTTY, minicom, etc.). ![Serial output showing DFU-enabled ble_app_blinky running](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-01-at-3-49-20-am.png) The serial output of DFU-enabled ble\_app\_blinky Now, if we run nRF Connect on mobile, you should see that the device is advertising with the name "**Nordic\_Blinky**", and when you connect to it, you'll see that the "Secure DFU Service" and its characteristic "**Buttonless DFU Without Bonds**" are both present in the GATT server. ![nRF Connect showing custom Blinky app with Buttonless DFU Service](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/nrf52-ota-dfu-nrf-connect-high.gif) Custom HRS+DFU app: advertising, connecting, Buttonless DFU Service ## 5\. Building the DFU package When upgrading the firmware on the device remotely (over BLE and using the bootloader), we need to provide a **DFU package** that's built specifically for this operation. To generate the DFU package we need to use the `nrfutil` tool from Nordic (which we included as a software requirement at the beginning of the tutorial). To ensure that the DFU package is secure, we will be creating a *signed DFU package*. Before we do this, let's make one change to our application so we can verify that the update actually installed the new firmware. Open the application solution again in SES (`/examples/ble_peripheral/ble_app_blinky/pca11056/s140/ses/ble_app_blinky_pca10056_s140.emProject`) and make the following change to the code (highlighted): ```c int main(void) { ret_code_t err_code; // Initialize. log_init(); // Initialize the async SVCI interface to bootloader before any interrupts are enabled. err_code = ble_dfu_buttonless_async_svci_init(); APP_ERROR_CHECK(err_code); leds_init(); timers_init(); buttons_init(); power_management_init(); ble_stack_init(); gap_params_init(); gatt_init(); services_init(); advertising_init(); conn_params_init(); // Start execution. NRF_LOG_INFO("Blinky example started. NEW VERSION!"); advertising_start(); // Enter main loop. for (;;) { idle_state_handle(); } } ``` Now, after the update we can monitor the serial output of the application and see that "**Blinky example started. NEW VERSION!**" is printed. Build the application and copy the hex file (`/examples/ble_peripheral/ble_app_blinky/pca10056/s140/ses/Output//Exe/ble_app_blinky_pca10056_s140.hex`) to the dfu folder we created. Now, we're ready to build our DFU package including this modified application. **Note**: in this example, I am including only the application hex file in the DFU package, but you can include a number of combinations. This is described in [more detail here](https://infocenter.nordicsemi.com/topic/ug%5Fnrfutil/UG/nrfutil/dfu%5Fpackage%5Fcombinations.html?ref=novelbits.io). Here's the command you will use to generate the signed DFU package (from within the dfu folder you created): ```bash nrfutil pkg generate --hw-version 52 --application-version 2 --application ble_app_blinky_pca10056_s140.hex --sd-req 0x0100 --sd-id 0x0100 --key-file private.key blinky_application_s140.zip ``` Let's analyze the different arguments passed into the command: - **`--hw-version 52`**: this specifies that the package is built for the nRF52 family - `**--application-version 2**`: if you look at the command we ran to create the Bootloader Settings page, you'll notice we supplied it with `--application-version 1`. By supplying the DFU package generation command with **version 2** we are relaying to the bootloader that the application is a newer version than the existing application on the device, which in turn triggers the bootloader to allow the update. For more information on version validation (for hardware, softdevice, bootloader, and application), refer to [the following documentation page](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv17.1.0/lib%5Fbootloader%5Fdfu%5Fvalidation.html?ref=novelbits.io). - **`--application ble_app_blinky_pca10056_s140.hex`**: this provides the complete firmware image hex file to use for generating the DFU package. - **`--sd-req 0x0100`**: this specifies the firmware IDs of the SoftDevices that are allowed to be updated from within the DFU package. Refer to the next argument described below to see how to determine the SoftDevice's firmware ID. Here were are telling the bootloader to only accept the same SoftDevice firmware ID. You can provide a comma-separated list instead if you want to allow multiple firmware IDs. - **`--sd-id 0x0100`**: this corresponds to the firmware ID of the SoftDevice present on the target device. In the case of SoftDevice version 7.2.0 (which is what we used in our tutorial), the id is 0x0100\. You can find the id that corresponds to the SoftDevice you are using by referring to the release notes for the specific SoftDevice version you're using in the [SoftDevice package downloadable available here](https://www.nordicsemi.com/Products/Development-software/S140/Download?ref=novelbits.io). - **`--key-file private.key`**: this supplies the private key used for signing the firmware image. This gets validated in the device's bootloader using the public key that we compile/hard-code in the DFU bootloader image. Finally, we are ready to use this DFU package (zip file) to upgrade the firmware on the target device. I'll be using nRF Connect on iOS for this: Open nRF Connect on iOS, then scan for the device and connect to it: ![nRF Connect iOS connected to custom Blinky+DFU app](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_2513.png) Connected to custom Blinky+DFU app Then click on the **DFU** tab: ![DFU tab in nRF Connect iOS app](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_2514.png) DFU tab Finally, click on "**Open Document Picker**" to select the DFU package\[zip\] file we created. You have to first transfer this file from your PC to the phone (on iOS, you can choose this file from a variety of sources including iCloud Drive, any other connected cloud drives such as OneDrive, or from a local folder on the phone). Once you've located the file, click on it and you'll be presented with the following view: ![DFU package file selected in nRF Connect iOS](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_2516.png) DFU package file selected in nRF Connect (iOS) You'll notice that nRF Connect analyzed our DFU package and that it lists the contents of it, in our case just the application. Ok, now we are ready to start the DFU process by clicking the **Start** button: ![DFU firmware update process running on nRF Connect iOS](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/dfu-process-nrf-connect-ios-high.gif) DFU process on nRF Connect iOS Head over to the serial port terminal connected to the device and you'll notice that our application now prints out the message: "**Blinky example started. NEW VERSION!**" Woohoo! Firmware update successful!! 🎉🎉🎉 ![Serial output showing new firmware version after successful DFU update](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-05-02-at-1-00-15-am.png) The new firmware image was upgraded successfully! 💡**Insider Tip:** Want to learn more about Bluetooth LE firmware updates, bootloaders, and secure OTA DFU? Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) for comprehensive, hands-on courses! ## Summary We covered a lot in this tutorial! But I hope you found it helpful. We outlined all the necessary steps to: - Integrate Buttonless DFU into our own application - Generate a public-private key pair for a secure DFU process - Integrate the generated public key into the bootloader - Create a Bootloader + SoftDevice + application image file \[hex\] - Flash the image to the development kit - Verify that our custom application is behaving correctly (advertising, accepting connections, and that the GATT server includes both the original application Services and Characteristics in addition to the DFU service) - Generate a signed DFU package that includes a new version of the application (with a modified print-out message) - Utilize nRF Connect for mobile to connect to our device and perform the DFU process using the DFU package that we created ### Maximum Data Size in a Bluetooth Advertising Packet URL: https://novelbits.io/maximum-data-bluetooth-advertising-packet-ble/ Last updated: 2026-04-08T17:51:16.000Z In a couple of previous posts ([here](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/) and [here](https://novelbits.io/bluetooth-low-energy-advertisements-part-2/)), we covered the basics of Bluetooth Low Energy (Bluetooth LE) advertising and advertisement packets. In this post, we'll go into more depth on Bluetooth advertisements and specifically the **advertising packet payload and the maximum amount of data** you can send out in the payload. Bluetooth beacons are the most prominent devices that take full advantage of Bluetooth advertising packets. This is due to the reason that most beacons stay in the advertising state throughout their lifetime (do not allow connections), so they rely completely on advertising for relaying the relevant information to the scanning devices. **TLDR: want to skip right to the answer to the question: "How many bytes can I send in a Bluetooth advertising packet?"** **[Click Here!](#answer)** ## Bluetooth Advertising Packet Format To fully understand how much data we can advertise as Bluetooth LE application developers, we need to understand the format of the advertising packet format, but before we dive into the advertising packet format, let's cover an important feature of Bluetooth Low Energy: the different PHY options available. ### The Three PHYs In Bluetooth Low Energy (Bluetooth LE), we have two main packet formats (which apply to both advertising and data packets – which are exchanged during a connection). They are the **Coded** **PHY** packet format and the **Uncoded PHY**s packet format. The **Uncoded PHY** includes the original LE 1M PHY (which is the default PHY that has existed since the first version of Bluetooth LE in version 4.0 of the Bluetooth specification) and the optional LE 2M PHY (which was introduced in version 5.0 of the Bluetooth specification providing the option to double the data throughput rate). The **LE Coded PHY** was introduced in version 5.0 of the Bluetooth specification. It is intended to be used for: - Long-range applications (achieving up to 1+ kilometer line-of-sight) - or for achieving more robust communication through obstacles, walls, and noisy RF environments The **LE 1M PHY** utilizes a 1 megasymbol/second modulation scheme where each symbol represents 1 bit. The resulting raw transmission rate, in this case, is 1 Mbps. The **LE 2M PHY** utilizes a 2 megasymbol/second modulation scheme where also each symbol represents 1 bit. The resulting raw transmission rate, in this case, is 2 Mbps. The **LE Coded PHY** utilizes a 1 megasymbol/second modulation scheme but differs from the other two PHYs in that it utilizes either: **2 symbols per bit** (S=2), or **8 symbols per bit** (S=8). This "redundancy" is utilized by an algorithm that can allow the receiver to recover data in the case of corruption in the received packets. The resulting raw transmission rate, in this case, is 500 Kbps (in the case of S=2) and 125 Kbps (in the case of S=8). In this post, we will focus on the Uncoded PHY packets since they are the most common. For more detailed information on the LE Coded PHY, see my [previous post on the subject](https://novelbits.io/bluetooth-long-range-coded-phy/). ### Advertising PDU Types For Uncoded PHY packets, there are two main types of advertising PDUs (Protocol Data Unit) that can be utilized: **Legacy Advertising PDU**s and **Extended Advertising PDU**s. Before we dive into the different types of legacy and extended advertising PDUs, it's important to note that they share the same packet format: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-20.png) Uncoded PHY Packet Format (applies to both advertising and data packets) The PDU portion is the field that contains the payload which you can utilize for sending out data in the advertising packet. #### Legacy Advertising Packets The **legacy advertising** PDUs are: - **ADV\_IND**: This is used for connectable and scannable undirected advertising events. So when advertising this type, the advertiser is telling the scanner that they can connect to the device, they can also send a scan request which will trigger a scan response from the advertiser, and it is "undirected", meaning any scanner will be able to receive this advertising. This is probably the most commonly used advertising PDU (especially for connectable devices). **It allows for up to 31 bytes of advertising data in the main packet payload.** **It also allows an additional 31 bytes of advertising data in the scan response packet payload.** - **ADV\_DIRECT\_IND**: This is used for directing advertising to a specific target scanner. It is less common. **It does not allow any advertising data in the packet payload.** - **ADV\_NONCONN\_IND**: This is used for nonconnectable and nonscannable advertising events. When using this type, the advertiser is telling the scanner that it is nonconnectable and nonscannable (does not respond to scan requests). **It allows for up to 31 bytes of advertising data in the packet payload.** - **ADV\_SCAN\_IND**: This is used for nonconnectable but scannable advertising events. When using this type, the advertiser responds to scan requests, but it does not allow connections from scanner devices. **It allows for up to 31 bytes of advertising data in the packet payload.** **It also allows an additional 31 bytes of advertising data in the scan response packet payload.** Here's a look at what a legacy advertising PDU format looks like: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-10.png) Generic Packet Format ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-2-9.png) Legacy Advertising PDU Payload Format The legacy advertising PDUs are sent **only** on the primary advertising channels (37, 38, and 39). This means they are supported by all Bluetooth Low Energy scanners. You can refer to my [previous post on Bluetooth Advertisements](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/) to learn more about the different types of advertising channels. #### Extended Advertising Packets The extended advertising PDUs are: - **ADV\_EXT\_IND**: This type of PDU is the only extended advertising PDU that is sent on the primary advertising channels (37, 38, and 39). **They do not contain any advertising data in their payload** and they act as a simple relayer of information to the scanner on where to find the advertising packets that are sent on the secondary advertising channels (0-36). Depending on the information contained within the header portion of the PDU, there are different even types (similar to those described in the legacy advertising types) such as connectable vs. nonconnectable, scannable vs. nonscannable, directed vs. undirected, etc. - **AUX\_ADV\_IND**: This behaves as the primary type that you would use for sending out advertising data (specifically on the secondary advertising channels). For the scanner to be able to locate and receive this packet, it will have to first discover and receive the ADV\_EXT\_IND packet that points to this one. Depending on the type of event (defined in the header in both the ADV\_EXT\_IND packet and this one), you will be able to include advertising data in this packet. **This type allows up to 254 bytes of advertising data in the packet payload.** - **AUX\_SYNC\_IND**: This type is used for implementing a feature called *Periodic Advertising*,** which allows a scanner to (eventually) sync to a chain of advertising packets (sent on the secondary advertising channels) that are sent out on a regular and deterministic point in time. This type is used to relay to the scanner the information needed to locate the periodic advertising packets that actually contain the data (these are the AUX\_CHAIN\_IND packets described in the next bullet point). Examples of applications that utilize this are for continuously sending out sensor data that potentially changes periodically to multiple scanners. It is also one of the main features utilized in the recent LE Audio standard. **It allows up to 254 bytes of advertising data in the packet payload.** - **AUX\_CHAIN\_IND**: This type contains the Periodic Advertising data that the ADV\_EXT\_IND -> AUX\_ADV\_IND -> AUX\_SYNC\_IND point to. **It allows up to 254 bytes of advertising data in the packet payload.** Here's a look at what an extended advertising PDU format looks like: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-3-8.png) Extended Advertising PDU Payload Format Notice that extended advertising packets utilize just two PDU types (ADV\_EXT\_IND + AUX\_ADV\_IND) to support the many types of advertising events by utilizing a field included in the PDU header. **Note that extended advertising is an optional feature (introduced in Bluetooth 5.0). So, they are not necessarily supported by any Bluetooth Low Energy scanner, even if it is listed to support Bluetooth 5.0\. In fact, as of the writing of this post, most Bluetooth LE-enabled smartphones do not support them.** ## Advertising Packet Payload Format Whether you are using legacy or extended advertising packets, the format of the payload is the same. It is structured in the following manner: | LTV #1 | | LTV #2 | | | | LTV #n | | | | | | | | ------ | ---- | ------ | | ------ | ---- | ------ | | --- | | ------ | ---- | ----- | | Length | Type | Value | | Length | Type | Value | | ··· | | Length | Type | Value | Advertising Data Format LTV stands for "Length-Type-Value". You can have as many of these as can fit within an advertising packet payload. The Length and Type fields are mandatory and each takes up **one byte**. - **Length:** This defines the length of the Type + Value fields. - **Type:** The different types are defined in the Core Specification Supplement document which you can [download here](https://www.bluetooth.com/specifications/specs/?ref=novelbits.io). Examples include Device Name, Service UUID, Tx Power Level, etc. - **Value:** This includes the actual data that is meaningful to the scanner. For example, it can be the actual device name, the sensor reading, etc. ## The Maximum Length of Data you can Include in a Bluetooth LE Advertising Packet So, we can already see that if we want to follow the Bluetooth specification, we will be losing two bytes to Length + Type. This leaves us with either **31 - 2 = 29 bytes** (in the case of legacy advertising packets) or **254 - 2 = 252 bytes** (in the case of extended advertising packets). If you are looking to maximize the amount of payload that you want to include in the advertising packet then you can: - Use the Manufacturer Specific Data type, which is the only type that allows you to send custom data (for generic use) per the Bluetooth specification. Unfortunately, this requires the use of an additional piece of data called **Company ID** which takes up an additional 2 bytes (you can find [all assigned Company IDs here](https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/?ref=novelbits.io)). Using this will allow any generic Bluetooth LE scanner to discover and parse the data. - Use the remaining 29 or 252 bytes as raw data, but rely on a custom Bluetooth LE scanner (that maybe you build) to discover and parse this *non-standard* data. - You can use a "**scannable**" advertising PDU to potentially double the amount of advertising data that you send out. - Utilize a data compression algorithm to compress the data you include in the advertising packet, and decompress it on the scanner side. **So, in summary, here's the answer to this very common question:** - If you are using l**egacy advertising** packets, you can include up to **27 bytes of actual data** (using the Manufacturer Specific Data type) or **29 bytes of actual data** (using a custom non-standard advertising data type). - If you are using the **extended advertising** packets, you can include up to **250 bytes of actual data** (using the Manufacturer Specific Data type) or **252 bytes of actual data** (using a custom non-standard advertising data type). But again, consider utilizing scan responses and/or data compression to increase the size of user data that you want to include in the advertising data packets. **Note: keep in mind that some Bluetooth LE scanners will require you to include other advertising data types (such as Flags) in your advertising data, so this will impact the total amount of user data that you can truly advertise.** I hope you found this post useful and that it provided the information needed to really understand the background behind the answer to this common question about Bluetooth LE advertising data capacity. 💡 **Want to learn more?** Check out the [Bluetooth Developer Academy](https://academy.novelbits.io/?ref=novelbits.io) for comprehensive courses on Bluetooth Low Energy development, including detailed guides on advertising, connections, and more! ### Bluetooth vs. Bluetooth Low Energy: What's the Difference? URL: https://novelbits.io/bluetooth-low-energy-vs-bluetooth-classic-br-edr/ Last updated: 2026-08-09T05:24:11.000Z ## First, a Short Story... Before I dive into the meat of the topic (Bluetooth Low Energy vs. Bluetooth Classic), I'd like to tell you a little story... A few years ago (circa 2012), a friend of mine came to me with an idea that he wanted to partner with me on developing. At that time, the "Internet of Things (IoT)" term was just picking up and becoming a hot topic. Venture Capitalists (VCs) were dumping loads of money into any startup that threw around the term "IoT" in their offering (*kind of like how it is these days with AI, ML, and VR...*), so this was very tempting to me! Anyways, the idea was to create a simple bracelet/watch-like product, not a smartwatch, not a bracelet, but something in between. Now, I was the go-to person for him (and many of my other friends) for tech-related questions and advice, so I was motivated to prove myself and my capabilities. All he was pitching was a "smart/connected bracelet" that would simply nudge you when you receive a text message or a phone call on your phone. ### Which Wireless Technology to Choose Now, at that time, I was an embedded software engineer with 7 years of experience, so I had the background and knowledge to at least do the right research into how this idea can be turned into reality... The first most important aspect that needed research was the answer to the following question: **"What technology or wireless protocol we would have to use to connect the bracelet to the phone?"** I knew smartphones pretty well, so I knew it would have to be either **WiFi** or **Bluetooth**. WiFi is great, but it just didn't make sense since the "smart bracelet" is more of a personal product that you would probably wear while traveling and in places where you don't necessarily have access to a WiFi network. So, logically, it only made sense to determine that **Bluetooth** was the technology to use. ## Getting to know Bluetooth technology The first thing I did was go to the Bluetooth SIG website: www.bluetooth.com (for kicks, here's what the Bluetooth SIG website looked like back then in 2012, courtesy of [Webarchive](http://web.archive.org/web/20121002023544/http://www.bluetooth.com/Pages/Bluetooth-Home.aspx)! 😯): ![Bluetooth.com website back in 2012](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2022-04-17-at-4-05-28-am.png) Bluetooth.com back in 2012 The website was pretty dated even for that time (looked like a 90s website). Unfortunately, the technical information was also pretty scarce, especially in terms of beginner-level content and tutorials. Of course, I was aware of Bluetooth technology being used primarily for streaming audio (headsets, wireless speakers, etc.), but I had no idea there were two "types" of Bluetooth: Bluetooth Classic and Bluetooth Low Energy (aka Bluetooth Smart back then). So, why am I telling you this story?? Well, even nowadays, there are still not many good resources that help you understand the difference between **Bluetooth Classic (BR/EDR)** and **Bluetooth Low Energy (Bluetooth LE)**. Lots of the blog posts out there covering this topic seem to cover it at a very high level without enough information to help you fully understand the extent of the difference between the two protocols. ...and that is the goal of this post: **To help you better understand the differences and similarities between these two Bluetooth protocols** **in the shortest time possible**. I will keep things pretty simple and won't bore you with all the nitty-gritty details. I will just present you with the meat of the content in a straight-to-the-point comparison table. ## Bluetooth Classic (BR/EDR) vs. Bluetooth Low Energy (Bluetooth LE) The first important thing you should know is that the two protocols **are incompatible** with each other. A Bluetooth Classic device cannot communicate with a Bluetooth Low Energy device. | | **Bluetooth Classic** | **Bluetooth Low Energy** | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Usage** | Used for streaming applications such as audio streaming, file transfers, and headsets | Used for sensor data, control of devices, and low-bandwidth applications | | **Data Rate** | Has a higher maximum data rate (2.1 Mbps) | The max data rate is at 2 Mbps (as of v 5.3)Higher data rate options are currently [in the works](https://www.bluetooth.com/learn-about-bluetooth/recent-enhancements/?ref=novelbits.io) | | **Power Consumption** | High power consumption Radio is always onShorter battery life | Lower power consumptionMore efficient radio usage and on-timeLonger battery life (up to 3-5 years for some applications!) | | **RF Channel Spectrum** | Operates over 79 RF channels(1 MHz wide channels) | Operates over 40 RF channels(2 MHz wide channels) | | **Device** **Discovery** | Discovery occurs on 32 channels | Discovery occurs on 3 primary channels, leading to quicker discovery and connections | | **Audio Streaming** | The original protocol currently used in most audio streaming applications | The new LE Audio standard will eventually replace Classic Bluetooth audio applications in addition to introducing many other new and more flexible use cases (broadcast audio, hearing aids, etc.) | | **Range** | Limited rangeUp to around 50 m | More flexible range configurationUp to over 1-kilometer line-of-sight(with use of long-range mode – introduced in version 5.0) | | **Topology** | Peer-to-peer (1:1) | Peer-to-peer (1:1)Star topology (many:1)Broadcast (1:many)Mesh (many:many) | | **Profiles/Use Cases** | Limited defined profiles and use cases | Wide variety of defined profiles (SIG-adopted)Flexibility for custom profiles | | **Developer Friendly** | Very strict, not flexible especially for custom, proprietary solutions | Very flexible and easy to customize to your own application and solution | | **Technical Resources** | Very few technical resources outside of the official Bluetooth Core specification | A lot more technical resources are available outside of the official Bluetooth Core specification.**Great example:**📘 **["Intro to Bluetooth Low Energy"](https://novelbits.io/introduction-to-bluetooth-low-energy-book/)** | | **Cost of Developer Tools** | Very high costA typical Bluetooth Classic sniffer [costs upwards of $20K-$30K](https://www.teledynelecroy.com/protocolanalyzer/frontline-sodera?ref=novelbits.io)! | Low-cost toolsA simple Bluetooth Low Energy sniffer can cost [only $10](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle?ref=novelbits.io)! | | **Smartphone Compatibility** | Available on 100% of smartphones | Available on \~100% of smartphones | | **Specification Documents** | Defined primarily in the Bluetooth Core specification + Profile specifications + Service specifications | Defined also in the Bluetooth Core specification + Profile specifications + Services specifications + Mesh specifications | | **Future-Proof** | Limited updates and limited new features introduced in new versions of the Bluetooth specification | Lots of new updates and new features introduced in new versions of the Bluetooth specification | | **Cost of chipsets** | Higher cost\> $10 | Lower cost< $10Down to $1-$2 in some cases! | | **Interesting use cases** | Not many unique use cases, mostly used for audio streaming, sometimes for file transfers and cable-replacement | Lots of innovative use cases including smart home applications, medical devices, industrial and manufacturing, LE Audio, mesh solutions, personal fitness trackers, and many more!Also used as a "positioning radio" for indoor navigation, asset tracking, and proximity applications (e.g. beacons) | ## Summary In this post, we covered the main differences between Bluetooth Classic (BR/EDR) and Bluetooth Low Energy (Bluetooth LE). Here are the key takeaways: - **Different use cases:** Bluetooth Classic is primarily used for audio streaming and file transfers, while Bluetooth LE targets sensor data, device control, and low-bandwidth IoT applications. - **Power consumption:** Bluetooth LE is designed for ultra-low power — some applications can run for 3-5 years on a single battery. - **Range:** Bluetooth LE offers more flexible range options, including long-range mode (1+ km line-of-sight) introduced in Bluetooth 5.0. - **Topology:** Bluetooth LE supports peer-to-peer, star, broadcast, and mesh topologies, while Bluetooth Classic is limited to peer-to-peer. - **Developer tools:** Bluetooth LE offers lower-cost development tools (a sniffer can cost as little as $10), more flexible customization, and a growing library of technical resources. - **The future:** Bluetooth LE continues to receive major updates with each new specification version, and LE Audio is set to eventually replace Bluetooth Classic for audio applications as well. You should now have a solid understanding of when to choose Bluetooth Classic vs. Bluetooth LE for your project. For most new embedded and IoT applications, Bluetooth LE is the clear choice. 💡 **Insider Tip:** Ready to dive deeper into Bluetooth LE development and understand how to build real-world applications? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### How to Manage Multiple Bluetooth LE Peripherals in iOS URL: https://novelbits.io/manage-multiple-ble-peripherals-in-ios-swiftui/ Last updated: 2026-08-09T05:25:38.000Z ****This tutorial is an excerpt from a course available within the [Bluetooth Developer Academy](https://novelbits.io/academy/), developed in collaboration with Anas Imtiaz, Ph.D.** For the purpose of this tutorial (separated into two parts), our goal is to create an iOS app that can manage multiple Bluetooth LE peripherals. Our example will be an app that can be used by runners to keep track of their speed, heart rate, and environmental temperature. These three inputs are provided by three separate sensors using notifications to update the central device. Note: If you're new to Bluetooth LE development on iOS, then check out the following previous tutorials: - [Introduction to Bluetooth LE Mobile Development \[iOS\] – Part 1](https://novelbits.io/intro-ble-mobile-development-ios/) - [Introduction to Bluetooth LE Mobile Development \[iOS\] – Part 2](https://novelbits.io/intro-ble-mobile-development-ios-part-2/) ## Prerequisites - An Apple computer: Macbook, Mac Mini, iMac - macOS - XCode 11+ - iPhone with Bluetooth LE (iOS 13+) - 3 x Bluetooth LE Peripherals (we have used 1x nRF52 Development Kit with Nordic HRS example, 1x nRF52 Development Kit with Nordic RSC example, 1x Nordic Thingy 52) - Enrollment in the Apple Developer Program (Free, unless you want to deploy to the App Store in which case it is $99 per year). For more information on setting up your account, refer to the following link: [https://developer.apple.com/support/account/](https://developer.apple.com/support/account/?ref=novelbits.io) - Basic understanding of Swift **Note**: we will be using SwiftUI to develop the user interface which requires iOS13 and Xcode 11\. If you are on a previous version, you can still follow along since the Core Bluetooth APIs are exactly the same regardless of the method used to build the user interface. For this tutorial, I am using: - MacBook Pro 2017 with macOS Big Sur (11.4) - XCode version 13.0 - iPhone 11 (iOS version 15) - Swift 5.1 - nRF52 Development Kit with Nordic HRS peripheral example - nRF52 Development Kit with Nordic RSC peripheral example - Nordic Thingy:52 ## Project Setup As always, the first thing to start off on an iOS app is to create a new project in Xcode. For the template, select **iOS** and then **App** from the Application section ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d7239a1.png) On the next screen, enter project details and make sure to uncheck **Use Core Data** since we will not be using that in this project. For interface, select SwiftUI. Continue with the setup process until the project is created. Build and run to make sure everything is ok. ## App Prototyping Before we proceed we need to figure out what the app is going to look like, how it is going to display the information from the sensors, and how it will actually interact with the sensors. This may involve input from a team of UI designers in a real-world project but for our purposes, we can assume we have some basic requirements as follows. - We need a main screen in the app that shows its name and purpose - The next screen should allow connections with various sensors and - Once the user is ready, following connections with the sensors, the next screen should display the resulting data obtained from the different sensors. Based on this, the app may look similar to the sketches shown below. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d752078.png) If you are developing in the real world I would expect you to get much more polished user journeys than this one! The end result will look like the screenshots shown below. ## First Screen Now that we know what our app should look like, let’s go about adding UI elements corresponding to the requirements of each screen. Let’s take a close look at the first screen. Essentially we have 4 UI elements that we can get from SwiftUI. From top to bottom we have Text, Image, Text, Button. Since these are laid out vertically we can use a VStack to arrange everything. Start a VStack inside the body of your ContentView ```swift struct ContentView: View { var body: some View { VStack { } } } ``` The first element is Text which we can add as follows. ```swift Text(“Track your run with\nreal-time metrics”) ``` Next, we have an Image. For this, I will use an icon from SFSymbols which is a library of vector icons from Apple. If you don’t already have it download and install SFSymbols here: [https://developer.apple.com/sf-symbols/](https://developer.apple.com/sf-symbols/?ref=novelbits.io) Now open up the SF Symbols app and search for “walk” in the top right bar. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d7a5c68.png) You can use any icon but I like the first one on the second line. Right-click on it top copy the name “figure.walk.circle.fill” Now to add the image, simply use this name as follows: ```swift Image(systemName: “figure.walk.circle.fill”) ``` Next, we have text again ```swift Text(“RUNTracker”) ``` And finally, a button which can be added as follows. ```swift Button(“Get Started”) { } ``` Build and run and you should see the following: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d80b01e.png) We have everything we need in terms of UI elements but they don’t look very nice so let’s stylize them in a way that they can be used elsewhere as well. At this point, the code in ContentView should look like this: ```swift struct ContentView: View { var body: some View { VStack { Text(“Track your run with\nreal-time metrics”) Image(systemName: “figure.walk.circle.fill”) Text(“RUNTracker”) Button(“Get Started”) { } } } } ``` ## Background Color The first thing I want to do is to change the background color to a custom color. Go to the project navigator and find the Assets Catalogue (Assets.xcassets). Hit the + sign at the bottom to add a new Color Set and call it ThemeColor (or anything else that you prefer). It shows two color squares that are to be used in Light and Dark modes. Let’s define the same color for both. Click on the color square, and show the inspector on the right if it is not already visible. In the Color section in the inspector, select sRGB for Content, 8-bit (0-255) for Input Method, and then define RGB values as 98, 207, 106. Do this for both. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d84080f.png) Now that we have our color defined we can use this name anywhere we want. For example, Color(“ThemeColor”) will always give us our custom color without needing RGB values everywhere. Now for the background color of the first screen, we could use the background modifier on our VStack that holds the UI elements. But the VStack itself only runs from the top of the first element to the bottom of the last so it will not fill the screen. We can define a view to hold the VStack or we can just use ZStack and change its background color. To do this, Cmd+click on VStack in your code and select Embed in ZStack. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d8aeb1e.png) Now simply add the following as the first line of ZStack before the start of your VStack. Color(“ThemeColor”) Now if you see in the preview you will see there is white color on top which is the safe area. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d8ce44d.png) To ignore the safe area, use the modifier .edgesIgnoringSafeArea(.all) and your code should look like this. ```swift var body: some View { ZStack { Color(“ThemeColor”) .edgesIgnoringSafeArea(.all) VStack { …… ``` Now for the first Text view, let’s change its appearance so that it is centred, uses a larger and bold font and its color is white. This is achieved by adding multiple modifiers as follows. ```swift Text(“Track your run with\nreal-time metrics”) .fontWeight(.bold) .font(.title2) .foregroundColor(.white) .multilineTextAlignment(.center) ``` The first modifier achieves the effect of bold text. For font, we are using .title2\. This is a good practice to use pre-defined styles with dynamic typing. This way if the system font size has changed then all the fonts are scaled appropriately. You can read more about dynamic typing here: ​​[https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/typography/](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/typography/?ref=novelbits.io) To add some space between this Text view and the next Image view, insert a Spacer(). ```swift Text(“Track your run with\nreal-time metrics”) .fontWeight(.bold) .font(.title2) .foregroundColor(.white) .multilineTextAlignment(.center) Spacer() Image(systemName: “figure.walk.circle.fill”) ``` For the image, which is an icon, we can actually use the font size to increase its size. We also want to change its foreground color to white. ```swift Image(systemName: “figure.walk.circle.fill”) .foregroundColor(.white) .font(.system(size: 120)) ``` Note that in this case, we are using the absolute font size to enlarge the icon size (in contrast to what I said above). This is because we want it to be much larger than any of the predefined styles. Insert another Spacer() Now for the next Text view, I want my app’s name to appear as follows. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d8f34bc.png) How can we achieve this? What we want is two text views with different modifiers stacked next to each other. Essentially, two Text views in HStack with no spacing! Embed two Text views in HStack (inside your VStack) as follows. ```swift HStack(spacing: 0) { Text(“RUN”) .font(.system(size: 52)) .fontWeight(.bold) .foregroundColor(.yellow) Text(“Tracker”) .font(.system(size: 50)) } ``` Again, I am using absolute font sizes to achieve a specific look. In reality you would have an image here as a logo that can scale on different screens. Next, I want some more space before I get to the button so insert two spacers. Finally, I want my main button to look like this on all screens ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d910055.png) So let’s make a custom view so that we can reuse this every time we need a button like this. What we want as the view of the button is text that is black in color, a rounded rectangle in background with some padding around the text. To achieve this, we can do the following. ```swift Button(action: { // some action }) { Text(“Get Started”) .font(.title2) .padding() .foregroundColor(.black) .background( RoundedRectangle(cornerRadius: 25) .stroke(Color.white, lineWidth: 2) .background(Color.white.cornerRadius(25)) ) } ``` The modifiers are self-explanatory except for the last one where we have used the background modifier with RoundedRectangle and then applied styling to it. Since we will be using this on other views, let’s create a new file for the custom views. Create a new empty Swift file. Let’s call it CustomViews.swift. After the file is created add the line to import SwiftUI We will then create a new struct called MainButton that is of type View and its body applying all the modifiers on the text that we just used above. ```swift struct MainButton: View { var text: String var body: some View { Text(text) .font(.title2) .padding() .foregroundColor(.black) .background( RoundedRectangle(cornerRadius: 25) .stroke(Color.white, lineWidth: 2) .background(Color.white.cornerRadius(25)) ) } } ``` Now we can update our Button function in the main ContentView to use this struct as follows. ```swift Button(action: { // some action }) { MainButton(text: “Get Started”) } ``` We will come back to this button later as we want it to do a few other things but for now, it does look the way we want it to. Add another Spacer() below and the final ContentView should look like this: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d92806e.png) ## Second Screen For the second screen, again we want the background to be of the ThemeColor. Then, from top to bottom we have a back button and the title. The back button comes in automatically when we use a NavigationLink (we will get to this later) and the title is added using the navigationBarTitle modifier. Following this, there is an image, three lines of similar-looking text and button, and an action button at the end. Let’s ignore the first two items as we will fix them once we establish the navigation link. Create a new SwiftUI file, calling it SensorsConnectionView.swift As before, use the same image of the walking person in a circle inside a VStack which itself is embedded in a ZStack. ```swift ZStack { VStack { Spacer() Image(systemName: “figure.walk.circle.fill”) .foregroundColor(.white) .font(.system(size: 120)) } } ``` Add a Spacer() and some informational Text as follows and set its foreground color to white. ```swift Text(“Connect to all the sensors before starting your run”) ``` Next, we have three rows of items that are next to each other so we will be using rows of HStack. We want the end result to be as shown below. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d9622d1.jpg) So each HStack here is a combination of an image/icon, text, and button. Let’s define the Connection button first. We will use a different method for this one just to demonstrate the alternative possibility. We will define a new ButtonStyle in our CustomViews.swift and then use it to style the button. ```swift struct ConnectionButton: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .padding(8) .background(Color.red) .foregroundColor(.white) .clipShape(Capsule()) } } ``` The makeBody() method is used to create the view of the Button. Now if we want to apply this style to a Button, we can simply apply the modifier to the button as: ```swift .buttonStyle(ConnectionButton()) ``` Now let’s create a new struct in which we put these three elements together in an HStack. ```swift struct SensorConnectView: View { var body: some View { HStack { } } } ``` Because we want the image and text to be different on each line we will define them as a variable. ```swift var imageName: String var dataName: String ``` Also, we may want the button text to be different so that can be another variable. ```swift var buttonText: String ``` Finally, we also want to pass the button action defining it in a closure. So we can define the action as follows since it doesn’t return anything. ```swift var buttonAction: () -> Void ``` Now putting an Image, Text and Button together with some modifiers we have: ```swift HStack { Image(systemName: imageName) .foregroundColor(.white) .font(.title2) .frame(width: 32) Text(dataName) .textCase(.uppercase) .foregroundColor(.white) .font(.title3) .frame(width: 196, alignment: .leading) Button(buttonText) { buttonAction() } .buttonStyle(ConnectionButton()) } ``` In the above code, for the image, we are using the SF Symbol icon name and defining the width to be fixed for both image and text just to keep things nicely aligned. For the button, we have used the buttonStyle that we defined earlier. At this point, putting everything together SensorConnectView should look like this: ```swift struct SensorConnectView: View { var imageName: String var dataName: String var buttonText: String var buttonAction: () -> Void var body: some View { HStack { Image(systemName: imageName) .foregroundColor(.white) .font(.title2) .frame(width: 32) Text(dataName) .textCase(.uppercase) .foregroundColor(.white) .font(.title3) .frame(width: 196, alignment: .leading) Button(buttonText) { buttonAction() } .buttonStyle(ConnectionButton()) } } } ``` Go back to the SensorsConnectionView,swift and define three new instances of SensorConnectView. ```swift SensorConnectView( imageName: “figure.walk”, dataName: “Running Speed”, buttonText: “Connect” { // button action } SensorConnectView( imageName: “heart.fill”, dataName: “Heart Rate”, buttonText: “Connect” { // button action } SensorConnectView( imageName: “thermometer.sun.fill”, dataName: “Temperature”, buttonText: “Connect” { // button action } ``` Add a Spacer() And another button of type MainButton with text Let’s Go. ```swift Button(action: { // some action }) { MainButton(text: “Let’s Go”) } ``` And then another Spacer() Now we have most things we need for this second screen but how do we get here from the main screen? Go back to the first screen in ContentView.swift and replace the Button at the bottom with a NavigationLink, using our custom MainButton as its view. ```swift NavigationLink(destination: SensorsConnectionView()) { MainButton(text: “Get Started”) } ``` While the NavigationLink creates a button to perform the transition it has to be part of the NavigationView. So, make sure everything inside the body of the ContentView is embedded in a NavigationView. ```swift NavigationView { ZStack { … } } ``` If you build and run you can see that this allows you to navigate from the first screen to the second. And then there is a back button at the top of the second view which we can use to return to the first view. Two more things are needed. We still don’t have a title at the top and I don’t like the blue color of the back button so I want to change it to white. For the second issue, the color can be defined in Assets.xcassets. Go to AccentColor in Assets.xcassets, and change its color to white. Select the Universal color and then set the sRGB values to 255,255,255 in the inspector. This will ensure white accent color throughout the app. If the inspector is not visible, click on the top right button in Xcode to toggle the visibility of the inspector. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d97d6d1.png) For the title, in SensorsConnectionView.swift, add a modifier right at the end where the ZStack curly brace is closed. ```swift .navigationBarTitle(“Configuration”, displayMode: .large) ``` This will add the word Configuration at the top as part of the navigation bar title. Our second screen is now complete! ## Third Screen Now we can move on to the last screen which will be significantly easier to set up based on the work we have done in the last two. Looking at the sketch, it is pretty similar to the second one except that its title will be different and the three rows here have placeholders for data to be displayed rather than the red button from the previous screen. Create a new SwiftUI file called SensorsDataView.swift Start with a ZStack with the background color defined (this is repetitive so we can actually create a custom view to replace this). Set the title using the navigationBarTitle modifier. ```swift .navigationTitle(“Active Session”) ``` Now embed everything in a VStack. The image is the same as before. ```swift ZStack { VStack { Spacer() Image(systemName: “figure.walk.circle.fill”) .foregroundColor(.white) .font(.system(size: 120)) } } .navigationTitle(“Active Session”) ``` For the rows, as before, we want a little icon and description of what is being displayed followed by the value and the unit. So instead of buttons we have more text. We can define the custom view as follows in CustomViews.swift file. ```swift struct SensorDataView: View { var imageName: String var dataName: String var dataValue: UInt16 var dataUnit: String var body: some View { HStack{ Image(systemName: imageName) .foregroundColor(.white) .font(.title2) .frame(width: 32) Text(dataName) .textCase(.uppercase) .font(.title3) .frame(width: 196, alignment: .leading) Text(String(dataValue) + ” ” + dataUnit) .font(.title3) .foregroundColor(.white) .frame(width: 80) .padding(8) } } } ``` Notice that the only difference here is the last element in the HStack where we are using Text view to display the string of data value and its unit. The dataValue is UInt16 because as you will see later this is what we get from the Bluetooth LE sensors. Define three new rows in the SensorsDataView: ```swift SensorDataView(imageName: “figure.walk”, dataName: “Running Speed”, dataValue: UInt16(0), dataUnit: “m/s”) SensorDataView(imageName: “heart.fill”, dataName: “Heart Rate”, dataValue: UInt16(0), dataUnit: “bpm”) SensorDataView(imageName: “thermometer.sun.fill”, dataName: “Temperature”, dataValue: UInt16(0), dataUnit: “C”) ``` For now, we have just passing constants and will update this in the later sections. Finally, add a button at the end with Spacer() before and after the button. ```swift Button(action: { // button action }) { MainButton(text: “End Session”) } ``` Now you also need to go back to the SensorsConnectView and replace the button at the end with a NavigationLink which points to this SensorsDataView. ```swift NavigationLink(destination: SensorsDataView()) { MainButton(text: “Let’s Go”) } ``` Now you should have the UI of the app complete with the navigation working from the first through to the last screen. ## Implementing the “Bluetooth LE Controller” module For this example, we are using two nRF52832 Development Kits. The first one has the Nordic HRS Bluetooth LE peripheral example code and has the heart rate service with a UUID of 0x180D and heart rate measurement characteristic with UUID 0x2A37. The second board has the Nordic RSC Bluetooth LE peripheral example. This consists of the running speed service (UUID 0x1814) and characteristic (0x2a53). Finally, a Nordic Thingy 52 is used to capture temperature. This is in the weather station service (UUID: EF680200-9B35-4933-9B10-52FFA9740042) with temperature characteristic (UUID: EF680201-9B35-4933-9B10-52FFA9740042). It is a good idea at this point to verify these are working by checking against common Bluetooth LE scanners and exploring the different services and characteristics. Back to the iOS app, our views are looking good now but they don’t do much since they can’t connect to the sensors yet. We have to give the usage permissions for Bluetooth LE which is normally done in the Info.plist file. You may have noticed that there is no Info.plist in the latest versions of Xcode. Navigate to the main project, select the Target and go to Info where you will find Custom iOS Properties. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836d9a9247.png) Add a new property for Privacy – Bluetooth Always Usage Description and a Value that gives the message to be displayed when asking for user permission. Additionally, we want to have Bluetooth LE communication in the background so while we are here go to Signing & Capabilities. Select + from the top left and then Background Modes. Now check Uses Bluetooth LE accessories. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a836da26b2a.png) That’s all the setup in Xcode done. We did something similar in the \[Bluetooth LE Background\] course within the [Academy](https://novelbits.io/academy/) where we created a separate class for handling the Bluetooth LE events. This is even more important in this app since we want a single class that can manage connections and update the UI across different screens of the app. So to start, create a new Swift file and import the CoreBluetooth framework. We will name the file as BLEController.swift. Define the class so that it conforms to the required CoreBluetooth delegates. ```swift class BLEController: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { … } ``` Note that we are ObservableObject here because we will observe the changes within this class from other classes. Xcode will show an error asking for the centralManagerDidUpdateState method so go ahead and use the Fix option to add it automatically. Next, I like to check the state of Bluetooth LE hardware to see if it is powered on and update a property. Define this property as follows. ```swift @Published var isSwitchedOn = false ``` The @Published property wrapper is used to update the views since this is part of an ObservableObject. This can be updated as follows. ```swift func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } ``` We also want to have a CBCentralManager to search for peripherals and manage connections. So go ahead and add a variable in the class. ```swift var myCentral: CBCentralManager! ``` Now this gets initialised in the init() function as follows. ```swift override init() { super.init() myCentral = CBCentralManager(delegate: self, queue: nil) } ``` We also want to define the UUIDs that are to be discovered. ```swift let runningSpeedServiceUUID = CBUUID(string: “1814”) let runningSpeedCharacteristicUUID = CBUUID(string: “2A53”) let heartRateServiceUUID = CBUUID(string: “180D”) let heartRateCharacteristicUUID = CBUUID(string: “2A37”) let thingyServiceUUID = CBUUID(string: “EF680100-9B35-4933-9B10-52FFA9740042”) let thingyWeatherStationServiceUUID = CBUUID(string: “EF680200-9B35-4933-9B10-52FFA9740042”) let thingyTemperationCharacteristicUUID = CBUUID(string: “EF680201-9B35-4933-9B10-52FFA9740042”) ``` Our basic BLEController class is now ready although it still doesn’t do much at this point. It should look like this: ```swift class BLEController: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { var myCentral: CBCentralManager! @Published var isSwitchedOn = false let runningSpeedServiceUUID = CBUUID(string: “1814”) let runningSpeedCharacteristicUUID = CBUUID(string: “2A53”) let heartRateServiceUUID = CBUUID(string: “180D”) let heartRateCharacteristicUUID = CBUUID(string: “2A37”) let thingyServiceUUID = CBUUID(string: “EF680100-9B35-4933-9B10-52FFA9740042”) let thingyWeatherStationServiceUUID = CBUUID(string: “EF680200-9B35-4933-9B10-52FFA9740042”) let thingyTemperationCharacteristicUUID = CBUUID(string: “EF680201-9B35-4933-9B10-52FFA9740042”) override init() { super.init() myCentral = CBCentralManager(delegate: self, queue: nil) } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } } ``` ## Updating Views with Bluetooth LE Events We want to be able to display the values obtained from the sensors on the third screen of our app. These are the running speed, heart rate, and temperature values. We can do this by having three @Published properties declared in our BLEController class. ```swift @Published var runningSpeed: UInt16 = 0 @Published var heartRate: UInt16 = 0 @Published var temperature: Float = 0 ``` The specific data types are based on the data received from the sensors. We will update these values when receiving data from the sensors and these, in turn, will result in the UI being updated at places where they are being used. The other thing we want to do is to connect with specific sensors from the second screen. This is the button action that we need to define. We need to have a method that can call the scanForPeripherals method of our CBCentralManager instructing it to look for a sensor with specific services. We can either have three different methods corresponding to each type of sensor or we can just have one method that can carry out the appropriate action. The latter case is a much more neat solution but how do we figure out which sensor to connect with? One way to do this is to define a specific sensor type. I will do this in a new Swift file called RTSensors.swift where I can keep everything to do with custom sensor models together. Since we have three sensors we can have three types. ```swift enum RTSensorType { case speed case heart case environment } ``` Now in our BLEController, first add a variable for the sensorType. And define a function called connectToSensor() that takes in the sensor type as an argument. ```swift var sensorType: RTSensorType! ``` ```swift func connectToSensor(type: RTSensorType) { } ``` We can call the same function from the Connect buttons on the second screen of the app changing only the type of sensor. This function will then look at the passed type of sensor and call the scanForPeripherals method with the right set of service UUIDs. ```swift func connectToSensor(type: RTSensorType) { sensorType = type var serviceUUIDs: [CBUUID] = [] switch sensorType { case .speed: serviceUUIDs = [runningSpeedServiceUUID] case .heart: serviceUUIDs = [heartRateServiceUUID] case .environment: serviceUUIDs = [thingyServiceUUID] case .none: serviceUUIDs = [] } myCentral.scanForPeripherals(withServices: serviceUUIDs, options: nil) } ``` ## Multiple Peripherals Data Model Before going ahead to perform other Bluetooth LE communication operations, let’s pause to think about how we are going to keep track of the different peripherals we are going to connect with. One simple way is to have an array of CBPeripheral so that every time we connect to a new sensor we just append the new CBPeripheral to this array. Imagine we connect to three sensors, we will have an array with three CBPeripheral objects. But which object corresponds to which sensor? The UUID property of the CBPeripheral object does not correspond to the service UUID and changes on every new connection so it is not possible to tell which element of the array is the heart rate sensor, for example, unless the order was fixed. If we want to disconnect the temperature sensor or read its battery level, how do we know which element to perform this communication with? To work around this problem we can create another custom data type that has a CBPeripheral and the RTSensorType as its members. We can also have a property for the advertised name of the peripheral as well as a flag to check if it is connected or not. It looks like this (in the RTSensors.swift file). ```swift struct RTSensor { let peripheral: CBPeripheral let name: String let type: RTSensorType var isConnected: Bool } ``` Now, we can have an array of RTSensor instead of an array of CBPeripheral. Add the following to your BLEController. ```swift @Published var sensors: [RTSensor] = [] ``` We have declared it as a published property because we want to use its connection status to update our UI. If, say, we want to read a value from the temperature sensor, we can look through the array and find the element with the temperature type and then use the CBPeripheral object from that element of the array. Note that if we have sensors that are of the same type then we will probably end up requiring some other form of uniquely discriminating aspect. But for this tutorial, we can assume that there will only be one type of each sensor hence we can find that and then use it for communication. ## Initializing the Bluetooth LE Controller Class Now that we have our custom types sorted and have the foundations of our Bluetooth LE Controller, let’s have a look at how it can be initialized. In the previous section, I mentioned that we want to be able to connect to the sensors from the second screen and show the values received on the third one. For any data that is to be shared between multiple views, we can use something called an @EnvironmentObject. What this does is allow us to create some data in the parent object and make it available for any of the views in the navigation link. So what do we want to be available in all the subsequent views? That’s right, we want our BLEController. Since the parent view is the main ContentView, that is where we create an instance of BLEController and describe it as a @StateObject. ```swift struct ContentView: View { @StateObject var bleController = BLEController() var body: some View { … } } ``` Next, we use the modifier .environmentObject to pass on our BLEController instance to all the other views. ```swift NavigationView { ZStack { … } .environmentObject(bleController) } ``` To access this BLEController instance in the second and third screens, we declare a property as an @EnvironmentObject in both of those views. ```swift @EnvironmentObject var bleController: BLEController ``` Now we can use this bleController from any of the UI views that we have created! ## Discovering Peripherals To start discovering peripherals, we need to call the connectToSensor() method that we created earlier. Go to the SensorsConnectionView and the call to this method for the button action. ```swift SensorConnectView( imageName: “figure.walk”, dataName: “Running Speed”, buttonText: “Connect” { bleController.connectToSensor(type: .speed) } ``` Here we are passing the sensor type as **speed**. For the next two, we will pass the **heart** and **environment** types respectively. Now the scanForPeripherals will be called with the correct service UUID since our connectToSensor method calls it with the correct service UUIDs to filter based on the sensor type. Next, as usual, the didDiscover method of the central manager gets called if we find the sensor with the right service UUID. Add the stub for the didDiscoverMethod. ```swift func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { … } ``` Once this is called, we want to save a reference to the peripheral which has been discovered in our **sensors** array of type RTSensor. So in our didDiscover method, the first thing we do is append to sensors. ```swift sensors.append(RTSensor(peripheral: peripheral, name: peripheral.name ?? “NoName”, type: sensorType, isConnected: false)) ``` What we are doing above is passing the discovered peripheral and its name (or NoName in case there isn’t any), setting the sensor type and its connected flag to false (since we aren’t connected yet). Next, we want to set the delegate of the peripheral object to self and since we have just appended the RTSensor object we can use the last element of the array. ```swift sensors.last!.peripheral.delegate = self ``` Then we stop scanning and attempt to connect to the peripheral we have just discovered. ```swift central.stopScan() central.connect(sensors.last!.peripheral, options: nil) ``` Note that regardless of any peripherals being connected before this will work since we are creating a new CBPeripheral as part of RTSensor every time we discover a new sensor. Of course, to avoid duplication we also want to clean up and remove a certain element if it has been disconnected. ## Summary & Closing There's still a lot that we haven't covered yet for a fully functional app. We cover the rest of the implementation in a dedicated course within the Bluetooth Developer Academy, including: - Connecting to Peripherals - Discovering Services and Characteristics - Subscribing to Notifications - Reading data from sensors - Canceling Peripheral Connections 💡 **Insider Tip:** Want to master iOS Bluetooth LE development, including managing multiple peripherals and building real-world apps? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### How Bluetooth Low Energy Works: Advertisements (Part 2) URL: https://novelbits.io/bluetooth-low-energy-advertisements-part-2/ Last updated: 2026-08-09T05:24:07.000Z In this week's post, we'll continue our discussion on Bluetooth Advertisements (first part [here](https://novelbits.io/bluetooth-low-energy-advertisements-part-1/)) and cover them in a bit more detail. Bluetooth Advertisements are crucial for any BLE device since they are utilized for all types of applications, whether that's a device that allows connections or one that simply advertises its presence and includes data for others to discover. In order to utilize advertising packets efficiently, we need to understand the way they get used, the different capabilities they provide, the format of the packets, and how much data they can hold. The most important goal of advertising packets is to convey information to other BLE devices via the **advertising packet type** and the **advertising data types** included in the packet. The best way to better understand the concept is by going through a few examples of advertisement packets, so let's do that next. ## Broadcasting Devices If you're looking to design a device with the main role of advertising its presence and possibly broadcast some data for other BLE devices (observers, centrals) to discover, then you can implement the Broadcast role. *One example would be a beacon device.* Going back to the different advertising packet types, here are the ones we can use for implementing this role: - **Legacy Advertisements** (supported by all Bluetooth versions): - `ADV_NONCONN_IND`: Non-Connectable Non-Scannable Undirected advertising. - **Extended Advertisements** (requires Bluetooth version 5.0 or later): - `ADV_EXT_IND`: Extended advertising (used for all advertising types except Connectable Scannable Undirected) – sent on the **Primary** advertising channels. - `AUX_ADV_IND`: Extended advertising (used for all advertising types except Connectable Scannable Undirected) – sent on the **Secondary** advertising channels. Let's revisit the packet format of advertising packets: ![BLE Uncoded PHY Packet Format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/uncoded-phy-packet-format.png) Source: Bluetooth Core Specification document PDU Payload format: ![BLE PDU Payload Format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-1-11.png) Source: Bluetooth Core Specification Document Depending on the platform and Bluetooth stack used on your device, the APIs will differ, but in general, you'll need to define the following: **PDU** **Content** - *PDU Header* **PDU Type:** `ADV_NONCONN_IND` (`0b100`) **Length:** the size of the advertising data - *PDU Payload* **Flags AD**: *they are optional in the case of non-connectable advertising packets, so you can skip this field.* **Manufacturer Specific Data**: (e.g., sensor data) **Device Name**: depending on how much data is used up by the previous fields, you may be able to fit a device name string into the advertising packet payload. Another option is to include the device name in a *Scan Response* packet. In the case of a Legacy Advertising Packet, the advertising data portion has a maximum size of 31 bytes (with at least 2 bytes used up by the Length and Type fields in the case of one advertising data type included, leaving a max of 29 bytes for the payload). Also, keep in mind that the Manufacturer Specific Data field will include 2 bytes containing the Company Identifier Code, which is followed by the user data. Company Identifier Codes can be obtained from the Bluetooth SIG for free (as long as the company is a Bluetooth SIG member company). Learn more here: [https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/](https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/?ref=novelbits.io) If you choose to implement a *Scan Response*, you could include a second advertising packet to send additional advertising data that does not fit into the main advertising packet. This relies on the Observer/Central sending a Scan Request packet to the advertising device, to which the advertiser responds with a Scan Response packet. The format of the Scan Response packet is exactly the same as the Advertising packet. Let's take a look at an example of a device that simply advertises its Complete Local Name. The PDU Payload would look something like this: | Value | Notes | | ----- | ----------------------- | | 0x0B | Length of the data | | 0x09 | <> | | 0x4e | 'N' | | 0x6f | 'o' | | 0x76 | 'v' | | 0x65 | 'e' | | 0x6c | 'l' | | 0x20 | ' ' (space) | | 0x42 | 'B' | | 0x69 | 'i' | | 0x74 | 't' | | 0x73 | 's' | Advertising PDU Payload data To learn more about the different advertising data types, refer to the **Supplement to Bluetooth Core Specification** document: [https://www.bluetooth.com/specifications/bluetooth-core-specification/](https://www.bluetooth.com/specifications/bluetooth-core-specification/?ref=novelbits.io) ## Connectable Devices If you're looking to design a device that primarily allows connections from another BLE device and operates mostly in connection mode, then here are a few things to keep in mind: - You are required to include the Flags AD field. In this case, you'd want to enable the <
> bit. - For Legacy Advertisements, use the `ADV_IND` advertisement type. - For Extended Advertisements (such as in the case of Coded PHY advertising which requires the use of Extended Advertisements), use the `ADV_EXT_IND` advertisement type on the primary advertising channels and `AUX_ADV_IND` on the secondary advertising channels. **Note:** Some SDKs will usually abstract this for the developer, and they'll provide a single API parameter that configures the appropriate advertisement types for both the primary and secondary channels. However, you will probably still need to define the PHY used for each of the channel types. One important thing to keep in mind is that Extended Advertisements are not supported by all scanners. So, if you're looking to implement a connectable device that can be connected to from both legacy devices and ones that support scanning for extended advertisements, it's highly recommended to configure your device to advertise using Legacy **and** Extended advertisements. ## LE Limited Discoverable Mode vs. General Discoverable Mode As part of the Flags AD field included in the advertisement data, there are two flags we haven't discussed yet: - Limited Discoverable mode - General Discoverable mode Limited Discoverable mode devices are discoverable for a limited period of time and this mode is typically triggered on a device by user interaction. Note that Limited Discoverable Mode is only allowed to be set in advertisements sent by devices operating in the peripheral role. Scanning devices need to perform what's called a limited discovery procedure in order to discover devices in this mode. Per the Bluetooth specification, there are two common reasons to use limited discoverable mode: > – Limited discoverable mode can be used to allow remote devices using the general discovery procedure to prioritize or otherwise identify devices in limited discoverable mode when presenting discovered devices to the end user because, typically, the user is interacting with them. > > – Limited discoverable mode can also be used to allow remote devices using the limited discovery procedure to filter out devices using the general discoverable mode. > > Core Bluetooth Specification document On the other hand, devices operating in the General Discoverable mode are discoverable for an indefinite period of time by devices performing the general discovery procedure. Similar to the limited discoverable mode, this mode is also only supported by devices operating in the peripheral role (devices that allow connections). Scanning devices need to perform what's called a general discovery procedure in order to discover devices in this mode. ## Advertising Parameters In addition to the advertising data, there are a few key parameters that define the behavior of an advertising device. For simplicity, we will focus on Legacy Advertisements which are the most popular. These parameters are: - **Advertising Interval**: this value ranges from 20 ms - 10.24 seconds (in 0.625 ms increment values (meaning that the valid values are 20 ms, 20.625 ms, 21.25 ms, etc.). - **Advertising Channels used**: a device can only advertise on a subset of the three primary advertising channels. - **Advertising Timeout**: this parameter determines how long the device continues advertising before stopping/turning off the radio. Each of these parameters has to be configured carefully in order to achieve the best user experience for your device. For example, here are some notes/tips to keep in mind: - The shorter the advertising interval, the more power is consumed by the device since the radio has to wake up more frequently to send out advertisement packets. - Shorter advertising intervals come with the advantage that discoveries and hence connections are faster. So, one has to strike a balance between a short enough advertising interval to satisfy a good enough discovery and connection speed while still achieving the desired power consumption level. - If customizable via the SDK in use, advertising on all three primary channels (37, 38, and 39) is the safest route to get your device discovered and connected to by another BLE device (since the scanning device will usually have to switch between the three advertising channels during the scanning process). - In general, you do not want your device to advertise indefinitely, so make sure that a reasonable advertising timeout value is set. You could also trigger advertising via a timer that expires every so often or via user interaction (e.g., click of a button on the device). - If you are developing a peripheral or broadcaster device that users will interact with via an iOS device, then make sure to check out the guidelines recommended by Apple in **section 35** of the following guide: [https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf](https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf?ref=novelbits.io). ## Summary In this post, we covered advertisements in a bit more detail. We went over: - Advertisements used in broadcasters (devices that do not allow connections) - Advertisements used in peripherals (devices that allow connections) - Advertising Parameters In the next post within the series, we'll take a deeper look into: - The timing of advertisements - The scanning parameters used on a scanning device - How to optimize them to reliably discover your peripheral or broadcaster device - How to develop a BLE scanner to discover broadcasters and peripherals ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE advertising, scanning, and beyond? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) ### Introduction to Bluetooth LE Mobile Development [iOS] - Part 2 URL: https://novelbits.io/intro-ble-mobile-development-ios-part-2/ Last updated: 2026-08-09T05:25:27.000Z ***This post is an excerpt from a course developed by Anas Imtiaz, Ph.D. which is available within the Bluetooth Developer Academy.*** In a previous post ([Introduction to Bluetooth LE Mobile Development for iOS](https://novelbits.io/intro-ble-mobile-development-ios/)), we covered: - Setting up Xcode for Bluetooth LE development - Bluetooth permissions - Scanning for Bluetooth LE peripherals - Connecting to a Bluetooth LE peripheral In today's post, we will take this a step further and look at developing a UI-based iOS app (using SwiftUI) that can perform most of the previous functionalities, with some additional features: - Display the status of Bluetooth on the device (turned on or off) - Act as a Central to discover Bluetooth LE Peripherals and display them as a list in the UI - Start and stop scanning by clicking dedicated buttons in the UI **Note**: we will be using SwiftUI to develop the user interface which requires iOS13 and Xcode 11\. If you are on previous versions you can still follow along since the Core Bluetooth APIs are exactly the same regardless of the method used to build the user interface. For this tutorial, we'll be using: - MacBook Pro 2017 - macOS Catalina (10.15.2) - XCode version 11.3.1 - iPhone 11 (iOS version 13.3.1) - Swift 5.1 - Optional: Another iDevice (we're using iPad Pro (1st generation, iPadOS 11.3)) The prerequisites for this tutorial include: - An Apple computer: Macbook, Mac Mini, iMac - macOS - XCode 11+ - iPhone with Bluetooth LE (iOS13+) - A Bluetooth LE Peripheral device - Enrollment in the Apple Developer Program (Free, unless you want to deploy to the App Store in which case it is USD99 per year) - Basic understanding of Swift **Note**: you can find the reference code for this tutorial towards the end of the post. ## Setting up the Project To start things off, fire up Xcode on your Mac and select **Create a new Xcode Project**. For the template select Single View App for iOS. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a391435.png) On the next screen, enter the app name and other details. Make sure to select SwiftUI for the user interface for this app. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a3be8f9.png) Next, select the location where you want to save the project and the press Create. On the left hand side you will see the list of files. The main file here that we will use for our UI is `ContentView.swift`. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a4387d5.png) On the right-hand side, you will see a live preview pane which will refresh every time the UI is being updated. It may be paused to start with, so hit the **Resume** button to build and preview the boilerplate code. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a459949.png) You should see the "Hello, World!" text on the preview. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a472451.png) ## Building the User Interface (*Note: We will keep this section brief in order to keep the focus of the tutorial on Core Bluetooth operations*) We are building an app that is able to scan for Bluetooth LE peripherals. For its functionality, as a Bluetooth LE scanner, we want to display a list of devices that we have found as well as the ability to start and stop scanning. For operation as a Bluetooth LE peripheral, we want our app to be able to start and stop advertising itself as a peripheral device (*covered in the full course in the Bluetooth Developer Academy*). Finally, we also want our app to display the status of our Bluetooth hardware i.e. whether its switched on or off. The user interface we want will look something like this: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ui.jpg) From top to bottom, we want some text for the title, a list of devices, status text, and a group of four buttons for control. Before we move forward, let's take a quick detour into the world of SwiftUI which is Apple's latest way of building user interfaces in a declarative way. In SwiftUI, if we want to add a text label, we simply say: ```swift Text("my text") ``` If we want to make this text italic we add a modifier: ```swift Text("my text") .italic() ``` If we want to change its color to red, we add another modifier: ```swift Text("my text") .italic() .foregroundColor(.red) ``` This is true for other UI elements as well where we simply add modifiers to achieve the desired look and functionality. Another important concept is that of *stacks*. UI elements are organised in horizontal and vertical stacks (HStack and VStack). For example, two buttons laid side by side will be in HStack: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/hstack.png) Two buttons laid vertically can be in a VStack: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/vstack.png) And they can also be nested where there are groups of VStack inside HStack or vice versa. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/hstack-vstack.png) Looking at our UI sketch above, we want a main VStack that holds all the elements inside starting with a Text object, a List object, a Text object saying STATUS following by another Text object which is showing the actual status, and finally a HStack with two VStacks each having a pair of Button objects. Additionally, for spacing between objects, we will use Spacer(). Adding all those UI elements in `ContentView.swift`, our starting point for the user interface will look like this. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a4adafc.png) And our `ContentView.swift` should have the following code: ```swift import SwiftUI struct ContentView: View { var body: some View { VStack (spacing: 10) { Text("Bluetooth Devices") .font(.largeTitle) .frame(maxWidth: .infinity, alignment: .center) List() { Text("placeholder 1") Text("placeholder 2") }.frame(height: 300) Spacer() Text("STATUS") .font(.headline) // Status goes here Text("Bluetooth status here") .foregroundColor(.red) Spacer() HStack { VStack (spacing: 10) { Button(action: { print("Start Scanning") }) { Text("Start Scanning") } Button(action: { print("Stop Scanning") }) { Text("Stop Scanning") } }.padding() Spacer() VStack (spacing: 10) { Button(action: { print("Start Advertising") }) { Text("Start Advertising") } Button(action: { print("Stop Advertising") }) { Text("Stop Advertising") } }.padding() } Spacer() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } ``` We will continue to add to this initial UI code while we are exploring the CoreBluetooth framework in the next sections. ## iPhone as a Bluetooth LE Central Device ### Setting Up Since we are using SwiftUI for our user interface, we will create a separate class as an *Observable Object* to manage Bluetooth connections. This will be a class that will handle all Bluetooth operations that any View can subscribe to in order to get updates about the peripheral device. The reason for having it as an observable object is to trigger a refresh and reload of the UI elements automatically whenever there is any data update. Go to **File --> New --> File** ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a4ee281.png) Choose iOS Swift File for the template. Click Next and save it as BLEManager.swift. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a53778f.png) In this new file, define a new class `BLEManager` that conforms to `NSObject` and `ObservableObject` classes. ```swift import Foundation class BLEManager: NSObject, ObservableObject { } ``` This is our empty class right now. We want to have our iOS device act as a Bluetooth LE Central. So, we need to import the CoreBluetooth framework, define a variable of type `CBCentralManager`, and define the required `CBCentralManagerDelegate` methods. Add the `CBCentralManagerDelegate` to your class definition. ```swift import Foundation import CoreBluetooth class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate { var myCentral: CBCentralManager! } ``` XCode will throw up an error saying: **Type 'BLEManager' does not conform to protocol 'CBCentralManagerDelegate'**. Use the auto-fix feature to get the stubs for the required methods that are currently missing in this class. In this case, the missing method is `centralManagerDidUpdateState`. Xcode will add the following in your class: ```swift func centralManagerDidUpdateState(_ central: CBCentralManager) { } ``` ### Initialising CentralManager When our `BLEManager` class is instantiated we want to initialise its `myCentral` instance variable and assign its delegate to self so that the delegate methods are called. This is done by overriding the default initializers `init()` method to perform the initialisation tasks. Add the following function to your BLEManager class to initialise the central manager. ```swift override init() { super.init() myCentral = CBCentralManager(delegate: self, queue: nil) myCentral.delegate = self } ``` **Note**: If you followed the *[Introduction to Mobile Development for iOS](https://novelbits.io/intro-ble-mobile-development-ios/)* tutorial, we used a single ViewController and included our Bluetooth LE functionality as part of the same class. In this tutorial, we are using a slightly different approach for the definition of Bluetooth LE functions as we are creating a separate class object and observing it through the new SwiftUI framework. The APIs are exactly the same and the only difference is the initial setup. So what we are doing right now is exactly the same process as the other tutorial. Before we finish the initial set up, let’s also add a `boolean` class variable that is set to `true` if Bluetooth is switched on `BLEManager` has been initialised, and false if it is switched off on our iPhone. Since we want to display the status on our UI and automatically update the UI whenever the status changes, we will define it with the `@Published` attribute. ```swift @Published var isSwitchedOn = false ``` The `@Published` variable, as part of an `@ObservableObject` class will trigger an automatic UI refresh whenever its value changes and we can query the value to present the appropriate view. We will assign the values of `isSwitchedOn` in our `didUpdateState` delegate method as follows. ```swift func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } ``` As a checkpoint, make sure your `BLEManager` class looks like the following at this time. ```swift import Foundation import CoreBluetooth class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate { var myCentral: CBCentralManager! @Published var isSwitchedOn = false override init() { super.init() myCentral = CBCentralManager(delegate: self, queue: nil) myCentral.delegate = self } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } } ``` Finally, we need to instantiate this class in our `ContentView`, so go ahead to `ContentView.swift`, and add the following as the first line inside the `ContentView` definition. ```swift @ObservedObject var bleManager = BLEManager() ``` To update the status, we will use a Text object that checks the value of `isSwitchedOn` variable. We can do it like this: ```swift // Status goes here if bleManager.isSwitchedOn { Text("Bluetooth is switched on") .foregroundColor(.green) } else { Text("Bluetooth is NOT switched on") .foregroundColor(.red) } ``` Copy the code above to replace the existing code for the status text in `ContentView.swift`. Now our UI and initial `BLEManager` class is set up and ready for use. Go ahead to build and run the code on your phone to see it in action. ### CoreBluetooth Central Permissions At this point, our app builds successfully but crashes on launch. In your debug console, you will be shown an error as follows. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a5ac313.png) What just happened? We forgot to add the right entitlement for Bluetooth usage in the `Info.plist` file. This is a mandatory requirement so that the users are presented with the right message when permission to access Bluetooth is being asked by the phone. To fix this, go to your `Info.plist` file and add a new row. From the dropdown select "**Privacy - Bluetooth Always Usage Description**" and add a message that you want to be displayed. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a5d4cfc.png) Now let’s try again and this time everything should work well. When you run the app you will see the user interface with the status that Bluetooth is not switched on. You will also be presented with the permissions dialog. Once you grant permission to use Bluetooth, the status should update as shown on the UI to indicate that it is now powered on as shown below. (Note that the relevant key here is `NSBluetoothAlwaysUsageDescription` since iOS13\. Prior to iOS13, the key for Bluetooth permissions was `NSBluetoothPeripheralUsageDescription`. Therefore, for compatibility it is recommended to have both these keys defined in the plist file.) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a5f0dda.jpg) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a63a7a1.jpg) The UI looks good now, however, our list is empty since we haven’t scanned and found any peripheral devices yet. Let’s now find devices to populate our list. ### Scan for Peripheral Devices As in the previous [tutorial](https://novelbits.io/intro-ble-mobile-development-ios/), we will use the `scanForPeripherals` method to start scanning. This will trigger callbacks to the `didDiscoverPeripheral` method where we will keep track of all the devices that we find and then populate our UI with them. The way we will tackle this is by creating an array where we can append the name and RSSI of every device we discover by scanning. Let’s define a struct called Peripheral to hold this information on top of our `BLEManager.swift` file - after the import statements (we can do this in a separate file too but for convenience, we will do it here). ```swift struct Peripheral: Identifiable { let id: Int let name: String let rssi: Int } ``` Our struct has three variables, with the **name** and **rssi** being the obvious ones. The **id** is of type `Int` which is added because we are subclassing from the Identifiable class. The reason for doing this is purely for user interface purposes. We have a List view in our UI that will have several rows. Each row needs to have a separate identifier so that when we pass this our array of Peripheral objects as the data source of our List, it becomes super easy to display them. An excellent explanation of working with Identifiable items can be found here: [https://www.hackingwithswift.com/books/ios-swiftui/working-with-identifiable-items-in-swiftui](https://www.hackingwithswift.com/books/ios-swiftui/working-with-identifiable-items-in-swiftui?ref=novelbits.io) Now, declare an array for Peripheral objects in the `BLEManager` class. We will do this with the `@Published` attribute as well so that the UI is refreshed when new peripherals are discovered. ```swift @Published var peripherals = [Peripheral]() ``` Now we will define the operation of the `didDiscoverPeripheral` delegate method. If you start typing `didDiscover`, Xcode will start showing a list of methods from where you can select the right method to autocomplete its definition. Fill up this method as follows. ```swift func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { var peripheralName: String! if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String { peripheralName = name } else { peripheralName = "Unknown" } let newPeripheral = Peripheral(id: peripherals.count, name: peripheralName, rssi: RSSI.intValue) print(newPeripheral) peripherals.append(newPeripheral) } ``` What we are doing here is that as soon as we discover a new peripheral, we define a new Peripheral object with its name as the name being advertised by the peripheral and its rssi as `peripheral.rssi`. Note that we are using `CBAdvertisementDataLocalNameKey` key to access the name being advertised. We can also use `peripheral.name` but this may return the name of the device that exists in its database as the GAP device name. We also assign the `id` as the length of the array making the id unique. Finally, we append this `newPeripheral` to our `peripherals` array. What we are doing here is appending the name of every peripheral we find in our scan and the peripheral rssi to the array of structs. Since this array is `@Published` and is part of an `@ObservableObject`, any changes to it will trigger a UI refresh automatically. We still haven’t fed this array as the data source, so go into your `ContentView.swift` file and replace the List object we had earlier with the following. ```swift List(bleManager.peripherals) { peripheral in HStack { Text(peripheral.name) Spacer() Text(String(peripheral.rssi)) } }.frame(height: 300) ``` Briefly, what is happening here is that we have a List view with its data source as `bleManager.peripherals` array. For each element (`peripheral`) in this array, we define a row as HStack (horizontal stack of elements) where we display a Text view with the peripheral name, some space, and then a Text view with the peripheral RSSI. That’s pretty much it, our list view is ready to use. One final piece of the puzzle left is that we still don’t have a method to start the scanning. We have a Button which we wish to use to do this. So let’s go to `BLEManager` and define a function called `startScanning()` as follows. ```swift func startScanning() { print("startScanning") myCentral.scanForPeripherals(withServices: nil, options: nil) } ``` And another one called `stopScanning()` as follows. ```swift func stopScanning() { print("stopScanning") myCentral.stopScan() } ``` Now we just need to add these functions as the corresponding Button actions in our user interface. Make the following changes to the Start/Stop scanning buttons in `ContentView.swift`. ```swift Button(action: { self.bleManager.startScanning() }) { Text("Start Scanning") } Button(action: { self.bleManager.stopScanning() }) { Text("Stop Scanning") } ``` That was a bit of work there setting up everything on the UI and linking it to our `BLEManager`. Build and run on your phone, and press start scanning. Keep an eye on your debug console as well to see which functions are being executed (the print statements have been added to help with that). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a67e0d5.png) As you can see several devices are quickly shown on the list (which is scrollable) so you can move up and down to view the complete list. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835a6a825b.jpg) **Congratulations**! You have set up the very basics of scanning as a Central Manager and displaying the list on your phone. ## Source Code `**ContentView.swift**`: ```swift import SwiftUI struct ContentView: View { @ObservedObject var bleManager = BLEManager() var body: some View { VStack (spacing: 10) { Text("Bluetooth Devices") .font(.largeTitle) .frame(maxWidth: .infinity, alignment: .center) List(bleManager.peripherals) { peripheral in HStack { Text(peripheral.name) Spacer() Text(String(peripheral.rssi)) } }.frame(height: 300) Spacer() Text("STATUS") .font(.headline) // Status goes here if bleManager.isSwitchedOn { Text("Bluetooth is switched on") .foregroundColor(.green) } else { Text("Bluetooth is NOT switched on") .foregroundColor(.red) } Spacer() HStack { VStack (spacing: 10) { Button(action: { self.bleManager.startScanning() }) { Text("Start Scanning") } Button(action: { self.bleManager.stopScanning() }) { Text("Stop Scanning") } }.padding() Spacer() VStack (spacing: 10) { Button(action: { print("Start Advertising") }) { Text("Start Advertising") } Button(action: { print("Stop Advertising") }) { Text("Stop Advertising") } }.padding() } Spacer() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } ``` `**BLEManager.swift**`: ```swift // // BLEManager.swift // BLE_Background // // Created by Mohammad Afaneh on 5/6/20. // Copyright © 2020 NovelBits. All rights reserved. // import Foundation import CoreBluetooth struct Peripheral: Identifiable { let id: Int let name: String let rssi: Int } class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate { var myCentral: CBCentralManager! @Published var isSwitchedOn = false @Published var peripherals = [Peripheral]() override init() { super.init() myCentral = CBCentralManager(delegate: self, queue: nil) myCentral.delegate = self } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { isSwitchedOn = true } else { isSwitchedOn = false } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { var peripheralName: String! if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String { peripheralName = name } else { peripheralName = "Unknown" } let newPeripheral = Peripheral(id: peripherals.count, name: peripheralName, rssi: RSSI.intValue) print(newPeripheral) peripherals.append(newPeripheral) } func startScanning() { print("startScanning") myCentral.scanForPeripherals(withServices: nil, options: nil) } func stopScanning() { print("stopScanning") myCentral.stopScan() } } ``` ## Summary & Closing In this tutorial, we covered a lot, including: - Setting up an Xcode project - Setting up an iOS device as a Bluetooth LE Central to scan for Peripherals - Designing a UI that supports starting the scanning process, stopping the scanning process, and listing the discovered Peripherals - Display the Bluetooth status on the iOS device (whether it's on or off) 💡 **Insider Tip:** Want to go beyond scanning and build a complete Bluetooth LE iOS app with GATT services, data transfer, and peripheral mode? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### How Bluetooth Low Energy Works: 21 Interesting Facts URL: https://novelbits.io/how-bluetooth-low-energy-works-21-interesting-facts/ Last updated: 2026-08-09T05:25:03.000Z Whether you're a beginner or an expert in Bluetooth Low Energy development, it's always good to take a step back and revisit some of the basics and facts. In this post, I'll be going through a list of 21 facts about Bluetooth Low Energy technology. You may know about all of these, but it's always good to get a refresher from time to time. 1. **Bluetooth Low Energy is backward-compatible** What this means is that if you develop a BLE device today that is running the latest version of Bluetooth (5.2), you are guaranteed that you can interact with another BLE device that's running the very first version that supported BLE (Bluetooth version 4.0). There are exceptions to this rule, specifically when one of the devices implements an optional feature of a specific Bluetooth version, but when it comes to the core functionality, the backward-compatibility is guaranteed by the spec. 2. **Bluetooth Low Energy is capable of achieving ranges of over 1 kilometer** When most people think of BLE, they think short-range communication, and due to good reasons, since the earlier Bluetooth specifications focused on these kinds of applications. However, with Bluetooth 5.0, a new mode called long-range mode (Coded PHY) was introduced and allowed BLE devices to communicate at much longer ranges, up to 1.5 km line-of-sight. 3. **Bluetooth Low Energy supports point-to-point, star, and mesh topologies** Bluetooth Low Energy is one of the few low-power wireless technologies to support multiple topologies that can address many different applications. It natively supports point-to-point communication such as between your smartphone and your fitness tracker. Also, it supports one-to-many topologies such as a Bluetooth Low Energy hub interfacing with multiple smart home devices at the same time. Finally, BLE also supports a many-to-many topology (mesh) with the introduction of the Bluetooth mesh specification in July 2017. 4. **Bluetooth Low Energy advertising packets contain up to 31 bytes of data** This is the standard size of the advertising payload for packets sent on the Primary Advertising channels (37, 38, and 39). However, keep in mind that the 31 bytes will include at least two bytes: one for length, and another for type. This leaves 29 bytes for user data. Also, keep in mind that if you have multiple fields of different advertising data types, then each of these types will use up two additional bytes for the length and type of each. For advertising packets sent on the Secondary Advertising channels (introduced in Bluetooth 5.0), the payload goes up to 254 bytes instead of 31 bytes. 5. **Bluetooth 5.0 introduced two new modes: high-speed and long-range** In Bluetooth version 5.0, two new modes were introduced (each utilizes a new PHY): high-speed mode (2M PHY) and long-range mode (Coded PHY). 6. **Bluetooth Low Energy can achieve a throughput of up to 1.4 Mbps** With the introduction of the 2M PHY in Bluetooth 5.0, a throughput of up to 1.4 Mbps can be achieved. If using the standard 1M PHY, then the maximum user-data throughput is around 700 kbps. The reason the throughputs are not up to the 2M or 1M is that the packets include header overhead and gaps in between the packets, so the user-level data throughput is reduced. 7. **Many new features introduced in new versions of Bluetooth are optional** When looking for a Bluetooth Low Energy chipset, it's important to keep in mind that an advertised Bluetooth version supported by the chipset does not necessarily mean that a specific feature of that version is supported. For example, the 2M PHY and Coded PHY are both optional features in Bluetooth 5.0, so make sure that you study the datasheet and specs of a chosen Bluetooth Low Energy chipset to make sure it supports the Bluetooth features you're interested in. 8. **100% of shipped smartphones, laptops, and tablets will support both Bluetooth Low Energy and Bluetooth Classic in 2024** Per the most recent [Bluetooth Market Update](https://www.bluetooth.com/bluetooth-resources/2020-bmu/?ref=novelbits.io) report, 100% of all new platform devices will support Bluetooth Classic + LE by 2024. 9. **There is no defined maximum number of connections between a Central and Peripherals per the Bluetooth spec** The Bluetooth specification does not dictate a limit to the number of connections between a BLE central and BLE peripherals. However, your device will probably be limited by the amount of memory available and the Bluetooth stack implementation. So, make sure you check your chipset vendor's documentation and datasheets for the limits imposed by the stack and memory available. 10. **Anyone can download the latest official Bluetooth specification documents for free** Unlike many other low-power wireless technologies, the Bluetooth SIG provides access to the official Bluetooth specification documents for anyone to download, for free. You can download the latest Bluetooth Core Specification documents here: [https://www.bluetooth.com/specifications/bluetooth-core-specification/](https://www.bluetooth.com/specifications/bluetooth-core-specification/?ref=novelbits.io) 11. **What is the Bluetooth SIG?** The Bluetooth SIG (Special Interest Group) is the non-profit organization behind managing the technical specification, marketing, and qualification/certification of Bluetooth products. But did you know that the technical specifications are actually created and developed by working groups run by Bluetooth member companies such as Apple, Google, Samsung, Qualcomm, etc.? 12. **Certification fees for a Bluetooth product are fixed per product listing** Certification fees for a Bluetooth product which include qualification and listing fees are not on a royalty-basis, but rather are per product shipped. 13. **Bluetooth beacons have become the most popular solution for indoor navigation and asset tracking** Over the past few years, and especially since Apple released the popular iBeacon standard (which is based on BLE), the utilization of Bluetooth beacons has become the most popular solution for indoor navigation and asset tracking applications. 14. **Bluetooth Low Energy operates in the 2.4 GHz ISM band shared by a few other wireless technologies including Zigbee and Wi-Fi** The one characteristic that distinguishes Bluetooth Low Energy from other similar wireless technologies is the utilization of a technique called *frequency hopping*. This technique allows it to coexist with the other RF signals in the area while still maintaining a robust connection between two Bluetooth devices. 15. **The Bluetooth Low Energy spectrum is divided into 40 RF channels** Three of these channels are called Primary Advertising channels. The remaining 37 channels are used for Secondary advertisements and data packets transmitted during a connection. Each of these channels is 2MHz wide. 16. **Long-range mode (Coded PHY) can be used for enhancing reliability** Coded PHY can be used not only for enhancing the range of Bluetooth Low Energy communication but also for increasing the reliability of connections and advertisements through multiple obstacles. When operating on the Coded PHY, the receiver sensitivity is increased and the transmitted packets utilize a Forward Error Correction mechanism, which both allow for the recovery of the original data from a corrupt packet. 17. **You can switch between using the three PHYs: Coded PHY, 1M PHY, and 2M PHY on the fly during a connection** This is a powerful feature that provides flexibility to Bluetooth developers. It allows devices to adjust and adapt based on the environment and implemented application. The capability, however, depends on both devices in a connection supporting the PHY being switched to. 18. **You can utilize different PHYs to be used in each direction** The Bluetooth specification allows a PHY update procedure that can be sent from the master or requested by the slave to use different PHYs in each direction of data transmission (master --> slave vs. slave --> master). 19. **Bluetooth Classic (BR/EDR) and Bluetooth Low Energy are not compatible** This means that a Bluetooth Classic device cannot interact with a Bluetooth Low Energy device and vice versa. That is why most smartphones, tablets, and PCs nowadays include dual-mode Bluetooth radios which allow the phone to interact with both types of devices. 20. **A guide for developing a BLE peripheral that interacts with an iOS device** If you are developing a Bluetooth Low Energy peripheral device that will be interfaced with an iOS mobile app, you should check out Apple's Accessory Design Guidelines document: [https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf](https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf?ref=novelbits.io). In this document, Apple lays out recommendations for the different Bluetooth Low Energy parameters including preferred connection parameters, advertising intervals, advertising types, etc. 21. **This one parameter allows your BLE peripheral to consume less power while still being able to achieve low latency** For optimal power consumption by a Bluetooth Low Energy peripheral, while also being able to achieve low latency, you can define a non-zero *Slave Latency* value. The Slave Latency parameter allows the slave to skip a number of connection events when no data is available for transfer. This ensures that even when the slave skips those connection events, the master will not consider the connection lost. However, a non-zero value still allows the slave to wake up and transfer data at every connection interval when needed and achieving low latency. For example, if you set a Slave Latency value of 3 and a connection interval of 15 ms, then if the slave does not have any data during the 15 ms, it can skip up to 3 consecutive connection intervals and then waking up the radio and sending data after around 45 ms. Hopefully you've learned something new from these facts, or at least refreshed your memory on some of these facts. --- 💡 **Insider Tip:** Want to dig deeper into Bluetooth LE and learn more about the technical details, including implementation on both mobile and embedded devices? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### How Bluetooth Low Energy Works: Advertisements (Part 1) URL: https://novelbits.io/bluetooth-low-energy-advertisements-part-1/ Last updated: 2026-08-09T05:24:03.000Z To fully understand advertisements in BLE, we need to take a step back and learn about one of the layers within the architecture of BLE: the **Generic Access Profile (GAP)**. ![Image](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/embeddable_852d4ee6-5455-496c-80f3-640ae33c67cc.jpg) GAP provides a framework that defines how BLE devices interact with each other. This includes: - Roles of BLE devices - Advertisements (Broadcasting, Discovery, Advertisement parameters, Advertisement data) - Connection establishment (initiating connections, accepting connections, Connection parameters) - Security There are four main GAP roles that a BLE device operates in: - **Central**: a device that discovers BLE peripherals and broadcasters capable of connecting to peripherals. - **Peripheral:** a device that advertises its existence with the capability of accepting connections from a central. - **Broadcaster**: a device that sends out advertising packets without the capability of accepting connections. - **Observer**: a device that discovers peripherals and broadcasters without initiating any connections. A peripheral or broadcaster always starts with advertising before accepting a connection. In fact, the advertisement packets are the only way that allows a central or scanner to discover a peripheral or broadcaster. The difference between two BLE devices being in a connected mode versus in an advertising-discovery mode is that the connected mode allows **bi-directional** data transfer between the two connected devices. An advertising device (peripheral or broadcaster), on the other hand, is not able to receive any data from the observer/central device in that state. One exception to this is that if an advertiser/broadcaster supports what's called "scan requests", it is able to "respond" to a "scan request" packet that can be sent by the central/observer with a "scan response". This is usually employed in order to transmit additional data in scenarios when you can't fit all your data within the original advertising packet. So I guess in a sense, this could be considered "bi-directional". ## Advertisement Channels In the Advertising state, a device sends out packets containing useful data for others to receive and process. The packets are sent at a fixed interval defined as the Advertising Interval. There are 40 RF channels in BLE, each separated by 2 MHz (center-to-center), as shown in the following figure. ![BLE RF Channels](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ble-rf-channels.png) Advertising Channels in BLE Three of these channels are called the **Primary Advertising Channels** (labeled 37, 38, and 39), while the remaining 37 channels are called the **Secondary Advertisement** **Channels** (they are also the ones used for data transfer during a connection). Secondary advertising channels are used as "auxiliary" channels meaning that a device has to first advertise on the primary advertising channels before sending out advertising packets on the secondary channels. If a device wants to utilize the secondary advertising channels, it sends out advertising packets on the primary channels that *point* to the secondary advertising packets. We'll go over how this exactly works in a later section. ## Advertising Packet Format Let's look at the format of the advertising packets: ![BLE Uncoded PHY Packet Format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/uncoded-phy-packet-format-1.png) Source: Bluetooth Core Specification document The PDU (Protocol Data Unit) field is what we're interested in. This is the field that changes depending on the type of packet being transmitted (data vs. advertising) and the one that includes the "user-data" that your application is interested in sending out. Even though the top diagram within the figure is for Uncoded PHY, the PDU is still the same for the Coded PHY case (if you're not familiar with Coded PHY, it is a new PHY that was introduced in Bluetooth version 5.0 and is useful in long-range communication and/or in noisy environments – refer to my post on [Long-range Bluetooth communication](https://novelbits.io/bluetooth-long-range-coded-phy/) for more information). Let's define each of the fields within the PDU: ### PDU Header **PDU Type**: this field is 4 bits in length and has the following possible values: ![BLE Advertising PDU Types](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/adv-pdus.png) Source: Bluetooth Core Specification document The PDUs are split up into multiple categories depending on the purpose. Before we list each of the PDUs, let's cover some common terminology: - **Directed vs. Undirected**: Directed advertising types accept connection requests from a known peer device, whereas Undirected accept connection requests from any peer device. - **Connectable vs. Non-Connectable**: determines whether an advertising device allows a connection to be established or not. - **Scannable vs Non-Scannable**: determines whether an advertising device is capable of handling a Scan Request message from an observer or central. Scan Requests and Responses are used to allow devices to advertise more data than can fit into one advertising packet. - **Extended advertising**: Extended Advertisements are a way to advertise more (offloaded) data than what’s allowed with Legacy Advertisements. Offloading is accomplished by first advertising on the primary channel that points to an auxiliary packet on the secondary channel. **Note:** Since *non*\-Bluetooth 5 devices will not be able to discover extended advertisements, it is recommended that advertisers also use an advertising set with legacy advertising PDUs for older scanning devices to be able to discover the end device. Advertising sets are used to send out different types of advertising events simultaneously. Each advertisement set will have different advertisement parameters such as advertising PDU type, advertising interval, and PHY. - **Periodic advertising**: Another feature of Bluetooth 5 Extended Advertisements is Periodic Advertisements. These are used for broadcasting packets to devices at a set period between two unconnected devices, meaning that more than one device can listen and tune in on these periodic advertisements. They consist of advertisements sent at a fixed interval with the advertisement data changing from time to time. **Legacy Advertising PDUs** These are available for all Bluetooth versions – also enables backward compatibility with older versions and are used on the **Primary** advertisingchannels. - `ADV_IND`: Connectable Scannable Undirected advertising. - `ADV_DIRECT_IND`: Connectable Directed advertising - `ADV_NONCONN_IND`: Non-Connectable Non-Scannable Undirected advertising - `ADV_SCAN_IND`: Scannable Undirected advertising **Extended Advertising PDUs** These types were introduced in Bluetooth version 5.0\. They provide devices the option to advertise on the Secondary advertising channels in addition to the Primary advertising channels. The benefit of the Secondary channels is that they allow increased advertising data capacity. - `ADV_EXT_IND`: Extended advertising (used for all advertising types except Connectable Scannable Undirected) – sent on the **Primary** advertising channels. - `AUX_ADV_IND`: Extended advertising (used for all advertising types except Connectable Scannable Undirected) – sent on the **Secondary** advertising channels. - `AUX_SYNC_IND`: used for Periodic advertising - `AUX_CHAIN_IND`: used with other advertising types to hold additional advertising data (chaining of advertising packets) **Scanning PDUs** These are used to utilize the **Scan Request → Scan Response** functionality, which enables devices to broadcast more advertising data than is allowed in a single advertising packet. - `SCAN_REQ`: used in Scan Request packets sent on the **Primary** advertising channels - `SCAN_RSP`: used in Scan Response packets sent on the **Primary** advertising channels - `AUX_SCAN_REQ`: used in Scan Request packets sent on the **Secondary** advertising channels - `AUX_SCAN_RSP`: used in Scan Response packets sent on the ****Secondary** advertising channels **Initiating PDUs** These are used in establishing a connection between a peripheral device and a central device. - `CONNECT_IND`: this is the connection request packet sent on one of the **Primary** advertising channels - `AUX_CONNECT_REQ`: this is the connection request packet sent on one of the **Secondary** advertising channels - `AUX_CONNECT_RSP`: this is the connection response packet sent by the peripheral on one of the **Secondary** advertising channels **RFU**: Reserved for future use **ChSel**: this bit will be set to **1** if the advertiser supports the LE Channel Selection Algorithm #2 feature (refer to the Bluetooth Core Specification Vol. 6, Part B, Section 4.5.8.3). **TxAdd**: this bit is set to **1** if the advertiser's address is **random**, and set to **0** if the address is **public** **RxAdd**: this bit is set to **1** if the target device's address is **random**, and set to **0** if the address is **public** **Length**: holds the Length of the payload of the packet. ### PDU Payload The content of the payload of the advertising packet and its maximum size are dependent on the PDU type used. The advertising data includes the information the advertiser wants to relay to the observer/central device. Here we're mostly interested in the PDU types that contain advertising data. Those PDUs are: - Legacy advertising PDUs including: `ADV_IND`, `ADV_NONCONN_IND`, `ADV_SCAN_IND` - Extended advertising PDUs including: `ADV_EXT_IND`, `AUX_ADV_IND`, `AUX_SYNC_IND`, `AUX_CHAIN_IND` #### Advertising Data There are a number of standard data types that can be included in the advertising data. The data is formatted as follows: ![BLE Advertising Data Format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Shot-2019-10-07-at-11.39.51-AM.png) Source: Bluetooth Core Specification Document These are defined in a specification document that's separate from the Core Specification document called the **Core Specification Supplement** ([https://www.bluetooth.com/specifications/bluetooth-core-specification/](https://www.bluetooth.com/specifications/bluetooth-core-specification/?ref=novelbits.io)). The different BLE advertising data types are: - **Service UUID**: used to include a list of Service UUIDs - **Local Name**: the device name (either *Shortened* or *Complete*) - **Flags**: one-bit flags that are included when an advertising packet is connectable. The flags are: LE Limited Discoverable Mode, LE General Discoverable Mode, BR/EDR Not Supported, Simultaneous LE and BR/EDR to Same Device Capable (Controller), Simultaneous LE and BR/EDR to Same Device Capable (Host). - **Manufacturer Specific Data**: used to include custom data identified by a [company identifier](https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/?ref=novelbits.io). - **TX Power Level**: transmit power level - **Slave Connection Interval Range**: a way to communicate the Peripheral's preferred connection interval range in advertising packets. - **Service Solicitation**: used to "invite" centrals that expose one or more of the specified Services to connect. - **Service Data**: includes a Service UUID and the data associated with the service. - **Appearance**: defines the "type" of the advertising device per the standard [Appearance assigned number](https://www.bluetooth.com/specifications/assigned-numbers/?ref=novelbits.io)[s](https://www.bluetooth.com/specifications/assigned-numbers/?ref=novelbits.io). - **Public Target Address**: defines the address of one or more intended recipients of an advertisement when one or more devices were bonded using a public address. - **Random Target Address**: defines the address of one or more intended recipients of an advertisement when one or more devices were bonded using a random address. - **Advertising Interval**: *self-explanatory*. - **Uniform Resource Identifier**: used to broadcast a URI such as a URL. - **LE Supported Features**: defines the LE-specific features supported by the device. These are defined in the Core Specification (Vol. 6, Part B, Section 4.6). Ok, that's it for this week's post. We'll be covering more in Part 2 of this series, including: - Examples of advertising packets - How to use advertising packets efficiently - Extended advertising packets - Advertising parameters - and more... Interactive Tool BLE Advertisement Builder Build and decode Bluetooth LE advertisement packets visually. Select AD types, set flags, and see the raw byte output in real time. [Launch the Builder →](https://novelbits.io/ble-advertisement-builder/) ## Frequently Asked Questions What is directed advertising in Bluetooth LE? Directed advertising targets a specific device (by its Bluetooth address) rather than broadcasting to all nearby devices. It is used to quickly reconnect to a previously bonded device. Directed ads carry minimal data — only the advertiser and target addresses — and are sent at a high duty cycle for fast reconnection. What is the difference between legacy and extended advertising? Legacy advertising (Bluetooth 4.x) uses only the 3 primary advertising channels (37, 38, 39) and supports up to 31 bytes of ad data. Extended advertising (Bluetooth 5.0+) can offload data to secondary advertising channels (0-36), supporting up to 254 bytes per fragment and chain multiple fragments for even larger payloads. How many advertising channels does Bluetooth LE use? Bluetooth LE has 40 RF channels total. Three are primary advertising channels (37, 38, and 39), chosen for minimal overlap with common Wi-Fi channels. The remaining 37 channels (0-36) are used for data connections and, with Bluetooth 5.0 extended advertising, also for secondary advertising. What is the maximum advertising data size in Bluetooth LE? With legacy advertising, the maximum payload is 31 bytes (plus an additional 31 bytes via scan response). With Bluetooth 5.0 extended advertising, up to 254 bytes can be sent per fragment, and multiple fragments can be chained to send up to 1,650 bytes total of advertising data. ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. 📚 **Continue the series:** In [Part 2](https://novelbits.io/bluetooth-low-energy-advertisements-part-2/), we cover real-world advertising examples, broadcasting vs. connectable behavior, discoverable modes, and advertising parameters. 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE advertising and beyond? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) ### A Deep Dive Into Eddystone Beacons (nRF52 + Zephyr use case) URL: https://novelbits.io/eddystone-beacons-zephyr-nrf52/ Last updated: 2026-08-09T05:44:08.000Z As a continuation of our series on Bluetooth beacons (check out our [guide to Bluetooth beacon technology](https://novelbits.io/what-is-a-beacon-guide-to-bluetooth-beacon-technology/) and our [Eddystone tutorial using the Silicon Labs BG22](https://novelbits.io/eddystone-beacon-tutorial-silicon-labs-bg22/)), today we'll be covering Google's Eddystone standard in more detail along with implementation using Zephyr RTOS and the nRF52. The Eddystone standard was released as an alternative and competitor to Apple's iBeacon standard. It provides similar functionality to iBeacon, but also goes a step beyond and adds some unique features. With Eddystone, you can still build similar functionality to include two levels of hierarchy. This includes a 16-byte Beacon ID which is composed of a 10-byte namespace and a 6-byte instance. Eddystone provides four frame types: - **Eddystone-UID**: this type is similar to iBeacon's UUID + Major + Minor setup. It defines a 16-byte Beacon ID composed of a 10-byte namespace and a 6-byte instance. For example, the namespace could define a nationwide retailer's ID for its stores and the instance would refer to each store uniquely. - **Eddystone-URL**: this type provides a way to broadcast a URL to be discovered by a Bluetooth LE scanner device, which in turn could navigate to the URL and present the webpage to the user. - **Eddystone-TLM**: this type provides telemetry information about the device such as battery level, temperature and a running counter of advertised packets. - **Eddystone-EID**: this type provides a framework for attaining a certain level of security and privacy of a device. EID stands for Ephemeral ID, which is an identifier that changes periodically at a rate determined during the deployment phase by registering it with a trusted web service. **NOTE:** Even though Google has pretty much abandoned the Eddystone standard on smartphones (specifically Android and Chrome), it can still serve as a good format for applications where you control both sides (broadcaster devices + scanner devices) and that do not depend on smartphone apps. It also serves as a great exercise for learning more about how Bluetooth advertisements work and how to utilize them for your own application. In this tutorial, we'll focus on **Eddystone-UID** and **Eddystone-URL** frame types. Here's what we'll cover today: - [Eddystone Format](#eddystone-format-384cc33d-ade4-44a6-9192-855e071a73cf) - [Service Data](#service-data-dab73e33-ca7b-4753-88c1-353026710d0a) - [Eddystone-UID](#eddystoneuid-83e21cda-a212-49b9-a86b-62f5f0a64689) - [Eddystone-URL](#eddystoneurl-5ef262f5-c7f8-4fcb-b593-8cac4bb23381) - [Eddystone-TLM and Eddystone-EID](#eddystonetlm-eddystoneeid-aaa85f04-9e47-4eb4-bc6c-6832e289639c) - [Implementing Eddystone on nRF52 using Zephyr RTOS](#implementing-eddystone-on-nrf52-using-zephyr-rtos-e244b4a6-8aee-49c8-9df1-7e42aef47208) - [Eddystone-UID Example](#eddystoneuid-example-a9fc2bb8-c6f3-4fa3-9887-e22c9ee34870) - [Take your Bluetooth LE knowledge to the next level](#take-your-ble-knowledge-to-the-next-level-09f30291-ec53-4dfb-a49d-fff35cba11a2) ## Eddystone Format In order to better understand how Eddystone broadcasting devices work, we need to look at the details of the advertising packets involved. Here's what the format of an Eddystone advertisement packet looks like: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/eddystone-format-2.png) Eddystone Advertisement Packet Format The part shown in the figure above is constant for all Eddystone advertisement packets, except for the **Service Data** portion. Advertisement data follows the format Length-Type-Value (similar to the popular [TLV format](https://en.wikipedia.org/wiki/Type-length-value?ref=novelbits.io)). The **Length** value indicates the length of the data that includes both the **Type** and the **Payload**. The Eddystone standard utilizes the Service Data Advertisement data type to send the data to the Bluetooth LE scanner devices. iBeacon, on the other hand, utilizes the Manufacturer Data Advertisement data type. Now, let's look at the Service Data portion which includes the information we're interested in parsing at the receiver end. ### Service Data The Service Data portion format depends on the frame type used (Eddystone-UID, Eddystone-URL, Eddystone-TLM, or Eddystone-EID). The first byte of the Service Data field always includes the frame type, which is defined as following: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-12-at-10-21-12-pm.png) Eddystone Frame Type Value (1 byte) *Source: [Eddystone Specification](https://github.com/google/eddystone/blob/master/protocol-specification.md?ref=novelbits.io#common-elements)* #### Eddystone-UID As we mentioned earlier, this frame type is used in a similar way as Apple's iBeacon. It includes the following: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-12-at-10-18-55-pm.png) Eddystone-UID Service Data Format *Source: [Eddystone Specification](https://github.com/google/eddystone/tree/master/eddystone-uid?ref=novelbits.io#frame-specification)* When using this frame type, we can utilize the 10-byte namespace for a unique ID of our choice (e.g. to indicate a specific store identifier), and then use the 6-byte as an identification of a subset of the namespace (e.g. to identify an aisle within the store). **Notes:** - This frame type utilizes the maximum 31 bytes of advertisement data available in a Bluetooth LE (primary) advertisement packet. - The **Ranging Data** field is the Tx power measured at 0 meters from the transmitter (-100 dBm to +20 dBm). Per the Eddystone specification, the best way to determine the value to include in this field is to measure the actual RSSI at 1 meter and then add 41 dBm to the value (based on the assumption that 41 dBm is the signal loss that occurs over 1 meter). - For more information and recommendations on the generation of the namespace ID and instance ID, refer to the Eddystone specification [here](https://github.com/google/eddystone/tree/master/eddystone-uid?ref=novelbits.io). **Important Note**: The Tx power value uses a two’s complement format to represent signed values. For more information on this calculation, refer to the [Two’s Complement section on Wikipedia](https://en.wikipedia.org/wiki/Two%27s%5Fcomplement?ref=novelbits.io#Converting%5Fto%5Ftwo's%5Fcomplement%5Frepresentation). #### Eddystone-URL The Eddystone-URL frame type is unique and different from the use of the Eddystone-UID or Apple's iBeacon format. It is used to advertise a URL for the scanner to discover and parse, then potentially point a web browser to. This frame type is primarily used in "**Physical Web**" applications and implementations. Since the maximum Bluetooth LE advertisement data length is 31 bytes, this limits the URLs that can be broadcast using this frame type. However, the format provides some level of compressed encoding to make the most of the limited space available for the advertisement data. Here's the format used for this frame type: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-12-at-10-41-26-pm.png) Eddystone-URL Frame Type Format *Source: [Eddystone Specification](https://github.com/google/eddystone/tree/master/eddystone-url?ref=novelbits.io#frame-specification)* The Tx power value is represented in the same way we described in the Eddystone-UID section above. The URL scheme is defined as follows: \- Different prefixes for URLs are represented as follows: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-12-at-11-02-52-pm.png) URL Scheme Prefix *Source: [Eddystone Specification](https://github.com/google/eddystone/tree/master/eddystone-url?ref=novelbits.io#url-scheme-prefix)* \- The main portion of the URL is then included as a sequence of characters. For example, "google" would be represented as a sequence of 'g' 'o' 'o' 'g' 'l' 'e', which would be converted to their ASCII values. \- Finally, the URL expansion (e.g. **.com/** or **.com**) is represented as follows: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-12-at-11-06-52-pm.png) HTTP URL Expansion values *Source: [Eddystone Specification](https://github.com/google/eddystone/tree/master/eddystone-url?ref=novelbits.io#eddystone-url-http-url-encoding)* For example, if we wanted to represent "https://www.google.com/" with a Tx power of 0 dBm, the Service Data array would look like this: | Frame Type (URL) | Tx power | https://www. | g | o | o | g | l | e | .com/ | | ---------------- | -------- | ------------ | ---- | ---- | ---- | ---- | ---- | ---- | ----- | | 0x10 | 0x00 | 0x01 | 0x67 | 0x6f | 0x6f | 0x67 | 0x6c | 0x65 | 0x00 | Example Eddystone-URL Service Data field value #### Eddystone-TLM and Eddystone-EID Eddystone-TLM frames are used for broadcasting telemetry data useful for monitoring the health of beacons in the field. This frame does not contain any identifier, so it is paired with either Eddystone-URL, Eddystone-UID, or Eddystone-EID frames. When paired with EID frames, the Eddystone-TLM packet is encrypted. When paired with URL or UID frames, however, the TLM packets are unencrypted. To learn more about these types, refer to the following links: - [Eddystone-EID specification](https://github.com/google/eddystone/tree/master/eddystone-eid?ref=novelbits.io) - [Eddystone-TLM specification](https://github.com/google/eddystone/tree/master/eddystone-tlm?ref=novelbits.io) - [Unencrypted TLM specification](https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md?ref=novelbits.io) - [Encrypted TLM specification](https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-encrypted.md?ref=novelbits.io) ## Implementing Eddystone on nRF52 using Zephyr RTOS For the practical part of this tutorial, we'll be using: - An nRF52840 development kit (you could use any Zephyr-supported board, but you'll have to change the board type in the build command arguments). - Zephyr RTOS. - Smartphone with a Bluetooth LE scanner app – we'll be using nRF Connect for iOS. **Note:** If you have not worked with Zephyr before, then check out my previous post on [Getting Started with Bluetooth LE development in Zephyr](https://novelbits.io/zephyr-getting-started-bluetooth-low-energy-development/). Zephyr already provides an example of setting up an Eddystone-URL advertisement, so we'll be using this as our starting point. The example is located at `/zephyr/samples/bluetooth/beacon`. To build the example, navigate to the `/zephyr/` folder, then run the following: ```bash $ west build -p auto -b nrf52840_pca10056 samples/bluetooth/beacon ``` Output: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-13-at-4-08-38-pm.png) Let's take a look at the example's source code first before we flash and run it on the development board. `main.c`: ```c /* main.c - Application main entry point */ /* * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) /* * Set Advertisement data. Based on the Eddystone specification: * https://github.com/google/eddystone/blob/master/protocol-specification.md * https://github.com/google/eddystone/tree/master/eddystone-url */ static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe), BT_DATA_BYTES(BT_DATA_SVC_DATA16, 0xaa, 0xfe, /* Eddystone UUID */ 0x10, /* Eddystone-URL frame type */ 0x00, /* Calibrated Tx power at 0m */ 0x00, /* URL Scheme Prefix http://www. */ 'z', 'e', 'p', 'h', 'y', 'r', 'p', 'r', 'o', 'j', 'e', 'c', 't', 0x08) /* .org */ }; /* Set Scan Response data */ static const struct bt_data sd[] = { BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), }; static void bt_ready(int err) { if (err) { printk("Bluetooth init failed (err %d)\n", err); return; } printk("Bluetooth initialized\n"); /* Start advertising */ err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; } printk("Beacon started\n"); } void main(void) { int err; printk("Starting Beacon Demo\n"); /* Initialize the Bluetooth Subsystem */ err = bt_enable(bt_ready); if (err) { printk("Bluetooth init failed (err %d)\n", err); } } ``` As you can see, the code is very simple. Let's change the URL to "https://www.google.com/" to match our example in the previous section. ```c /* * Set Advertisement data. Based on the Eddystone specification: * https://github.com/google/eddystone/blob/master/protocol-specification.md * https://github.com/google/eddystone/tree/master/eddystone-url */ static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe), BT_DATA_BYTES(BT_DATA_SVC_DATA16, 0xaa, 0xfe, /* Eddystone UUID */ 0x10, /* Eddystone-URL frame type */ 0x00, /* Calibrated Tx power at 0m */ 0x01, /* URL Scheme Prefix https://www. */ 'g', 'o', 'o', 'g', 'l', 'e', 0x00) /* .com/ */ }; ``` Now, that we have made some changes, we need to rebuild the application. Again, run: ```bash $ west build -p auto -b nrf52840_pca10056 samples/bluetooth/beacon ``` We can now run nRF Connect (iOS, Android, or Desktop) to confirm the changes: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_7212.jpg) nRF Connect discovering an Eddystone-URL advertising As you can see, the URL matches exactly what we updated it to be. Also, the *Type* detected is "**Physical Web**" and the *Frame Type* is **0x10 (URL)**. The device name "**Test beacon**" is set in the `prj.conf` file: ```kconfig CONFIG_BT=y CONFIG_BT_DEBUG_LOG=y CONFIG_BT_DEVICE_NAME="Test beacon" ``` ### Eddystone-UID Example Let's go ahead and update the example to transmit a UID frame type instead of URL: ```c /* * Set Advertisement data. Based on the Eddystone specification: * https://github.com/google/eddystone/blob/master/protocol-specification.md * https://github.com/google/eddystone/tree/master/eddystone-url */ static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe), BT_DATA_BYTES(BT_DATA_SVC_DATA16, 0xaa, 0xfe, /* Eddystone UUID */ 0x00, /* Eddystone-UID frame type */ 0x00, /* Calibrated Tx power at 0m */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, /* 10-byte Namespace */ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f) /* 6-byte Instance */ }; ``` ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_7213.png) nRF Connect discovering an Eddystone-UID advertising As you can see, the *Type* detected is "**Eddystone**" and the *Frame Type* is **0x00** **(UID)**. ## Summary In this tutorial, we covered Google's Eddystone beacon standard and built a working implementation using Zephyr RTOS and the nRF52\. Here's what we went through: - The Eddystone advertisement packet format and how it uses the Service Data AD type - Eddystone-UID frame type — a 16-byte Beacon ID with namespace and instance - Eddystone-URL frame type — compressed URL broadcasting for Physical Web applications - Eddystone-TLM and Eddystone-EID for telemetry and security - A hands-on Zephyr implementation with both URL and UID examples on the nRF52840 You should now be able to set up your own Eddystone beacons using Zephyr and customize them for your specific use case. If you're looking to take your beacon development further — including building a combined iBeacon + Eddystone broadcaster and a Bluetooth LE scanner that parses advertisement data at the byte level — here's a preview of what that looks like: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-04-13-at-6-48-43-pm.png) Bluetooth LE Scanner Example Serial Output 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Bluetooth Addresses & Privacy in Bluetooth Low Energy URL: https://novelbits.io/bluetooth-address-privacy-ble/ Last updated: 2026-08-09T05:23:39.000Z Like a MAC address for LAN-connected devices, Bluetooth devices also have an identity address associated with each device. Understanding how Bluetooth addresses work is crucial for every BLE developer, especially when device privacy is a concern. So, what is a Bluetooth Address? A *Bluetooth address* sometimes referred to as a Bluetooth MAC address, is a **48-bit value that uniquely identifies a Bluetooth device**. In the Bluetooth specification, it is referred to as `**BD_ADDR**`. Per the [Bluetooth Core specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/?ref=novelbits.io) document, there are two main types of Bluetooth addresses: **public** and **random** addresses. A Bluetooth device must use one of these types of addresses, and in some cases, it contains **both** types. Let's take a look at a diagram that summarizes the different types of Bluetooth addresses available: ![Bluetooth Address Types hierarchy diagram](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/address-types-1.png) Bluetooth Address Types The above diagram shows the hierarchy of Bluetooth address types. To summarize, the four Bluetooth address types are: - Public Address - Random Static Address - Random Private Resolvable Address - Random Private Non-Resolvable Address Random Address and Private Address, as shown in the diagram, are simply classifications and are not types used in and of themselves in implementation. ## Public Address A Bluetooth Public address is a global fixed address that must be registered with the IEEE. It follows the same guidelines as MAC Addresses and shall be a 48-bit extended unique identifier (EUI-48). The creation of a valid EUI-48 requires one of the following MAC Address Block types to be obtained from the IEEE Registration Authority: - MAC Address Block Large (MA-L) - MAC Address Block Medium (MA-M) - MAC Address Block Small (MA-S) This address never changes and is guaranteed to be unique for a Bluetooth device. However, there is a fee associated with obtaining/reserving a block with the IEEE. The following diagram represents the simplified format of a Public Bluetooth Address. ![Public Address format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/public-address.png) Public Address Format (little-endian format) - **Company ID:** the publicly assigned portion of the address by the IEEE (MSB) - **Company Assigned:** the internally assigned ID as part of the allocated block (LSB) To learn more about the details of IEEE-assigned MAC address blocks, refer to the following links: - [https://standards.ieee.org/products-programs/regauth/](https://standards.ieee.org/products-programs/regauth/?ref=novelbits.io) - [https://standards.ieee.org/content/dam/ieee-standards/standards/web/documents/tutorials/eui.pdf](https://standards.ieee.org/content/dam/ieee-standards/standards/web/documents/tutorials/eui.pdf?ref=novelbits.io) ## Random Address Random addresses are more popular than Public addresses since they do not require registration with the IEEE. A Random address is an identifier that's either: - programmed into the device or - generated at runtime (depending on the subtype). The two subtypes of Random addresses are: - Random Static Address - Random Private Address Let's dig into each of these types in more detail. ### Random Static Address This specific type of Bluetooth address serves as a popular alternative to Public addresses since there are no fees involved with using it. Random Static Addresses can be used in one of two ways: - It can be assigned and fixed for the lifetime of the device - It can be changed at bootup However, it **cannot** be changed during runtime. The format of Random Static Addresses looks like this: ![Random Static Address format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/random-static-address.png) Random Static Address format (little-endian format) - 1 and 1 are fixed in the most significant bits (MSB) - The remaining 46 bits are chosen randomly by the developer/manufacturer **IMPORTANT NOTE**: All Bluetooth devices must use one of either type: a **Public Address** or a **Random Static Address**. The next type of address (*Private Addres*s) is optional and is solely used to address privacy concerns (i.e. device may use one of them in addition to either a Public or Random Static Address). ### Random Private Address There are two types of Random Private addresses: **resolvable** and **non-resolvable**. Random Private addresses are used specifically for protecting the privacy of a Bluetooth device, to hide the identity, and to prevent tracking of the device. Let's take a look at each of these types: **Resolvable Random Private** **Address** The purpose of a Resolvable Random Private Address is to prevent malicious third-parties from tracking a Bluetooth device while still allowing one or more trusted parties from identifying the Bluetooth device of interest. A Resolvable Random Private address is "resolvable" using a key shared with a trusted device. This key is referred to as the IRK (Identity Resolving Key). The address is originally generated using this IRK and a random number. So, what makes a device "trusted" by another device? In this case, a trusted device is a **bonded** device. Bonding is the optional step that takes place after the **pairing** of two BLE devices. The Bonding process involves the storage of keys by each of the devices that are bonded with each other. Bonding also allows the two devices to pair seamlessly in connection subsequent to the original connection when the two devices were paired. One of the keys exchanged by the two bonded BLE devices is the IRK of each device involved. This type of address changes periodically. The recommendation per the Bluetooth specification is to have it change every 15 minutes (this is evident in all iOS devices). A Resolvable Random Private address is made up of the following fields: ![Random Private Resolvable Address format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/random-resolvable-private-address-2.png) Random Private Resolvable Address format (little-endian format) - 0 and 1 are fixed in the most significant bits (MSB) - The next 22 bits are randomly generated - The **prand** constitutes of these most significant 24 bits - The lower 24 bits represent a hash value which is generated using the **prand** and the **IRK** **Non-Resolvable Random Private Address** The other type of Random Private Address is the **Non-Resolvable Random Private Address**. This type of address also changes periodically. However, unlike resolvable addresses, it is not resolvable by any other device. The sole purpose of this type of address is to prevent tracking by any other BLE device. This type is not very common but is sometimes used in beacon applications. The format of Non-Resolvable Random Private Addresses is as follows: ![Random Private Non-Resolvable Address format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/random-nonresolvable-private-address.png) Random Private Non-Resolvable Address format (little-endian format) - 0 and 0 are fixed in the most significant bits (MSB) - The remaining 46 bits are chosen at random ## Privacy in BLE Privacy is a major concern for users of Bluetooth devices, and it needs to be taken seriously. What we mean by privacy in this context is making sure that untrusted parties are not able to track a device by its Bluetooth address. If no careful measures are put in place, this Address can be used to track users. Fortunately, BLE provides Privacy features to safeguard against such attacks. Privacy for Bluetooth devices is achieved by using a resolvable private address. This type of address requires bonding of the two Bluetooth devices in order for one to resolve the address of the other. Here are the steps involved in implementing privacy for BLE devices: - A key referred to as the IRK (Identity Resolving Key) is used in generating and resolving the resolvable random private address. - The IRK is generated by each device locally either randomly or assigned during manufacturing. - During bonding, each device stores its peer’s IRK in what’s called a **resolving list**. - The IRK is then used to resolve the private address of a peer device. *For example, when it receives the peer’s advertising packets at a later time.* - This is done by verifying that the hash included in the private address matches the output of the local hash computation according to the following equation: **hash = ah(IRK, prand)** ![Resolvable Private Address hash computation](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/random-resolvable-private-address-3.png) (little-endian format) - Since the device has the IRK stored locally and has access to the prand included as part of the private address which is included in the BLE packets, it can perform this computation. It’s important to note that the IRK is not used to directly reveal the peer’s Identity Address (which is either a Public Address or a Random Static Address). Rather, it is used for verification purposes only. The device can then map the RPA (Resolvable Private Address) back to the Identity Address via the IRK and the security database (once the address is verified). 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE security, privacy, and address management? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. ### A Deep Dive into BLE Packets and Events URL: https://novelbits.io/deep-dive-ble-packets-events/ Last updated: 2026-08-09T05:24:39.000Z In BLE, there are many events and operations that can be exchanged between a Peripheral and a Central. Understanding these events is imperative for any BLE developer, and there are two aspects to achieving this: - Learn the concepts in theory. - Learn by analyzing them using [Bluetooth analyzer (sniffer)](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) captures. I believe these two methods go hand in hand in helping achieve a full understanding of BLE. We cover the first aspect in my **Intro to Bluetooth Low Energy** book (which you can download for free [here](https://novelbits.io/introduction-to-bluetooth-low-energy-book) or purchase in [paperback format](https://www.amazon.com/dp/B07KTDG6KG?ref=novelbits.io)). In this post, we will go through a number of events and better understand them by analyzing captures from a Bluetooth sniffer ([Ellisys Bluetooth Tracker](https://www.ellisys.com/products/btr1/index.php?ref=novelbits.io)). Here’s a list of events/operations we’ll be looking at: - Advertisements: - Types: Connectable Scannable Undirected & Nonconnectable Scannable Undirected - Advertisement Interval - RF channels used - PHY used - Advertisement data fields - Bluetooth Address and type - Connection requests - Post-connection operations: - Version Exchange message - Feature Exchange message - Exchange MTU - Attribute discovery including GATT Services, Characteristics, Descriptors, and others. ## Advertisements In this section, we’ll take a look at a couple of different advertisement packet types including: - **Nonconnectable scannable undirected advertisements**: this type is used most commonly in Beacon applications where a device broadcasts data to be discovered by multiple other BLE devices, and does not accept connections. - **Connectable scannable undirected advertisements**: this type is used most commonly by a device that wants to accept connections from other BLE devices that discover the advertisements. For each of these types, we’ll look at: - The different advertisement data fields - RF Channel used - PHY used - Bluetooth Address & Type Before we get into specific examples, let’s first look at the format of an Uncoded (1M PHY, 2M PHY) Advertisement packet (*figure taken from the Bluetooth 5.1 specification document*): ![Uncoded PHY advertisement packet format](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/uncoded-phy-packet-format-2.png) Source: Core Bluetooth Specification version 5.2 You’ll notice that there are two main parts in the PDU: **Header** and **Payload**. The Header is standard for all advertisement packets, and the Payload depends on the advertisement type (PDU). ### Nonconnectable Scannable Undirected Advertisements Let’s take a look at a nonconnectable scannable advertisement from a [BLE sniffer](https://novelbits.io/bluetooth-low-energy-ble-sniffer-tutorial/) capture: ![Nonconnectable scannable advertisement packet in sniffer capture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-06-at-11-54-27-pm-copy.png) Here are the details as shown by the sniffer software. The first screen capture shows the details of the Link Layer information: ![Link Layer details of nonconnectable scannable advertisement](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-12-58-07-am.png) A few notes about the above fields: - The RF Channel this selected packet was sent on is channel 37 (which is a primary advertisement channel) - The PHY used is the 1M PHY (Uncoded) - The Bluetooth Address is **CD:54:DD:CD:90:6A** and it’s a Static Address. The remaining details show the contents of the Link Layer packet itself. I’ve gone ahead and highlighted the most important fields: ![Advertisement packet contents with highlighted fields](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-12-58-23-am.png) A few notes about the fields in the capture: **Advertisement type (PDU):** *ADV\_SCAN\_IND*. This refers to the nonconnectable scannable undirected advertisement type. The value in Hex is shown to the right: 0x6 and is defined in the official specification: ![ADV_SCAN_IND PDU type definition from Bluetooth specification](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Shot-2019-10-07-at-12.26.41-AM-1.png) **Payload** length is *28 (bytes)*. **Appearance** value is *Unknown (0x0000).* **Advertising Flags**: LE Limited Discoverable Mode: *No* LE General Discoverable Mode: *Yes* Simultaneous LE and BR/EDR (Controller): *No* Simultaneous LE and BR/EDR (Host): *No* **Device name (Local Name)**: “*Nordic\_Blinky*“ **Raw Data**: ![Raw advertisement packet data in hex](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/raw-data-1.png) Let’s take a look at how the raw data maps to the values listed in the Details screenshot. **Advertising physical channel PDU header**: ![Advertisement PDU header raw data breakdown](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Raw-Header-data.png) **Payload** The payload for an ADV\_SCAN\_IND packet is defined in the specification as: ![ADV_SCAN_IND payload format from specification](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Shot-2019-10-07-at-11.21.31-AM.png) So, we have the AdvA (Bluetooth Address of the advertising device) and the advertising data: **Bluetooth Address**: *CD:54:DD:CD:90:6A* ![Bluetooth address bytes in raw packet data](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Bluetooth-Address-1.png) **AdvData (Advertisement Data)**: The advertising data takes the following format (from the Bluetooth specification): ![Advertisement data structure format from specification](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Shot-2019-10-07-at-11.39.51-AM.png) This follows the well-known LTV (length-type-value) format. In our example, we have the following fields: ![Advertisement data fields breakdown](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/AdvData.png) Now, let’s look at what each of these fields represents. To do this, we need to refer to: - The **Advertising Data Type (AD Type)** listing at [https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/](https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/?ref=novelbits.io) - The “**Bluetooth Core Specification Supplement (CSS)**“ [https://www.bluetooth.com/specifications/bluetooth-core-specification/](https://www.bluetooth.com/specifications/bluetooth-core-specification/?ref=novelbits.io) From these references, we can now analyze the fields: **03 19 00 00**: 03 is the Length. This field has type = 0x19 which represents «Appearance». It has a value of 0x00 0x00 which maps to “Unknown”. **02 01 06**: 02 is the Length. This field has type = 0x01 which represents «Flags». Flags are defined as following (from the CSS document): ![Advertising Flags bit definitions from specification](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/Screen-Shot-2019-10-07-at-4.39.51-PM.png) In our example, the Flags field has a value of 0x06 (or 00000110 binary) which means: Bit 1 is set –> LE General Discoverable Mode is **enabled** Bit 2 is set –> Br/EDR Not Support is **enabled** **0E 09 4E 6F 72 64 69 63 5F 42 6C 69 6E 6B 79**: This field has type = 0x09 which represents «Complete Local Name» or what’s known as the *Device Name*. It has a value of 4E 6F 72 64 69 63 5F 42 6C 69 6E 6B 79 (in Hex), which maps to “Nordic\_Blinky” in ASCII. The last bytes are the CRC of the Payload: ![CRC bytes in advertisement packet](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/01/CRC.png) ### Connectable Scannable Undirected Advertisements Now, let’s look at another type of advertisement packet: a connectable scannable undirected advertisement. We won’t go into the details as we did for the previous advertisement type example. ![Connectable scannable undirected advertisement sniffer capture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-5-02-09-pm.png) In this example, we notice a lot of similarities to the previous example. All we changed is the type of advertisement. Here are the details of the selected packet: ![Connectable advertisement Link Layer details](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-5-09-43-pm.png) ![Connectable advertisement packet details](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-5-09-56-pm.png) ## Connection Requests One of the most important packets in BLE is the *Connection Request* packet. It’s the packet that the Central sends to an advertising Peripheral (sending a connectable advertising packet) to initiate a connection. This packet type is very important because of the crucial information it contains (which the Central needs to convey to the Peripheral). Let’s take a look at the contents of a connection request packet (taken from the official Bluetooth specification document): ![Connection request packet format from Bluetooth specification](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/connection-request-packet.png) The important information is contained in the LLData part of the packet: - **AA:** Access Address - **CRCInit**: contains the initialization for the CRC calculation. - **WinSize** & **WinOffset:** both used to set the *transmitWindowSize* (WinSize \* 1.25 ms) and the *transmitWindowOffset* (WinOffset \* 1.25 ms) which allow the Central some flexibility in the timing of transmitting the first connection event anchor point. - **Interval:** used to calculate the *connectionInterval* (Interval \* 1.25 ms) which is the frequency at which the Central and Peripheral exchange data. - **Latency:** used to set the *connSlaveLatency* (= Latency) which allows the Slave/Peripheral to skip a number of connection events to conserve power and stay at sleep longer: - *connSlaveLatency=*0** –> the Slave is not allowed to skip any connection events. - *connSlaveLatency=*n** –> the Slave is allowed to skip ***n*** connection events. - **Timeout:** used to set the *connSupervisionTimeout* (Timeout \* 10 ms) value. - **ChM:** contains the *channel map* indicating which RF data channels are used for data transmission. The LSB represents data channel index 0 and the bit in position 36 represents data channel index 36\. A bit of 0 indicates **unused** and 1 indicates **used.** *Note: recall that RF data channels are channels 0-36.* - **Hop:** used to set the *hopIncrement* value (a random value in the range of 5-16). - **SCA:** used to set the *masterSCA* value which is used to determine the worst-case Master's sleep clock accuracy. ### Sample Connection Request Packet (Sniffer Capture) Here’s an example of a connection request packet as captured by the Ellisys Bluetooth Tracker sniffer: ![Connection request packet sniffer capture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/connection-request-packet-capture.png) And here are the details of the packet: ![Connection request packet details part 1](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-5-43-21-pm-1.png) ![Connection request packet details part 2](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-07-at-5-43-44-pm-1.png) Let’s look at the raw data and see how it maps to these details: ![Connection request raw packet data](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/connection-request-packet-raw.png) Now, let’s look at the LLData fields: ![LLData fields in CONNECT_IND packet](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/lldata-connect_ind.png) Keep in mind that the data displayed here is LSB to MSB (as it is received at the receiver, from left to right). That’s it. Now you know about *every single bit* in a connection request packet! ## Post-Connection Requests and Operations Once two BLE devices are connected, they go through a few operations and data packet exchanges that are necessary before any user-initiated data is exchanged between the two. Let's look at the following operations: - Version Exchange - Feature Exchange - Exchange MTU - Attribute discovery (including GATT Services, Characteristics, Descriptors, and others) - Read Device Name (for UI purposes to display a meaningful name for the discovered device) ### Version Exchange This packet gets sent from each of the devices to inform the peer of the Bluetooth version used and the manufacturer of the chipset. Let’s take a look at the packets being exchanged in the following example (iPhone Xs MAX <–> Nordic nRF52840 DK): ![Version exchange packets between iPhone and Nordic DK](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-29-at-11-15-39-pm.png) As you can see, the packet is sent from each of the devices. Each contains four fields: - **Opcode**: LL\_VERSION\_IND, which defines the PDU type - **Bluetooth version**: indicates the version of the Bluetooth specification being used - **Company ID**: contains the company identifier of the manufacturer of the Bluetooth controller - **Implementation revision**: specifies the revision of the implementation of the Bluetooth controller Following is what is sent by each of the devices (first being the iPhone, and second being the Nordic DK): ![iPhone version exchange details](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-29-at-11-19-39-pm-copy.png) ![Nordic DK version exchange details](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-29-at-11-20-09-pm.png) ### Feature Exchange Since not all features within a Bluetooth specification version are mandatory (some are optional), the devices need to communicate to each other what specific features are indeed supported. This is done via the *Feature Exchange* packet. One of the devices sends the LL\_FEATURE\_REQ listing all the features it supports, and the other device responds back with an LL\_FEATURE\_RSP listing the features it supports. As of version 5.1 of the Bluetooth specification, there are 28 defined bits that indicate whether a feature is supported or not. Let’s take a look at the list of features supported by each of the devices in our example. *iPhone:* ![iPhone supported Bluetooth LE features list](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-29-at-11-38-00-pm-1.png) *Nordic Dev Kit:* ![Nordic DK supported Bluetooth LE features list](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-29-at-11-38-23-pm.png) ### Exchange MTU First, let’s define what MTU is: *MTU stands for Maximum Transfer Unit and it defines the maximum amount of data that can be handled by the transmitter and receiver and which they can hold in their buffers.* There is no limit per the spec on how high the MTU value can be, but the specific stack in use may have its own limitations. The effective MTU gets determined by the minimum value of ATT MTU that the client and server support. For example, if a client supports an ATT MTU of 100 bytes and the server responds that it supports an ATT MTU of 150 bytes, then the client will decide that the ATT MTU to be used for the connection from thereon is 100 bytes. Here’s a look at the Exchange MTU packet in our example. The client (iPhone) sends an Exchange MTU Request packet and the server (Nordic DK) sends back an Exchange MTU Response packet. **Exchange MTU packet sent by the iPhone, with an MTU value of 293 bytes:** ![Exchange MTU request from iPhone with value 293](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-30-at-10-10-29-am.png) **Exchange MTU packet sent by the Nordic Dev Kit, with an MTU value of 23:** ![Exchange MTU response from Nordic DK with value 23](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-30-at-10-10-37-am.png) ### Attribute Discovery The Attribute discovery process happens whenever two devices connect to each the first time. After that, the client may cache all attributes (including services, characteristics, descriptors, etc.) to avoid performing the discovery process the next time the two devices connect. If a client does not cache the attributes, then it must perform the discovery process each time it connects to the server. The attribute list will contain a **key-value** pair for each of the attributes with an *Attribute Handle* being the **key** and the *Attribute Type (UUID)* being the **value**. If the server would like to support changes in the attribute handles (e.g. due to a firmware update or factory reset), then it must include the *Service Changed* characteristic to notify the client that an attribute handle has changed, which in turn triggers a service discovery. Here’s a look at what the discovery process looks like: ![GATT attribute discovery process in sniffer capture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-30-at-11-31-34-am.png) As you can see, this usually requires multiple packets especially if there are many defined services and characteristics on the server-side. The client keeps requesting to read the Attributes until it receives “Attribute Not Found” error message which indicates the end of the discovery process: ![Attribute Not Found response ending discovery process](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-30-at-11-34-09-am.png) ### Reading the Device Name Another request that usually gets sent by the client (especially in applications that have a UI element) is reading the *Device Name*. This is a simple *Read Request GATT operation*: ![Read Device Name GATT operation in sniffer capture](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-10-30-at-11-36-03-am.png) ## Conclusion We covered a lot in this post! Let's do a quick recap of what we went through: - **Advertisement packets** — we analyzed both nonconnectable scannable and connectable scannable types, and I walked you through the raw data byte by byte (including the LTV-formatted AdvData fields) - **Connection request packets** — we broke down the LLData fields that define how the connection will operate (interval, latency, channel map, hop increment, and more) - **Post-connection operations** — we looked at version exchange, feature exchange, MTU negotiation, and the GATT attribute discovery process I've found that being comfortable reading packets at the bit level makes a huge difference when you're trying to track down issues in your Bluetooth LE applications. If something isn't working as expected, a sniffer capture will almost always point you in the right direction. There are, of course, many more Bluetooth LE packets and events beyond what we covered here, including GATT operations (Read, Write, Notifications, Indications) and miscellaneous events like Connection Parameters Update, PHY Update, and Data Length Extension (DLE). 💡 **Insider Tip:** Want to go even deeper into Bluetooth LE packets and events? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Getting Started with the Silicon Labs BG22 Chipset URL: https://novelbits.io/getting-started-silicon-labs-bg22/ Last updated: 2026-08-09T05:24:59.000Z ⚠️ **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. Today (March 23, 2020), Silicon Labs released the next generation of their Bluetooth SoCs: the **EFR32BG22** chipset family. The chipset features an ARM Cortex-M33 which supports the latest version of Bluetooth: version 5.2 (including features from versions 5.1 and 5.0). More importantly, the chipset features the following enhancements: - Significantly lower power consumption compared to the previous generations (up to 60% lower) - Enhanced security features including a Hardware-Accelerated Crypto, a True Random Number Generator (TRNG), Secure Boot with Root of Trust and Secure Loader (RTSL), Secure Debug with Lock/Unlock, and ARM TrustZone. Here's a table that provides a comparison of the new chipset and the previous generation: ![Comparison table of Silicon Labs BG22 and BG13 chipsets showing RAM, Flash, security features, and power consumption](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-12-at-10-45-54-am.png) Source: Silicon Labs **So, as a Bluetooth LE developer, why should you care?** With the increased demand for securing embedded devices, especially those with wireless connectivity capabilities, this new generation of Silicon Labs Bluetooth chipsets provides an attractive platform for developing your next-generation Bluetooth LE product. This is especially applicable in applications that require **low-power consumption** and need to run on batteries for long periods of time. Here are some examples of applications suitable for implementation based on the new BG22 chipset: - Asset Tags and Beacons - Consumer Electronics Remote Controls - Portable Medical devices - Bluetooth mesh Low Power Nodes (LPN) - Sports, Fitness, and Wellness devices - Connected Home devices - Building Automation and Security applications In terms of Bluetooth LE features, here are the main ones supported by the new chipset: - LE Power Control (Bluetooth 5.2) - GATT Caching (Bluetooth 5.1) - 2M PHY and Coded PHY (Bluetooth 5) - Extended Advertisements and Advertisement Sets (Bluetooth 5) - Up to 8 simultaneous connections (mix of master or slave) **In collaboration with Silicon Labs, I was provided with early access to their SDK and development kit based on the new BG22 chipset.** In this post, I will guide you through setting up your development environment and getting started with your first BG22-based Bluetooth LE application. ## Hardware and Software Requirements Here's the list of hardware and software requirements for following this tutorial: - [EFR32xG22 Wireless Gecko Starter Kit](https://www.silabs.com/development-tools/wireless/efr32xg22-wireless-starter-kit?ref=novelbits.io) (SLWSTK6021A) - A mini USB cable (included with the development kit) - A development PC (macOS, Linux, or Windows) – we'll be using macOS in this tutorial - Silicon Labs [Simplicity Studio IDE](https://www.silabs.com/software-and-tools/simplicity-studio?ref=novelbits.io) - Included free GCC compiler – *we'll be using this option* *in this tutorial* - IAR Embedded Work Bench for ARM (30-day eval license available) ## Development Environment Setup Let's go through the steps for setting up your development environment. The first step is to install the Simplicity Studio IDE. Once you've downloaded Simplicity Studio and installed it, you may run into an error that complains that the application not being secure to run. This issue can be fixed from within the Security settings under System Preferences and clicking on "Open Anyway". ![macOS Security and Privacy settings showing Open Anyway option for Simplicity Studio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-12-at-4-43-51-pm.png) After launching the application, you will be presented with a login screen. If you do not have a Silicon Labs account, you can sign up from this screen as well (or simply go to [https://siliconlabs.my.site.com/apex/SL\_CommunitiesSelfReg?form=short](https://siliconlabs.my.site.com/apex/SL%5FCommunitiesSelfReg?form=short&ref=novelbits.io)): ![Simplicity Studio login screen with Silicon Labs account sign-in](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-12-at-4-52-09-pm-2.png) Once signed in, the application will check for software updates. It's recommended that you allow it to download and install these updates – this may take a few minutes. Once finished, the updates may require a restart of the application. After restarting, make sure you have the main development board with the radio board mounted and plugged into the development computer. Make sure that the development board Power Switch is set to "AEM" (which stands for "Advanced Energy Monitor" and is necessary for using the energy profiler application) : ![EFR32xG22 development board with power switch set to AEM position](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-21-at-3-16-50-pm-1.png) Source: *UG430: EFR32xG22 2.4 GHz 6 dBm Wireless Starter Kit User's Guide* Now, click on the *software update* icon: ![Simplicity Studio toolbar showing the software update icon](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-16-at-11-40-20-pm.png) Once clicked, you will be presented with the following screen: ![Simplicity Studio software update options screen](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-16-at-11-42-28-pm.png) Since we are developing for a specific device (the BG22), the easiest method is to choose the "Install by Device" option: ![Simplicity Studio Install by Device screen showing detected EFR32BG22 device](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-16-at-11-43-50-pm.png) The application should detect the connected device (shown above). Click on the device, then on the ">>" button to add it to the "Selected devices:" section: ![Simplicity Studio with EFR32BG22 device added to Selected devices list](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-12-00-38-am.png) Click "Next" and make sure you have at least "Bluetooth" and "32 bit MCU" are selected: ![Simplicity Studio SDK selection with Bluetooth and 32 bit MCU checked](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-12-10-55-am.png) Press "Next" again, and make sure the latest "Bluetooth SDK" is selected (I have the "32 bit MCU SDK" package selected as well, but that is not required): ![Simplicity Studio SDK package selection showing Bluetooth SDK](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-12-13-02-am.png) Press "Next" again and wait for the installation to finish. This will likely take a few minutes. ![Simplicity Studio SDK installation progress screen](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-12-13-10-am.png) Once the installation is finished, click the "Close" button – a restart of the application may be required. ## Running a Bluetooth LE Peripheral Example The Silicon Labs Bluetooth SDK includes a few examples that you can run on the board. Let's take a look at the different examples included: ![List of Bluetooth SDK example projects in Simplicity Studio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-11-00-32-am.png) But before we run any of the examples. check to see if there's an update for the Adapter. If so, then click on "Download": ![Simplicity Studio adapter firmware update available with Download button](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-14-at-9-21-43-pm.png) Make sure you do **not** unplug the development board while the Adapter firmware is being updated. Once the download and update are complete, it will display a prompt informing you that it's "Waiting for the kit to restart": ![Simplicity Studio waiting for development kit to restart after firmware update](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-14-at-9-21-47-pm.png) ![Simplicity Studio showing adapter firmware update complete](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-14-at-9-22-48-pm.png) If you're using the development board for the first time, then you will need to flash the bootloader to the chipset. To do so, you have two choices: - Flash the "Internal Storage Bootloader (single image on 512 kB device)" project (located under the "Gecko Bootloader Examples") to the board. If you take this path, open the project then double click the \*.isc file and click on "Generate". The .isc file allows you to customize the bootloader in a GUI tool and then generates the source code for that configuration. - Flash one of the "Bluetooth (SoC)" to the board (which already includes the bootloader). Now, we're ready to run one of the Bluetooth LE examples. Let's run the Thermometer example (labeled "SOC - Thermometer"). Simply click on the name, and you will be presented with the following view: ![SOC Thermometer example project overview in Simplicity Studio](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-2-01-35-pm.png) ### GATT Configurator Tool Silicon Labs provides a very useful interface for setting up and designing your GATT Services and Characteristics. It also allows you to import and adopt Bluetooth SIG standard GATT Profiles (e.g. Heart Rate, Find Me, etc.), Services, and Characteristics. This is really helpful for visualizing your GATT design and is much easier than trying to visualize and manage your Services and Characteristics in source code. In the Thermometer \[Server\] example, you'll notice that the following GATT is defined: ![GATT Configurator showing the Health Thermometer service and characteristics](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/gatt-configurator-1.png) ### Building, Flashing, and Testing To build the application, right-click on "soc-thermometer" in the left-hand side and then click on "Build Project": ![Simplicity Studio context menu with Build Project option](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-2-33-17-pm.png) In the Console area, you'll see the output of the build process: ![Simplicity Studio console showing successful build output](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-2-34-38-pm.png) Once the build is successful, now we can flash and run it on the device. To do this, click on the "Debug" icon: ![Simplicity Studio toolbar highlighting the Debug button](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-2-44-05-pm.png) ![Simplicity Studio debug session running the Thermometer example](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-17-at-2-45-19-pm.png) Once the application is run, we can confirm this by running a Bluetooth LE scanner mobile app. The Silicon Labs **EFR Connect** allows us to do just that. The EFR Connect mobile is available for both [iOS](https://apps.apple.com/us/app/simplicity-connect/id1030932759?ref=novelbits.io) and [Android](https://play.google.com/store/apps/details?id=com.siliconlabs.bledemo&hl=en%5FUS&ref=novelbits.io). ![EFR Connect mobile app main screen on Android](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screenshot_20200321-190745.png) Once you run the app, you'll be presented with the following screen: ![EFR Connect Demo tab showing Health Thermometer option](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screenshot_20200321-190025.png) You'll notice that the main screen is the "Demo" screen with the "Health Thermometer" listed. If you navigate to the "Develop" screen, you'll see the option for a "Browser" which allows you to scan for any Bluetooth LE peripheral in the vicinity. ![EFR Connect Develop tab with Bluetooth LE Browser option](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screenshot_20200321-191451.png) Since we are running the Thermometer example on our development board, we can utilize the "Health Thermometer" scanner within the app. Click on "Health Thermometer": ![EFR Connect Health Thermometer scanner showing Thermometer Example device](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screenshot_20200321-190017.png) If you've set up and run the Thermometer example correctly on the board, you'll see your device listed in the app (as shown above). If the device does not show up in the "Blue Geckos" tab, try switching to the "Other" tab. Tap on the device with the name "Thermometer Example" and the app will attempt to connect to the device. Once connected, you'll be presented with the following screen: ![EFR Connect connected to Thermometer Example showing temperature reading](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screenshot_20200321-190039.png) To test out the sensor's functionality, place your finger on the temperature sensor on the development board and notice that the temperature reported rises gradually: ![EFR32xG22 development board with temperature sensor location highlighted](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-21-at-6-40-04-pm.png) Source: *UG430: EFR32xG22 2.4 GHz 6 dBm Wireless Starter Kit User's Guide* ![EFR Connect showing rising temperature reading after touching sensor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screenshot_20200321-190133.png) ### Basic Structure of a Bluetooth LE Application The Bluetooth SDK enables the development of Bluetooth LE apps in two different configurations: - Standalone application configuration, where the Bluetooth stack and the application both run in the BGM22 chipset. - Network Co-Processor (NCP) configuration, where the application runs on an external host and the Bluetooth stack runs in the BGM22 chipset. The Thermometer example we ran on the development board is a standalone configuration. Here's a diagram that shows the architecture used in each configuration: ![Diagram comparing standalone and NCP Bluetooth LE application architectures](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/ncp-standalone-config.png) To better understand the structure of a standalone Bluetooth LE application, let's take a look at the different parts of `main.c` in the project. First, the header files included in the file: ```c /* Board Headers */ #include "init_mcu.h" #include "init_board.h" #include "init_app.h" #include "ble-configuration.h" #include "board_features.h" /* Bluetooth stack headers */ #include "bg_types.h" #include "native_gecko.h" #include "infrastructure.h" /* GATT database */ #include "gatt_db.h" /* EM library (EMlib) */ #include "em_system.h" /* Libraries containing default Gecko configuration values */ #include "em_emu.h" #include "em_cmu.h" /* Device initialization header */ #include "hal-config.h" #ifdef FEATURE_BOARD_DETECTED #if defined(HAL_CONFIG) #include "bsphalconfig.h" #else #include "bspconfig.h" #endif #else #error This sample app only works with a Silicon Labs Board #endif #ifdef FEATURE_I2C_SENSOR #include "i2cspm.h" #include "si7013.h" #include "tempsens.h" #endif ``` Following the header file includes, we have a few configuration variables defined. The first of which is the maximum number of connections, which is defined as 4 in our example: ```c /* Gecko configuration parameters (see gecko_configuration.h) */ #ifndef MAX_CONNECTIONS #define MAX_CONNECTIONS 4 #endif uint8_t bluetooth_stack_heap[DEFAULT_BLUETOOTH_HEAP(MAX_CONNECTIONS)]; ``` Another crucial part is the main gecko configuration data structure: ```c static const gecko_configuration_t config = { .config_flags = 0, #if defined(FEATURE_LFXO) || defined(PLFRCO_PRESENT) || defined(LFRCO_PRESENT) .sleep.flags = SLEEP_FLAGS_DEEP_SLEEP_ENABLE, #else .sleep.flags = 0, #endif .bluetooth.max_connections = MAX_CONNECTIONS, .bluetooth.heap = bluetooth_stack_heap, .bluetooth.heap_size = sizeof(bluetooth_stack_heap), #if defined(FEATURE_LFXO) .bluetooth.sleep_clock_accuracy = 100, // ppm #elif defined(PLFRCO_PRESENT) || defined(LFRCO_PRESENT) .bluetooth.sleep_clock_accuracy = 500, // ppm #endif .gattdb = &bg_gattdb_data, .ota.flags = 0, .ota.device_name_len = 3, .ota.device_name_ptr = "OTA", .pa.config_enable = 1, // Set this to be a valid PA config #if defined(FEATURE_PA_INPUT_FROM_VBAT) .pa.input = GECKO_RADIO_PA_INPUT_VBAT, // Configure PA input to VBAT #else .pa.input = GECKO_RADIO_PA_INPUT_DCDC, #endif // defined(FEATURE_PA_INPUT_FROM_VBAT) .rf.flags = GECKO_RF_CONFIG_ANTENNA, /* Enable antenna configuration. */ .rf.antenna = GECKO_RF_ANTENNA, /* Select antenna path! */ }; /* Flag for indicating DFU Reset must be performed */ uint8_t boot_to_dfu = 0; ``` The most important configurations defined above are: - Bluetooth max connections = 4 `.bluetooth.max_connections = MAX_CONNECTIONS,` - Device name = "OTA" `.ota.device_name_len = 3, .ota.device_name_ptr = "OTA",` - Pointer to generated GATT database `gattdb = &bg_gattdb_data` This Next in `main.c` we have the definition for the function `temperatureMeasure()`. The code is self-explanatory with very detailed comments: ```c /** * @brief Function for taking a single temperature measurement with the WSTK Relative Humidity and Temperature (RHT) sensor. */ void temperatureMeasure() { uint8_t htmTempBuffer[5]; /* Stores the temperature data in the Health Thermometer (HTM) format. */ uint8_t flags = 0x00; /* HTM flags set as 0 for Celsius, no time stamp and no temperature type. */ int32_t tempData; /* Stores the Temperature data read from the RHT sensor. */ uint32_t rhData = 0; /* Dummy needed for storing Relative Humidity data. */ uint32_t temperature; /* Stores the temperature data read from the sensor in the correct format */ uint8_t *p = htmTempBuffer; /* Pointer to HTM temperature buffer needed for converting values to bitstream. */ static int32_t DummyValue = 0l; /* This dummy value can substitute the temperature sensor value if the sensor is N/A. */ /* Convert flags to bitstream and append them in the HTM temperature data buffer (htmTempBuffer) */ UINT8_TO_BITSTREAM(p, flags); #ifdef FEATURE_I2C_SENSOR /* Sensor relative humidity and temperature measurement returns 0 on success, nonzero otherwise */ if (Si7013_MeasureRHAndTemp(I2C0, SI7021_ADDR, &rhData, &tempData) != 0) #endif { /* Use the dummy value and go between 20 and 40 if the sensor read failed. * The ramp-up value will be seen in the characteristic in the receiving end. */ tempData = DummyValue + 20000l; DummyValue = (DummyValue + 1000l) % 21000l; } /* Convert sensor data to correct temperature format */ temperature = FLT_TO_UINT32(tempData, -3); /* Convert temperature to bitstream and place it in the HTM temperature data buffer (htmTempBuffer) */ UINT32_TO_BITSTREAM(p, temperature); /* Send indication of the temperature in htmTempBuffer to all "listening" clients. * This enables the Health Thermometer in the Blue Gecko app to display the temperature. * 0xFF as connection ID will send indications to all connections. */ gecko_cmd_gatt_server_send_characteristic_notification( 0xFF, gattdb_temperature_measurement, 5, htmTempBuffer); } ``` Finally, we have the `main()` function. We won't list the whole contents of the function, but here are some of the most important parts. First, we have different general initializations: ```c // Initialize device initMcu(); // Initialize board initBoard(); // Initialize application initApp(); initVcomEnable(); // Initialize stack gecko_init(&config); #ifdef FEATURE_I2C_SENSOR // Initialize the Temperature Sensor Si7013_Detect(I2C0, SI7021_ADDR, NULL); #endif ``` Next, in the `while()` loop, we have a function call to wait for events to be reported from the Gecko stack: ```c /* Event pointer for handling events */ struct gecko_cmd_packet* evt; /* Check for stack event. */ evt = gecko_wait_event(); ``` The return value from the `gecko_wait_event()` API is then parsed to handle the reported event from the stack. A few cases are handled: - The **boot-up event**, in which case the device then starts advertising. - An event generated in the case of a **notification** or **indication** being enabled/disabled, or when an **indication** **confirmation** was received. - A **timer** event in which case the function `temperatureMeasure()` used to measure the temperature is called - An event generated when a **connection has been closed**, in which case the device either enters DFU mode (if the dfu boot flag was set) or going back to Bluetooth LE advertising mode. - Events of characteristic write operations related to DFU mode. As you can see, the main structure of a Bluetooth LE application is event-driven. ## Silicon Labs Thunderboard™ BG22 Kit The SiLabs Thunderboard™ EFRBG22 is a small and cost-effective prototype and development platform based on the EFR32 Wireless Gecko SoC. It features a number of on-board sensors: - Humidity and temperature sensor - UV index and ambient light sensor - Hall effect sensor - 6-axis inertial sensor - PDM stereo microphones In addition to the sensors, the board features a user LED and push-button. It is powered by either USB or a coin-cell battery. ![Silicon Labs Thunderboard BG22 development board](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-22-at-11-03-15-pm.png) Source: Thunderboard™ Wireless EFR32BG22 User's Guide The board ships with a ready-to-use Bluetooth demo and includes a built-in SEGGER J-Link debugger. To learn more about this development kit: [https://www.silabs.com/development-tools/wireless/bluetooth/bg22-explorer-kit](https://www.silabs.com/development-tools/wireless/bluetooth/bg22-explorer-kit?ref=novelbits.io) ## Silicon Labs Software Tools There are a few tools provided by Silicon Labs as part of the Blue Gecko suite of software tools. Some of these tools are integrated into Simplicity Studio including: GATT Configurator, Multi-Node Energy Profiler, and Network Analyzer. Others such as Simplicity Commander and BGTool Application are external and exist separately from Simplicity Studio (though Simplicity Commander can also be run from within Simplicity Studio). ### GATT Configurator This tool allows you to define and design the GATT database of a device via a visual interface. To re-launch the GATT Configurator tool at any point for a specific project, simply double-click the \*.isc file in the project explorer pane: ![GATT Configurator tool in Simplicity Studio showing service and characteristic editor](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-18-at-3-11-00-pm.png) ### Multi-Node Energy Profiler This tool allows you to accurately measure the energy consumption of your device in runtime including finding peak current consumption and sleep mode current measurement. To run the profiler simply click on the Profile button in the Simplicity IDE perspective and select "Simplicity Energy Profiler Target": ![Simplicity Studio Profile button menu with Energy Profiler Target option](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-18-at-3-18-09-pm.png) ![Multi-Node Energy Profiler displaying real-time current consumption graph](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-18-at-3-22-30-pm.png) ### Network Analyzer This tool is a packet capture and debugging tool that can be used to debug Bluetooth connectivity between Wireless Geckos and other Bluetooth devices. The Packet Trace application captures the packets directly from the Packet Trace Interface (PTI) available on the Wireless Gecko SoCs and modules. It, therefore, provides more accurate capture of the packets compared to air-based capture. ![Network Analyzer showing captured Bluetooth LE packet trace](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-18-at-3-26-35-pm.png) ### Simplicity Commander This tool is a simple, yet very effective, tool that allows you to efficiently flash firmware images, erase flash, lock and unlock debug access, and perform other related operations on your device. To run the application from within Simplicity Studio, go to the Preferences menu under **Simplicity Studio** **➝** **Adapter Packs** **➝** **Simplicity Commander** **➝** **commander: commander for macosx.x86\_64** (or whatever operating system you're running on): ![Simplicity Studio preferences showing Simplicity Commander path configuration](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-18-at-3-36-03-pm.png) ![Simplicity Commander application interface for flashing and device management](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2020-03-18-at-3-39-43-pm.png) ## Summary & Closing In this tutorial, we introduced the new Silicon Labs BG22 SoC and covered how to get started with this exciting new platform. The topics we covered are: - Hardware and Software Requirements - Development Environment Setup - Running a Bluetooth LE Peripheral Example - GATT Configurator Tool - Building, Flashing, and Testing - Basic Structure of a Bluetooth LE Application - Silicon Labs Thunderboard BG22 Kit - Silicon Labs Software Tools - GATT Configurator - Multi-Node Energy Profiler - Network Analyzer - Simplicity Commander ## References - **SiLabs EFR32BG22:** [https://www.silabs.com/wireless/gecko-series-2/efr32bg22](https://www.silabs.com/wireless/gecko-series-2/efr32bg22?ref=novelbits.io) - **SLWSTK6021A Development Kit:** [https://www.silabs.com/development-tools/wireless/efr32xg22-wireless-starter-kit](https://www.silabs.com/development-tools/wireless/efr32xg22-wireless-starter-kit?ref=novelbits.io) - **Simplicity Studio:** [https://www.silabs.com/software-and-tools/simplicity-studio](https://www.silabs.com/software-and-tools/simplicity-studio?ref=novelbits.io) - **Simplicity Commander:** [https://community.silabs.com/s/article/simplicity-commander?language=en\_US](https://community.silabs.com/s/article/simplicity-commander?language=en%5FUS&ref=novelbits.io) - **"BGTool where to download" discussion:** [https://community.silabs.com/s/question/0D51M00007xeHokSAE/bgtool-where-to-download?language=en\_US](https://community.silabs.com/s/question/0D51M00007xeHokSAE/bgtool-where-to-download?language=en%5FUS&ref=novelbits.io) - **Silicon Labs Account Registration:** [https://siliconlabs.my.site.com/apex/SL\_CommunitiesSelfReg?form=short](https://siliconlabs.my.site.com/apex/SL%5FCommunitiesSelfReg?form=short&ref=novelbits.io) 💡 **Insider Tip:** Want to dive deeper into Silicon Labs Bluetooth LE development and build real-world applications? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Introduction to BLE Mobile Development [iOS] - Part 1 URL: https://novelbits.io/intro-ble-mobile-development-ios/ Last updated: 2026-08-09T05:25:30.000Z **This tutorial is an excerpt from a course on Bluetooth LE development for iOS in the [Bluetooth Developer Academy](https://novelbits.io/academy/). The course was developed in partnership with Anas Imtiaz, Ph.D.** In this tutorial, we will look at developing iPhone/iPad apps that interface with a Bluetooth Low Energy peripheral to send/receive data. We will start by looking at *Core Bluetooth*, a framework provided by Apple to make Bluetooth LE development easy through the use of APIs to perform different actions. We will also look at setting up a project in Xcode for Bluetooth LE development, looking at the setup stages for first-time use, and taking into account permission handling for different iOS versions. Once we set up the workflow, we will dive into the world of *Core Bluetooth* APIs and code our way to develop an app that is able to: - Scan the area to find the different Bluetooth LE peripherals - Display information about peripherals scanned - Connect to a specific peripheral **IMPORTANT**: we are not going to look at building the UI in this tutorial and will focus strictly on getting started with Bluetooth LE development. Instead, we will use print statements to show different outputs visible in the debug area at the bottom of Xcode. ## Prerequisites - An Apple computer: Macbook, Mac Mini, iMac - macOS - XCode - iPhone with Bluetooth LE (iPhone 4S onwards) - Bluetooth LE Peripheral (we have used nRF52 Development Kit with Nordic HRM example) - Enrollment in the Apple Developer Program (Free, unless you want to deploy to the App Store in which case it is USD99 per year) - Basic understanding of Swift \[preferred, but not essential\] Generally, the latest version of macOS and XCode are recommended, but anything from 2015 or later should be fine. For this tutorial, we'll be using: - MacBook Pro 2017 - macOS Catalina (10.15.2) - XCode version 11.3.1 - iPhone 11 (iOS version 13.3.1) - Swift 5 ## What is CoreBluetooth? Core Bluetooth is a framework provided by Apple on iOS/iPadOS/macOS for communicating with all Bluetooth devices (BLE or Classic). If you have some experience in programming on mobile devices, particularly Apple devices, this will come across as very familiar i.e., a framework providing access to certain system features through the use of APIs. Core Bluetooth provides support for several features, including: - Setting up an iOS device as a Bluetooth LE central or peripheral - Handling low-level connection parameters - Establishing and maintaining a connection - Transferring data between Bluetooth LE devices - Bluetooth Classic - Error handling The two important Apple Developer resources related to Core Bluetooth that help understand some of the features and APIs are: [**Core Bluetooth | Apple Developer Documentation**](https://developer.apple.com/documentation/corebluetooth?ref=novelbits.io) **[Core Bluetooth Programming Guide](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth%5Fconcepts/AboutCoreBluetooth/Introduction.html?ref=novelbits.io#//apple%5Fref/doc/uid/TP40013257)** Note that there are several other libraries out there that provide different methods for carrying out Bluetooth LE operations on iDevices. However, all of them are built on top of Core Bluetooth since that is the only API Apple has made available to developers. Some of the popular libraries include: - **[BluetoothKit](https://github.com/rhummelmose/BluetoothKit?ref=novelbits.io)** Provides easy-to-use functions for carrying out simple tasks - **[RxBluetoothKit](https://github.com/Polidea/RxBluetoothKit?ref=novelbits.io)** Uses Core Bluetooth and RxSwift - [**BlueCap**](https://github.com/troystribling/BlueCap?ref=novelbits.io) Simple methods for asynchronous operations Regardless of the library used, the core concepts will remain the same. With that in mind, let’s get started! ## Setting up an iOS Bluetooth LE Project in Xcode When ready, fire up XCode and select **Create a new XCode project**. Choose **iOS** as the platform from the tab on top, and then select Single View Application and press Next. Enter *Product Name*. This is the name of our app, so let’s call it **TheBlueApp**. From the *Team* menu, you should be able to select your name as a personal team if you have already enrolled in the Apple Developer Program. If you don’t see the option now, we will come back to it later and you can leave the default for now. The *Organization Identifier* is normally your domain in reverse. So you can use `io.novelbits`. In *User Interface*, select Storyboard. Strictly speaking, it doesn’t matter which method you select since this is applicable for displaying the different UI components. SwiftUI is fairly new, and many developers (including myself) still continue to use Storyboard, so we will keep it that way for this tutorial. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture1.png) Click Next, select the location on your hard drive where you want to create the new project, and then click Create. Our new project is ready now. Let’s have a quick look at what XCode has created for us. On the left-hand side is the file explorer, which lists a bunch of files. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture2.png) The two files of immediate concern to us are: - `**ViewController.swift**` This file contains everything related to the display and functionality of our single view app. - `**Info.plist**` This is, sort of, the settings and permissions file which we need to use to enable the use of Bluetooth in our app. Now, just to make sure our iPhone is correctly set up for deploying the app, let’s try and build this (empty) app. - Plug your iPhone in via USB to your development computer. - The phone may ask if you trust this computer, make sure you allow that. - Select the phone from the top menu in XCode as shown below. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture3.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture4.png) - It is important to note that while you can use the simulator for most app development, you have to use a physical device to test Bluetooth LE connectivity. - Click the play button on top to build. If there are issues with respect to your Apple ID in relation to the developer program, they will be reported here, and you will be given options to fix them. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture5.png) - Another option is to go to the Signings & Capabilities section and select the option to *Automatically manage signing* and press the button to *Try again*. Hopefully, this will iron out any issues related to signing and certificates. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture6.png) - If needed, build again and wait for the process to complete. Your Mac may prompt you to enter your password. Enter the password and select *Always Allow*. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture7-1.png) - Once the build process is complete, the app will be installed and try to launch. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture8.png) - On newer versions of iOS, you will get the following error: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture9.png) - On the iPhone, go to **Settings** → **General** → **Device Management**. Select your development profile and then tap on **Trust “Apple Development: ”** - Launch the app again, and it should work, but since we haven’t added anything to the app, it will show a blank screen. We haven’t done any Bluetooth LE development so far, but we have managed to set up our workflow to develop apps on Xcode and deploy them to our physical iPhone. ## Importing CoreBluetooth Now let’s get to work on setting up the use of CoreBluetooth. The very first step is to import the CoreBluetooth framework into your project. To do this, add the following line at the top of your `ViewController.swift`: ```swift import CoreBluetooth ``` Next, we will be using `CBCentralManager` and `CBPeripheral` classes since our phone will be the central manager and we will use methods to interface with the peripheral Bluetooth LE device. While we get access to the different methods of these classes, we still need to conform to the delegate methods defined by the `CentralManagerDelegate` and `CBPeripheralDelegate` protocols. These are slightly advanced concepts, but in simpler terms, Swift has these design patterns where the timing of the function calls is defined, but their behaviours are not. Hence the behaviour of these functions must be defined. For example, CBCentralManager can tell you that it has connected to a peripheral, but what happens on connection needs to be defined by you. Similarly, if there is a disconnection, what should the central manager object do…ignore or try to re-establish a connection? You can read more about this concept of delegation [here](https://www.kodeco.com/477-design-patterns-on-ios-using-swift-part-1-2?ref=novelbits.io). To use these protocols, add CBCentralManagerDelegate and CBPeripheralDelegate to the line where your class is defined. ```swift class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { ... } ``` As soon as you do this, Xcode will start complaining that: *`Type ‘ViewController’ does not conform to protocol ‘CBCentralManagerDelegate’`* This is because some of the methods of these protocols need to be defined, while others are optional. If you click on the red circle showing the error, as follows, there should be a little Fix button. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture10.png) This is Xcode trying to help you write the stubs for the required methods (functions). Once you click Fix, the outline for function centralManagerDidUpdateState appears: ```swift func centralManagerDidUpdateState(_ central: CBCentralManager) { <#code#> } ``` Remove the “code” stub for now - we will fill this in later. This method is an absolute requirement because it gets called whenever you define a `CBCentralManager`. It is used to check the hardware status of Bluetooth on your device, i.e., whether it's powered on and available to use or disabled. Any further operations to connect with a peripheral must only be carried out if Bluetooth is powered on and enabled. We also want to declare a variable for our central device so we can refer to it later. Within the class, add the following: ```swift var centralManager: CBCentralManager! ``` The exclamation mark at the end means this is an unwrapped optional variable, and if we refer to it later, we can check for null safety. We also want to declare a variable for our peripheral object once we establish a connection, so add the following line. ```swift var myPeripheral: CBPeripheral! ``` In the viewDidLoad() function, add the following line to initialize the `centralManager` variable: ```swift centralManager = CBCentralManager(delegate: self, queue: nil) ``` Now in order of sequence, after viewDidLoad() is called, and our `centralManager` is initialized, the delegate method `centralManagerDidUpdateState` will be called. Let’s look at how to figure out the different states of Bluetooth low energy within this method. ## Check Bluetooth Low Energy Status The different Bluetooth LE states of the iOS device are of enumerated type CBCentralManagerState. They are: ```swift CBManagerState.poweredOff CBManagerState.poweredOn CBManagerState.resetting CBManagerState.unauthorized CBManagerState.unknown CBManagerState.unsupported ``` You can find the definitions of these states [here](https://developer.apple.com/documentation/corebluetooth/cbmanagerstate?ref=novelbits.io). The important ones to know are poweredOff indicating Bluetooth is off, `poweredOn` indicating it’s on so we can continue, and unsupported, indicating the lack of hardware support for Bluetooth LE on the device. Your app can have different alerts for the different statuses, but you need to have the state as poweredOn to continue. To check for that, within the centralManagerDidUpdateStatus method, check the central state as follows: ```swift func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("BLE powered on") // Turned on } else { print("Something wrong with BLE") // Not on, but can have different issues } } ``` Note that I have added print statements to show the status in the debug window. Compile this code and run on your device. The app builds fine but crashes on launch with the following error: **TheBlueApp\[8555:2463449\] \[access\] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSBluetoothAlwaysUsageDescription key with a string value explaining to the user how the app uses this data.** ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture11.png) This is a self-explanatory message that Apple warned us about on the CoreBluetooth page [here](https://developer.apple.com/documentation/corebluetooth?ref=novelbits.io). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picturemissing1.png) ## Setting Permissions What the earlier error says is that we need to define a value for the `NSBluetoothAlwaysUsageDescription` key if using iOS13 or `NSBluetoothPeripheralUsageDescription` if using iOS12 or earlier. This is the message displayed to the user when asking for Bluetooth permission for the app. If we are designing for apps to be used on phones with iOS13 and previous versions as well, then it makes sense to define values for both of these keys. This needs to be done in the **Info.plist** file. Go to the `Info.plist` file from the explorer on the left. Press the “+” button next to Information Property List. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture12.png) A new row appears with a dropdown menu with a list of keys (as descriptive text). Select **Privacy - Bluetooth Always Usage Description**, and enter a message in the Value field for this row. Something that tells your users what the app uses Bluetooth for. I have entered the following. *This app uses Bluetooth to receive data from my sensor.* ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture13.png) Next, press the “+” button again to add another key. This time select **Privacy - Bluetooth Peripheral Usage Description** and enter the same message for the value of this key. Your plist file will look like this: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture14.png) Now build and run the app again by clicking the little play button on the top toolbar. Your phone will show a notification asking for permission for TheBlueApp to use Bluetooth. Select OK when prompted on the phone, asking for permission to use Bluetooth. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture15.png) If all goes well, your debug area will show the text *Bluetooth LE powered on* (our print statement). ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture16.png) Feel free to experiment with different states to see how the phone responds to different settings. We can now use our iOS device as the central manager, with all settings and permissions sorted. It is time to ask our central manager to scan for devices to find our sensor. ## Scanning for a Bluetooth LE Peripheral If the `CBManager` state is powered on; we will ask the central to scan for peripheral devices with the following: ```swift central.scanForPeripherals(withServices: nil, options: nil) ``` The `withServices` and options parameters allow customised scanning based on service UUIDs, but for now, we will just use nil to go for a broad-based scan. The effect of this statement is that for each peripheral that the iPhone finds, there the `CBCentralManagerDelegate` method `centralManager(_:didDiscover:advertisementData:rssi:)` gets called. From Apple’s documentation on Core Bluetooth, this method *“Tells the delegate the central manager discovered a peripheral while scanning for devices.”* For each peripheral, it gives information about the advertisement data as a key-value pair dictionary and the RSSI. In our project, we need to define the behaviour of this delegate method. Go to the end of the previous delegate method (centralManagerDidUpdate), hit enter to start on a new line, and start typing `diddiscoverperipheral`. Xcode will automatically list the methods that match the keywords. Make sure you select the `didDiscoverPeripheral` method which is part of the `CBCentralManagerDelegate`, as shown below. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture17.png) Double click the method, and the stub appears. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture18.png) We can identify our peripheral by name, UUID, manufacturer ID, or basically anything that is part of the advertisement data. The simplest way is to search by the name, but that is certainly not a safe way. Ideally, we should check the name, UUID as well as manufacturer ID. For now, we will just check the name of each of the devices that our central manager has found. Inside the `didDiscover` delegate method, type in the following: ```swift if let pname = peripheral.name { print(pname) } ``` The first line checks whether the peripheral has a name (many of them don’t), so to avoid our app from crashing, we are checking for nullability. If there is a name, we assign it to a constant and print the value. Build and run the project, and you will see a list of names appearing in your debug area depending on how many devices are around. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/picture19.png) I have a Nordic nRF52832 Development Kit with the stock HRM example running on it, and I can see that my device is listed as Nordic\_HRM. The next step is to stop scanning when our preferred peripheral is found and establish a connection with this peripheral. ## Establishing a Connection While scanning, as soon as we find our peripheral, we want to stop scanning and establish a connection with the peripheral. At the same time, we want to keep a reference to this peripheral so we can perform read/write actions. Although the easiest way of identifying a peripheral is by its name, that is not the best way to do it. You would be advised to check other information such as manufacturer ID, advertisement data and service UUIDs. However, for simplicity, we will still use the peripheral name in the following example. So, update the code where we printed the peripheral name as follows. ```swift if let pname = peripheral.name { if pname == "Nordic_HRM" { self.centralManager.stopScan() self.myPeripheral = peripheral self.myPeripheral.delegate = self self.centralManager.connect(peripheral, options: nil) } } ``` First, we are checking if pname is `Nordic_HRM`, which is the name being advertised by my Nordic dev kit. If that is the case, we ask the central manager to stop scanning since we have found our peripheral. Next, we assign this peripheral to the `myPeripheral` object and subsequently its delegate as the current view controller class. This second part is important because `CBPeripheralDelegate` needs to know who is the delegate here that will be conforming to its methods. Forgetting to do this is often the cause of hours of headaches since the `CBPeripheralDelegate` methods are not called and the developer is left wondering why that is the case. Finally, we ask the central manager to connect to this newly found peripheral of ours. Once the connection is established, the `centralManager(_:didConnect:)` delegate method gets called. At this point, we ask the peripheral to provide us with more information about its services using the following line in the `didConnect` delegate method (as before, when you start typing `didConnectPeripheral`, Xcode will present you with the options to autocomplete). The method will look like this: ```swift func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { self.myPeripheral.discoverServices(nil) } ``` Note that you can pass the service UUIDs as an argument if you already know what you are looking for or you can check that manually later. (Also, note that if you are scanning for a peripheral while your app is in the background, you ***need*** to provide the service UUID. We talk more about this in the full course included in the [Bluetooth Developer Academy](https://novelbits.io/academy/)). At this point, your ViewController.swift will look like this: ```swift import UIKit import CoreBluetooth class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { var centralManager: CBCentralManager! var myPeripheral: CBPeripheral! func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("BLE powered on") // Turned on central.scanForPeripherals(withServices: nil, options: nil) } else { print("Something wrong with BLE") // Not on, but can have different issues } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if let pname = peripheral.name { if pname == "Nordic_HRM" { self.centralManager.stopScan() self.myPeripheral = peripheral self.myPeripheral.delegate = self self.centralManager.connect(peripheral, options: nil) } } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { self.myPeripheral.discoverServices(nil) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. centralManager = CBCentralManager(delegate: self, queue: nil) } } ``` ## Summary In this tutorial, we had an introductory look at interfacing an iOS device with a Bluetooth LE peripheral. We covered: - Setting up Xcode for Bluetooth LE development - Bluetooth permissions - Scanning for Bluetooth LE peripherals - Connecting to a Bluetooth LE peripheral ## Take your Bluetooth LE knowledge to the next level There's still so much more to interfacing with a Bluetooth LE peripheral from an iOS app, including: - Discovering services of a Bluetooth LE peripheral - Discovering characteristics of a service - Reading/Writing characteristic values - Receiving notifications (subscribing/unsubscribing) - Connection management: - Disconnecting from a Bluetooth LE peripheral - Handling a disconnection - Background operation We cover all this and much more in the **[Bluetooth Developer Academy](https://novelbits.io/academy/)**. 💡 **Insider Tip:** Want to go deeper into Bluetooth LE mobile development for iOS? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Understanding the "SweynTooth" BLE Vulnerabilities URL: https://novelbits.io/sweyntooth-ble-vulnerabilities/ Last updated: 2026-08-09T05:26:33.000Z About two weeks ago (February 11, 2020), a group of Singaporean researchers released a group of vulnerabilities discovered in quite a few BLE vendor SDKs. They named the group of vulnerabilities "**SweynTooth**". Here's their explanation: The statement "This may, in turn, lead the Bluetooth technology to be obsolete." seems a bit too extreme. While this is a group of serious vulnerabilities, it by no means poses a threat to Bluetooth technology itself, but rather may affect **adoption** and **trust** of some of the vendors suffering from the vulnerabilities. The vulnerabilities are specifically in vendor SDKs, and not in the Bluetooth specification itself. However, the researchers do suggest that the BLE certification process, so that's something to keep in mind when testing your BLE application/product. The researchers state that the isolation between the Host and Controller defined by the HCI layer adds complexity to the testing of a BLE stack, and is likely the reason for inadequate security testing of BLE stack implementations. This also means that as BLE developers we need to test our products thoroughly for security vulnerabilities and not rely exclusively on security testing performed by vendors. ## Which BLE chipset vendors are affected? So, which vendors are affected by the vulnerabilities covered in the research paper? SoCs from seven vendors are listed in the research paper: - Texas Instruments - NXP - Cypress Semiconductor - Dialog Semiconductor - Microchip - STMicroelectronics - Telink Semiconductor **UPDATE (Feb 25, 2020):** *Texas Instruments has already issued a public disclosure regarding these vulnerabilities. They also informed me that "TI has closed on the CVE and notified its customers and has already, or is currently in the process, of providing updated SDKs that will address each CVE that affects TI".* You can find out more information here: [https://e2e.ti.com/support/wireless-connectivity/bluetooth/f/538/t/882244](https://e2e.ti.com/support/wireless-connectivity/bluetooth/f/538/t/882244?ref=novelbits.io) Keep in mind that **only** certain SoCs provided by these vendors and specific SDK versions are affected. Here's a list of all the affected SoCs, the associated SDK versions, and which SDKs were patched to address the vulnerabilities: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/image-21.png) Source: [https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf](https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf?ref=novelbits.io) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a835797e060.png) Source: [https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf](https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf?ref=novelbits.io) Almost all the vendors have already published patches to address the issues disclosed. However, this still means: - The manufacturers have to provide these patches in firmware update releases to their end-customers. - Devices that incorporate the affected chipsets need to update their devices with the appropriate patch. - It is recommended that device manufacturers perform regression testing and ensure that the security vulnerabilities have been addressed and fixed in the final implementation in their end-product. The researchers describe one of the sources of the vulnerabilities as “Concrete flaws in the BLE stack certification process” and recommends that vendors and implementers should do their own testing outside of the required certification testing. IMO, this is always sound advice, and not just in the case of discovery of zero-day vulnerabilities such as the ones listed in the paper. ## What are the different categories of "SweynTooth" vulnerabilities? The researchers categorize the vulnerabilities into three types: 1. **Crash**: this happens primarily due to a buffer overflow on the target device caused by a remote device over BLE. One example is a buffer overflow caused by the reception of a "malicious" or even invalid BLE packet. If the target device handles the crash by resetting/rebooting, then this would cause temporary interruption to the operation of the device and may potentially cause loss of important data that was not saved in time before the crash. **This is the least critical of the vulnerability categories and does not require manual interaction from the end-user for recovery.** 2. **Deadlock**: this occurs due to improper synchronization between the application level and the BLE stack. This causes the application to get stuck in a state that out-of-sync from the BLE stack preventing it from resuming normal operation and causing a "deadlock" situation. Crashes such as those caused by category #1 above but not handled correctly by the firmware have the potential to lead to a deadlock. **This requires interaction from the end-user to manually restart the device.** 3. **Security bypass**: this type of vulnerability allows malicious parties to bypass the LE Secure Connections pairing mode allowing them to read/write to BLE characteristics that require security permissions by design. **This is the most critical of the categories!** ## Products in the market affected by "SweynTooth" According to the paper, by doing a Bluetooth Listing search, they found that around **480 product listings** use the affected SoCs. The vulnerabilities are, however, implementation-dependent which means that not all these products are affected. Here's a list of some of the products tested by the researchers and verified to be affected by at least one of the vulnerabilities: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a83579d7ea9.png) Source: [https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf](https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf?ref=novelbits.io) As you can see, this is just a sampling of affected products, and there are probably many others out there. Also, since the vulnerabilities are in the SDKs of the SoCs mentioned, there will be a wide variety of products affected ranging from minimally critical (such as a key finder tag) to highly critical (such as a medical device)! In terms of how these vulnerabilities affect the products, it widely varies depending on which vulnerability exists in the SoC used and how the application layer handles certain error cases. For example, the researchers found that **CubiTag** (a personal belonging tracker which incorporates a vulnerable TI CC2640R2 SDK) can be forced to crash and go into **deadlock** mode. The device then will then stop advertising and can not be discovered by the companion mobile app, requiring the user to manually restart it, which requires opening the device with a screwdriver and re-inserting its battery. Here’s a graph that shows the total number of product listings using the affected SoCs (as of February 8, 2020) listed by SoC: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a8357a5ebb5.png) Source: [https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf](https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf?ref=novelbits.io) ## I'm not a BLE developer, so why should I care? Think about it. Even if you're not a BLE developer or manufacturer, there's some likelihood that you may personally be using a BLE product that is affected by one or more of these vulnerabilities. So, what should you do? What you can do in reality may be limited, but depending on the criticality of the device in question, this investigation may be worth taking the time to do: 1. First, think about any BLE connected devices that you use in your daily life. For example, any device that you can directly connect to from your smartphone will likely utilize BLE for its connectivity to the smartphone. Wi-Fi may be implemented instead, but if it's a device that runs on batteries, it's most likely a BLE device. 2. Look up the device online and find out more about its manufacturer. Look for information about how to contact the support team. Reach out to support and mention the "SweynTooth" vulnerabilities and that you need to know whether the device in question is affected by them. If the device in question is one of those listed in the paper, then you already know that it is affected, and you can refer the support team to the paper and mention that their product is listed there. 3. Depending on what you find out from step #2, if the device is vulnerable then request more information on the timeline of when these issues will be addressed. 4. If the device is affected and the manufacturer has addressed the security issues, you should request more information on the firmware version that includes the fixes. Also, request information on steps you need to take to make sure that your device has the patch(es) applied (including the methodology for updating the device's firmware). 5. Finally, spread the word and make your friends and family aware of these critical vulnerabilities! These steps are generic and apply to any case where vulnerabilities are discovered in IoT devices, not just BLE. Unfortunately, some device manufacturers may be very slow in addressing these issues (depending on the application), and some may even not be aware of these security vulnerabilities! The best we can do, as end-users, is spread the word and make others aware (including device manufacturers!). ## Where do I get more technical information and details? The "SweynTooth" research paper goes into each of the vulnerability categories and specifics in a lot more detail than in this blog post. If you'd like to learn more, then check out the following links: - "SweynTooth" website: [https://asset-group.github.io/disclosures/sweyntooth/](https://asset-group.github.io/disclosures/sweyntooth/?ref=novelbits.io) - "SweynTooth" research paper: [https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf](https://asset-group.github.io/disclosures/sweyntooth/sweyntooth.pdf?ref=novelbits.io) 💡 **Insider Tip:** Tired of wasting hours searching for Bluetooth LE answers that don't exist online? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Implementing Over-the-Air Device Firmware Update for nRF52 - Part 3 URL: https://novelbits.io/ota-device-firmware-update-part-3/ Last updated: 2026-08-09T05:44:04.000Z ⚠️ **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## Introduction In the previous post, [Implementing Over-the-Air Device Firmware Update for nRF52 - Part 2](https://novelbits.io/ota-device-firmware-update-part-2/), we introduced the OTA DFU process on the nRF52. In this post, we'll go over testing the process using one of the DFU examples included in the nRF5 SDK, the "Bluetooth LE Secure DFU Bootloader" example.. The **hardware requirements** for running the Bluetooth LE Secure DFU Bootloader example are: - A development PC (Windows, Linux, or macOS) – for building the bootloader and application, and generating cryptographic keys. - An nRF52832 or nRF52840 development kit – used as the DFU target (**Note:** In all the steps below, we’ll be using an nRF52840 DK). - A mobile phone (iOS or Android) – used as the DFU controller (alternatively, you could use a second nRF52 DK along with your development PC and use nRF Connect for Desktop). The **software requirements** are: - **[nRF5 SDK version 15.3.0](https://www.nordicsemi.com/Software-and-tools/Software/nRF5-SDK/Download?ref=novelbits.io)** - **[Segger Embedded Studio (SES)](https://www.segger.com/downloads/embedded-studio?ref=novelbits.io)** - **Python (and pip)** – check out the following articles for installation instructions: - [Nordic nrfutil Installation Instructions](https://infocenter.nordicsemi.com/topic/ug%5Fnrfutil/UG/nrfutil/nrfutil%5Finstalling.html?ref=novelbits.io) - [Python 3 Installation and Setup Guide](https://realpython.com/installing-python/?ref=novelbits.io) - **GNU ARM Embedded Toolchain** - Download from the official website [here](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads?ref=novelbits.io) - Set your system’s path to include the `/bin` folder – mostly needed for Linux and macOS. Windows will do this automatically during the installation of the toolchain. - Edit nRF5 SDK’s Makefile.posix file to point to the correct location of the GNU ARM Toolchain and indicate the correct version (you can find out the version by running `arm-none-eabi-gcc –version`). The Makefile.posix file is located at `/components/toolchain/gcc/Makefile.posix`. - **nRF Connect for Mobile** ([iOS](https://apps.apple.com/us/app/nrf-connect/id1054362403?ref=novelbits.io), or [Android](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=en%5FUS&ref=novelbits.io)) or **[nRF Connect for Desktop](https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-desktop/Download?ref=novelbits.io#infotabs)** if you’re using a PC as the DFU controller. - **[nRF Command Line Tools](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools/Download?ref=novelbits.io)** – download the appropriate version for your operating system and install the two packages included (JLink installer & nRF Command Line Tools installer). - **Git** - Set up the [**micro-ecc library**](https://github.com/kmackay/micro-ecc?ref=novelbits.io): - Clone the GitHub repo. You can simply run the following command in your terminal or command prompt: `git clone https://github.com/kmackay/micro-ecc.git` - Make sure to clone it in the folder: /external/micro-ecc/micro-ecc - Navigate to the folder /external/micro-ecc/nrf52hf\_armgcc/armgcc/ - **Note:** the **\*hf\*** in the folder name above is used for chipsets that have an FPU (floating-point unit). If your target chipset does not include an FPU, then use the folder with **\*nf\*** in the name. - Build the library by running `make` - The output file will be linked when building the Secure Bootloader Once you’ve got all the hardware and software installed, you’re ready to move on to the next step. ## Testing Out OTA DFU on nRF52 Here are the general steps needed to add and perform Secure OTA DFU over Bluetooth LE for your nRF52 project. In our specific case, we'll be testing the `BLE Secure DFU Bootloader` example. ### 1 – Generate Private-Public Key Pair - Navigate to a folder of your choice for storing the private-public key pair files. - Run the commands: ```bash nrfutil keys generate private.key nrfutil keys display --key pk --format code private.key --out_file public_key.c ``` These commands will create private-public key pair files. For example: **private.key** ```text -----BEGIN EC PRIVATE KEY----- MHcCAQEEIJ1fndsl3rf22bc7caRjj4bjm2jc0GZYT4TZqDJvbrIloAoGCCqGSM49 AwEHoUQDQgAE4qdJSqLzn7x9PbwEO5oqkTnRokObRdZyZveQKgUd3GvS0BuJyDU+ Zy1vtGLrn3CaSsPGiJsuwzWmR/pBMQqg/g== -----END EC PRIVATE KEY----- ``` **public\_key.c** ```c /* This file was automatically generated by nrfutil on 2019-11-22 (YY-MM-DD) at 14:51:03 */ #include "stdint.h" #include "compiler_abstraction.h" /** @brief Public key used to verify DFU images */ __ALIGN(4) const uint8_t pk[64] = { 0x6b, 0xdc, 0x1d, 0x05, 0x2a, 0x90, 0xf7, 0x66, 0x72, 0xd6, 0x45, 0x9b, 0x43, 0xa2, 0xd1, 0x39, 0x91, 0x2a, 0x9a, 0x3b, 0x04, 0xbc, 0x3d, 0x7d, 0xbc, 0x9f, 0xf3, 0xa2, 0x4a, 0x49, 0xa7, 0xe2, 0xfe, 0xa0, 0x0a, 0x31, 0x41, 0xfa, 0x47, 0xa6, 0x35, 0xc3, 0x2e, 0x9b, 0x88, 0xc6, 0xc3, 0x4a, 0x9a, 0x70, 0x9f, 0xeb, 0x62, 0xb4, 0x6f, 0x2d, 0x67, 0x3e, 0x35, 0xc8, 0x89, 0x1b, 0xd0, 0xd2 }; ``` ### 2 – Replace the Placeholder Public Key File - Open the example located at `/examples/dfu/secure_bootloader/pca10056_ble/ses/secure_bootloader_ble_s140_pca10056.emProject` - Replace the file **dfu\_public\_key.c** with the one generated in step #1, or simply copy/paste the contents of **public\_key.c** into **dfu\_public\_key.c** ### 3 – Build the Bluetooth LE Secure DFU Bootloader Build the Bluetooth LE Secure DFU Bootloader example project (using Segger Embedded Studio). ### 4 – Flash the Bootloader and the SoftDevice to the nRF52 DK - Load both the Bootloader and the SoftDevice using SES. - Choose the top menu “**Target**” ==> “**Connect J-Link**”. - Once connected, choose the top menu “**Target**” again ==> “**Erase All**”. - When that’s finished, we can now load the Bootloader and SoftDevice. Choose “**Target**” ==> “**Download secure\_bootloader\_ble\_s140\_pca10056**”. ### 5 – Verify that Bluetooth LE Secure Bootloader is running - After loading the images in the previous step, verify that both LED 1 and LED 2 are on. - Next, open up nRF Connect on Mobile (or Desktop ==> Bluetooth app) and verify that the device is advertising with the name “DfuTarg”: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5188-1-scaled.png) - This indicates that the Bluetooth LE Secure DFU Bootloader is running correctly and ready to accept a new DFU package. ### 6 – Building the nRF52 Application - Next, we’ll build our nRF52 application in SES. - This is the application that we want to include in the DFU package. - Once you build it, locate the output **.hex** file. ### 7 – Generating the DFU Package - To generate the DFU package .zip file, we need to use the `nrfutil` command-line tool. - The command takes in the private key generated from step #1 and the .hex file from step #6. - In this example, we’ll be including the application only (no Bootloader or SoftDevice). - Copy the .hex file from step #6 (.hex file of the application) to the same location as the private key from step #1. - Now, run the following command: ```bash nrfutil pkg generate --hw-version 52 --application-version 1 --application ble_app_blinky_pca10056_s140.hex --sd-req 0xB6 --sd-id 0xB6 --key-file private.key app_dfu_package.zip ``` - Let’s look at each of the arguments passed into the command: - `pkg`: Display or generate a DFU package (zip file). - `generate`: Generate a zip file for performing DFU. - `--hw-version 52`: The hardware version. - `--application-version 1`: The assigned application version. - `--application ble_app_blinky_pca10056_s140.hex`: The application hex file to be included in the DFU package. - `--sd-req 0xB6`: The SoftDevice firmware ID(s) required for the update to be processed, of which one must be present on the target device. Below is the list of SoftDevice firmware IDs supported by version 5.2.0 of the nrfutil command-line tool. We are using SoftDevice s140 version 6.1.1 which matches ID value: **0xB6.** - `--sd-id 0xB6`: The new SoftDevice ID to be used as –sd-req for the Application update in case the ZIP contains a SoftDevice and an Application. - `--key-file private.key`: The private (signing) key in PEM format. - `app_dfu_package.zip`: Name of the output ZIP file (the DFU package). ### 8 – Discover and Connect to the DFU Target - Use nRF Connect for Mobile (or nRF Connect for Desktop Bluetooth App with a second nRF52 DK connected to the PC) and look for the “DfuTarg” advertisement. - You’ll need to make sure the package you created in step #7 is accessible on the mobile phone you’re using (if you’re using nRF Connect for Mobile). - Now, connect to the DFU target: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5190-scaled.png) ### 9 – Start the DFU Process - After you’ve connected to the DFU target in nRF Connect on Mobile, swipe to the left twice to navigate to the DFU screen. Then click “Open Document Picker”: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5193-scaled.png) - Choose the .zip file (from step #7) and start the DFU process. - Click the “Start” button: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5194-scaled.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5195-scaled.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5196-scaled.png) ### 10 – New Firmware Application Once the DFU process is complete, you should see that your new application (that was part of the DFU package) is now running on the DFU Target development kit. In this example, I used the **ble\_app\_blinky** peripheral application: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_5197-scaled.png) ## Next Steps: Buttonless DFU for your Nordic nRF52 project If you want to take this further and implement Buttonless DFU in your own nRF52 project, I cover it end to end in a full course inside the [Bluetooth Developer Academy](https://novelbits.io/academy/). ## Summary & Closing In this post, we went over: - Hardware Requirements - Software Requirements - The different tools needed to build a DFU image - Steps for building and testing out the DFU example 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Implementing Over-the-Air Device Firmware Update for nRF52 - Part 2 URL: https://novelbits.io/ota-device-firmware-update-part-2/ Last updated: 2026-08-09T05:44:00.000Z ⚠️ **Insider Tip:** Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ## Introduction In the previous post, [Implementing Over-the-Air Device Firmware Update (OTA DFU) – Part 1](https://novelbits.io/ota-device-firmware-update-part-1/), we gave an introduction to over-the-air device firmware update (OTA DFU) and went over the best practices for implementing secure and efficient firmware updates. In this second post in the series, we'll go over the OTA DFU process used and implemented for nRF52 series chipsets. We'll cover: - Introduction to OTA DFU on the nRF52 - nRF52 BLE Secure Bootloader - DFU Mode - Firmware Activation - Bootup Sequence on nRF52 - The Device Firmware Update (DFU) Process - The nRF DFU BLE GATT Service - Next Steps: Testing the Nordic Secure Bootloader DFU example Let's get started! ## Introduction to OTA DFU on the nRF52 The nRF SDK provides a few example implementations of bootloaders, each for a different transport (BLE, USB, UART, etc.). The bootloader is used to launch the main application and in some cases switch between multiple applications present in the firmware, and is also used to initialize the device before loading the application. Here's a diagram showing the architecture of the nRF bootloader modules: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-11-27-at-11-01-30-pm.png) The different modules are: - **nrf\_bootloader:** the bootloader module which is responsible for activating new firmware, booting into the application, feeding the watchdog, and entering into DFU mode which allows new firmware to be received. - **nrf\_crypto:** the cryptography library which is responsible for running the cryptographic operations needed for implementing secure firmware updates. - **nrf\_dfu:** the module that provides Device Firmware Update (DFU) capabilities common across the different supported transport mediums. - **nrf\_dfu\_transport:** the intermediary layer that defines a generic interface that must be implemented by each transport layer. - The different **transport modules** that implement the transport-specific operations (BLE, USB, UART, etc.). ## nRF BLE Secure Bootloader The **nRF BLE Secure Bootloader** implements security measures to protect the DFU process from malicious parties. It uses the Bootloader and DFU modules to implement a bootloader with secure DFU functionality. The bootloader is loaded into a dedicated portion of flash memory separate from the SoftDevice and the Application. It will also live in its own Segger Embedded Studio (SES) project that gets compiled separately and loaded onto the target device. **Keep in mind:** the nRF BLE Secure Bootloader depends on the SoftDevice for BLE operation, so the SoftDevice must be present on the device before being to perform a DFU operation. Here's a detailed diagram showing the locations of the different components in flash memory: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-11-27-at-11-37-08-pm.png) The different sections are: - DFU Bootloader section: - Bootloader settings - MBR parameter storage - Bootloader - Application section: - Application data - Application - SoftDevice - MBR (Master Boot Record) ## DFU Mode When the bootloader is in DFU mode, it activates the DFU BLE transport module and the device is ready to receive new firmware. The bootloader goes into DFU mode if one of the following occurs: - There is no valid application present in flash memory. - When a valid SoftDevice and application are present, it is triggered by one of the following: - A pre-defined button is pressed (defined by [NRF\_BL\_DFU\_ENTER\_METHOD\_BUTTON](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv16.0.0/group%5F%5Fnrf%5F%5Fbootloader%5F%5Fconfig.html?ref=novelbits.io#ga2a0043889d40d5b09e524cc701f93fbf)) - A pin reset event (defined by [NRF\_BL\_DFU\_ENTER\_METHOD\_PINRESET](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv16.0.0/group%5F%5Fnrf%5F%5Fbootloader%5F%5Fconfig.html?ref=novelbits.io#gaa89bea64482f2c4d83919922e5e84bc3)) - A special value is present in the GPREGRET register ([NRF\_BL\_DFU\_ENTER\_METHOD\_GPREGRET](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv16.0.0/group%5F%5Fnrf%5F%5Fbootloader%5F%5Fconfig.html?ref=novelbits.io#ga4e1297da5d25948277b4323a6fb87659)) - A request from the application is written to the settings page ([NRF\_BL\_DFU\_ENTER\_METHOD\_BUTTONLESS](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv16.0.0/group%5F%5Fnrf%5F%5Fbootloader%5F%5Fconfig.html?ref=novelbits.io#gab540083b75cd50e020bbd166198476c4)) Once DFU mode is entered, an inactivity timer is started. When this timer expires, the bootloader resets. The timer is on any DFU activity. ## Firmware Activation This is the final step of the firmware update process. It is triggered based on the settings stored in the settings section shown above in the memory layout. It involves either copying the new firmware to replace the old firmware (Single Bank update) or switching to running the new firmware placed in a separate location of the original firmware (Dual Bank update). Once the new firmware replaces the old firmware, the bootloader settings are updated to allow the new firmware image to boot. ## Bootup Sequence Based on the settings stored in the bootloader settings page, the bootloader determines: whether the application exists, and the location of it. The secure bootloader performs a signature verification of the application before booting into it. Here are the boot-up steps that occur from reset to starting the application: 1. First, the MBR is booted. 2. The MBR looks up the location of the bootloader. 3. If a bootloader is found, it is run by the MBR. 4. A secure bootloader (1) uses cryptographic operations to verify the signature of the firmware (Authenticity) and (2) that is it not corrupted (Data Integrity). This is performed in two scenarios: at bootup, and when a new firmware image is received. 5. If a bootloader is not found, the MBR boots the image that follows it (the MBR) at address 0x1000 (the SoftDevice). 6. The SoftDevice then boots the application. There are four different **boot validation** modes that can be configured. - Signature validation (ECDSA) - most secure, and data integrity check. - Hash validation (SHA-256) - less security, and data integrity check. - CRC validation (CRC32) - no security, only data integrity check. - No validation - no security, no integrity check. This is configured as part of the firmware update package. If a signature mode is specified, then the signature will exist in the package. For hash and CRC validation, the cryptographic digest is created on-chip and written to flash when the update is applied. **Important Note:** the boot validation is independent of the firmware update validation process. This means that the update package is signed regardless of the secure boot mode contained in it. This ensures that the system is protected from unauthorized firmware updates even with no boot validation. ## The Device Firmware Update (DFU) Process The DFU process can be run by using one of the following Nordic tools. Each of these tools is used to send the DFU package to the target device to perform the update. - The `nrfutil` command-line tool - nRF Connect for desktop - nRF Connect for mobile Two devices are involved in the DFU process: the **DFU controller** which transfers the DFU package, and the **DFU target** which receives and applies the DFU package. Here's the diagram that we looked at in the previous post, which shows the workflow of the DFU process: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-11-26-at-2-56-11-pm.png) The `nrfutil` command-line tool is used to generate the DFU package that gets transferred by the DFU controller to the DFU target. The update package contains: - The **init packet** - The **binary data** (any combination of Bootloader + SoftDevice + Application) Here are the basic steps involved in the DFU process: 1. The init packet gets transferred to the DFU target first. 2. The target then validates the init packet. 3. If the init packet is successfully validated, the DFU controller then transfers the binary data. 4. The target then post-validates the binary data. 5. If the target validates the binary successfully, it then resets. 6. After reset, the bootloader activates the new firmware image. The DFU package will contain two updates if both the SoftDevice and Application are to be updated. The process is seamless to the end-user and is perceived as a single update (even though in reality it is two updates). ### The Init Packet The manifest portion of the DFU image (referred to as the *init packet* in nRF terminology) must be signed to protect against malicious parties attempting to impersonate the authentic author of the DFU image. The secure bootloader uses the cryptography library (nrf\_crypto) to perform the different necessary cryptographic operations to validate the init packet. Different *backends* are available for use in the bootloader (we'll be using the micro-ecc backend, which is an open-source third-party library available on [GitHub](https://github.com/kmackay/micro-ecc?ref=novelbits.io)). The init packet contains different fields that describe the contents of the DFU package. Here's a table (taken from Nordic's documentation) that shows all the fields within the init packet: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-11-28-at-10-24-57-pm.png) In addition to validation of the signature, the init packet is also verified to make sure that it is compatible with the device and the current firmware and hardware. The different steps of the validation process are performed in the following order: - Signature of the packet, `signature`. To be able to verify the signature, the validation code needs the public key that corresponds to the private key that was used to sign the init packet. This key is located in the file `dfu_public_key.c`. - Firmware type, `fw_type`. - Hardware version, `hw_version`. - SoftDevice version, `sd_req`. - Firmware version, `fw_version`. - Firmware size to see whether the update will fit. The signature is generated using a private key that you create using the `nrfutil` command-line tool (before creating the DFU package). This private key needs to be protected and kept a secret from malicious parties. The bootloader contains a copy of the public key only, which is used to verify the signature created by the associated private key. ## nRF DFU BLE GATT Service The GATT Service implemented as part of the Nordic Secure DFU module is referred to as the **Secure DFU Service**. It is a 16-bit UUID registered with the Bluetooth SIG with the value **0xFE59**. It's a standalone primary service that does not depend on any other services. This is implemented on the DFU target side (GATT Server) and exposed to the DFU controller (GATT Client). It contains the following Characteristics: - **DFU Control Point** **UUID:** 0x8EC90001-F315-4F60-9FB8-838830DAEA50 Permissions: Write, Notify - **DFU Packet** **UUID:** 0x8EC90002-F315-4F60-9FB8-838830DAEA50 **Permissions:** Write Without Response, Notify Security requirements (encryption) are not required for the service, however, its implementation is recommended to provide higher security. ### DFU Control Point Characteristic The DFU Control Point characteristic is used to control the state of the DFU process. DFU operations are initiated by writing to this characteristic. At the end of the DFU process, a notification is sent back to the DFU controller to report the status of the update. The DFU controller is responsible for keeping track of the update progress. ### DFU Packet Characteristic The DFU Packet characteristic is used to transfer the DFU data from the DFU controller to the DFU target. ### DFU Init Packet Transfer First, the init packet is sent to the DFU target. Once it's been verified to be transferred successfully, the DFU controller will issue a command to initiate the validation of the init packet. ### DFU Data Transfer Once the init packet has been successfully validated, the firmware image is split up into several chunks to be transferred to the DFU target. If the transfer operation is suspended at any point (e.g. due to a power failure), the DFU process is able to continue from the last valid data chunk that was received. Once all the data chunks have been transferred successfully, the DFU controller will issue a CRC check command to verify the integrity of the data. If the CRC check passes, the DFU controller will then issue a command to trigger the actual firmware update. ## Buttonless DFU The BLE Secure DFU Bootloader example included in the SDK relies on pressing a button (Button 4 on the nRF52840 DK) during bootup to go into DFU mode and be able to start the OTA DFU process. In production and in practice, however, a "Buttonless DFU" probably makes more sense. This allows you to expose the DFU GATT Service alongside your application's GATT Services and be able to go into DFU mode from within the Application running on your device. ## Next Steps: Testing the Nordic Secure Bootloader DFU example In the next post in this series, we'll go through testing Nordic's OTA DFU example on the nRF52840 dev board and guide you through doing the same step-by-step. If you want over-the-air device firmware update in more detail, including implementing it for your nRF52 project, I cover it end to end in a full course inside the [Bluetooth Developer Academy](https://novelbits.io/academy/). The course includes implementing **Buttonless DFU**, which integrates DFU into your application and allows triggering DFU mode by a remote BLE Client instead requiring to be triggered manually on the end-device. ## Summary & Closing In this post, we covered: - What is Device Firmware Update (DFU)? - What is Over-the-Air Device Firmware Update (OTA DFU)? - How does OTA DFU work? - The role of the bootloader - The basic steps of OTA DFU 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Implementing Over-the-Air Device Firmware Update (OTA DFU) - Part 1 URL: https://novelbits.io/ota-device-firmware-update-part-1/ Last updated: 2026-08-09T05:43:56.000Z ## Introduction One of the most important and critical features of wirelessly-connected devices is the capability of **over-the-air device firmware updates** (aka OTA DFU). You may be asking "why is this becoming an increasingly popular and in-demand feature?" Well, it's due to many good reasons, some of which are: - The increasing demand by end-users for new functionality. - To address bugs and security vulnerabilities (critical and non-critical). - To ship products to market faster and have the option of delaying lower priority features and being able to roll them out to devices in the field. As you can see, these reasons (and many others) make OTA DFU one of the most critical and important features in a wireless connected device. Bluetooth Low Energy has recently become very popular especially in wearables, medical devices, beacons, and other devices that utilize a smartphone as a way to interface with small resource-constrained devices. As such, Bluetooth Low Energy serves as one of the most popular mediums for performing OTA DFU for wirelessly-connected devices. Unfortunately, the resources on the subject are either scarce, very scattered or very specific to a certain platform. So, I set out with the goal to gather all the important guidelines and theory behind the subject and put them all in a **single post**. In this tutorial, we'll go over: - What is Device Firmware Update (DFU)? - What is Over-the-Air Device Firmware Update (OTA DFU)? - How does OTA DFU work? - The role of the bootloader - The basic steps of OTA DFU - Best practices in implementing OTA DFU ## **What is DFU (Device Firmware Update)?** A device firmware update (DFU) is an operation used to, partially or fully, update the firmware on a device. In most cases, DFU relies on the existence of a ***bootloader***. A bootloader is a minimal piece of code that is responsible for: - Launching the main firmware or operating system (OS) in a device. - Providing the capability of updating the device’s main firmware or OS. It is usually optimized and kept to a minimum due to the following reasons: - To ensure minimum impact on boot times. - To ensure bugs are kept to a minimum in this critical part of the device’s firmware. Bootloaders are rarely updated, so they need to be robust (more lines of code usually increase the probability of bugs)*.* - The size of the bootloader impacts how much ROM is left for the application firmware. In general, the main operations of a DFU process include: - Updating the application, the stack/OS (and sometimes even the bootloader). - Verifying DFU package authenticity. - Downgrade prevention. - Verifying hardware compatibility. - Verifying data integrity. - Decrypting encrypted data. - Support for updating over different transport mediums. One thing to note is that DFU sometimes involves multiple parts of the system that can be all, or partially, updated with the firmware update process (e.g. bootloader, RTOS/stack, and application). ### What is Over-the-Air Device Firmware Update (OTA DFU)? OTA stands for “Over-the-Air” and simply refers to the fact that the DFU package is sent to the target/end-device over a wireless connection. In our case, the wireless medium is **Bluetooth Low Energy**. For OTA DFU over Bluetooth Low Energy, there are three main parts: 1. Packaging of the DFU image to be transferred to the target device. 2. Design of the GATT Services and Characteristics needed for the transfer of the DFU image down to the target device. 3. Design of the device firmware update process itself for the target chipset once the device receives the DFU image. Vendors usually provide an implementation of #3 on the target chipset as well as the tools necessary for #1\. Part #2 is optional and sometimes not provided by the vendor. Even if this part is provided by the chipset vendor, in some cases, the end-device designer may wish to design their own implementation. ### **Why implement OTA DFU capability?** While implementing OTA DFU might be/seem like a daunting and complex feat, it has very important benefits. Also, with the proliferation of connectivity for battery-powered and remote devices in recent years, OTA DFU has become more of a product requirement rather than a nice-to-have feature. Some of the most important benefits of OTA DFU include: - Adding new features to the end product. - Fixing critical bugs and addressing security vulnerabilities. - Cutting costs: a product recall is usually way more costly than implementing OTA DFU, especially in large product deployments. As you can see, the benefits of OTA DFU will usually outweigh the cost of implementing this capability in your end product. ### Ensuring a Robust and Secure OTA DFU Process With the introduction of OTA DFU, you are exposing your device to a new attack vector. With the increasing popularity of OTA DFU capability in IoT devices, many devices are now getting more exposure to vulnerabilities and security threats. Because of this, it is extremely important to make sure that your device’s OTA DFU process is very robust and, most importantly, secure. Here are a few of the most important aspects to keep in mind when designing your OTA DFU process: - **Secure**: encryption + identity verification (via digital signatures). - **Reliable:** verifying integrity + failure recovery. - **Version management:** rollback prevention + versioning system. ## **How Does OTA DFU work?** Here are the basics of how an over-the-air device firmware update (DFU) process works: ![Diagram showing the basic steps of the OTA DFU process: encrypt and sign firmware, transfer over wireless, decrypt and validate on device](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/img_62a8356306e5b.png) Basic steps of OTA DFU process 1. Firmware Image and manifest are encrypted, signed, and uploaded to the firmware update server. 2. End-device queries the firmware update server and fetches new firmware image and manifest. 3. The package will be decrypted, validated and applied. These are simply generic steps and depending on the chipset used and system design, there will usually be differences in your own implementation. ### Example of an OTA DFU Process Workflow Let’s look at an example of the DFU process. Here’s an example from the [documentation of Nordic’s DFU process](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv16.0.0/lib%5Fbootloader%5Fdfu%5Fprocess.html?ref=novelbits.io): ![Flowchart of Nordic nRF52 DFU process showing bootloader validation, image transfer, and activation steps](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-11-26-at-2-56-11-pm-1.png) Nordic nRF52 DFU process workflow A few notes about this diagram: - The diagram shows the operations and workflow that occurs on the target device. - “DFU controller” refers to the device that connects to the target Bluetooth LE device that needs to be updated and transfers the firmware image to. This could be a mobile phone running an app or nRF Connect on desktop (via an nRF52 DK). - The target device may be running the bootloader in DFU mode or running the application with DFU running in the background. - The DFU controller connects to the target device and initiates the transfer of the DFU image. - The target device will first receive an init packet which it validates (pre-validation phase). - The init packet contains important information such as the type of image, hash of the image, firmware version, hardware version, allowed versions of the SoftDevice, and others. - If the init packet is validated, the controller will then initiate the transfer of the DFU image to the target. - The target will receive the full DFU image and validate it. - Once the DFU image is validated, the target will reset and the bootloader will activate the new DFU image to replace the original image. - The process is capable of handling updates to the Bootloader + SoftDevice + Application all in one package. Other subsets of this combination are allowed as well, with some exceptions (more information can be found [here](https://infocenter.nordicsemi.com/topic/sdk%5Fnrf5%5Fv16.0.0/lib%5Fbootloader%5Fdfu%5Fprocess.html?ref=novelbits.io)). ### Other Examples of OTA DFU using Bluetooth Low Energy Here are a few other great examples of OTA DFU implementations: - [mbed FOTA service](https://developer.mbed.org/teams/Bluetooth-Low-Energy/wiki/Firmware-Over-the-Air-FOTA-Updates?ref=novelbits.io) - [ST BlueNRG OTA firmware upgrade (AN DM00293821)](https://www.st.com/resource/en/application%5Fnote/dm00293821-the-bluenrg1-bluenrg2-ble-ota-overtheair-firmware-upgrade-stmicroelectronics.pdf?ref=novelbits.io) - [Bluetooth LE113 over the air update](http://www.sureshjoshi.com/embedded/ble113-ota-over-the-air-programming/?ref=novelbits.io) ### Best Practices for Implementing OTA DFU Designing an OTA DFU process can be a lengthy process, and rightfully so. OTA DFU is a risky operation that can break a device’s functionality or make a device vulnerable to security holes. In order to reduce these risks, best practices need to be followed. Here are some of the best practices to follow when designing your system’s OTA DFU process: 1. **Digital Signing:** digital signatures ensure the **authenticity** of the image and **integrity** of the data in the image. Without a signature, there’s no way to verify that the image came from an authentic source, and it could’ve come from a malicious third-party. A digital signature also ensures that the data within the image has not been modified (preserving integrity) and is intact/complete as it was generated at the source/author. 2. **Encryption:** encrypting the image ensures the **confidentiality** of the data. This makes that no unauthorized parties are able to peek at the contents of the image and make sense of it. Only the end-device should be able to decrypt the image. This is especially true for wireless over-the-air updates since the data will be susceptible to third parties sniffing the communications channel used to transfer the image. Security measures also have to be in place to protect any decrypted version of the image that’s stored locally on the end-device. 3. **Communications channel protection:** in addition to taking the necessary security measures to protect the DFU image itself (at the source and destination), measures need to be taken to secure the communications channel over which the DFU image is transferred. Depending on the communication technology used, there are different configurations and implementations that would make sure the communications channel is secure. Examples include utilizing Bluetooth LE Secure Connections (which requires version 4.2 or later), TLS, etc. Keep in mind that communications channels are not always wireless and may involve intra-system transfers such as from an SoC to external flash. This could pose a security threat if a malicious party gets physical access to the end-device. 4. **Versioning:** one of the security measures that need to be put in place is to make sure that a DFU update cannot be performed with an older version of the firmware. In order to achieve this, a versioning system must be put in place allowing only newer versions to be installed. 5. **Recoverability:** a process needs to be put in place to recover from failures in different stages of the DFU process. This includes handling scenarios such as loss of power, data corruption, manipulated DFU image, etc, and being able to roll back the firmware to the original image. 6. **Logging and status reporting:** It’s good practice to log operations and their statuses during DFU processes over the lifetime of a product. These logs could be reported to other devices within the system (such as a gateway, cloud server, etc.) for remote monitoring purposes. They could be useful for debugging purposes or for a better understanding of the causes of failures that may have occurred during a DFU. 7. **Timely updates:** ensuring timely updates can be critical for certain systems or in specific scenarios such as when a security vulnerability has been discovered. In this case, the manufacturer would want to make sure all devices in the field are updated as soon as possible. 8. **Minimize downtime:** depending on the application, some system functionality may be critical and need to be available even during a DFU operation. 9. **User awareness:** It is good practice to make the user aware of an available update. This helps to make sure the user performs the update in close-to-optimal circumstances (e.g. connected to power, sufficient battery levels, minimal disruptions to functionality and usability of the end-device, etc.). It could also help to accelerate initiating the update process in cases where the update addresses vulnerabilities or software bugs (user is more incentivized to perform/allow the update if they’re aware of issues that will be fixed by the update). 10. **Utilize a [hardware-accelerated cryptoprocessor](https://en.wikipedia.org/wiki/Cryptographic%5Faccelerator?ref=novelbits.io)** to speed up cryptographic operations (e.g. in time-critical applications, memory-constrained applications). 11. **Integrate a [secure cryptoprocessor](https://en.wikipedia.org/wiki/Secure%5Fcryptoprocessor?ref=novelbits.io)** into your system when feasible (e.g. in safety-critical applications, time-critical applications, memory-constrained applications). ## Next Steps: OTA DFU for Nordic nRF52 chipsets In [part 2](https://novelbits.io/ota-device-firmware-update-part-2/), we'll be learning about implementing OTA DFU on the nRF52 platform. If you want over-the-air device firmware update in more detail, including implementing it for your nRF52 project, I cover it end to end in a full course inside the [Bluetooth Developer Academy](https://novelbits.io/academy/). That includes **Buttonless DFU**, which folds the update into your application instead of leaving it a separate step someone has to trigger on the device itself. ## Summary & Closing In this post, we covered: - What is Device Firmware Update (DFU)? - What is Over-the-Air Device Firmware Update (OTA DFU)? - How does OTA DFU work? - The role of the bootloader - The basic steps of OTA DFU 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### Zephyr Tutorial: Bluetooth Low Energy Development URL: https://novelbits.io/zephyr-getting-started-bluetooth-low-energy-development/ Last updated: 2026-08-09T05:43:53.000Z **Note:** This tutorial was originally written in late 2019 and some of the code examples and APIs referenced may be outdated. The Zephyr project has evolved significantly since then (including changes to the GPIO API, devicetree macros, and build system). The core concepts still apply, but please refer to the [official Zephyr documentation](https://docs.zephyrproject.org/latest/?ref=novelbits.io) for the most up-to-date code examples and API references. ## What is the Zephyr Project? Zephyr is an open-source real-time operating system (RTOS) meant for use on resource-constrained embedded systems. This can range from simple sensor devices without connectivity to much more complex IoT devices such as smartwatches and medical devices. Zephyr is a Linux Foundation project that is backed by many members including Intel, NXP Semiconductors, Synopsys, Linaro, Texas Instruments, DeviceTone, Nordic Semiconductor, Oticon and Bose. The project's source code is licensed under the Apache 2.0 license. However, it also includes imported components that carry different licenses (learn more [here](https://docs.zephyrproject.org/latest/LICENSING.html?ref=novelbits.io#zephyr-licensing)). It supports multiple architectures including ARM Cortex-M, Intel x86, ARC, and others. For a full list of supported development boards and architectures, refer to the following link: [https://docs.zephyrproject.org/latest/boards/index.html#boards](https://docs.zephyrproject.org/latest/boards/index.html?ref=novelbits.io#boards) Zephyr is powerful because it can be customized to contain only the components that are needed to support the specific requirements of your project. This allows much more efficient use of memory and resources and cuts out anything that is unnecessary for your specific application. The project offers a large number of supported features that are also growing. Some of the features it supports include: - Multi-threading - Interrupt services - Memory allocation - Interthread communication and synchronization - Power management - Memory protection - Compile-time resource definition - Device tree support - Bluetooth Low Energy (including Bluetooth 5.0 and Bluetooth mesh support) - Native Linux, macOS, and Windows development - Virtual filesystem interface - Multi-backend logging - Full-featured shell interface - Non-volatile storage - POSIX **Fun fact:** Zephyr is an English name for the Latin [Zephyrus](https://en.wiktionary.org/wiki/Zephyrus?ref=novelbits.io), the ancient Greek god of the west wind. ## Bluetooth Low Energy Support in Zephyr Bluetooth Low Energy is one of the major supported features and the main wireless connectivity option for devices running Zephyr (as of January 2020). Some of the most important Bluetooth LE features supported are: - Bluetooth Host, Bluetooth Controller, and HCI layer - Unlimited role and connection count, all roles supported - Generic Access Profile (GAP) with all possible LE roles: Peripheral & Central, Observer & Broadcaster. - GATT Server and Client - Pairing and LE Secure Connections - Bluetooth mesh: Relay, Friend Node, Low-Power Node (LPN) and GATT Proxy features. Both Provisioning bearers supported (PB-ADV & PB-GATT) **Interesting fact:** Did you know that Nordic Semiconductor has decided to migrate away from the nRF5 SDK and SoftDevices to using Zephyr for their new products, including the nRF9160 and the nRF5340? [Learn more.](https://developer.nordicsemi.com/nRF%5FConnect%5FSDK/doc/latest/nrf/index.html?ref=novelbits.io) ## The Bluetooth Stack in Zephyr Zephyr implements both the Controller and Host layers of a Bluetooth stack on top of the 2.4 GHz radio hardware layer. It allows two common Bluetooth LE configurations: - **Single-chip configuration:** the three layers are all implemented on a single microcontroller. In this case, the Host and Controller interact with each other via API calls. So, while there's no standard specification for implementing the HCI layer in the Bluetooth specification in a single-chip configuration, the HCI layer is still present in Zephyr when used in this way. However, keep in mind that, in this scenario, how HCI commands, events and data flows between the Host and Controller are implementation-specific. This is becoming the more popular configuration of the two. - **Dual-chip configuration:** in this case, the Controller and radio hardware are on a separate microcontroller from the Host (and Application). The HCI protocol is standardized per the Bluetooth specification document and ensures interoperability, and it allows a developer to choose whatever platform for the Bluetooth Host while choosing any other platform for the Bluetooth Controller. This means a solution could use a Zephyr-based Bluetooth LE Host with a non-Zephyr Bluetooth LE Controller and vice versa. HCI is standardized for UART, SPI, and USB interfaces between the Host and Controller. Here are some diagrams that show examples of the different possible configurations (taken from Zephyr project's documentation): ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-8-44-35-am.png) ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-8-45-00-am.png) The Zephyr stack is also qualified with the Bluetooth SIG, meaning you can qualify your Zephyr-based product without having to go through testing. ## The Zephyr West tool Zephyr includes a command-line tool called west which is used for various operations and purposes. It is called in the following format: ```bash west [common-opts] [opts] ``` One of the tool's important purposes is to handle managing the multiple Git repositories included within the Zephyr repository. The common parent directory of the included repositories is called a *west installation*. In the following, the parent directory **zephyrproject** is a west installation: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-2-25-33-pm.png) The directory **zephyr** that contains the west.yml file is called the **manifest repository** (this is the default for the upstream Zephyr repo, but can be configured differently). The west.yml file is the west manifest and along with the west configuration files controls the installation's behavior. ## Installation and Setup Zephyr development is supported on all the major operating systems including Windows, macOS, and Linux. We won't go through the detailed steps of the installation and setup – those are listed in the Zephyr project documentation: [https://docs.zephyrproject.org/latest/getting\_started/index.html](https://docs.zephyrproject.org/latest/getting%5Fstarted/index.html?ref=novelbits.io). The documentation provides the steps for each of the different operating systems. The steps involve: - Setting up the command-line development environment (including Python3, pip3, the west tool, the software development toolchain, and other dependencies) - Obtaining the Zephyr source code - Building, flashing and testing a sample example on one of the supported development boards ### Troubleshooting You may run into issues during the installation and setup process. The Zephyr documentation includes a section named "**Beyond the Getting Started Guide**" that I found myself referring to for troubleshooting and solving these issues. This documentation section can be found at: [https://docs.zephyrproject.org/latest/guides/beyond-GSG.html](https://docs.zephyrproject.org/latest/guides/beyond-GSG.html?ref=novelbits.io). One example of an issue I ran into on macOS is an error while installing the Python dependencies for the Zephyr project using the pip3 command-line tool. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-3-05-47-pm.png) This can be solved by using the --user pip3 option: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-3-06-58-pm.png) Another issue on macOS is that the Zephyr SDK toolchain is not supported, and instead you will have to install the GNU Arm Embedded Toolchain (for Arm-based development). This is explained in the same "**[Beyond the Getting Started Guide](https://docs.zephyrproject.org/latest/guides/beyond-GSG.html?ref=novelbits.io)"** documentation section. Once you have the toolchain installed on your system, you will need to set a couple of environment variables. In my case, I added the following to the \~/.bashrc file: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-3-16-36-pm.png) And another issue you may run into on macOS when building an example from the repo: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-3-38-47-pm.png) This can be solved by deleting the folder **\~/Library/Caches/zephyr** and rerunning the build command. ### Building an Example To verify that the installation is complete, let's build one of the included examples: the **Blinky** example. When building any of the Zephyr examples, you'll need to specify the target board to be used. In the following example, I built the example for the **nRF52840 DK board** from Nordic Semiconductor. To find out the identifier for a specific board you want to use, simply run the following command: ```bash west boards ``` To get a full list of the supported boards, refer to the **Supported Boards** section in the Zephyr documentation: [https://docs.zephyrproject.org/latest/boards/index.html#boards](https://docs.zephyrproject.org/latest/boards/index.html?ref=novelbits.io#boards) To build the Blinky example on macOS, run the following commands (in a macOS Terminal): ```bash cd ~/zephyrproject/zephyr source zephyr-env.sh west build -p auto -b nrf52840_pca10056 samples/basic/blinky ``` You should see an output similar to the following: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-10-30-55-pm.png) If you need to clean the build folder, run the following command: ```bash west build -t clean ``` ## The Zephyr Build System Zephyr's build system is based on CMake. The build system is application-centric and requires Zephyr-based applications to initiate building the kernel source tree. The application build controls the configuration and build process of both the application and Zephyr itself, compiling them into a single binary. A Zephyr application in its simplest form will contain the following: ``` /app ├── CMakeLists.txt ├── prj.conf └── src └── main.c ``` The main files are: - **CMakeLists.txt**: tells the build system where to find the other application files, and links the application directory with Zephyr’s CMake build system. This link provides features supported by Zephyr’s build system, such as board-specific kernel configuration files, the ability to run and debug compiled binaries on real or emulated hardware, and more. - **prj.conf**: specifies application-specific values for one or more kernel configuration options. These application settings are merged with board-specific settings to produce a kernel configuration. - **Application code**: all the application's source code files, generally included under the src folder. The simplest application will have just a single source file: main.c. When building an application, the build artifacts are generated and placed in a **build** directory. ## Devicetree Zephyr uses the *devicetree* data structure to describe the hardware available on a development board, as well as its initial configuration in an application. The devicetree specification is available online at [https://www.devicetree.org](https://www.devicetree.org/?ref=novelbits.io). Devicetree is used in the Linux kernel as well. Zephyr uses a devicetree to generate code during the build process. It uses what's called [devicetree bindings](https://docs.zephyrproject.org/latest/guides/dts/index.html?ref=novelbits.io#devicetree-bindings) along with a set of rules to generate the C definitions. The C macros generated by this process all begin with `DT_`. The following diagram shows how the devicetree is used in Zephyr's build process: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-24-at-11-05-20-pm.png) We won't get into the details of devicetrees in this post. To learn more about devicetrees and how they fit within the Zephyr build process, refer to the documentation at: [https://docs.zephyrproject.org/latest/guides/dts/index.html#device-tree](https://docs.zephyrproject.org/latest/guides/dts/index.html?ref=novelbits.io#device-tree). ## The Blinky Example Once you have everything set up from the previous lesson, you're now ready to build one of the examples included in the Zephyr repository. The simplest example is the **Blinky** example app. Let's take a look at this example's source code to understand what a typical Zephyr application looks like. If you take a look at the files in the Blinky example's folder zephyrproject/zephyr/samples/basic/blinky: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-22-at-10-35-35-pm.png) You'll notice the example is very simple with only one source file under the src folder: **main.c**. In addition to that, you'll find the following files: **CMakeLists.txt**: tells the build system where to find the other application files, and links the application directory with Zephyr’s CMake build system. This link provides features supported by Zephyr’s build system, such as board-specific kernel configuration files, the ability to run and debug compiled binaries on real or emulated hardware, and more. ```cmake # SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.13.1) include($ENV{ZEPHYR_BASE }/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(blinky) target_sources(app PRIVATE src/main.c) ``` **prj.conf**: specifies application-specific values for one or more kernel configuration options. These application settings are merged with board-specific settings to produce a kernel configuration. This is where you would add the specific Zephyr features and modules that your application needs (e.g. Bluetooth LE support, GPIOs, etc.). ```kconfig CONFIG_GPIO=y ``` **README.rst**: a readme file that describes the application. ```rst .. _blinky-sample: Blinky Application ################## Overview ******** The Blinky example shows how to configure GPIO pins as outputs which can also be used to drive LEDs on the hardware usually delivered as "User LEDs" on many of the supported boards in Zephyr. Requirements ************ The demo assumes that an LED is connected to one of GPIO lines. The sample code is configured to work on boards that have defined the led0 alias in their board devicetree description file. Doing so will generate these variables: - DT_ALIAS_LED0_GPIOS_CONTROLLER - DT_ALIAS_LED0_GPIOS_PIN Building and Running ******************** This samples does not output anything to the console. It can be built and flashed to a board as follows: .. zephyr-app-commands:: :zephyr-app: samples/basic/blinky :board: reel_board :goals: build flash :compact: After flashing the image to the board, the user LED on the board should start to blink. ``` **sample.yaml**: used for testing purposes. ```yaml sample: name: Blinky Sample tests: sample.basic.blinky: tags: LED gpio filter: dt_compat_enabled_with_alias("gpio-leds", "led0") depends_on: gpio harness: led ``` Here's what main.c looks like: ```c /* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #define LED_PORT DT_ALIAS_LED0_GPIOS_CONTROLLER #define LED DT_ALIAS_LED0_GPIOS_PIN /* 1000 msec = 1 sec */ #define SLEEP_TIME 1000 void main(void) { u32_t cnt = 0; struct device *dev; dev = device_get_binding(LED_PORT); /* Set LED pin as output */ gpio_pin_configure(dev, LED, GPIO_DIR_OUT); while (1) { /* Set pin to HIGH/LOW every 1 second */ gpio_pin_write(dev, LED, cnt % 2); cnt++; k_sleep(SLEEP_TIME); } } ``` In **main.c**, we: - Included the necessary header files (lines 7-9) - Defined the LED port and pin (lines 11-12) The example assumes that an LED is connected to one of the GPIO lines. The sample code is configured to work on boards that have defined the led0 alias in their board devicetree description file. Doing so will generate the variables: **DT\_ALIAS\_LED0\_GPIOS\_CONTROLLER** and **DT\_ALIAS\_LED0\_GPIOS\_PIN** - Defined a sleep period (line 15) - Implemented the main function which configured the LED pin and toggles the pin every second (lines 17-32) ## Building the Blinky Example Building the example is simple. All you have to do is run the following commands (for macOS and Linux. For Windows, refer to the Zephyr official documentation): ```bash cd ~/zephyrproject/zephyr source zephyr-env.sh west build -p auto -b nrf52840_pca10056 samples/basic/blinky ``` Sourcing the zephyr-env.sh shell file is only needed once for each shell session. You could also add it to your shell init file (e.g. \~/.bashrc or \~/.bash\_profile) to have it persist across different sessions. ## Flashing the Blinky Example Flashing the example is also simple. Just make sure the target development board is connected to your computer and run the command from the folder where the build folder exists: ```bash west flash ``` ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-24-at-12-48-58-am.png) If you have multiple applications and want to flash a specific build, run the following command: ```bash west flash --build-dir path/to/build/directory ``` ## Serial Output Debugging For simple debugging by printing messages to the UART, you can use printk() to print out messages to the serial port. The serial port is the default backend for printing messages in Zephyr. Let's modify our main.c to add a couple of log messages: ```c /* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #define LED_PORT DT_ALIAS_LED0_GPIOS_CONTROLLER #define LED DT_ALIAS_LED0_GPIOS_PIN /* 1000 msec = 1 sec */ #define SLEEP_TIME 1000 void main(void) { u32_t cnt = 0; struct device *dev; printk("Configuring the LED port and pin\r\n"); dev = device_get_binding(LED_PORT); /* Set LED pin as output */ gpio_pin_configure(dev, LED, GPIO_DIR_OUT); printk("Blinky started\r\n"); while (1) { /* Set pin to HIGH/LOW every 1 second */ gpio_pin_write(dev, LED, cnt % 2); cnt++; k_sleep(SLEEP_TIME); } } ``` Lastly, we recompile the application and flash it to the DK. ```bash west build -p auto -b nrf52840_pca10056 west flash ``` Now, we can simply run a serial terminal program, connect it to the J-Link interface and see the log messages: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2019-12-24-at-1-32-23-am.png) ## **Next Steps: Implement Custom GATT Services and Characteristics** Naturally, the next step would be to implement our own custom Services and Characteristics for our specific application. ## **Summary** In this post, we went over: - An introduction to the Zephyr project - Setup and installation steps - Building and flashing an example Zephyr-based application (nRF52840 use case) - Bluetooth LE development using Zephyr Zephyr is a really exciting project, and it's gaining a lot of traction. Nordic Semiconductor, for example, has switched to using Zephyr for their latest products (nRF9160 and nRF5340), and I wouldn't be surprised if other vendors followed suit. I believe it has the potential to become a dominant RTOS in the world of IoT device development. Imagine in a few years if Zephyr was used officially supported on most chipsets in the market (kind of like the embedded Linux for microcontroller-based systems)! This means you could learn this new development platform and then apply that knowledge across many projects. I can't imagine a better time to start learning Zephyr than now! 💡 **Insider Tip:** Want the fundamentals underneath all of this? Start with the free [Bluetooth LE Crash Course](https://novelbits.io/bluetooth-le-crash-course/): twelve short lessons, one a day, covering the fundamentals from the radio up. ### The nRF52840 USB Dongle Tutorial (Part 1) URL: https://novelbits.io/nrf52840-usb-dongle-tutorial-1/ Last updated: 2026-04-26T17:49:18.000Z When it comes to Bluetooth Low Energy modules, chipsets and development kits, prices are only getting lower. Take for example the new [nRF52840 USB dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle?ref=novelbits.io). The dongle costs **only $10** and can serve as a great development kit with a few I/O peripherals including one button, two LEDs (one green, one RGB), and 15 GPIO pins. The nRF52840 dongle is a compact USB dongle that's based on the [nRF52840 chipset](https://www.nordicsemi.com/eng/Products/nRF52840?ref=novelbits.io) from Nordic Semiconductor. The dongle can be used in two main use cases: - As a dongle that enables nRF Connect PC applications such as the **Bluetooth Low Energy application** (central and peripheral emulator), the **nRF Cloud Gateway application**, and the **RSSI Viewer application.** - As a development kit that can run your own custom applications or the sample applications provided with the nRF52 SDK. These include Bluetooth Low Energy, Bluetooth mesh, Thread, ZigBee, 802.15.4, ANT and 2.4GHz proprietary applications. Keep in mind that the dongle does not have debug capabilities, but rather only supports programming or communicating via the USB port. Also, as of the time of this tutorial, the **nRF Sniffer** application **does not** support the nRF52840 dongle, but this is inevitable to change. When this feature becomes available, this low-cost dongle will serve as a great sniffer especially for capturing Bluetooth 5 BLE traffic including long-range mode (Coded PHY), high-speed mode (2M PHY), and extended advertisements packets. In today's blog post, we will cover how to use the dongle for running the **Bluetooth Low Energy nRF Connect application** as a **central** or a **peripheral**. In an upcoming post, we will go over how to use the dongle to run your own custom BLE application. More info on the dongle can be found at the Nordic InfoCentral documentation website here: [nRF52840 USB dongle](https://www.nordicsemi.com/?sc%5Fitemid=%7BCDCCA013-FE4C-4655-B20C-1557AB6568C9%7D&ref=novelbits.io). If you're interested in **buying it**, check out this [page](https://www.nordicsemi.com/eng/Buy-Online?search%5Ftoken=nRF52840DONGLE&ref=novelbits.io). **Follow-up posts:** - [Prototyping BLE apps on the nRF52840 USB Dongle (Part A)](https://novelbits.io/nrf52840-usb-dongle-tutorial-2/) ## nRF Connect Bluetooth Low Energy application The nRF Connect application on the desktop supports a few applications (with more being added continuously). It started out as a simple application but is now becoming the single hub for all desktop-based nRF applications. As of the writing of this tutorial, the applications included in the desktop nRF Connect app are: - Bluetooth Low Energy application - nRF Cloud Gateway application (experimental) - Power Profiler - Programmer (experimental) - RSSI Viewer Today we will be focusing on using the Bluetooth Low Energy application. The different applications that support the dongle will automatically prompt you to update the dongle with the appropriate firmware that allows the application to interface with the dongle. The Bluetooth Low Energy supports two modes of operation: - As a BLE central device that can discover advertising devices (broadcasters and peripherals). - As a BLE peripheral that advertises, allows connections, and exposes a GATT server. The GATT can be customized with SIG-adopted services and characteristics or your own custom services and characteristics. ### Installing the nRF Connect and Bluetooth Low Energy Applications To get started, follow these steps: - Make sure you have the nRF52840 USB dongle connected to your computer - Install the nRF Connect desktop application from [this link](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF-Connect-for-Desktop?ref=novelbits.io). The application is available for Linux, macOS, and Windows. - Once you have the application installed, launch the application. you will be presented with the following screen: ![Main nRF Connect Window](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-1.png) Figure 1: Main nRF Connect window - Navigate to the **Add/remove apps** tab ![Add/Remove apps](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-2.png) Figure 2: nRF Connect Add/Remove apps - Make sure that the Bluetooth Low Energy application is installed. If not, click the **Install** button. - Make sure the application is up-to-date. Navigate to the **Settings** tab then click **Check for updates now.** ![nRF Connect Check for Updates](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-3-1.png) Figure 3: nRF Connect Check for Updates - Navigate back to the **Add/remove apps** tab. If there's an update available, click **Update.** - Navigate back to the **Launch app** tab, and launch the **Bluetooth Low Energy** application. ![nRF Connect Launch Bluetooth Low Energy app](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-4-1.png) Figure 4: Launch nRF Connect BLE app - If this is the first time you're using this application, or if you've used the dongle with another app or programmed it with your own application, you will have to update the dongle with the appropriate firmware that enables it to run the Bluetooth Low Energy application. To do this, select the device from the **Select serial port** drop-down menu and you will be prompted to update the firmware on the device: ![nRF Connect select device from serial port](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-5.png) Figure 5: nRF Connect select device from the serial port - Once it's programmed correctly, you will see the following screen: ![Connected to USB Dongle](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-6.png) Figure 6: Connected to USB Dongle Now you're ready to run interface with the dongle and use it as either a BLE central or as a BLE peripheral. ### BLE Central Mode Whether you're testing a new feature of your BLE device or want to interact with an existing one, using an application that acts as a BLE central (*aka central emulator apps*) can help a lot. It saves you from spending hours programming a custom application to perform your own testing. This is especially useful during the early phases of a project when the mobile companion app is not ready yet and may require a lot of effort to get it working. There are two main aspects of acting as a central device: - Discovering advertising devices in the surrounding area. - Connecting to an advertising device (that allows connections). Usually, following a connection, the central will also interact with the peripheral's GATT server (and vice versa) via reads, writes, notifications, and indications on characteristics. Let's cover each of these aspects and how to accomplish them using nRF Connect's Bluetooth Low Energy application. #### Scanning for BLE peripherals To perform a scan for advertising BLE devices: - Start by clicking the **Start scan** button. ![nRF Connect Start Scan](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-7.png) Figure 7: nRF Connect Start Scan - I find it helpful to sort the list of scanned devices by RSSI. You could do this by clicking **Options** then **Sort by signal strength.** ![nRF Connect Sort by RSSI value](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-8-1.png) Figure 8: Sort by RSSI value - To see more details about the advertising device, click the **Details** button. This will display the advertising data and any fields it contains. ![nRF Connect Advertising details](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-9-1.png) Figure 9: Advertising details #### Connecting to BLE peripherals After scanning for devices, you can connect to a device by clicking the **Connect** button next to a device in the scan results. Once you're connected to a peripheral, you can browse and navigate the different services and characteristics exposed by the GATT server on the device. nRF Connect's Bluetooth Low Energy app allows you to connect to multiple peripherals at the same time, and they will all be displayed in the same window: ![Connected to multiple peripherals](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-10.png) Figure 10: Connected to multiple peripherals You could also see the parameters and properties of the connection such as: - Connection interval - Slave latency - Supervision timeout - Bonding status - Pairing status ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-13-1.png) Figure 11: Connection information Another feature available is the ability to change the properties of the connection (since the dongle acts in the central role, and hence it controls the parameters) such as: - Connection parameters - Initiating pairing - Disconnecting ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-14-1.png) Figure 12: Connection parameters Once you're connected to a peripheral, you can now interact with the device's GATT server. For example, you could read, write and enable/disable notifications and indications. #### Reading characteristics To read a characteristic, click on the characteristic of interest then click on the "reload" icon: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-15-1.png) Figure 13: Read Characteristic Now the new value (if any) will be updated. #### Writing to characteristics To write to a characteristic, select the characteristic of interest, then click on the text input box located under the properties (read, write, indicate, etc.). Then enter the value you wish to write, and press the **checkmark** button: ![nRF Connect Writing to a characteristic](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-16-1.png) Figure 14: Writing to a characteristic ### BLE Peripheral Mode To set up the dongle to act as a peripheral, we first need to configure the different parameters and services and characteristics exposed by the GATT server. To do this, navigate to the **Server Setup** tab: ![nRF Connect Server Setup](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-17.png) Figure 15: Server Setup You'll notice that the Generic Access service already exists since it's a mandatory service. Within the service, you'll find three characteristics defined: - Device Name - Appearance - Peripheral Preferred Connection Parameters You can customize each of these characteristics by clicking on them. ![Modifying characteristics](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-18.png) Figure 16: Modifying characteristics You can also add services and characteristics of your own. Once you're done with the customizations, click the "**Apply to device"** button. Now you can go back to the **Connection Map** tab. Click the **gear** button next to the nRF5u dongle listing, then click on **Start advertising**. ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/figure-21.png) Figure 17: Start Advertising Once it starts advertising, a wireless icon will be displayed: ![](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/advertising-started.png) Figure 18: Advertising started To verify the device is advertising and working properly, you can use a BLE client emulator app on a mobile phone such as Nordic nRF Connect or LightBlue Explorer. #### Peripheral mode example Let's go ahead and set up the nRF52 USB dongle to include the **Battery service** and **Battery Level characteristic,** then connect and interact with it from a mobile app. For the mobile app I will be using [LightBlue.](https://itunes.apple.com/us/app/lightblue-explorer/id557428110?mt=8&ref=novelbits.io) Here's a video showing the whole process: As you can see, with just a few quick steps we can set up a peripheral, discover it and connect to it from a mobile app. We can also see that changing the value of a characteristic on the device side (via the nRF Connect app on the PC) is reflected and can be seen on the mobile side. ## Summary In this tutorial, we introduced the nRF52840 USB dongle. We then talked about the two main use cases of the dongle: as a **tool for nRF Connect apps** or as a **general nRF development kit**. Today's tutorial focused on using the dongle as an nRF Connect tool. In an upcoming follow-up tutorial, we'll cover the other use case: how to use the dongle as a general nRF development kit to run your own custom applications. ### Bluetooth 5 Advertisements: Everything you need to know URL: https://novelbits.io/bluetooth-5-advertisements/ Last updated: 2026-05-01T15:52:40.000Z You’ve probably heard so much about the recently released [Bluetooth 5](https://www.bluetooth.com/bluetooth-resources/bluetooth-5-go-faster-go-further/?ref=novelbits.io). You’ve seen all the hype on **2x Speed**, **4x Range**, and **8x Advertising data increase** capabilities. But what does this all mean?? How does it achieve all these improvements? Is it really possible to achieve all these simultaneously?? What about power consumption? How is that affected? Look: There was so much media hype surrounding the release of Bluetooth 5, and lots of conflicting information with very few details. Many media articles made it *sound like you can achieve all these simultaneously!* In this first post of a series on **Bluetooth 5**, I’ll go ahead and demystify all these facts for you as well as cover Bluetooth 5 Advertisements in detail. The goal with this series of blog posts is: - Fully understand the **3 main improvements** that Bluetooth 5 achieves (Speed, Range, and Advertisements). - Know which of these will benefit your application/use-case the most. - How you can utilize the new improvements of Bluetooth 5 to your advantage. - How to determine whether a BLE chip/module supports the new features you’re interested in utilizing. - Which applications and use cases will benefit from each of these improvements. - Have a full example of implementing each of these features on a chosen platform. ![Intro to Bluetooth Low Energy book cover](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Free eBook Intro to Bluetooth Low Energy Get the key concepts every developer needs before diving into Bluetooth LE development. Send Me the eBook Check your email! We sent a confirmation to . No spam. Unsubscribe with one click. **First, let's make it clear that Bluetooth 5 does not achieve both increased range and speed simultaneously - in fact, you will absolutely sacrifice speed in favor of range and vice versa!** A few things to note: - Not all these new Bluetooth 5 features require new **hardware**. - Some vendors will provide software updates to support some of these new features of Bluetooth 5 (for features that don't require a hardware update). - Vendors can claim Bluetooth 5 support, but they won’t necessarily support the popular improvements, so **be careful when choosing a module/chip** with the intention of utilizing higher speeds or extended range. According to the spec section Volume 1, Part A, 1.2: > The mandatory symbol rate is 1 megasymbol per second (Msym/s), where 1 symbol represents 1 bit therefore supporting a bit rate of 1 megabit per second (Mb/s), which is referred to as the LE 1M PHY. The 1 Msym/s symbol rate may **optionally** support error correction coding, which is referred to as the LE Coded PHY. > > An **optional** symbol rate of 2 Msym/s may be supported, with a bit rate of 2 Mb/s, which is referred to as the LE 2M PHY. Notice the “*optional*” keyword in both cases of the **LE 2M PHY** (achieving 2x speed) and **LE Coded PHY** (achieving longer range via Forward-Error Correction). PHY is the term used to refer to the Physical Layer of Bluetooth technology. For more info on the term, refer to the [Wikipedia article on PHY](https://en.wikipedia.org/wiki/PHY%5F%28chip%29?ref=novelbits.io). So, let's take a look at what's new with Bluetooth 5.0 (compared to 4.2 and earlier versions). Several new features are introduced in the Bluetooth Core Specification 5.0 Release (compared to version 4.2): - Slot Availability Mask (SAM) - **2 Msym/s PHY for LE** - **LE Long Range** - High Duty Cycle Non-Connectable Advertising - **LE Advertising Extensions** - LE Channel Selection Algorithm #2 We will start by talking briefly about the new higher speed **2 Msym/s PHY** and the Long Range feature (utilizing the **Coded PHY**). After that, we will go deep into **Bluetooth** **5 Advertisements** in general as well the new **LE Advertising Extensions** feature. In upcoming posts, we'll go over each of the longer range and higher speed features in more detail. We will also go over how to implement Extended Advertisements on the nRF52840 Preview Development Kit using the nRF Connect SDK (which is based on Zephyr RTOS) using nRF Connect for Desktop's Bluetooth Low Energy app. **Bonus:** [Download](#) my free report on the 5 Essential Bluetooth Low Energy Tools which help you develop for BLE in the most efficient manner. ## **How Bluetooth 5 increases speed to 2x and range to 4x** With the addition of the new 2 Msym/second PHY, Bluetooth 5 can now transfer data at 2x the rate of the original 1 Msym/s PHY. There are three PHYs in Bluetooth 5: - **1 Mbps PHY**: This PHY is mandatory and is **uncoded** (modulated at 1 Megasymbol/sec). *Uncoded* means that each symbol is represented by exactly one bit, so a theoretical data rate of 1 Megasymbol/sec equates to 1 Mbps of data. - **2 Mbps PHY**: This is **uncoded** as well (modulated at 2 Megasymbol/sec), and helps achieve the *higher speed* (2 Mbps) than Bluetooth 4.2. - **Coded PHY:** This is also modulated at 1 Megasymbol/sec. By using a coding technique, the data can be error-corrected on the receiving end (to a given extent). This helps achieve the *longer range* in Bluetooth 5 - we are simply increasing the receiver sensitivity rather than changing transmit power on the transmitter side. ![Table for PHY types in Bluetooth 5](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/phy_types_bluetooth_5.png) This following figure from the official spec better explains this: There are certainly trade-offs for choosing one of these PHYs over the other (*there are also restrictions on where each can be used*). In addition to the increased speed, the new 2M PHY also reduces power consumption since the same amount of data is transmitted in less time reducing the radio-on time. Coexistence is also improved because of the less radio-on time. The benefit of using the LE Coded PHY is increased range with the trade-off of both higher power consumption and reduced speed (down to 125kbps or 500 kbps depending on the coding used S=2 vs. S=8). Here are a few videos showing both the longer range and higher speed features of Bluetooth 5 by [Nordic Semiconductor](http://www.nordicsemi.com/?ref=novelbits.io) and [Texas Instruments](http://www.ti.com/?ref=novelbits.io): ## **Bluetooth 5 Advertisements** Bluetooth Low Energy uses **40** different frequency channels (PHY channels), separated by 2 MHz. **Three (3)** of these channels are called Primary Advertisement channels, while the remaining **37** channels are used for Secondary Advertisements as well as Data channels for transfers during a connection. Advertisements are used by devices to broadcast data and info for other observer devices to discover and process. It allows the device to broadcast this information for multiple devices to discover without a connection between the observers and broadcaster. Advertisements always start with advertisement packets sent on the 3 primary channels (or a subset of these channels). Extra information can then be offloaded to the Secondary advertisement channels to allow for more data to be broadcast. There's also an additional mode called **Periodic Advertisement** that allows a scanner or observer to be synchronized with the advertisements sent continuously by the broadcaster. The two main categories of advertisements are: 1. *Legacy Advertisements* (same advertisements from the previous versions of Bluetooth Low Energy 4.0, 4.1, 4.2 and also exist in 5.0). They include the following types of PDU (Protocol Data Unit): 1. ADV\_IND 2. ADV\_DIRECT\_IND 3. ADV\_NONCONN\_IND 4. ADV\_SCAN\_IND 2. *Extended Advertisements* (introduced in Bluetooth 5). These can be utilized for sending more data than the legacy advertisements allow. They can also be used to initiate *Periodic Advertisements*. Extended Advertisements can *only* be discovered by devices that support this feature. They include the following types of PDU (Protocol Data Unit): 1. ADV\_EXT\_IND 2. AUX\_ADV\_IND 3. AUX\_SYNC\_IND 4. AUX\_CHAIN\_IND To better understand the different advertising PDUs and which PHY is allowed for each, we refer to the spec (*Volume 6, Part B, Section 2.3*): ![Advertisement PDU PHY Table Part 1](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/phy-advertisement-pdus-1.png) ![Advertisement PDU PHY Table Part 2](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/phy-advertisement-pdus-2.png) This table lays out the PHYs can be used for each of the Advertising PDU Types. You will notice that all the legacy advertisement PDUs we listed can only be sent on the original LE 1M PHY, and that the only Primary Advertisement PDU that can be sent on anything other than the 1M PHY is the ADV\_EXT\_IND (which is the only case where one of the new PHYs can be used on the primary advertising channels). All others are Secondary Advertising packets and can be sent on any of the three PHYs. To better understand where each of these PDU types is used, let's look at another table from the Bluetooth 5.0 Spec (*Volume 6, Part B, Section 4.4.2, Table 4.1):* ![Bluetooth 5 Advertising Event Types Table](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/screen-shot-2017-07-03-at-12-20-59-pm.png "Bluetooth 5 Advertising Event Types Table") You'll notice that the only Advertising Event that does not allow **ADV\_EXT\_IND** is the Connectable and Scannable Undirected Event. For this advertising event type, **ADV\_IND** is the only type allowed. A few notes about the two types of advertising channels: ### **Primary advertisement channels** - Set of 3 fixed PHY channels (channels 37, 38 & 39) - Divided into advertising events where each event can occur on each of the 3 advertising PHY channels (or a subset) - Consecutive events start with the first advertising PHY channel (e.g. if advertisements start with channel 37, then each event will start with an advertisement packet sent on channel 37) - Events occur at regular intervals - Some advertising devices allow scan requests or connection requests on the same advertising PHY channel - The advertising device can send a scan response packet on the same advertising PHY channel within the same advertising event ### **Secondary advertisement channels** - Set of 37 fixed PHY channels (same as the data channels used during a connection - channels 0-36) - Not part of the advertisement event, but rather part of the *extended advertisement event* - Begin at the same time as the advertisement event on the primary channel and end with the last packet on the secondary channel - Used to offload data that would otherwise exist on the primary channel - They are called “auxiliary packets” - An advertisement packet on the primary channel contains the PHY channel and the offset to the start time of the extended advertisement packet - Secondary advertisement channel can use any LE PHY (Uncoded 1M PHY, Uncoded 2M PHY, or Coded S=8 or S=2 PHY) - All advertising packets in the secondary channel should use the same PHY ## **Bluetooth 5 Extended Advertisements** Extended Advertisements are a way to advertise more (offloaded) data than what's allowed with Legacy Advertisements. Offloading is accomplished by first advertising on the primary channel that points to an auxiliary packet on the secondary channel. **Note:** Since *non*\-Bluetooth 5 devices will not be able to discover extended advertisements, it is recommended that advertisers also use an advertising set with legacy advertising PDUs for older scanning devices to be able to discover the end device. Advertising sets are used to send out different types of advertising events simultaneously. Each advertisement set will have different advertisement parameters such as advertising PDU type, advertising interval, and PHY. When advertising on the LE Uncoded 1M PHY: - Scan requests and responses can take place on the same PHY channel as the original advertisement or be offloaded to the secondary channel. - In some cases when advertising on the Uncoded PHY, connection requests and responses are offloaded to the secondary channel. When advertising on the LE Coded PHY: - Scan requests, scan responses, connection requests, and connection responses ARE ALWAYS offloaded to the secondary channel. ### **Periodic Advertisements** Another feature of Bluetooth 5 Extended Advertisements is Periodic Advertisements. These are used for broadcasting packets to devices at a set period between two unconnected devices, meaning that more than one device can listen and tune in on these periodic advertisements. They consist of advertisements sent at a fixed interval with the advertisement data changing from time to time. The way this is accomplished is as follows (from the spec Volume 6, Part B, Section 4.4.2.3): ![Periodic Advertisements in Bluetooth 5 using Extended Advertisements](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2025/07/periodic-advertisements-bluetooth-5.png) As you can see from the figure above, the primary advertisement channel is used to transmit the ADV\_EXT\_IND PDU type which holds information (Time offset, PHY...etc) that can be used to find the AUX\_ADV\_IND PDU packet. That packet, in turn, contains the SyncInfo field which defines the data needed to synchronize to the periodic advertisement packets (AUX\_SYNC\_IND and AUX\_CHAIN\_IND) in a way similar to how connections are formed (channel map, hop sequence, which PHY...etc). Therefore, a scanner can target an advertising device by first discovering the advertisement event on the primary channel, and then tuning into the appropriate secondary channel and timing based on information sent in the primary advertisement packet. ## **How and when can you utilize Bluetooth 5 Advertisements?** No doubt that Beacon applications will benefit the most from extended advertisements. However, it will take time before you can practically utilize this feature since it will depend on the scanning devices (smartphones, tablets, PCs) supporting Bluetooth 5 Extended Advertisements. Beacons can now broadcast more data and allow for a better user experience. Connectable devices can also utilize this to send more data and allow connections on the secondary advertising channels (which can help avoid interference and noise from other devices broadcasting on the primary channels). The use of Periodic Advertisements can also help in making the broadcasting device more consistently discovered and monitored, with the possibility of the broadcast data being updated to reflect certain attributes and aspects of the broadcasting device (e.g. in the case where a scanning device is always present in the proximity of a broadcasting device, now this scanning device can more consistently "follow" the advertiser and monitor its updates more frequently). ## **Conclusion & Summary** Extended Advertisements (including periodic advertisements) is just one of the exciting new features of Bluetooth 5\. Next time, I will cover another major feature included in Bluetooth 5: the new PHYs (2 Mbps PHY and the Long Range PHY which supports up to 4x the range of Bluetooth 4.2). Stay tuned! To summarize what we covered today: - Overview of Bluetooth 5 and its major improvements - How Bluetooth 5 achieves higher speed and longer range - General overview of Bluetooth advertising - Types of Bluetooth 5 advertising channels - In-depth look into Extended Advertisements and Periodic Advertisements - Example code for sending extended advertisements using the nRF52840 Preview Development Kit - Video showing the capture of these advertisements by a commercial Bluetooth 5 sniffer (Ellisys Bluetooth Tracker) - How and when to utilize Extended Advertisements ![Intro to Bluetooth LE book](https://storage.ghost.io/c/86/70/8670d5a8-12b7-448c-b3db-a85bc1fcdea7/content/images/2026/02/18005-Mohammad-A-3D-Book-Cover-V3.png) Want a solid foundation in Bluetooth LE? Get the free Intro to Bluetooth Low Energy eBook — or grab the expanded 2nd Edition in print. [Get the Book →](https://novelbits.io/intro-to-ble-book/) ### How do I choose a UUID for my custom services and characteristics? URL: https://novelbits.io/uuid-for-custom-services-and-characteristics/ Last updated: 2026-08-09T05:26:41.000Z First, a few things to know: - "A UUID is a universally unique identifier that is guaranteed to be unique across all space and all time" (*Bluetooth 4.2 spec, Vol 3, Part B, section 2.5.1 UUID)* - A UUID is a 128-bit value. - There are reserved UUIDs by the Bluetooth SIG that are generally represented by their 16-bit aliases. These aliases are used for convenience and represent a 128-bit value computed as follows: 128-bit value = 16-bit-value \* 2^96 + BluetoothBaseUUID where the BluetoothBaseUUID is 00000000-0000-1000-8000-00805F9B34FB Examples include: 0x180F -> Battery Service UUID (128-bit UUID: 0000180F-0000-1000-8000-00805F9B34FB) 0x2A00 -> Device Name Characteristic UUID (128-bit UUID: 00002A00-0000-1000-8000-00805F9B34FB) These reserved UUIDs cannot be used for any custom services or characteristics, so you need to avoid them. *Note: you can actually purchase and reserve a 16-bit alias from the Bluetooth SIG [here](https://support.bluetooth.com/hc/en-us/articles/360062030092-Requesting-Assigned-Numbers?ref=novelbits.io) for a fee of $3,000, which would allow you to use the alias instead.* So, to create a UUID for your custom services and characteristics you would: 1. Use a website such as [GUID Generator](https://www.guidgenerator.com/?ref=novelbits.io) to generate a UUID (or multiple UUIDs) 2. Make sure it does not conflict with a reserved UUID (avoid any containing XXXXXXXX-0000-1000-8000-00805F9B34FB where XXXXXXXX is any number) **Helpful Resources:** - [https://support.bluetooth.com/hc/en-us/articles/360062030092-Requesting-Assigned-Numbers](https://support.bluetooth.com/hc/en-us/articles/360062030092-Requesting-Assigned-Numbers?ref=novelbits.io) - [https://support.bluetooth.com/hc/en-us/articles/360058202612-Bluetooth-SIG-Membership-Fee-Changes-Effective-1-January-2022](https://support.bluetooth.com/hc/en-us/articles/360058202612-Bluetooth-SIG-Membership-Fee-Changes-Effective-1-January-2022?ref=novelbits.io) 💡 **Insider Tip:** Want to master Bluetooth LE GATT services and characteristics design? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C. ### Bluetooth Low Energy (BLE) Connection Intervals and Events URL: https://novelbits.io/ble-connection-intervals/ Last updated: 2026-08-09T05:23:27.000Z A BLE connection interval is the time between two data transfer events (BLE connection events) between the central and the peripheral device. The theoretical value ranges from 7.5 ms to 4 secs (with increments of 1.25 ms). A few notes regarding BLE connection intervals: - The connection is established with the interval parameter value set by the master (central) device. However, the peripheral may suggest/request different values. The master still has the final say in the values and may end up choosing values different than but closer to the requested values. However, this feature allows dynamic changes in the connection interval (and thus the throughput speed) during a connection which may address a need in larger data transfers. - The parameter value has to be chosen with a balance of throughput and power consumption in mind. A high connection interval value (e.g. 4 seconds) will decrease power consumption but will also decrease data throughput, and vice versa. So, if you want to increase the data throughput, you can do so by decreasing the connection interval value, but keep in mind that this will also increase power consumption. In the end, make sure you choose the highest connection interval that achieves the data throughput required by your application, and that will make sure that power consumption is the most it needs to be. - Sometimes the BLE stack on peripheral devices allows setting a **minimum** and **maximum** connection interval. The maximum connection interval value provided by the peripheral allows the central to choose an accepted value within the range rather than choosing a value different than the minimum and possibly outside the acceptable range for the peripheral device. It’s important to understand that multiple packets can be transferred during one connection event. Each OS/device (iOS, Android.. And their different versions etc) may have different max numbers of packets that is allowed per connection event. Smartphones also perform many tasks which means the data transfer may not occur at the calculated rate as well (the central device may be busy performing other tasks delaying the packet transfer process). Throughput is also affected by interference in the 2.4 GHz spectrum, and if a packet (or packets) fails to transfer correctly then a retransmit will occur thus decreasing the calculated throughput. To learn more about this and specifically the effect of this parameter on BLE data throughput I've found a great blog post covering this topic [**here**](https://punchthrough.com/maximizing-ble-throughput-on-ios-and-android/?ref=novelbits.io). 💡 **Insider Tip:** Want to dive deeper into Bluetooth LE connection parameters and data throughput optimization? Take it hands-on with [Bluetooth LE Unplugged](https://novelbits.io/ble-unplugged-course/): two USB dongles ship with the course, and you build working Bluetooth LE devices without an SDK or a line of embedded C.