Radiant Machines · Rev B design package · 30 Oct 2026

A cordless night light in 620 nm red.

No blue, no flicker, no cord. AshLight drives 24 red-orange LEDs with true DC current from a 21700 cell, so it reads by candle-like light without telling your body it's morning. Everything here is real and buildable: the schematics, the board, the firmware, the printable case, and the bill of materials.

615 / 621 nmdominant / peak wavelength
0 PWManalog constant-current drive
~220×less melanopic light per lux than a 2700 K bulb
30 h → 3 wkruntime, brightest → dimmest
USB-Ccharges and reprograms, drag-and-drop
~$15electronics per lamp at 10 units
Mode
Off
Z1 baseZ2Z3Z4 tip
Level–
LED current0 mA
Light output0 lm
Runtime here–
Pattern
Room
Try
Same timing as the real lamp. Or click the lamp itself.

The light, flicker and button logic you see come from the actual firmware, ported line-for-line to JavaScript and checked frame-for-frame against the C build (3,601 of 3,601 frames identical). Light output and the sleeve's optical efficiency are estimates until the first units are measured. Your screen can't show 620 nm exactly; it's the closest sRGB red.

Why red at night

Light your eyes can use, without the signal your body clock reads as morning.

Melanopsin, the photopigment that sets your circadian clock, responds most strongly to blue-cyan light around 490 nm and barely at all past 600 nm. A narrow-band LED centred near 620 nm still looks clearly bright to the cones you see with, while contributing almost nothing to the melanopic signal.

The chart compares melanopic stimulation per unit of visible light (melanopic daylight efficacy ratio, D65 = 1). Note the log scale: by this estimate AshLight is roughly 220× lower than a warm-white 2700 K bulb and about 6× lower than an amber 590 nm LED.

These are analytic estimates (hardware/optics.py, calibrated to CIE illuminant A within 6 %). The real claim needs a spectrometer reading of an assembled lamp and the CIE S 026 toolbox. AshLight is a lighting product, not a medical device. It makes no clinical sleep claims.

Melanopic stimulation per lux

Show as a table
How it works

Four analog current sinks, one button, one cell.

Every LED current is set by a voltage, not chopped by a switch. A 12-bit DAC sets four set-points, and four op-amp + MOSFET sinks hold each vertical zone of LEDs at exactly that current. Steady mode is flat DC by construction. Candle mode moves the four set-points slowly and independently, so the flame moves up the lamp instead of the whole thing blinking.

USB-C 5 Vbq24073 chargerRT9013 3.3 V DW01A protection21700 · 5 Ah RP2040MCP4728 DACLED flex Button (bottom) charge · data · programpower path, 0.74 A, NTCsoft-latch enable 2 × AO3400A switchNTC on the flex tail UF2 bootloader in ROM12 MHz, ~3 mA 4 × 12-bit, 2.048 V ref → 4 × TLV9002 op-amp→ 4 × AO3400A→ 4 × 10 Ω sense 0–35.9 mA per zone, DC wakes the lamp 24 × LUXEON 2835Red-Orange 615 nm Z4 tipZ3Z2Z1 base wraps a triangular mast USB D+/D− (programming)
~10 µAstandby draw. The logic rail is switched off entirely when the lamp is off; about 2 % of the cell per year.
3.1 Vfirmware cutoff, with a soft dip warning at 3.4 V. The DW01A backs it up at 2.4 V.
+0.06 Vcurrent-regulation headroom at cutoff with worst-case LEDs. Brightness doesn't sag as the battery drains.
Controls · exactly as specified

One button underneath. Five steps. A candle that moves.

GestureFromResult
ClickOffOn, steady, at the remembered level. 150 ms fade-in.
ClickOn (any mode)Off, with a 220 ms fade.
Double-clickOff or steadyCandle mode. The first click's fade is caught mid-way, so it never goes dark.
Double-clickCandleBack to steady (toggle).
HoldOnSteps one level every 0.6 s, up then back down. A gentle wink marks each end. Release to keep. Saved to flash 2 s later.
Hold 0.8 sOffBattery gauge: 1–4 zones light, then fade. (Replaces the green LED the spec removed.)
Plug in USBOffOne slow red breath at the base: charging. No other indicator, ever.
Hold 8 s, plugged inOffReboots into the USB bootloader to install new firmware.

