Lightweight C++ Error-Codes Handling
The traditional C++ approach to error handling tends to distinguish the happy path from the unhappy path. This makes handling errors hard (or at least boring) to write and hard to read. In this post, I present a technique based on chaining operations that merges the happy and the unhappy paths. Thanks to C++ template and inlining the proposed technique is lightweight and can be used proficiently for embedded software.
Getting Started With Zephyr: Saving Data To Files
In this blog post, I show how to implement a Zephyr application to mount a microSD card, create a new file on the microSD card, and write data to it. The lessons learned from such an application can be helpful for devices out in the field that need to write data to off-board memory periodically, especially in cases where Internet access may be sporadic.
Creating a Hardware Abstraction Layer (HAL) in C
In my last post, C to C++: Using Abstract Interfaces to Create Hardware Abstraction Layers (HAL), I discussed how vital hardware abstraction layers are and how to use a C++ abstract interface to create them. You may be thinking, that’s great for C++, but I work in C! How do I create a HAL that can easily swap in and out different drivers? In today’s post, I will walk through exactly how to do that while using the I2C bus as an example.
Getting Started With Zephyr: Devicetree Overlays
In this blog post, I show how the Devicetree overlay is a valuable construct in The Zephyr Project RTOS. Overlays allow embedded software engineers to override the default pin configuration specified in Zephyr for a particular board. In this blog post, I use I2C as an example. Specifically, I showed the default I2C pins used for the nRF52840 development kit in the nominal Zephyr Devicetree. Then, I demonstrated how an overlay can be used to override this pin configuration and the final result.
nRF5 to nRF Connect SDK migration via DFU over BLE
This writeup contains some notes on how I was able to migrate one of my clients projects based on the nRF5 SDK, to nRF Connect SDK (NCS) based firmware, via a DFU to devices in the field over BLE.
Bellegram, a wireless DIY doorbell that sends you a Telegram message
A wireless button that uses the M5 STAMP PICO and Mongoose to send a Telegram message when pressed. The code is written in C
An Iterative Approach to USART HAL Design using ChatGPT
Discover how to leverage ChatGPT and an iterative process to design and generate a USART Hardware Abstraction Layer (HAL) for embedded systems, enhancing code reusability and scalability. Learn the step-by-step journey, improvements made, and the potential for generating HALs for other peripherals.
Working with Strings in Embedded C++
This article discusses the use of strings in embedded systems. It explains how the need for and use of strings in embedded systems has changed with the advent of cheaper, full graphic displays and the growth of the ‘Internet of Things’ (IoT). The article also covers character literals, C-Strings and string literals, and the difference in memory models between them. It also highlights the safety and security issues that arise from using strings in embedded systems. Finally, it explains how C++11 introduced a Raw string literal type that is useful for storing file paths or regular expressions.
Peripheral Interaction Without a Linux Device Driver Using Spidev
Kernel-space drivers are not always necessary; many SPI peripherals can be handled from userspace using spidev. This post shows how to expose an SPI device through the device tree and kernel, wire a Bosch BMP388 to a Toradex Apalis iMX8 Ixora board, and implement a C userspace app that uses ioctl to read the chip ID. Practical tips on SPI settings and logic-analyzer validation are included.
Working With ESP-C3-32S-Kit Dev Board
This hands-on guide walks through setting up the ESP-C3-32S-Kit with ESP-IDF, from installing the toolchain to flashing and monitoring a hello-world example. It shows JTAG debugging with OpenOCD and GDB, how to use the NimBLE BLE stack for peripheral and central roles, and how to capture and filter BLE traffic with a Nordic sniffer and Wireshark so you can inspect pairing and connection behavior.
Picowoose: The Raspberry Pi Pico-W meets Mongoose
This example application describes the way to adapt the George Robotics CYW43 driver, present in the Pico-SDK, to work with Cesanta's Mongoose. We are then able to use Mongoose internal TCP/IP stack (with TLS 1.3), instead of lwIP (and MbedTLS).
Working with Strings in Embedded C++
This article discusses the use of strings in embedded systems. It explains how the need for and use of strings in embedded systems has changed with the advent of cheaper, full graphic displays and the growth of the ‘Internet of Things’ (IoT). The article also covers character literals, C-Strings and string literals, and the difference in memory models between them. It also highlights the safety and security issues that arise from using strings in embedded systems. Finally, it explains how C++11 introduced a Raw string literal type that is useful for storing file paths or regular expressions.
The CRC Wild Goose Chase: PPP Does What?!?!?!
Jason Sachs walks through a CRC rabbit hole and explains why ambiguous CRC names and incomplete specs lead to subtle protocol bugs. He demonstrates how XMODEM and KERMIT variants with a zero initial value can miss dropped leading-zero bytes, praises the X.25 standard for providing test vectors and a clear CRC16 definition, and warns that RFCs that ship only sample code are a poor substitute for a proper specification.
When a Mongoose met a MicroPython, part I
This is more a framework than an actual application, with it you can integrate MicroPython and Cesanta's Mongoose.
Mongoose runs when called by MicroPython and is able to run Python functions as callbacks for the events you decide in your event handler. The code is completely written in C, except for the example Python callback functions, of course. To try it, you can just build this example on a Linux machine, and, with just a small tweak, you can also run it on any ESP32 board.
A wireless door monitor based on the BANO framework
Fabien Le Mentec built a battery-powered wireless door monitor and a reusable node framework called BANO to monitor doors across seven floors without wired links. The post highlights BANO's 17-byte key,value protocol, the node runtime that enables wake-on-interrupt low-power operation, and practical RF choices like the NRF905 plus a 330 µF cap to handle coin-cell transmission peaks. It includes source, PCB, and base station notes.
When a Mongoose met a MicroPython, part II
In the first part of this blog, we introduced this little framework to integrate MicroPython and Cesanta's Mongoose; where Mongoose runs when called by MicroPython and is able to run Python functions as callbacks for the events you decide in your event handler. Now we add MQTT to the equation, so we can subscribe to topics and publish messages right from MicroPython.
Beyond the Packet: Designing Reliable Serial Communication for Embedded Systems
Serial communication between microcontrollers sounds simple until the protocol quietly breaks your system. Prabo Semasinghe walks through the design steps for building a robust communication framework: packet structure, error detection, acknowledgment handling, state machine design, and the failure-mode testing that actually proves it works.
Bellegram, a wireless DIY doorbell that sends you a Telegram message
A wireless button that uses the M5 STAMP PICO and Mongoose to send a Telegram message when pressed. The code is written in C
Using GPIO in (Apache) NuttX RTOS
Blinking an LED is the embedded Hello World, and this tutorial walks through using GPIOs on NuttX running on a Raspberry Pi Pico. It shows how to enable the GPIO driver and example in menuconfig, build and flash the nuttx.uf2, and use NSH gpio device files to read and write pins. The post also explains polling versus interrupt-driven inputs and the pull-up/edge setup needed for button interrupts.
Racing to Sleep
Jason Sachs walks through a realistic field sensor case study, the BigBrotherBear 2000, to show how a careful power budget exposes surprising energy costs. He demonstrates that radios and data transmission often dwarf quiescent MCU current, explains the race-to-sleep principle for computation-bound tasks, and outlines practical wake-up and measurement trade-offs so engineers can extend battery lifetime in real deployments.
Getting Started With Zephyr: Devicetree Overlays
In this blog post, I show how the Devicetree overlay is a valuable construct in The Zephyr Project RTOS. Overlays allow embedded software engineers to override the default pin configuration specified in Zephyr for a particular board. In this blog post, I use I2C as an example. Specifically, I showed the default I2C pins used for the nRF52840 development kit in the nominal Zephyr Devicetree. Then, I demonstrated how an overlay can be used to override this pin configuration and the final result.
Linear Feedback Shift Registers for the Uninitiated, Part XIV: Gold Codes
Gold codes solve a practical spread-spectrum problem, sharing one PRBS across many transmitters eventually runs into ugly synchronization and correlation issues. Jason Sachs walks through why shifted copies of a single LFSR sequence are not enough, then shows how preferred pairs of m-sequences create a family of Gold codes with bounded cross-correlation. The post wraps with Python experiments and a UART DSSS demo that decodes multiple overlapping messages cleanly.
Linear Feedback Shift Registers for the Uninitiated, Part XV: Error Detection and Correction
CRCs and Hamming codes look a lot less magical when you view them as redundancy with a purpose. Jason Sachs walks from parity bits and checksums into finite-field polynomial arithmetic, then shows how CRCs map cleanly onto LFSRs and how Hamming codes use syndromes to locate single-bit errors. It is a practical tour of error detection and correction, with enough worked examples to make the theory feel usable.
Designing Communication Protocols, Practical Aspects
When your MCU must talk to a PC or smartphone, a clear protocol saves time and headaches. This post gives practical guidance for fast bring-up: how to structure a compact header, keep payloads byte-aligned and debug-friendly, and reserve bits for future use. It also covers CRCs for integrity, timeout and retry strategies for resynchronisation, and the simple start code trick that makes debugging easier.
A wireless door monitor based on the BANO framework
Fabien Le Mentec built a battery-powered wireless door monitor and a reusable node framework called BANO to monitor doors across seven floors without wired links. The post highlights BANO's 17-byte key,value protocol, the node runtime that enables wake-on-interrupt low-power operation, and practical RF choices like the NRF905 plus a 330 µF cap to handle coin-cell transmission peaks. It includes source, PCB, and base station notes.
Linear Feedback Shift Registers for the Uninitiated, Part XII: Spread-Spectrum Fundamentals
Jason Sachs shows why LFSR-generated pseudonoise is a natural fit for direct-sequence spread spectrum, then walks through Fourier basics, spectral plots, and runnable Python examples. The article demonstrates how DSSS multiplies a UART bitstream with a chipping sequence to spread energy, how despreading concentrates the desired signal while scrambling narrowband interference, and how multiple transmitters can share bandwidth when using uncorrelated sequences.
Reverse engineering wireless wall outlets
Fabien Le Mentec reverse engineers a cheap set of wireless wall outlets to add them to his BANO home automation while avoiding uncertified mains hardware. He uses PCB inspection to identify a Holtek MCU and RF83C, captures 433.92 MHz OOK signals with an RTL-SDR and ookdump, then replays commands using an RFM22 in direct mode controlled by an ATmega328P. The post explains frame structure and links to a working GitHub implementation.
Getting Started With Zephyr: Saving Data To Files
In this blog post, I show how to implement a Zephyr application to mount a microSD card, create a new file on the microSD card, and write data to it. The lessons learned from such an application can be helpful for devices out in the field that need to write data to off-board memory periodically, especially in cases where Internet access may be sporadic.
An Iterative Approach to USART HAL Design using ChatGPT
Discover how to leverage ChatGPT and an iterative process to design and generate a USART Hardware Abstraction Layer (HAL) for embedded systems, enhancing code reusability and scalability. Learn the step-by-step journey, improvements made, and the potential for generating HALs for other peripherals.
Modulation Alternatives for the Software Engineer
Jason starts with a hardware curiosity, the 7497 synchronous rate multiplier, and turns it into a practical lesson for firmware engineers. He contrasts conventional PWM with a simple accumulator-based method called "synthetic division," showing how it implements first-order delta-sigma behavior in software. The post explains when to pick PWM or delta-sigma and why the accumulator trick can give higher effective resolution at low update rates.


















