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.