Levels follow a perceptual ladder: 3, 8, 20, 45 and 100 % of full current, so each step looks like a similar change. The renders' linear 10/25/50/75/100 % bunches the top steps together and has no true night-light step.

Live zone currents

From the 3D lamp above, last 8 seconds. Double-click for candle mode and watch the tip (Z4) move while the base stays calm.

Runtime by level

Electronics

Two boards, every part in stock.

A Ø38 mm 4-layer main board sits in the lamp's foot, and a 2-layer polyimide flex wraps the LED mast and runs its tail past the cell to a flip-lock connector. Every LCSC part code is checked against JLCPCB's live catalogue by hardware/verify_sourcing.py: …

Main board, placed

Main board top side: RP2040, flash, crystal, DAC, op-amps, charger, flex and battery connectors, USB-C
Top: 43 parts. USB-C at the front edge, flip-lock flex connector by the tail window.
Main board bottom side: button in the centre, pogo test pads, passives
Bottom: 74 parts. Button in the centre, a ring of pogo pads, passives within 1.6 mm of the cover.

Ø38 mm, 4 layers (signal / GND / power / signal), JLCPCB 4-layer rules. A KiCad script places all 117 parts with simulated annealing, which minimises wire length while keeping courtyards, the board edge and the enclosure's screw bosses clear. Placement passes KiCad DRC. Routing is the next step. Downloads: main.kicad_pcb · main.kicad_pro · JLC CPL (pick and place)

LED flex, placed and routed

LED flex top and bottom: 24 LEDs in eight rows on three faces, zone buses, tail with gold fingers

The flex is routed by its own generator (hardware/pcb/flex_layout.py) with no autorouter. The layout is regular enough to make the routing planar by construction. Each face has an LED_A spine on top. Four zone buses on the bottom are ordered so that a higher zone's bus always runs outside every bus that exists at its height. A collector strip then gathers everything into a 6.5 mm tail that runs past the cell (carrying the NTC) to eight 0.5 mm gold fingers.

KiCad DRC: 0 violations, 0 unconnected. 24 LEDs, 136 track segments, 50 vias. It folds 120° along two lines with no vias or pads within 1 mm of a fold.

Downloads: Gerbers + drill (zip) · BOM · CPL · flex.kicad_pcb

Bill of materials

Prices are JLCPCB catalogue prices per part at the quantity for 10 / 100 / 1,000 lamps, fetched . LEDs are consigned (bought from Digi-Key/Mouser), so they're priced from distributor quotes.

Downloads: main board JLC BOM · LED flex JLC BOM · full BOM with notes · live sourcing report · KiCad netlist (main) · (flex) · design calculations

Enclosure

Printed now, matched to the reference renders.

216 mm (8.5 in) tall, a 43 mm flared foot and a 34 mm body, close to the original's 33 mm. The 21700 cell stands upright in the lower body. The round main board sits in the foot with the USB-C port in the flare and the button underneath. The patterned sleeve slides over a thin diffuser around the LED mast.

Every part is generated by mechanical/build.py, the same script that feeds the 3D view above, and checked watertight. Three sleeve patterns ship today, each printing as a single solid piece.

Optical note: Stars & moons leaves only about 6 % of the sleeve open, so it's the most decorative and the dimmest, an estimated ~30 % of the light escapes. Flower of life and quatrefoil are about 35 % open, so expect roughly twice the light in the room.

PartMaterialVolumeFile

Print settings: 0.2 mm layers, 3 walls. Lower body upside down, no supports. Sleeve upright in copper silk PLA. Diffuser in natural PETG at 0.8 mm (vase mode works). Bottom cover flat. Three M2×8 self-tapping screws clamp the board.

Firmware · open source

Plug in, drag a file, done.

  1. Plug the lamp into a computer with USB-C. Hold the button 8 s while it's off, or run picotool load -f -x ashlight.uf2 and it reboots itself.
  2. A drive called RPI-RP2 appears. Drag ashlight-ashlight_revb.uf2 onto it. The lamp restarts with the new firmware.
  3. Can't brick it. The bootloader is in the RP2040's ROM. If all else fails, short the BOOT pad to ground while plugging in.
  4. Talk to it. It's also a USB serial port: s prints status, b reboots to the bootloader.

Downloads: ashlight-ashlight_revb.uf2 (custom board) · ashlight-pico_proto.uf2 (Raspberry Pi Pico breadboard)

