The idea
Proper survey echosounders cost more than the boat carrying them. But a consumer fish-finder transducer is the same physics — a 200 kHz piezo ping and a clock — wrapped in a bass-fishing UI. Ours outputs NMEA 0183 $SDDPT sentences at 1 Hz. That’s a depth logger.
Bolted under Remora and fused with RTK GPS positions, it produced a genuinely usable depth map of our test bay. Here’s the pipeline, including the three corrections that matter.
Hardware
- Transducer: generic 200/83 kHz dual-frequency unit, €38
- Head unit with NMEA out: second-hand, €22
- Interface: NMEA (RS-422) → ESP32 UART, timestamped and merged into the MAVLink telemetry stream
Mount the transducer ahead of the props, faired, and dead level. Our first mount angled 4° bow-down read 3% deep everywhere and we spent a day blaming the tide tables.
The three corrections
1. Draft offset
The transducer sits 9 cm below the waterline. Every reading is 9 cm short of true depth. Trivial, and forgotten by everyone once.
2. Sound velocity
The sounder assumes 1500 m/s. Our estuary in March: ~1480 m/s (12 °C, brackish). That’s a 1.3% depth error — 13 cm at 10 m. We correct in post using a temperature/salinity → velocity formula (Mackenzie) fed by a €5 DS18B20 on the hull.
3. Tide
The big one. A 3-hour survey here spans up to 1.8 m of tidal change. We reference every ping to the harbour tide gauge (10-min data, interpolated) and reduce all depths to chart datum. Without this step the map is fiction.
Processing
Half a million corrected (x, y, z) points go through a short Python pipeline:
import pandas as pd
from scipy.interpolate import griddata
df = pd.read_parquet("pings_corrected.parquet")
df = df[df.depth.between(0.3, 40)] # gate the junk
df = df[df.quality > 0.6] # sounder confidence
grid = griddata(df[["x", "y"]], df.depth,
(gx, gy), method="linear")
Median-filter the grid (3×3), mask cells with fewer than 5 supporting pings, export GeoTIFF.
How wrong is it?
We crossed our own survey lines and compared depths at 1,240 intersection points: 95% within ±18 cm. Against the official chart (which is from 1987 in this bay), differences up to 1.2 m — some of which, we suspect, is the chart.
Limits
One beam means no swath: resolution is trackline spacing. Weed beds return false bottoms. And below ~0.8 m the transducer rings and reads garbage, so the interesting shallow edge is exactly where the data ends. A multibeam this is not — but for €60 and an afternoon of soldering, it’s a map.