Depth sounder for shallow water and recording                  Mobiel schrijvend echolood

                                                      

2023 05 19 Sounder Mobile Survey
PDF – 8,2 MB

Depth Sounder for shallow water

English version of the page below in pdf. Building a mobile sounder that records depths with their position on an SD card. Suitable for use in a dinghy without electrical installation or an SUP board. (9 pages). 

Mobiel schrijvend echolood                                                                                 2023 03 23

 

Doel

Het vastleggen van waterdieptes met hun positie ten behoeve van een diepte survey. Het apparaat moet geschikt zijn voor mobiel gebruik in een dinghy zonder electrische installatie of op een SUP board.

 

Databronnen

Een echolood voor de waterdiepte en een GPS ontvanger voor de positie.

 

Weergave en bewaren

De diepte wordt digitaal op een voltmetertje weergegeven. (beperkt tot 5m)

De diepte en positie worden vastgelegd op een mini SD card in een txt file zodat de data in een later stadium verwerkt kan worden.

 

Het echolood

Voor dit project wordt het zend- en ontvangst gedeelte van een Seafarer Mk3 of 4 Echolood gebruikt.

De gemeten tijd van de zendpuls bedraagt ongeveer 300 µs. In die tijd legt de puls 44.4 cm af.

(vSound = 1480 m/s) = (148000 cm/s) = (0.148 cm/ µs) = (44.4 cm/ 300 µs)

Er wordt een 150 kHz transducer gebruikt die gedurende deze puls 45 trillingen maakt,

(150 kHz ) = (150000 trillingen/ s) = (0.150 trilling/ µs) = (45 trillingen / 300 µs)

 

 

Enigszins op schaal geschetst voor een periode van 1000 µs ziet dit er zo uit:

De kleinste metingen liggen rond de 45 cm.

 

Oorspronkelijk werd de diepte bij het Seafarer echolood zichtbaar gemaakt met een ledje op een rond draaiend armpje dat oplichtte bij de ontvangst van de echo. Op een cirkelvormige schaal rond de arm was de diepte af te lezen.

 

Arduino Uno type microprocessor

Omdat de data digitaal verwerkt moet worden, gebruik ik een Arduino Uno microprocessor om de zender te triggeren en om de tijdsduur te meten. Het motortje, armpje en verder overbodige onderdelen zijn van de print gehaald om stroom te besparen en om ruimte te maken voor Arduino en batterijen.

Het punt tussen weerstanden R19 en 20 is het punt waar de Arduino de zender op transistor TR10 triggert. R19 zelf en TR9 zijn verwijderd. (De onderdelen zijn ook op de print benoemd.)

 

De Arduino wordt voor dit doel geprogrammeerd via haar USB verbinding. Het programma blijft behouden op de Arduino en begint te lopen zodra er spanning op de Arduino komt. Met de functie pulsIn(pulseInPin, LOW) berekent de microprocessor de tijdsduur dat het signaal 0 is. Met andere woorden de tijdsduur tussen zend- en ontvangst- puls

Bij een vSound in m/s en travelTime in µs is de Diepte in cm: travelTime x vSound / 20000.0

De geluidssnelheid in water, vSound = 1480 m/s

 

Bij een vSound in m/s en travelTime in µs is de Diepte in cm: travelTime x vSound / 20000.0

De geluidssnelheid in water, vSound = 1480 m/s

 

Een voorbeeld:

Stel de tijdsduur tussen zend- en ontvangst puls is 700 µs, en de pulseduur 300 µs dan is de totale traveltime 1000 µs en de diepte 1000 x 1480 / 20000 = 74 cm

 

Display

Om de diepte weer te geven gebruik ik een digitaal voltmetertje met een refreshrate van 200 ms. (Een digitaal aangestuurd LCD schermpje was moeilijk afleesbaar en te traag) De berekende waterdiepte wordt omgezet in een voltwaarde d.m.v. PWM op een digitale uitgang.

Het bereik van het metertje is hiermee wel beperkt tot 5 meter. (5V limiet Arduino) Voor de berekende getalswaarde die op het SD kaartje geschreven wordt geldt die restrictie niet.

 

Het programma

// 230322_Sounder_Timer0_pulses

// Trigger a pulse 2 times a second via pin 5 (orange)

// Messure time between pulse and echo on pin 2 (grey)

// Display depth with PWM voltage via pin 3 (yellow)

// 1500 m/s = 1.5 m/millis or 1.500 mm/micro

 

#include <SoftwareSerial.h>

#include <SD.h>

SoftwareSerial mySerial(8,7);

