Bathymetry Measuring Apparatus

A mega will certainly do the job, but generally, NMEA emitting devices use a fairly slow baud rate and GPS is usually only one update a second, so an Uno will probably do fine using soft serial.

Also- I bought a gps unit that simply has a six strand harness coming out. I was wondering the best way to connect this to the arduino. Do I cut off the harness, trim the wires, and run them through a breadboard? Do I need to just go ahead and get a gps shield? Is there some kind of adapter?

Mine looks like this minus the circuit board under the gps chip. Just the chip and the small wiring harness coming out of it:

http://www.ladyada.net/make/gpsshield/gpstest.html

I have no problem buying a gps logging shield if that would make this project easier, but I do need to record the transducer reading at the same time the gps records a position.

This sounds really interesting did you manage to get it working?

Seems like a neat project. How are you measuring the depth to the ocean floor? You mentioned a transducer, but what kind -- an off-the-shelf product? I'm guessing a sonar-based method

I've been distracted by other research but now I've got some time to make some progress. I'm such a noob that this stuff is like learning a new language. I've been reading a few books on sketching to get it going.
Equipment list:
-Airmar Transducer: off the shelf, basically a piezo-electric sensor that pings and receives. Sound travels ~1560 m/s through water depending on temperature, 2 way travel time between the ping and reception of the ping will then be used to calculate depth in meters. I plan on using an adaptation of the "Ping" sketch to operate the depth sounder.
-Arduino: Controlling and computing
-EM406 GPS: Location reference
-SD Card Shield: Data logging

The hardest part is getting the GPS to log the location and the Transducer to log the depth simultaneously in one file on the SD card.

My Sparkfun package arrives this weekend with the missing prototyping components. I'll be sure to post if I get things pinging.

Any tips/suggestions are always a appreciated. I did get a Arduino Mega as suggested btw.

I've basically gotta combine the following sketches:

This guy used this sketch to take accelerometer readings at GPS coordinates. I want to do the same thing, but instead take depth readings at GPS coordinates by calculating the two way travel time measured by a transducer

// ====================== START PROGRAM ==========================
/*

PROJECT: Bump-O-Meter (Geo Data Logger for Sensors )

DEVELOPER:  Hazim Bitar (techbitar at gmail dot com)

DESCRIPTION:  This program reads the ADXL335 accelerometer sensor data (X,Y,Z)  or any
sensor data then saves   this data to an SD card along with geo-location and a date/time stamp
generated by the LS20031 GPS receiver

LICENSE:      I am placing this code in the public domain

DATE:         NOV 16, 2012

*/

#include 
#define LED 8           // status LED for SD operations
#define BUFF_MAX 100   // size of GPS & SD buffers

File GPSlog;

void setup()
{
  Serial.begin(4800); // The LS20031 GPS receiver must be set to 4800 for program to work

  // You can use the statements below to send configuration commands to the LS20031 GPS.
  // But for this to work, the baud rate must be set on the LS20031 GPS receiver to 4800.
  // You can use the MiniGPS 1.4 utility to configure or query the LS20031 GPS receiver.
  //
  // LS20031 COMMANDS:
  // Serial.print("$PMTK251,4800*27\r\n");  // Set GPS baud rate
  // Serial.print("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2C\r\n"); // Set RMC to 5 fixes/second. 
  // Serial.print("$PMTK220,200*2C\r\n");  // GPS update rate at 5Hz
 
  pinMode(10, OUTPUT);   // Per SD library notes, pin 10 must be set to output
  pinMode(LED, OUTPUT);

  if (!SD.begin(4)) {        // SD card detected?
    digitalWrite(LED,LOW);   // turn off status LED if SD detection fails
    return;
  }
  else   digitalWrite(LED, HIGH); // turn on LED if SD detection is OK

  GPSlog = SD.open("GPS.log", O_CREAT | O_WRITE);  // open/append to a file GPS.log
  if (!GPSlog) {               // test if file can be opened
    digitalWrite(LED,LOW);     // turn off status LED if file open fails
    return;
  }
  else digitalWrite(LED, HIGH);  // turn on status LED if file open is OK
}

