Vibe-coding an Ultrasonic Tide Gauge

AI coding tools have been fantastically useful for working through my long backlog of vaguely-planned projects that I never found the time or energy to finish. This post tells the story of how I used AI coding tools to help me build a project that presented a number of challenges that were previously insurmountable due to lack of time.
I built a self-contained solar-powered tide gauge that reports water level, water temperature and battery status to my Home Assistant server once a minute. It does this over a LoRa connection to a The Things Network (TTN) base station in my loft.
Requirement
I live near a creek with unpredictable tides: it’s at the top of a large bay and the water level is strongly influenced by wind direction and strength. I want to build a simple tide gauge that reports the present water level back to my Home Assistant server so I know when it’s suitable for paddle-boarding and kayaking. This device has to be small, cheap, and self-contained. It will be powered from a small Li-Ion battery charged by a small photovoltaic panel, which means it also has to be very low power.
Design
I will bang a 4" pipe into the mud in the creek. It will have some holes drilled in to it to let the water in and out, a 3D-printed “pot” containing all the electronics at the top. On the bottom of the pot is a a downward-facing ultrasonic transducer to measure the water level in the pipe. You will also need to drill a small hole in the pipe below the pot to let the air in and out as the water level changes.
Water level sensor
I’m going to use an ultrasonic transducer to measure the distance from the water. The standard cheap ultrasonic module that everyone uses with a RPi is the HC-SR04. There are waterproof versions available, like the JSN-SR04T which are drop-in replacements for the HC-SR04 (spoiler alert: they’re not!)
Water temperature
This one is easy - plug in a DS18B20 and go! I had to extend the cable with some 3-core 22AWG, and ran the resulting longer cable down the inside of the pipe so the probe can sit on top of the mud at the bottom. I zip-tied the cable to the side of the pipe by drilling pairs of holes at the top and bottom.
Compute
I’m going to use a RP2040 microcontroller because I’m a hopeless Raspberry Pi fanboi it’s simple and low-power. It’s trivially easy to get distance readings off an HC-SR04 on an RP2040, so I should be able to knock up some workable code in Micropython and then do the transport bit quite easily (another spoiler alert: I couldn’t!)
Data link
The data rate will be very low: a few bytes every minute or so. WiFi is impractical: it’s a long way from the nearest base station, WiFi is too power-hungry, and I don’t need its high data rate.
LoRa fits the bill perfectly: long range and low power. I have a The Things Network base station in my loft (using a RAK2287) and there is an integration available for Home Assistant.
Adafruit sells a RP2040 with a built-in RFM95 LoRa radio, which is should make this easy (final spoiler alert: this was unexpectedly hard!)
Power
The Adafruit RP2040 has a JST connector for a LiPo battery, and appropriate circuitry to charge it from the USB port. Be careful - many of the batteries available on Amazon are wired with the wrong polarity, so you might have to get your soldering iron out and swap the cables over (I did).
There are plenty of small photovoltaic (PV) panels available on Amazon; most of them are described as suitable for powering security cameras. I tried a 5W one and it didn’t provide enough power to keep the battery topped up. I rewrote the code (well, I didn’t - see below) to reduce the RP2040’s power consumption, added a transistor to turn off the HC-SR04’s power between transmissions and fitted a bigger 10W PV panel. That works well.
Why this is perfect for AI
We choose to do these things not because they are easy, but because we thought they would be easy
- All engineers
This should not be a particularly complex project, and yet… a whole host of annoying blockers conspired to prevent the darned thing from just working and I had neither the time nor patience to persevere with the project long enough to fix them - until AI came to the rescue. The main challenges were:
- Compatability. Those waterproof ultrasonic transducer is not a drop-in replacement for the HC-SR04, despite all the claims to the contrary. I tried several different heads and boards from different suppliers and they all seemed to max out at 60cm, with other weird anomalies messing up my readings. I tried them on 3V3, 5V, I installed a buck boost converter to help clean up VCC - nothing worked. Figuring this out was extremely frustrating, but it would have taken much longer without AI to write test-scripts on demand. By contrast, the HC-SR04 proved utterly reliable when just plugged in to the RP2040’s 3V3 pin, reliably returning accurate measurements with a Standard Deviation of less than a millimeter across 16 readings… until I put them in a 4" pipe (see below).
- Documentation (or lack of it). Adafruit has some handy guides on how to get their RP2040/RFM95 to talk to The Things Network… but they don’t work any more because TTN changed their spec! There are some great Micropython and Circuitpython LoRa libraries… that also don’t “just work” with TTN (see above). So I had to write my own libraries based on the TTN APIs and… this is where my patience ran out. AI made this easy.
- Physics. Putting an ultrasonic transducer at the top of a tube feels like it should just work, but in practice it will pick up lots of stray reflections. That wouldn’t be so bad if these cheap modules returned all echos because you could just pick the longest path and dismiss the rest, but they only return the first one which is often spurious. In my case, the electronics “can” at the top of the tube acted as a resonant chamber and it took me ages to figure that out! AI was a great help with debugging the physics as much as the code. I ended up putting a 20g bag of silica gel on top of the transducer - the beads scatter the sound in the same way as a submarine’s anechoic tiles, and also helps keep the electronics dry! I also increased the number of samples and returned the median of the longest-range grouping. It isn’t perfect but, since the tide changes quite slowly, I can improve this even further in Home Assistant by taking the minimum of the last 10 readings.
This is where AI comes in, because it’s perfect for lazy hacky coders like me looking up API specs, building test rigs, debugging (code and physics!) and delivering working code quickly.
Bill of materials
- 4" pipe, at least 8ft long. DWV if you’re feeling cheap, SCH40 if you’re feeling flush (which is ironic, because things that are flushed normally go through DWV…)
- Adafruit RP2040 / RFM95 combined microcontroller and LoRa radio module (you just need to solder on the included helical antenna).
- HC-SR04 ultrasonic transducer
- DS18B20 temperature sensor. The cable wasn’t long enough, so I extended it with some 3-core 22AWG cable and sealed it up with heatshrink to keep it waterproof.
- 10W photovoltaic panel with USB lead. This USB lead is far too long, so you will need to coil it up inside the “pot”.
- LiPo battery (you might need to swap the postive and negative over)
- BC548 transistor to control power to the HC-SR04
- Resistors to create a potential divider for battery voltage measurement. I used a 100kΩ and a 220kΩ.
- Dupont wires, female-to-female, lots of! Some of these will need to be cut and soldered to make multi-way connectors.
- 3D-printed parts: STLs are available along with the RP2040 code on my Github.
- M3x16mm screws to attach the PV to the top of the assembly, and M2 screws (optional) to attach the RPi2040 board to its 3D printed base.
- Paint, if you or a family member objects to having a big white pipe banged into the mud on your waterfront. Brown paint makes it practically invisible.
Wiring
Unfortunately (at time of writing) Codex is not very good at making wiring diagrams. I could probably fix this by telling it which open source tools to use, but for now I’ll just list the RP2040 pinout here:
- D6 -> HC-SR04 TRIG
- D5 <- HC-SR04 ECHO
- D10 -> BC548 base through 1k resistor
- BC548 base -> GND through 10k resistor
- BC548 emitter -> GND
- BC548 collector -> HC-SR04 GND
- 3V3 -> HC-SR04 VCC
Battery measurement
- A0 / GPIO26 <- divider midpoint
- BATT -> 100k -> divider midpoint
- Divider midpoint -> 220k -> GND
Temperature sensor
- D9 <-> DS18B20 DQ
- D9 -> 3V3 through 4.7k pull-up (the Amazon link above comes with a small board that includes the resistor)
- 3V3 -> DS18B20 VDD
- GND -> DS18B20 GND
The LiPo battery plugs into the RP2040 battery connector (check the polarity first!) and the USB-C connector from the PV panel plugs into the USB-C connector on the RP2040: its build-in circuitry handles the charging.
There are not enough 3V3 and GND pins on the RP2040, so you will have to solder some Dupont connectors together to make “splitters”. You could put the legs of the resistors and transistor into the Dupont connectors to save some soldering, but make sure you heatshrink everything to prevent shorts.
Software
This would normally be the bit where I’d write - in excruciating detail - what commands you need to type to install the right packages, tweak the right config files and build the image properly. But in 2026 I don’t need to do any of that, because all you need to do is install and run Codex CLI.
Clone my github repo and run codex in the resulting directory. It will figure it all out. In fact, if you don’t know how to clone my repo you can just ask Codex to do that too!
Plug your RP2040 into a USB port and Codex will instruct you what to do with it.
You will need to create an “Application” in your TTN dashboard and, yes, Codex can walk you through that as well. Here is the “live data” feed from my working tide gauge:

If you don’t have a TTN node within range then you can ask Codex (or Claude, or Copilot, etc) how to set up one on a Raspberry Pi too! You will then set this up as a Gateway in your TTN portal.
The Home Assistant bit is quite straightforward but, if you get stuck… yup, Codex! Here’s mine in Home Assistant - still a bit noisy due to spurious reflections, but eminiently usable.


These coding agents also make awesome sysadmins. I have some Cisco IP phones I wanted my kids to be able to play with, but I know nothing about PBX systems. No problem - I installed FreePBX on a fresh VM and Codex just made it all work! I’m not brave enough to use Codex on an important production system yet, but it’s excellent at finding and fixing stuff on home servers. It also diagnosed a problem on my Home Assistant server: I told it “find the memory leak” and it replied “it’s not a memory leak, you’ve misconfigured a data source and it’s filling up your DB and causing the system to churn”. It was right - and it then fixed the misconfiguration for me!.
I’m living in the future. I don’t write code any more, and I don’t debug complex system glitches any more. I administer fleets of agents that do it all for me!
