The Lean approach to Embedded Systems

My ‘TCP/IP Lean’ books are out of print, but I’m still using the same philosophy when designing embedded systems: trying to understand the fundamentals, so as to avoid the bloat that results from a simplistic building-block approach to hardware & software.

So I’m posting some projects taken from my experience working for the Iosoft consultancy, in the hope they will be of use – feel free to adapt and extend them for your own purposes, but please credit this blog as the origin of the material.

Accurate frequency measurement using a Pi Pico RP2040

freq_edge_time

Traditional edge-counting techniques for finding the frequency of an input can be quite inaccurate, since they rely on a rapid response-time of the CPU. This Pi Pico project explores two ways of measuring frequency, using DMA so that there no time-critical code. The project description and C source files are here. There is also a MicroPython version here.

Standalone WiFi driver for the Pico W

picowi_parts

This is a port of my Zerowi code to the Pi Pico W, to provide a high-speed standalone driver and TCP/IP stack for the CYW43439 WiFi chip, and the similar CYW4343W. See the introduction to this multi-part project.

Remote logic analyser using ESP32 and Web protocols

distributed_acq

There are plenty of low-cost logic analysers but they all share a common characteristic; a USB link is used to transfer the data into a PC for analysis.

If the equipment is in a safe & comfortable office environment, then this isn’t a problem, but in many cases it is operating in an distant, inaccessible or hostile location, so remote monitoring is desirable. If the analyser unit is small and low-cost, it can remain attached on a semi-permanent basis, enabling long-term monitoring & diagnosis of remote equipment. Read more about this hardware & software project here.

Pi Pico wireless Web server using ESP32 and MicroPython

pico_esp32a

rspscope2

The Espressif ESP32 can provide WiFi connectivity for the Pi Pico, and to keep the development process simple, the code can completely be written in Python (MicroPython or CircuitPython). The first post of this project gives an outline of the processes involved, with full source code for a simple Web server; then the second post uses Direct Memory Access (DMA) to fetch analog data at high speed using MicroPython. The third post runs a Web server on the Pico, that provides an oscilloscope-type display in a Web browser.

RP2040 WiFi using Microchip ATWINC1500 module

winc1500_pico2

This project adds low-cost wireless networking to the Pi Pico, and any other RP2040 boards. It uses a low-cost Microchip ATWINC1500 or 1510 module which has built-in TCP/IP stack, to keep the microcontroller software as simple as possible. Part 1 of this project, with C source code, is available here.

Part 2 describes the socket interface, with TCP and UDP servers here.

PicoReg: real-time diagnostics for the Pi Pico using SWD

picoreg1

To debug a Pico C or Python application, it can be very helpful to know the value in the RP2040 I/O registers; instead of adding ‘print’ calls, or using a heavyweight debugger, you can use a 3-wire connection between the Pico and a Raspberry Pi, and view the state of any register without modifying or disrupting the software.

The PicoReg project, with full Python source code, is available here.

Remote logic waveform display using WebGL

webgl_logic5

Having used WebGL to create a remote oscilloscope display, the next step is the displaying of logic waveforms, similar to those seen in logic analysers / analyzers. To maximise the display speed, all the sample processing is done on the graphics processor (GPU), including the splitting of the 16-bit word into individual channels for display. Read more about this high-speed binary viewer here.

Remote oscilloscope display using WebGL

webgl_graph7

A Web-based oscilloscope display can be useful for the remote viewing of fast-changing data; it takes advantage of the high-speed graphics capabilities of modern PCs, tablets and mobile phones, allowing remote diagnosis with a minimum of hardware. Learn more about this useful technique here.

Fast oscilloscope display using OpenGL on the Raspberry Pi

graph_1k_200

The problem with streaming ADC data into the Raspberry Pi is that most applications can’t cope with the rapid data flow. I wanted an oscilloscope-type data display, and to get the required speed,  it was necessary to program the VideoCore Graphics Processing Unit (GPU) using OpenGL. The end-result  is remarkably fast, making it easy to visualise rapidly-changing signals on multiple input channels. The project description, and full source code, can be found here.

Streaming analog data from a Raspberry Pi

adc_streaming

Analog to Digital Converter (ADC) driver software usually captures a single block of samples; if a larger dataset (or continuous stream) is required, it can be very difficult to merge multiple blocks without leaving any gaps. Find out how to do this, and feed the resulting data into any other program, by reading  this post.

Driving 16 channels of WS2812 smart LEDs from a Raspberry Pi

Exif_JPEG_PICTURE

The Raspberry Pi Secondary Memory Interface can act as a very accurate multi-channel pulse generator, so can drive 8 or 16 channels of WS2812 NeoPixel ‘smart’ LEDs. You can potentially control hundreds of LEDs, with each LED having its own RGB colour. Brighten up your festive displays, starting here.

Raspberry Pi Secondary Memory Interface (SMI)

smi2

The Secondary Memory Interface (SMI) provides fast parallel I/O, and is included in every Raspberry Pi, but is rarely used due to the lack of public documentation. Find out more about this versatile interface, with C code driving a parallel ADC and DAC at very high speed – over 80 megabytes per second on a Pi ZeroW. Learn more here.

Fast data capture with the  Raspberry Pi