void loop()
{
  char inBuffer[BUFF_MAX];    // buffer used to read NMEA lines from GPS
  byte outBuffer[BUFF_MAX];   // buffer used to write NMEA lines to SD card
  int sizeBuffer = 0;        // counter of how many chars per line

// HERE WE DECLARE MORE OR LESS ANALOG SENSOR VARIABLES
  char an0[4], an1[4], an2[4];  // char variables to store analog pin values. Total 6 pins from 0-5

  while (Serial.available()>0)  // if serial data available from GPS
  {         
    sizeBuffer = Serial.readBytesUntil('\n', inBuffer, BUFF_MAX);  // read one NMEA line from GPS until end of line

//  THIS IS WHERE WE READ SENSOR VALUES
    itoa (analogRead(A0),  an0, 10);    // X read and convert numeric analog pin to char
    itoa (analogRead(A1),  an1, 10);    // Y  ..
    itoa (analogRead(A2),  an2, 10);    // Z  ..
    for (int i = 0; i < BUFF_MAX; i++) outBuffer[i] = inBuffer[i];   // create CSV file on SD 
    int j = 0;

    // THIS IS WHERE WE WRITE SENSOR DATA TO THE SD FILE
    if (GPSlog) {
      GPSlog.print(an0);    // write ANALOG0 (X) to SD
      GPSlog.print(" , ");      
      GPSlog.print(an1);    // write ANALOG1 (Y) to SD     
      GPSlog.print(" , ");      
      GPSlog.print(an2);    // write ANALOG2 (Z) to SD
      GPSlog.print(" , ");     
      // If you only want NMEA output logged, comment out all above GPSlog.print statements
      GPSlog.write(outBuffer, sizeBuffer);  // write GPS NMEA output to SD
      GPSlog.print("\r\n");     
      GPSlog.flush();
      digitalWrite(LED, HIGH);  // Keep LED on so long as SD logging is working.
    }
    else {
      // if the file didn't open, turn LED off
      digitalWrite(LED, LOW);  // turn LED off if writing to file fails
    }
  }
}
// ================ END PROGRAM =====================

For the transducer, I need to use a sketch similar to the following, and work it into the sketch above.

/*  This code initializes a Ping))) sensor on pin 13 and
outputs the information over a serial connection */
#include <Ping.h>
 
Ping ping = Ping(13,0,0);
 
void setup(){
  Serial.begin(115200);
}
 
void loop(){
  ping.fire();
  Serial.print("Microseconds: ");
  Serial.print(ping.microseconds());
  Serial.print(" | Inches ");
  Serial.print(ping.inches());
  Serial.print(" | Centimeters: ");
  Serial.print(ping.centimeters());
  Serial.println();
  delay(1000);
}

Easy enough. Once I get my stuff this weekend I'll agonize over it some more.

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

  char an0[4], an1[4], an2[4];  // char variables to store analog pin values. Total 6 pins from 0-5

What does that comment have to do with the code? The arrays are too small. The values being stored in the arrays can range from 0 to 1023. With the terminating NULL, that's 5 characters.

I've basically gotta combine the following sketches:

So, basically, what's the problem?

The GPS logger logs data as fast as the GPS spits out a complete sentence. Log the ping data at the same rate.

I have not had an opportunity to really tinker with it yet. I've been involved in other research (geoscientist) and haven't had time to commit other than background research. I hope to make some progress this weekend.

These are just two sketches I pulled off the web to give me a starting point. But any suggestions you have will be appreciated. You stated my plan exactly: make the ping(transducer) sample at the same rate as the GPS. And then I need that data to go into the CSV file with the GPS data. So at a point, the GPS read (X,Y), the ping simultaneously read Z, and the point was saved as (X,Y,Z) on the SD card. This is really basic stuff for any electronics hobbyist I'm sure. I'm trying to learn.

And I do not know what the code concerning the analog inputs is all about. I don't plan on using analog inputs for this project. That guy ran his accelerometer through an analog input, and his GPS through a serial. I was actually wondering if I should run the ping through a separate serial port. I have a mega if that is the case.

I was actually wondering if I should run the ping through a separate serial port.

The GPS is a serial device. The ping sensor is not. Perhaps that will influence your decision.

Yeah after reading a few sketches with similar sensors I was thinking that. But it shows my ignorance. Thanks for confirming and thanks for following up instead of leaving me here lost.

Hi

It's a cool project you have here, i'm looking forward to hear how it goes.
I'm a noob myself, still tinkering with blinking LED's and motors.

I just have a thought regarding the issue logging the data simultaneously.
The question might more be to the guys following the thread with some more experience.

Would it be possible to take a time stamp from the GPS NMEA sentence and stamp the transducer data with it? then you would have a latency from the equipment.
Many GPS systems can output more than one sentence at once (GGA, GGL, ZDA(time and data as i recall), ect.)
I'm sure it will involve some advanced programming if its possible.