#define chipSelect 10

File logfile;

#include <Adafruit_GPS.h>

#include <SPI.h>

Adafruit_GPS GPS(&mySerial);

#define LOG_FIXONLY false

 

const int pulseOutPin = 5;

const int displayPin = 3;

const int pulseInPin = 2; //

const int vSound = 1480; // m/s

const int pulseOutDuration = 20; //microseconds

const int timeBetweenPulsea = 500; // milliseconds

float volt = 0.0;

unsigned long previousMillis;  //violate

 

void Update(unsigned long currentMillis)

{

  if(currentMillis - previousMillis >= timeBetweenPulsea)

  {

    previousMillis = currentMillis;

 

    // send a pulse to the sounder          

    digitalWrite(pulseOutPin, HIGH);

    delayMicroseconds(pulseOutDuration);

    digitalWrite(pulseOutPin,LOW);

 

    // messure depth and display

    unsigned long travelTime = pulseIn(pulseInPin, LOW) + 300;

    // 300 is pulselenght at mode 6x    

    unsigned long depth = travelTime * vSound / 20000; //cm    

    // devide depth in a way volts equals meters approximately 

    volt = depth/ 1.55;

    if (volt >= 255) // max of range 5V

      volt = 255;

    analogWrite(displayPin,volt);

 

    // get $GPRMC from GPS

    if (GPS.newNMEAreceived())

    {        

      char *stringptr = GPS.lastNMEA();

      if (!GPS.parse(stringptr))

        return;      

      if (LOG_FIXONLY && !GPS.fix)            

        return;

      //write the string to the SD file  

      uint8_t stringsize = strlen(stringptr);    

      if (stringsize != logfile.write((uint8_t *)stringptr, stringsize))    

        Serial.println("ërror");    

      if (strstr(stringptr, "RMC"))

      {

        unsigned long travelTime = pulseIn(2,LOW) + 300;    

        unsigned long depth = travelTime * vSound / 20000;    

        logfile.println();      

        logfile.print("$SDDBT,");

        logfile.println(depth);

        logfile.println(millis());

        logfile.println();        

        logfile.flush();

      }

    }    

  }  

}

 

void setup()

{

  pinMode (pulseOutPin, OUTPUT);

  pinMode (pulseInPin, INPUT);

  pinMode (displayPin, OUTPUT);

  pinMode(chipSelect, OUTPUT);  

  if (!SD.begin(chipSelect))       // see if the card is present and can be initialized:

    Serial.println("Card init. failed!");  

  char filename[15];

  strcpy(filename, "RMCDPT00.TXT");

  for (uint8_t i = 0; i < 100; i++)

  {

    filename[6] = '0' + i/10;

    filename[7] = '0' + i%10;

    // create if does not exist, do not open existing, write, sync after write

    if (! SD.exists(filename))

    {

      break;

    }

  }

  logfile = SD.open(filename, FILE_WRITE);

 

  GPS.begin(9600);

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);  

  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);  // 5 times per second

  GPS.sendCommand(PMTK_API_SET_FIX_CTL_5HZ);    

  GPS.sendCommand(PGCMD_NOANTENNA);  

  OCR0A = 0xAF;

  TIMSK0 |= _BV(OCIE0A);        

}

 

// Interrupt is called once a millisecond

SIGNAL(TIMER0_COMPA_vect)

{

  char c = GPS.read();

  #ifdef UDR0               //USART I/O Data Register

    if (c) UDR0 = c;        

  #endif

  unsigned long currentMillis = millis();

  Update(currentMillis);  

}

 

void loop()

{  

}

 

De GPS positie en het SD Card gedeelte

Voor het ontvangen van de GPS positie en het bewaren van de data wordt een tweede Arduino gebruikt met een GPS shield erop. Hier zit een GPS ontvanger op en een SD card houder. Door een tweede microprocessor te gebruiken loopt de timing van het echolood niet in de war.

De eerste Arduino zorgt voor het aansturen van de zender en geeft de berekende diepte op het voltmetertje aan. De tweede Aduino zorgt voor het bewaren van de GPS positie en de berekende diepte op een SD kaartje.

 

Het programma voor de tweede Arduino

// 230322_shield_sdlog                Saving $GPRMC string and depth on SDcard

#include <SPI.h>

#include <Adafruit_GPS.h>

#include <SoftwareSerial.h>

#include <SD.h>

#include <avr/sleep.h>

SoftwareSerial mySerial(8, 7);

Adafruit_GPS GPS(&mySerial);

#define chipSelect 10

File logfile;

const int vSound = 1480; // m/s

 

