LML Project Pages

Pico Spectrometer

Firmware for a Raspberry Pi Pico that reads a Hamamatsu C12880MA micro-spectrometer and draws its spectrum live on a small TFT screen, with a knob for exposure. Built in 2023 as a self-contained instrument, so a spectrum could be seen without a computer attached.

This is firmware, not a web page. There is nothing to run in the browser here. The page describes what the device does and how it was put together, for the sake of keeping the work on the record alongside the rest.


What it does

The C12880MA is a fingertip-sized grating spectrometer with a 288-element detector. The Pico clocks data out of it, converts each of the 288 channels into a screen column, and redraws the whole display in a loop. The result is a live spectrum: point the slit at a light source and the shape of its output appears immediately.

Each bar is drawn in the color of its own wavelength rather than a single flat color, so the plot reads as a spectrum rather than as a bar chart. That conversion runs once at startup: every channel index is turned into a wavelength, the wavelength into a CIE XYZ triple, and that into the 16-bit color the display wants.

The pieces

Microcontroller Raspberry Pi Pico, built against the pico-sdk with pico_stdlib, hardware_adc and hardware_spi.
Detector Hamamatsu C12880MA, 288 channels. Clock, start and video lines on GPIO 2, 3 and 26.
Display ILI9341 TFT, 240×320, over SPI0 on GPIO 4 to 10. One full frame is pushed per reading.
Exposure control A potentiometer on ADC channel 1, GPIO 27.
Wavelength range Roughly 307 to 878 nm across the 288 channels, about 2 nm per channel.

Calibration

Hamamatsu ships each C12880MA with its own calibration, a fifth-order polynomial mapping pixel index to wavelength. The coefficients in the firmware are for the specific unit the lab had, serial 20L00801, and are hard-coded as SERIAL_20L00801. A different sensor needs its own numbers; using these with another unit would shift every wavelength.

That polynomial is also what makes the colored plot honest. The color of a bar is derived from the same calibration that places it, so the hues line up with where the lines actually fall.

The exposure knob

Integration time is set by hand because the useful range is enormous: a bright lamp and a dim reflectance reading are orders of magnitude apart. Turning the knob linearly across that range would make almost the whole sweep useless, so the reading is raised to the fourth power before it becomes a time. Most of the knob's travel sits in the short exposures, where the difference matters, and the long end arrives quickly at the top.

The knob is also sampled fifty times and smoothed into a running value rather than read once, which keeps a noisy ADC reading from making the plot flicker between frames.

Known rough edges

These are marked in the source and were never resolved:

Source

The firmware is eleven files of C: the sensor driver, the display driver, the color conversion and a main loop that ties them together. It builds with the standard pico-sdk toolchain and the README covers the dependencies. It is not published in this repository and lives in the pico-spectrometer project on its own.

The color conversion is based on John Walker’s specrend.c, as noted in color.h. The main loop began from a Raspberry Pi example and keeps its BSD-3-Clause header. The C12880MA datasheet and its per-unit calibration sheet come from Hamamatsu.