Just putting it out there :slight_smile:

This guy has done something very similar to my project:

http://letsmakerobots.com/node/21098

He gives his sketches but they are way different than what I have been putting together. I asked him about the logging data simultaneously problem and he kinda shrugged it off like it wasn't really as big of a deal as I made it out to be.

You can argue that it really depends on what the collected data is used for, if its just for fun or you actually have to use the data for serious purposes.
I have been working with Multibeam echosounders for a couple of years, here the latency of all instruments is of high importance, but here you also have gyro and motion sensor, so if one sensor is off by a second the result bad.

What rate does the transducer send data with compared to the GPS?

It might be worth to think about the accuracy of your GPS, compared to your speed, and the transducer "latency" during logging.
If the GPS has an accuracy of a few meters or more, how much do you gain in data quality from a correct logging time?
I must note, i dont know what systems you are using, so you might have far better accuracy if you are using an argumentation system.
see GPS.gov: GPS Accuracy

Hi all,

strange coincidence - I am working on exactly the same problem.

I am using a GPS module that transmits NMEA 0183 and is mounted on a data logger shield

http://www.ladyada.net/make/gpsshield/

I can get this to work no problem with the code "supplied" with the unit - SD-Basic-GPS-logger/SD_GPSLogger.pde at master · adafruit/SD-Basic-GPS-logger · GitHub. I am using an UNO so am using softwareserial for communication.

I also have a depth sounder that transmits NMEA 0183 data - a Garmin Intelliducer. I can connect it to the arduino and with a very slight modification of the gps program (get it to look for the appropriate NMEA string for depth instead of gps) I can log the data from the depth sounder. I did have to run the output of the depth transducer through an inverter but that was no big deal.

So, I then thought to define two softwareserial ports, one for gps and one for depth and alternately poll them. I have tried many iterations and versions of this but basically cannot get two softwareserial ports to alternate reliably.

Any clever folks out there with a solution? Will share all code once we get it working nicely

Thanks,

Peter

From the documentation for SoftwareSerial.listen:

Only one software serial port can listen at a time; data that arrives for other ports will be discarded. Any data already received is discarded during the call to listen() (unless the given instance is already listening).

Could this be your problem? If not, it's time to post your code.

Hi,

i have messed around with the port.listen() to no avail.

Code

I started with a working program that read on a single port and logged the data to a SD card. I did the following.

Anticipating I would need a few functions to get the gps and depth data, I

  1. declared a void function getgps() and moved all the code from the original program that read and logged the gps data to that function
  2. called the function getups() from the main program

I run this and and it works just fine - logs the gps data

Wanting to make sure I could read the depth sounder ok I
3) connected the depth sounder to the pin the gps had been connected to
4) modified getgps to look for a NMEA depth string instead of a gps string
5) run this and it works just fine - logs the depth data

So, thinking if I declare two software serial ports, I will be good to go, I create a void function getdepth() which is identical to get gps except it looks for a depth NMEA string and it looks on a different serial port. I also modify getgps() so it is looking for GPS data again.

To create the second serial port i do the following

#if ARDUINO >= 100
 SoftwareSerial gpsSerial =  SoftwareSerial(2, 3);
 SoftwareSerial depthSerial =  SoftwareSerial(7, 8); // add a port for the depth sounder
#else
 NewSoftSerial gpsSerial =  NewSoftSerial(2, 3);
 NewSoftSerial depthSerial =  NewSoftSerial(7, 8);  // add a port for the depth sounder
#endif

// Set the GPSRATE to the baud rate of the GPS module. Most are 4800
// but some are 38400 or other. Check the datasheet!

#define GPSRATE 4800
#define DEPTHRATE 4800  // added this for the depth sounder

a little farther along we "start" the serial ports

gpsSerial.begin(GPSRATE);
 depthSerial.begin(DEPTHRATE);

and then in the main loop we call the void functions

getgps();
getdepth();

When I run this program I only get depth data

If I switch the order of the begin statements to

 depthSerial.begin(DEPTHRATE);
 gpsSerial.begin(GPSRATE);

I only get gps data.

I tried adding listen commands as follows

gpsSerial.listen();
getgps();
depthSerial.listen();
getdepth();

I get mostly nothing but occasionally I get an error message from wither getgps or getdepth that is related to a checksum failure or a buffersize problem.

