VolksEEG Project: Initial Hardware Architecture
The VolksEEG prototype pairs an Adafruit Feather nRF52840 Sense MCU with an ADS1299 analog front end, organized into non-isolated and isolated domains to protect patients. The post explains why isolation is required, which chips bridge the domains, and why simple, high-level power and signal diagrams help clarify the KiCad schematics for engineers and reviewers.
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.
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.
Off the shelf availability of Custom IoT Gateway
Choosing the right gateway can make or break an IoT deployment, yet industrial gateways are often expensive and generic. This post walks through practical criteria for off-the-shelf and custom gateways, covering edge computing trade-offs, mainframe versus embedded Linux, SoC and ADC choices, interfacing and debugging needs, and when to design your own hardware for real-time or protocol demands.
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.
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 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.
Designing IoT Wireless Sensor Nodes
Mahesh Balan outlines practical strategies for building tiny IoT wireless sensor nodes that run on harvested energy. The post explains using small solar cells with coin-cell or supercapacitor buffering, pairing sensors with Bluetooth Low Energy for short-range telemetry, and choosing PMICs with ultra-low quiescent and startup power. A Cypress PMIC example shows operation can be sustained under low-brightness conditions near 100 lx.
How to Give Persistent Names To USB-Serial Devices on Ubuntu 14.04
When your dock reshuffles ttyUSB assignments, Tayyar shows how to bind USB-serial devices to persistent names on Ubuntu 14.04. The post walks through using dmesg and udevadm to locate unique attributes like KERNELS and ATTRS{serial}, creating /etc/udev/rules.d entries with NAME and SYMLINK, and applying rules with udevadm trigger. It includes common pitfalls and quick fixes to get minicom talking to the right port.
Surprising Linux Real Time Scheduler Behavior
An embedded Linux data acquisition project ran into puzzling UART latency whenever heavy UI animations ran. Moving all app threads to SCHED_FIFO helped but did not eliminate delays. After reading about kernel worker thread interactions, Matthew moved the UI back to the normal scheduler and the jitter vanished. The post highlights an unexpected kernel level priority inversion risk and a pragmatic workaround.
MSP430 LaunchPad Tutorial - Part 4 - UART Transmission
Want to stream sensor or debug data from an MSP430 LaunchPad to a PC or Bluetooth module? Enrico swaps in an MSP430G2553 and shows how to configure SMCLK, P1 pin multiplexing, and UCA0 baud/dividers (with modulation) to approximate 115200 baud. The post also walks through interrupt-driven RX/TX handling and a low-power wait loop that sends a "Hello World" reply on demand.
How to use I2C devices in (Apache) NuttX: Adding support for an I2C device in your board
You can add an I2C sensor to NuttX with a few file edits, menuconfig tweaks, and a standard build-and-flash cycle. This guide shows how the BMP280 barometer was integrated into the Raspberry Pi Pico bringup by copying and adapting an existing board driver, wiring the sensor to I2C0, enabling the BMP280 option in menuconfig, and compiling and flashing the resulting nuttx.uf2. It includes exact wiring and build tips.
VolksEEG Project: Initial Hardware Architecture
The VolksEEG prototype pairs an Adafruit Feather nRF52840 Sense MCU with an ADS1299 analog front end, organized into non-isolated and isolated domains to protect patients. The post explains why isolation is required, which chips bridge the domains, and why simple, high-level power and signal diagrams help clarify the KiCad schematics for engineers and reviewers.
Help, My Serial Data Has Been Framed: How To Handle Packets When All You Have Are Streams
Framing byte streams is easier to get wrong than you think, and a bad scheme can leave your embedded device acting on the wrong packet. Jason Sachs walks through common plaintext and binary framing approaches, explains why CRCs alone can still permit false resynchronization, and demonstrates COBS as a simple, low-overhead byte-stuffing method that prevents delimiter collisions and guarantees resynchronization.
Getting Started With Zephyr: Bluetooth Low Energy
In this blog post, I show how to enable BLE support in a Zephyr application. First, I show the necessary configuration options in Kconfig. Then, I show how to use the Zephyr functions and macros to create a custom service and characteristic for a contrived application.
Getting Started With Zephyr: Writing Data to EEPROM
In this blog post, I show how to implement a Zephyr application to interact with EEPROM. I show how the Zephyr device driver model allows application writers to be free of the underlying implementation details. Unfortunately, the application didn't work as expected, and I'm still troubleshooting the cause.
SIGFOX – A new network technology for IoT comms?
Built for tiny, infrequent messages, SIGFOX promises ultra-low-cost, long-life IoT connectivity using ultra-narrowband radios and a managed back-end. The network supports 12-byte uplinks, up to 140 messages per day, deep indoor penetration, and multi-year battery life, making it ideal for meters, alarms, and simple sensors. The article covers coverage, available modules, and practical trade-offs like limited bandwidth and vendor lock-in.
ANCS and HID: Controlling Your iPhone From Zephyr
In this blog post, we see how certain BLE services can be used to control an iPhone from a Nordic nRF52840 using The Zephyr Project. Specifically, we see how to control certain multimedia functionality using the HID service. Finally, we learn how to use the ANCS client library provided by Nordic in The Zephyr Project to accept or decline an incoming call.
A Working Real Time Clock (RTC) Implementation
When the GPRS modem would not provide network time, Dr Cagri Tanriover implemented a compact hardware real time clock using the NXP PCF8523T. The post highlights why automatic backup switching, I2C integration, BCD register handling, and alarm/timer features matter for embedded timestamps. It also shows battery-life math with a CR1225 and offers practical build notes after an initial ESD-related failure.
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.
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.
A Working Real Time Clock (RTC) Implementation
When the GPRS modem would not provide network time, Dr Cagri Tanriover implemented a compact hardware real time clock using the NXP PCF8523T. The post highlights why automatic backup switching, I2C integration, BCD register handling, and alarm/timer features matter for embedded timestamps. It also shows battery-life math with a CR1225 and offers practical build notes after an initial ESD-related failure.
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.
Getting Started With Zephyr: Writing Data to EEPROM
In this blog post, I show how to implement a Zephyr application to interact with EEPROM. I show how the Zephyr device driver model allows application writers to be free of the underlying implementation details. Unfortunately, the application didn't work as expected, and I'm still troubleshooting the cause.
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.
On hardware state machines: How to write a simple MAC controller using the RP2040 PIOs
Hardware state machines are nice, and the RP2040 has two blocks with up to four machines each. Their instruction set is limited, but powerful, and they can execute an instruction per cycle, pushing and popping from their FIFOs and shifting bytes in and out. The Raspberry Pi Pico does not have an Ethernet connection, but there are many PHY boards available… take a LAN8720 board and connect it to the Pico; you’re done. The firmware ? Introducing Mongoose…
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.
Getting Started With Zephyr: Bluetooth Low Energy
In this blog post, I show how to enable BLE support in a Zephyr application. First, I show the necessary configuration options in Kconfig. Then, I show how to use the Zephyr functions and macros to create a custom service and characteristic for a contrived application.
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.
Surprising Linux Real Time Scheduler Behavior
An embedded Linux data acquisition project ran into puzzling UART latency whenever heavy UI animations ran. Moving all app threads to SCHED_FIFO helped but did not eliminate delays. After reading about kernel worker thread interactions, Matthew moved the UI back to the normal scheduler and the jitter vanished. The post highlights an unexpected kernel level priority inversion risk and a pragmatic workaround.






