void setup()

{

   Serial.begin(115200);

   pinMode(chipSelect, OUTPUT);

   if (!SD.begin(chipSelect)) // see if the card is present and can be initialized:

      Serial.println("Card failure"); // message via USB to serial monitor program

      char filename[15];

      strcpy(filename, "RMCDPT00.TXT"); // Automatic numbering of TXT files

      for (uint8_t i = 0; i < 100; i++)

      {

         filename[6] = '0' + i/10;

         filename[7] = '0' + i%10;

         // create if does not exist, do not open existing, write, sync after write

         if (! SD.exists(filename))

         {

           break;

         }

      }

logfile = SD.open(filename, FILE_WRITE);

GPS.begin(9600); // Baudrate GPS

GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);

GPS.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ); // 5 times a second

GPS.sendCommand(PMTK_API_SET_FIX_CTL_5HZ);

GPS.sendCommand(PGCMD_NOANTENNA);

OCR0A = 0xAF; // Output Compare Register A

TIMSK0 |= _BV(OCIE0A); // Timer/Counter Interrupt Mask Register

}

SIGNAL(TIMER0_COMPA_vect) // Interrupt is called once a millisecond.

{ // writing direct to UDR0

char c = GPS.read();

#ifdef UDR0 //USART I/O Data Register

if (c) UDR0 = c;

#endif

}

void loop()

{

   if (GPS.newNMEAreceived())

   {

      char *stringptr = GPS.lastNMEA();

      if (!GPS.parse(stringptr))

         return;

      uint8_t stringsize = strlen(stringptr);

      if (stringsize != logfile.write((uint8_t *)stringptr, stringsize))

         Serial.println("ërror");

      if (strstr(stringptr, "RMC"))

      {

         unsigned long travelTime = pulseIn(2,LOW) + 300.0;

         unsigned long depth = travelTime * vSound / 20000.0;

         logfile.println();

         logfile.print("$SDDBT,");

         logfile.println(depth); // (not NMEA standard, just DBT in cm)

         logfile.println();

         logfile.flush();

      }

   }

}

//POWERCONSUMPTION 95 - 105 mA

//(Sounder, 2 Arduino's, GPS shield and Voltmeter display)

 

Voorbeeld van van een bewaard txt bestand

$GPRMC,102659.000,A,5254.2002,N,00537.5766,E,0.43,222.76,030917,,,D*6F

$SDDBT,64 // Dit is niet de NMEA 0183 standaard Depth Below Transducer Sentence Format

                     // maar cm. (nauwkeuriger dan de standaard in meters met 1 decimaal)

$GPRMC,102700.000,A,5254.2002,N,00537.5765,E,1.07,226.13,030917,,,D*67

$SDDBT,65
$GPRMC,102701.000,A,5254.1998,N,00537.5761,E,1.01,224.19,030917,,,D*65

$SDDBT,67

$GPRMC,102702.000,A,5254.1995,N,00537.5758,E,1.28,218.16,030917,,,D*6A

$SDDBT,63
$GPRMC,102703.000,A,5254.1992,N,00537.5754,E,1.33,217.97,030917,,,D*6C

$SDDBT,49
$GPRMC,102704.000,A,5254.1987,N,00537.5750,E,1.40,213.54,030917,,,D*64

$SDDBT,46

en zo verder....

De 150 kHz transducer voor gebruik in een Europe dinghy. De stok en kabel worden van buiten af in de voorzijde van de zwaardkast naar boven getrokken. Hierdoor komt de transducer met fairing block, vóór het zwaard, tegen de romp te liggen. Bij de geregistreerde diepte moet in deze positie 28 cm opgeteld worden om de waterdiepte DBS (Depth below Surface) te krijgen. Het echolood kan, in een netje gehangen tegen het voorschot., door de zeiler bediend en afgelezen worden. Tijdens de opnames moet uiteraard niet te schuin gezeild worden

Gebruik op een SUP Board

Dezelfde transducer op een nylon blok gemonteerd samen met een vin. Dit geheel schuift in de rail aan de onder/achter zijde van het SUP board. Bij de geregistreerde diepte wordt 5 cm geteld om de waterdiepte vanaf het oppervlak (SDDBS) te krijgen

Waterdiepte 't Hop (Slotermeer Friesland) en omgeving

Voorbeeld: Oude opnames van 2017 geprojecteerd op de betonnings situatie van begin 2023. (De verdwenen gerapporteerde meerboei mb7 is in mei 2023 weer teruggelegd.)

 

Jeroen Droogh                                                                                                                  bootprojecten@gmail.com