hanoi cosmic-ray classifieds

Dev log

Building a cosmic ray decision clock in public. Breadboards, debug screwups, the occasional small win.

Making a cosmic MIDI instrument and finalizing the breadboard

#permalink

MIDI instrument

Just for fun I wired up the coincidence circuits and the individual tubes to work as a MIDI device, and I've been making ambient music all day while I work. I've also set up some space-based APIs like the ISS velocity/sensors, international seismic activity, moon phase, and sun arc, all to create either MIDI notes or knob variables. Currently I have the individual Geiger tubes triggering drum breaks, the ISS controlling filter cutoff, muon events are a massive stab with lots of delay and reverb, and so on. So much fun.

The last round of debugging

Getting six channels online was an accomplishment, but I spent two weeks chasing noise sources. First it was loose wiring, then I was missing a capacitor, and so on. I did a full audit of the board layout, then brought it home. I've been building it at the maker space of the school I work at, so the drive home on a motorbike through Hanoi rush hour was a good durability test for the tubes.

Everything was working when I got it home, but I still had an unacceptable amount of noise. Tube 3 would get stuck in continuous discharge for hours, then return to 40% lower counts than the other tubes, and T4 and T2 would randomly dip to 50% counts. After 3-4 days on my bench at home, and just leaving tube 3 unplugged, I decided to meter every connection in the anode chain and immediately noticed my high voltage boosters were sitting around 530V, which is way too high. My target was 410V, so I tried adjusting the pot and it was bottoming out at 520V. After some deliberation with Claude we decided to add some resistor chain shunts out of each HV booster, running parallel to the 5V ground rail. This worked beautifully, and it's currently about 18 hours into a soak test with completely even distribution counts from all tubes. The only downside is that the HV booster whines are so frickin loud now that I need to wear headphones while I work and set up some baffling (which actually helps quite a bit when the headphones are off).

Soak test

Now we are on to the final (hopefully) soak test. I'm having a bit of trouble with the SD card reader initializing, but I'm sure it won't be a bottleneck, and I can just log things over WiFi worst case scenario.

What's next

Next up is designing the PCB, then getting it in the hands of my designer and myself so we can start iterating on the enclosure. I'm also working on a farming simulator that uses muon collection as a resource, plus a number of other clock faces. I've also been building a data dashboard where each window's size and placement is customizable. I've got a bunch of space-based APIs hooked up to it like solar arc, moon phase, distance to the ISS, an international seismic events ticker, local weather forecast, and more.

On Vibecoding a Muon Detector

#permalink

context: I'm building an e-ink smart clock, that uses 4x geiger counters to detect muons/high energy particles, and uses that to give users a cosmic oracle experience, and RNG based games/events. Press a button, ask a question, then a cosmic ray hitting the earths upper atmosphere answers.

3-4 million tokens before I ordered a single part

