Overview

A Measurement Pipeline.

The Arduino Mega gathers sensor data in the field, checks whether a reading is usable for mapping, writes both raw and filtered logs to SD, and hands the accepted points to Python scripts that turn those points into map products.

Workflow

From field reading to map output

  • 1. Capture: GPS, sonar, temperature, IMU, UTC time.
  • 2. Validate: Fix quality, depth stability, motion, spacing.
  • 3. Log: Full record plus accepted mapping dataset.
  • 4. Reconstruct: IDW surfaces, contours, KML, KMZ overlays.
Hardware

The Platform

The system runs on an Arduino Mega, integrating a GPS module, waterproof ultrasonic sensor, DS18B20 water temperature sensor, BNO085 IMU for pitch/roll orientation, an LCD display, and an SD card module for offline field logging.

Validation Logic

Measurement thresholds.

The logger does not just collect sensor output. It defines what counts as an acceptable mapping condition. Those choices show up directly in the constants and helper functions in the Arduino code.

Parameter Current Value Role in the survey
sonarCalSoundSpeed 1500.0 m/s Baseline sound speed used when correcting sonar range.
maxMapHdop 1.8 Rejects GPS fixes with poorer horizontal precision.
maxMapFixAgeMs 2000 ms Rejects stale GPS fixes that no longer match the platform position closely.
maxMapSpeedKmph 8.0 km/h Limits mapping when the platform is moving too quickly.
maxMapPitchDeg / maxMapRollDeg 10.0° Rejects mapping points when platform tilt exceeds the allowed pitch/roll range.
minMapSats 5 Minimum satellite count required before a fix can produce a mapping point.
minMapSpacingMetersBase 2.0 m Base minimum spacing between accepted points; scales adaptively with speed (2–10 m) to prevent oversampling.
maxDepthJumpCm 50.0 cm Rejects isolated depth samples that jump too far from the smoothed value, suppressing transient sonar spikes.
Geospatial Data

Depth becomes bathymetry when tied to position.

A single depth value only says how far the bottom was below the sensor at one moment. Bathymetry needs depth plus coordinates so the measurement can become part of a spatial pattern.

Context Attached

The map file records each accepted point with time, latitude, longitude, depth, temperature, satellite count, HDOP, speed, fix age, pitch, roll, and IMU accuracy. That structure keeps the measurement conditions attached to the point.

point,date_utc,time_utc,lat,lng,depth_cm,temp_c,satellites...

Raw vs Mapping Logs

The raw data log preserves the complete field record, including conditions that may not be suitable for mapping. The map log contains only accepted points. That separation makes the reconstruction step more predictable and keeps the record transparent.

Signal Conditioning

Cleaning the signal in the field.

Beyond the acceptance gates, the firmware does work on each reading before it is ever logged, so the recorded series is already conditioned by the time it reaches the Python scripts.

Depth smoothing

Moving average and spike rejection

Sonar range is read over UART with a checksum, then passed through a 5-sample moving average. Samples that jump more than maxDepthJumpCm (50 cm) from the previous value are discarded, and depth is invalidated after a 2-second timeout with no valid return.

Sound-speed correction

Temperature-based, no salinity input

Acoustic depth depends on the speed of sound in water. The firmware adjusts the reported range from a 1500 m/s baseline using the measured DS18B20 temperature. It is a temperature-only model; the repository lists salinity-aware correction as a future improvement.

SD recovery

Reopen files after a write failure

If a log write fails or the card drops out, the logger retries SD.begin() and reopens both files on a 3-second interval, counting recoveries so a field session is not lost to a transient card fault.

UTC time & GPS warmup

Trustworthy timestamps

All timestamps are logged in UTC to remove timezone ambiguity, and a 10-second GPS warmup window keeps early, unreliable fixes out of the mapping dataset.

Algorithm Implementation

Executing IDW Interpolation.

OMEGA uses inverse distance weighting to estimate values between measured points. The Python scripts build a grid over the survey area and estimate a depth for each grid cell. Nearby measured points receive more weight than distant ones.

scripts/csv_to_png_depth_interpolated.py
import numpy as np

def idw_interpolation(x, y, z, xi, yi, power=2.0, epsilon=1e-12):
    """
    Inverse Distance Weighting (IDW) spatial interpolation.
    """
    zi = np.zeros_like(xi, dtype=float)
    
    # Iterate across the target 2D raster grid
    for row in range(xi.shape[0]):
        for col in range(xi.shape[1]):
            dx = x - xi[row, col]
            dy = y - yi[row, col]
            dist = np.sqrt(dx * dx + dy * dy)
            
            # Prevent division by zero
            if np.any(dist < epsilon):
                zi[row, col] = z[np.argmin(dist)]
                continue
                
            # Weight = 1 / (d^p)
            weights = 1.0 / np.power(dist, power)
            zi[row, col] = np.sum(weights * z) / np.sum(weights)
            
    return zi

The Math: The weight of a known sonar point decreases as the distance increases. The scripts default to a power of 2.0 (inverse square), so a ping 2 meters away has 4 times less influence than a ping 1 meter away. The exponent is adjustable via --power, alongside --grid-size for interpolation density.

Data Pipelines

Offline Python Processing.

The same accepted points can become several different map products. OMEGA-bath includes a set of offline Python scripts that read a mapping CSV and produce interpolated depth surfaces, contour maps, and georeferenced Google Earth overlays.

  • csv_to_png_depth_points.py: Scatter view of the recorded points, colored by depth, for checking survey coverage before interpolation.
  • csv_to_png_depth_interpolated.py: Continuous depth surface estimated from the accepted points via IDW.
  • csv_to_png_depth_contours.py: Renders the interpolated surface as filled contour bands with sample points overlaid, emphasizing shape and slope.
  • csv_to_kml_points.py / csv_to_kml_points_colored.py: Export measured points to Google Earth, optionally colored by depth.
  • csv_to_kmz_depth_overlay.py: Places the interpolated surface over its geographic footprint in Google Earth, packaging the result into a compressed KMZ.

The repository documents the outputs as exploratory mapping products. The system uses single-beam depth sensing and IDW interpolation, so the reconstructed surface is a modeled estimate rather than a formal hydrographic survey.