adc_test1a

Following on from my experimentation with Direct Memory Access, I’ve  used that technique for fast data acquisition from analog-to-digital converters (ADCs). Read more here.

Raspberry Pi DMA programming

dma

Direct Memory Access (DMA) is an excellent high-speed technique for moving data around a system without any CPU intervention, but it can be tricky to program. Find out more, with complete worked examples in the C language, here.

Bare-metal WiFi driver for the Raspberry Pi

zerowi_hw

The Cypress / Broadcom WiFi chips used on the Raspberry Pi are complex devices, possessing their own CPU, memory and peripherals, controlled over a Secure Digital I/O (SDIO) interface. Programming these chips in ‘bare metal’ mode (with no operating system) isn’t easy, but offers very significant speed improvements, for example booting from power-up in 1 second.

Find out more about this challenging project here.

Raspberry Pi bare-metal programming using Alpha

alpha_debug

Programming without an operating system (on the ‘bare-metal’) isn’t easy, particularly when the board is as complex as the Raspberry Pi. Alpha makes this process slightly easier, providing a simple way to download and debug programs. Learn more here.

Real Time Location using Ultra-Wideband (UWB)

ranging_sys

Need an indoor positioning system? With 10 cm (4 inch) accuracy? Up to 100 readings per second? Not line-of-sight? Also carrying data? No problem, this is all possible using low-cost Decawave Ultra Wideband modules. Full details of my test system, with Python source code, are here.

ARM GCC Lean: programming and debugging the Nordic NRF52

gdb_openocd

The nRF52832 is an ARM Cortex M4 chip with an impressive range of peripherals, including an on-chip 2.4 GHz wireless transceiver. Learn how to program and debug these devices, using open-source tools. Details here.

Raspberry Pi position detection using fiducial tags

Exif_JPEG_PICTURE

Fiducial tags are little known outside the robotics world, but they provide a quick way of finding a known item using a low-cost camera system, such as the Raspberry Pi. Details and full source code are here.

Accurate position measurement using low-cost cameras and OpenCV

Exif_JPEG_PICTURE

OpenCV is a very powerful image-processing package, and in this post I’ve used it to measure the position of an object in 2 dimensions, with 2 low-cost webcams a right-angles. The technique has remarkably high resolution, when compared with other optical methods. Read more here.

PC / Rpi camera display using PyQt and OpenCV

pi_cam2

A PyQt and OpenCV application for Windows or Linux that can act as a basis for experimentation with image processing: you just need a PC with a USB camera, or a Raspberry Pi with the standard camera. See this post for a description and full source code.

Python Websocket programming

winsock

To create a dynamic real-time display on a browser, you need a method of ‘pushing’ display data from the server to the browser. For a simple example of WebSocket programming in Python, see this post.

3D design with Python and FreeCAD

freecad5

3D CAD packages can be hard work; there is a lot to learn, which can be a major problem for an infrequent user such as myself. FreeCAD is free, and supports Python scripting, so is it possible to create a design from scratch in Python? Click here to learn more.

Simple PyQt serial terminal

pyqt_serialterm1

This is an example of PyQt programming with threading, that I’ve tried to make universal; it runs on Windows or Linux, with Python 2.7 or 3.x, and PyQt v4 or v5.

If you need a serial application you can customise, or a simple example of Python threading in action, take a look here.

Programming PSoC: an ARM CPU with programmable hardware

Exif_JPEG_PICTURE
PSoC development kit

Want to craft your own high-speed CPU peripheral? Experiment with programmable hardware, but are deterred by the complexity and cost? Take a look at my blog post.

Creating real-time Web graphics with Python

Web vector graphics (SVG) are very useful for displaying real-time information in a browser, for example annotating a circuit diagram with real-world values. As a first step, I’m demonstrating how an SVG real-time clock display can be created using Python, with animation in Javascript. See my post here.

Viewing ARM CPU activity in real time

viewing_cpu2

I’ve created a short video of my ‘reporta’ project, demonstrating a real-time graphical display of I/O port activity. The code is pure Python; it accesses the CPU internals via the SWD interface, so its operation is completely transparent to the target CPU.

See this post for a detailed description; the source files are on GitHub

If you need a more powerful debug system, take a look at my post OpenOCD on the Raspberry Pi.

Programming FTDI devices in Python

Exif_JPEG_PICTURE
FTDI modules

FTDI chips are frequently used as USB-to-serial adaptors, but the newer devices have the ability to drive more complex protocols such as SPI and I2C.

I like to use Python when first experimenting with new PC hardware, and there are some Python libraries for interfacing to FTDI chips, but I couldn’t find any real projects or complete worked examples.

The following posts demonstrate a step-by-step approach to driving the FTDI chips from Python, to learn about their functionality. In the final part, I implement a pure-Python SWD interface that can access the internals of a CPU while it is running, in a similar way to much more sophisticated debug tools, such as OpenOCD.

Part 1: Initial experimentation

Part 2: Using Linux

Part 3: Using MPSSE to drive an SPI device

Part 4: First steps towards accessing an ARM CPU using SWD

Part 5: Reading CPU internals with SWD

Copyright (c) Jeremy P Bentham 2020. Please credit this blog if you use the information or software in it.