I have been toying around with this idea for a year or two (since watching Alpha-Phoenix's youtube video of the same idea) so I had a good idea of the shape and user experience that I was going for, but very little substance in terms of execution and design. I spent around two weeks and easily 2-3 million Opus 4.6 tokens, and >300k on GPT 5.4 reducing my uncertainty as much as possible. That phrasing is important because the model's were not in the designer seat; they would help me visualize and fill in understanding gaps far more than actually making architectural decisions. I'm sure they could have, but I wouldn't have been able to troubleshoot anything if it wasn't my own design. I think one thing people miss about AI workflows, when used properly, you learn exactly what you need to know, but not much else. If I were doing this 10 years ago I would have likely needed to learn 50-60% more information that was never used, because I didn't actually know what I needed to know. With the current generations of tools I was able to laser focus on information that was worth investing in, and basically nothing else. Take it or leave it, I'm sure some people will see that as passe, but experiencing it has been a breath of fresh air from my previous-overly-ambitious projects.

The result of this pre-planning phase was a fully designed and simulated breadboard, high confidence decision tree and a breadth of edge cases. One of my proudest accomplishments in this project so far is not hitting any roadblocks that required ordering a new part to continue working. I only have maybe 3 or 4 unused components, now that the breadboard prototype is proven. Anytime I hit a snag, I had the right capacitor or resistor or ferrite bead or whatever already to just keep moving forward. The entire build process was planned in isolated phases with concrete deliverables at the end of each phase, so if a new problem arrived, it would be clear what general area the source is from.

Claude Code as a live lab notebook

During the entire breadboard phase I had a terminal window open with Claude Code running alongside the physical build. Every time I moved a jumper, measured a voltage, swapped a component, or observed a behavior change, I'd relay it to the session to be documented. This was incredibly valuable, and allowed me to run simulations when i wasn't with the device (remote Claude code sessions running simulations of my breadboard design to test a hypothesis while I'm out on a run is wild, taking a step back). Another advantage of documenting through Claude Code was allowing me to export the full breadboard schematic with descriptions of problems, then going to GPT 5.4/5.5 for a second opinion. This was fruitful every time I did it, and the two models work incredibly well together, more on this later though. Multiple times I would give Claude "jumper 56,g-46,a" and it would tell me that 46,a is already taken by something else, are you sure, and I would find I wired something wrong an hour ago, then correct it before needing to power on again.

Quick model notes

This project started mid-way thought the Opus 4.6 /GPT 5.4 lifecycle, then as both rolled over to 4.7 and 5.5 I switched over to that (gradually for 4.7; I'll explain in a second). Opus 4.6 did 95% of the planning phase with GPT 5.4 for second opinions when it was clear I was hitting a knowledge gap in 4.6, or it was struggling with something that was clearly a limitation of the model. It's hard to describe what that constitutes, but if you've worked with these models extensively, you get a feel for different types of mistakes and uncertainties. For planning specifically, I much prefer Anthropic models if only for their tone. I am capable of doing the technical side of things, but if the model's tone doesn't align with me, or their output isn't structured how I like, it takes mental energy away from the task. This is my number one issue with OpenAI models; on a technical level I am absolutely certain I would have been fine with GPT 5.x alone, but the list of lists and bullet points style writing feels not-human. Also, to comment their tone or prose, Anthropic models actually feel like they are enjoying the project, they will show "excitement" when I come up with a novel solution, and get terse when I am getting distracted. I have found OpenAI models much more egalitarian and "I-am-a-tool-don't-pretend-I-am-human" which is probably healthier for my mental state, but I don't get the boost of focus or mental energy that comes along with the model telling me I'm the bestest boy for solving a problem it was struggling with.

During the introduction of 4.7 I am always wary about giving new models access to production code (sonnet 3.7 iykyk), especially because 4.7 has a massive prose change from 4.6, which on it's surface doesn't inspire confidence. I kept 4.6 active for two weeks or so, occasionally flipping over to 4.7 only to see the overly verbose prose and the "wait this isn't right" outside of thinking tokens (really, that should only ever be in thinking tokens. I suspect Anthropic's post training restricted it's thinking budget to save compute so that stuff just got moved to the output, but I digress). But after it passing tests and finding things 4.6 missed I switched over fully and it's actually been better than 4.6 on most technical dimensions. It can certainly trace a signal path better, but I've found it makes mistakes after 250k tokens (all models do), so I have an alert to remind me to compact or make a handoff doc if I hit that. I really can't tell the difference between GPT5.4 and 5.5, but I only used either of them for less than 10 prompts each. Always professional and very very knowledgable. OpenAI models feel like a contractor from a different firm is in the office for the day, whereas Anthropic models feel like an old coworker that doesn't like small talk.

Would I have done this without AI?

Honestly probably not. In hindsight I very clearly had the skillset and capabilities, but passing the threshold of confidence to take this idea and turn it into a physical object, was probably too high for me to reach on my own. I don't really have anyone in my life that is capable of troubleshooting or spitballing technical solutions if something goes wrong. Two geiger tubes would have certainly been reachable with tutorials, but after seeing it's low detection rate, and deciding that was a poor user experience, I don't think I would have had confidence to pursue 4 tubes/six way coincidence gates. This is also not mentioning anything about programming the firmware for the ESP32 or the e-ink display, which again would have been doable, but taken weeks not minutes, for me to learn and execute.

Takeaway

Overall, amazing experience doing this AI assisted, Claude Code is an incredible tool. I understand a lot of people have mixed feelings about AI in general, but in my sample size of one, I am getting massive massive value from it on a daily basis, across disparate parts of my life. I would love to hear other people's thoughts. How are you using LLMs in a hardware setting? Do you think I actually did this myself or should I put an asterisks every time I say "I made this"? Anyway thank for reading o7.

From e-ink headaches to high voltage unknowns

#permalink

It's been a few weeks since the last update and a lot has happened, so this is going to be a longer one covering multiple milestones. I'll try to keep it moving.

The display swap

While waiting for the HV boost modules I started working on the e-ink display. I'd originally planned to use a Waveshare 3.97" (800×480, 4-level grayscale) but switched to a Good Display 5.79" wide-format panel (792×272, monochrome) because it had a much faster full refresh on paper (3.5s v 0.7s). Trade-off is losing grayscale, but for a clock and oracle readout, monochrome with good typography is plenty.

What I didn't expect was spending a full week debugging this thing. I've realized it doesn't do partial updates without RAM buffering, I just assumed it had partial updates, and my little ESP32 is just barely enough, so to avoid this again, I just went and ordered an e-reader HD display and we are going to call it a luxury experience. I'll go more into it later, I've put the display on the back burner now that the HV boosters have arrived.

Laser-cut tube scaffold

I had an acrylic scaffold laser-cut to hold four J305 tubes for testing. The design puts each of the six possible tube pairs at a different angle with a different geometric aperture, so I can eventually compare coincidence rates across different alignments. The tubes are wrapped in black heat shrink for light shielding (J305s are photosensitive and will false-trigger from ambient light), then taped securely into the cradles.

Single tube bring-up

The HV boost modules finally arrived and I spent a full day getting a single tube working. It did not go smoothly.

First problem: one of the HV boosters was dead on arrival. No output at all, trimpot did nothing. Swapped it for the second module and got a clean ~410V output. Good reminder to always order spares. I have more on the way.

Second problem, and the one that ate most of the day: with a working HV module and a tube connected, I was getting zero signal. The tube was powered, presumably counting background radiation, but nothing was making it through to the ESP32. I went through the chain methodically (checked voltages, checked connections, then checked the 74HC14 inputs) and eventually traced it to the pulse stretcher. The BAT54/RC network that worked perfectly with clean synthetic pulses from the ESP32 wasn't behaving the same way with the real analog signal from the cathode. I rebuilt the stretcher section and it started working. I probably had a jumper out of place.

That moment when the serial monitor starts printing counts at roughly the right background rate (~25–40 CPM for a J305) is genuinely satisfying. Finally one tube, clicking away, counting background radiation on my desk in Hanoi.

Two tube rebuild

With one tube proven, I broke down the single-tube setup and rebuilt for two channels. This is where it got messy.

The second channel needed its own pulse conditioning chain (coupling cap, bias network, 74HC14 shaping, stretcher, re-squaring), a copy of the first one. And the coincidence gate needed both stretched outputs feeding the 74HC08 AND gate cleanly. In theory I'd already validated all of this with synthetic pulses. In practice, with real analog signals and two HV modules running simultaneously, new problems appeared.

The coincidence timing was off. I was either getting zero coincidences (window too narrow or pulses not overlapping) or suspiciously high counts that were clearly noise rather than real events. First I was getting 1000+ hits a second, clearly noise. I wrapped the cathode lines with grounded cables, that brought it down to 200-ish.

Then I threw capacitors on the HV boosters' inputs (which felt so wrong). That brought it down to around 30. I tried to solder up a tiny 100pF ceramic cap and it was a joke, didn't do anything. Interestingly enough, Claude recommended ferrite beads on the input...

Testing the signal chain with synthetic pulses

#permalink

Before the HV boost modules arrive (40 days in transit), I wanted to validate as much of the detection circuit as possible using just the ESP32 itself. The idea is simple: use one GPIO as a signal generator to inject fake pulses into the front end, and use another GPIO to listen for interrupts at the output. If the right number of pulses come out the other end with the right timing, the chain works.

Digital chain first

I started with just the digital side: the 74HC14 pulse shaping, BAT54/RC stretcher, second 74HC14 re-squaring stage, and the 74HC08 AND gate. I wrote a quick sketch that toggles a GPIO to produce short pulses at a known rate, fed those into the 74HC14 input, and counted rising-edge interrupts on the AND gate output with a separate pin.

For single-channel testing I injected pulses into one channel at a time and confirmed the ESP32 counted every one. For coincidence testing I fed the same pulse into both channels simultaneously. The AND gate output fired on every injected pulse, which is exactly what you'd expect when both inputs see the same signal at the same time. I also confirmed that pulsing only one channel produced zero coincidence counts on the output. That's the whole point of the AND gate and it's reassuring to see it actually reject single-channel events.

Not the most sophisticated test. A logic analyzer would let me see the actual pulse shapes at each stage and verify the stretcher timing. But for a go/no-go check of "is this circuit wired correctly and are the ICs behaving," it's enough. The logic analyzer is sitting on my desk for when I need it later.

Then the analog front-end

With the digital chain proven, I wired up the analog input network: the 1nF coupling caps, 4.7kΩ series protection resistors, and 100kΩ bias pull-downs that sit between the GM tube cathodes and the 74HC14 inputs. No tubes, no HV, just the passive components that will eventually condition the real cathode pulse.

Same test: synthetic pulses from the ESP32 into the analog input side, interrupt counting on the coincidence output. The pulses now travel through the full path: coupling cap, bias network, first Schmitt trigger stage, stretcher, re-squaring, AND gate. Everything that isn't the tube and HV module.

It worked. Same pulse counts in, same counts out. The coupling caps and bias resistors aren't filtering out or attenuating the synthetic pulses, which makes sense because the ESP32 GPIO puts out a clean 3.3V edge that's well above the 74HC14's ~1.9V threshold. The real question is whether actual GM tube cathode pulses will be strong enough, and that's something I genuinely won't know until the HV modules show up and I can power a tube.

That's the next milestone: HV module bring-up. The boost converters are still in transit, so in the meantime I've been working on the e-ink display, which turned into its own adventure. More on that next time.

Digital circuits breadboarded

#permalink

With the schematics drawn and parts sorted into their labeled bins, it was finally time to start populating a breadboard. The plan was to build the entire digital chain first: pulse shaping, stretching, re-squaring, and the coincidence AND gate. Without any of the analog front-end, and definitely without any HV anywhere on the bench.

I'll spoil the post: it was uneventful. Which is the goal, honestly. The fun part of breadboard work is that satisfying click of components going into rows and the slow accumulation of a circuit that starts to look like the schematic on paper. Two 74HC14s, a 74HC08, a 100nF decoupling cap on every IC's VCC pin (every IC!!), the BAT54 diodes and RC networks for the stretchers, all the bias and pull-down resistors. About an hour of work, a couple of moments where I had to recount pin numbers, and a finished chain.

A few small choices worth calling out:

The BAT54s are SOT-23 SMD parts, which is annoying on a breadboard. I soldered short lead wires onto each one before plugging them in. Ugly but functional, and they'll be replaced with through-hole packages once the design moves to PCB anyway.

I tied all unused 74HC14 and 74HC08 inputs to ground rather than leaving them floating. CMOS inputs that float pick up noise and can self-oscillate, which is exactly the kind of subtle problem you don't want chasing later when the analog side is also misbehaving.

I left the cathode pulse inputs (TUBE1_RAW and TUBE2_RAW on the schematic) terminated at unused breadboard rows for now. Those will get connected to the GM tubes once the analog front-end exists. Until then, they're just landing pads waiting for a signal.

Next post is going to be the more interesting one: validating that the chain actually works using synthetic pulse injection. I'm generating test pulses from an ESP32 GPIO and walking through the chain stage-by-stage with a logic analyzer to make sure each transformation happens the way the schematic says it should. That's the post where I find out if I drew the circuit correctly.

Designing a cosmic ray decision oracle on paper

#permalink

I have been thinking about building a muon-based RNG device ever since watching an Alpha Phoenix video on YouTube. It seemed like such a cool way to have a direct connection to both sub-atomic and astronomical scales. I mulled the idea around for ~2 years and finally decided to pull the trigger.

I haven't designed a circuit from scratch since high school, but I have done a number of repairs on analog equipment working as a sound engineer over the years, so the first thing I wanted to do was draw out the schematics to make sure I understand everything and can start preparing myself mentally for dealing with analog components without an instruction manual. Specifically because the high voltage boosters are not something you can really troubleshoot on the breadboard without burning the rest of the hardware.

Page 1 of the sketch set. USB-C 5V in, AMS1117 LDO dropping to 3.3V for peripherals, ferrite beads isolating the two HV boost modules so their switching noise stays out of the logic rail.

Page 2, repeated for both tubes. HV module trimmed to ~420V, series-stacked resistors on the anode and bleeder (no single resistor sees more than its rated working voltage), and a divider down to ~2.2V for the ESP32 ADC to monitor. The tube cathode is where the signal is picked off, not the anode.

Page 3, the heart of the detection circuit. Each tube's cathode pulse gets AC-coupled, shaped through a 74HC14 Schmitt trigger, stretched with a BAT54 diode and RC network to ~3-5µs, then re-squared through another 74HC14 channel. Both stretched pulses feed a 74HC08 AND gate. Its output fires only when both tubes trigger within the coincidence window, which is the muon signal.

Page 4. The e-ink display and SD card share MOSI and CLK but get their own chip-select pins (with pull-ups so both stay deselected during boot). Only the SD card uses MISO. The e-ink is write-only.

Page 5. BME280 environmental sensor on I²C, KY-040 rotary encoder for navigation, dedicated decision button (the hero interaction so it's kept physically separate from the encoder), and a passive piezo for audio feedback.

Every component bag hand-labeled with value, purpose, and where it goes in the circuit. "100nF -> IC decoupling -> every IC!!" is for future me at 2am who forgot to drop a cap next to a chip.

Missing page 6: the ESP32-S3 pinout map. Forgot to photograph it.

Stay in the loop
Build updates while we get this thing real, then the launch alert when reservations open.