firmware/
  include/ashlight_core.h  behaviour API
  src/ashlight_core.c      gestures, fades, candle, safety
  src/settings.c           torn-write-safe flash records
  rp2040/                  board support (Pico SDK)
  tests/test_core.c        15 host tests, all passing
  tests/trace.c            reference trace for the web sim
site/sim/core.js           JS port, frame-exact vs C

$ make test     # host unit tests
$ make rp2040   # → build/…/ashlight-ashlight_revb.uf2
$ make flash    # over USB-C
Build plan · draft orders · cost

From breadboard to ten working lamps.

Stage A0 · ~1 week · ~$90

Breadboard

Raspberry Pi Pico + Adafruit bq24074 and MCP4728 breakouts + four op-amp sinks on perfboard + a hand-soldered LED strip. Runs the same firmware (pico_proto build). Proves the optics, the dimming floor and the candle look before any custom PCB is ordered.

Stage B1 · 2–3 weeks

Two engineering units

First JLCPCB run of both boards, fully assembled. Bring-up with a current-limited supply, then spectrum, flicker (photodiode), charge thermals, cutoff and runtime tests. Fix anything found and re-spin once if needed.

Stage B2 · 2–3 weeks

Ten prototypes

Ten assembled lamps plus spares, printed shells, tabbed 21700 cells, end-of-line test (5 levels, candle, charge, gauge, sleep current) and a three-unit runtime soak.

Draft orders (nothing placed)

VendorWhatQtyEst. costStatus
JLCPCBMain board: Ø38 mm, 4-layer, 1.6 mm, ENIG, PCBA both sides12$190–270placed · routing
JLCPCBLED flex: 2-layer PI, 0.5 mm-pitch fingers stiffened to 0.3 mm, PCBA with consigned LEDs12$140–220Gerbers ready
Digi-Key / MouserLumileds L128-RNG1003500000 (alt Cree JE2835ARO), ship to JLC320$75–100ready
18650BatteryStore or similar21700 ~5 Ah cells with welded solder tabs (e.g. Samsung 50S / Molicel P50B)12$80–110ready
Adafruit / Raspberry PiStage A0 breadboard kit (Pico, #4755, #4470, op-amps, FETs)1$60–90ready
Local print / print farmCopper silk PLA + natural PETG, ~85 g per lamp12 sets$40–60ready (STLs)

Full order specs, quantities and copy-paste RFQ text: docs/orders.md. The LED flex has Gerbers, BOM and CPL ready to upload for a quote. The main board is placed and still needs routing.

Cost per lamp

Item10 lamps1001,000

Hard costs only, before engineering time, certification (FCC Part 15B, IEC 62133 / UL 2054 battery safety, IEC 62471 photobiological, roughly $6–15k to sell in the US/EU) and margin. The 1,000-unit column assumes the LED price break (~$0.15) and a contract-printed or aluminium shell.

Validation · open risks

What still has to be proven on the bench.

Must measure

  • Spectrum of the assembled lamp: peak 615–625 nm, <0.1 % of output below 500 nm.

  • Flicker in steady mode at every level, on battery and on USB: target <1 % modulation, 1 Hz–2 kHz.

  • Lowest level at the pillow: dim enough to sleep by, bright enough to be useful. Retune the ladder if not.

  • Charge thermals at 0.74 A in the printed foot. Cell <45 °C, surfaces <45 °C at 25 °C ambient.

  • Runtime per level on three units. Advertise only measured numbers.

Known design risks

  • Zone matching at level 1. Op-amp offset can make zones differ by up to ±12 % at the dimmest step. Firmware can store per-zone trims if the samples show it.

  • Main board density. 117 parts need about 104 % of one side of the Ø38 mm disc, so the board is assembled on both sides (+≈$30 per run). Placement is done and checked. If routing turns out too tight, the fallback is a 6-layer board.

  • LED supply. JLC lists both LED options but rarely stocks them, so the LEDs are consigned. Keep both footprint-compatible parts qualified.

  • RP2040 standby while on is about 3–4 mA (estimate). It's the biggest drain at the dimmest level, so measure it.

  • IP65 from the original spec is not met by a printed, perforated shell (indoor use only). The original listing's patent status has not been checked.

Open source

Everything needed to build, change or fix it.

Firmware under the MIT licence; hardware and enclosure under CERN-OHL-P v2. The whole design regenerates from a handful of Python and C files: change a value in hardware/design.py and the BOM, netlist, schematics and calculations all follow.

Download the complete source (zip) · README