If I tell it to wait after I start listening like this

gpsSerial.listen();
delay(10000);
getgps();
depthSerial.listen();
delay(10000);
getdepth();

i get nothing at all

pretty much stumped. appreciate any help!

Full code attached. Please note that for testing purposes, I am using two gps modules as my depth sounder is attached to the boat which is a little tricky to get in to the lab.

Peter

SD_GPSlogger_modified.ino (5.24 KB)

Without the two key routines it's hard to say what's wrong. Do they share any buffer to accumulate NMEA sentences?

Below is the one routine

the other is identical except it calls depthserial in stead of gps serial and it looks for the appropriate NMEA string.

buffer is global and used by both...

p

void getgps() {
  
  char c;
  uint8_t sum;

Serial.println("getgps");

  // read one 'line'
  if (gpsSerial.available()) {
    c = gpsSerial.read();
#if ARDUINO >= 100
    //Serial.write(c);
#else
    //Serial.print(c, BYTE);
#endif
    if (bufferidx == 0) {
      while (c != '

)
        c = gpsSerial.read(); // wait till we get a $
    }
    buffer[bufferidx] = c;

#if ARDUINO >= 100
    //Serial.write(c);
#else
    //Serial.print(c, BYTE);
#endif
    if (c == '\n') {
      //putstring_nl("EOL");
      //Serial.print(buffer);
      buffer[bufferidx+1] = 0; // terminate it

if (buffer[bufferidx-4] != '') {
        // no checksum?
        Serial.print("g
");
        bufferidx = 0;
        return;
      }
      // get checksum
      sum = parseHex(buffer[bufferidx-3]) * 16;
      sum += parseHex(buffer[bufferidx-2]);

// check checksum
      for (i=1; i < (bufferidx-4); i++) {
        sum ^= buffer[i];
      }
      if (sum != 0) {
        //putstring_nl("Cxsum mismatch");
        Serial.print("g~");
        bufferidx = 0;
        return;
      }
      // got good data!

gotGPRMC = strstr(buffer, "GPRMC");
      if (gotGPRMC) {
        // find out if we got a fix
        char *p = buffer;
        p = strchr(p, ',')+1;
        p = strchr(p, ',')+1;      // skip to 3rd item
       
        if (p[0] == 'V') {
          digitalWrite(led1Pin, LOW);
          fix = false;
        } else {
          digitalWrite(led1Pin, HIGH);
          fix = true;
        }
      }
      if (LOG_RMC_FIXONLY) {
        if (!fix) {
          Serial.print('_');
          bufferidx = 0;
          return;
        }
      }
      // rad. lets log it!
     
      Serial.print(buffer);    //first, write it to the serial monitor
      Serial.print('#');
     
      if (gotGPRMC)      //If we have a GPRMC string
      {
        // Bill Greiman - need to write bufferidx + 1 bytes to getCR/LF
        bufferidx++;

digitalWrite(led2Pin, HIGH);      // Turn on LED 2 (indicates write to SD)

logfile.write((uint8_t ) buffer, bufferidx);    //write the string to the SD file
        logfile.flush();
        /

        if( != bufferidx) {
          putstring_nl("can't write!");
          error(4);
        }
        */

digitalWrite(led2Pin, LOW);    //turn off LED2 (write to SD is finished)

bufferidx = 0;    //reset buffer pointer

if (fix) {  //(don't sleep if there's no fix)
         
          if ((TURNOFFGPS) && (SLEEPDELAY)) {      // turn off GPS module?
         
            digitalWrite(powerPin, HIGH);  //turn off GPS

delay(100);  //wait for serial monitor write to finish
            sleep_sec(SLEEPDELAY);  //turn off CPU
 
            digitalWrite(powerPin, LOW);  //turn on GPS
          } //if (TURNOFFGPS)
       
        } //if (fix)
       
        return;
      }//if (gotGPRMC)
     
    }
    bufferidx++;
    if (bufferidx == BUFFSIZE-1) {
      Serial.print("g!");
      bufferidx = 0;
    }
  } else {

}
 
 
 
 
}

Hi,

declared separate buffers for the two routines- no change

p

That getgps routine is designed to be called multiple times in the course of reading a gps sentence. It builds up the string in the buffer until it sees a end of line and then parses it. The problem is that as you are switching between soft serial ports, there is opportunity to miss data. You need to restructure this so that you listen on one serial port until you have a complete sentence ($ to '\n') and then you can parse it. Then switch to the other serial port and repeat.