Question about data logging with Arduino and Ping2

Hi!

I’m seeking some help with a data logging project. I am interested in using the Ping2 paired with an Adafruit data logger to measure the depth in a pond. I intend to leave the Ping2 submerged in the pond over a few weeks and see how the depth changes. The Ping2 will be attached to a floatation device on the surface and angled downwards.

I created a logging setup composed of an Arduino Uno, Adafruit data logging shield, Ping2, solar panel, and battery. However, I ran into some issues in writing code for the data logger. I receive an error in the Serial Monitor in the Arduino IDE (attached image) and nothing writes to the SD card, and I am not sure why. The Serial Monitor is supposed to display timestamped readings taken by the sensor. I have confirmed that the hardware works - I believe the error is with how I am incorporating taking data from the sensor and recording it with the data logger in my code, specifically pertaining to baud rate. I didn’t get any issues when compiling.

I have attached photos of my setup, error message in the Arduino IDE, and code. If anyone has any advice or guidance that would be very much appreciated. Thank you for your time!

#include "ping1d.h"
#include "SoftwareSerial.h"
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

// A simple data logger for the Arduino analog pins

// Pin definitions and initialization
static const uint8_t arduinoRxPin = 8; // white
static const uint8_t arduinoTxPin = 9; // green
SoftwareSerial pingSerial(arduinoRxPin, arduinoTxPin);
static Ping1D ping { pingSerial };

// how many milliseconds between grabbing data and logging it. 1000 ms is once a second
#define LOG_INTERVAL  1000 // mills between entries (reduce to take more/faster data)

// how many milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
// the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 1000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()

#define ECHO_TO_SERIAL   1 // echo data to serial port
#define WAIT_TO_START    0 // Wait for serial input in setup()

// the digital pins that connect to the LEDs
#define redLEDpin 2
#define greenLEDpin 3

RTC_PCF8523 RTC; // define the Real Time Clock object

// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;

// the logging file
File logfile;

void error(char *str) {
  Serial.print("error: ");
  Serial.println(str);
  
  // red LED indicates error
  digitalWrite(redLEDpin, HIGH);

  while (1);
}

void setup(void) {
  Serial.begin(9600);
  Serial.println();
  
  // use debugging LEDs
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);
  
#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif // WAIT_TO_START

  // initialize the SD card
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
  }
  Serial.println("card initialized.");
  
  // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (!SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
  
  if (!logfile) {
    error("couldn't create file");
  }
  
  Serial.print("Logging to: ");
  Serial.println(filename);

  // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println("RTC failed");
#endif  // ECHO_TO_SERIAL
  }
  
  logfile.println("millis,stamp,datetime,distance,confidence");    
#if ECHO_TO_SERIAL
  Serial.println("millis,stamp,datetime,distance,confidence");
#endif // ECHO_TO_SERIAL

  // Initialize Ping2 device with the correct baud rate
  pingSerial.begin(115200); // Set SoftwareSerial to 115200 baud for Ping2
  Serial.println("Initializing Ping2 device...");
  while (!ping.initialize()) {
    Serial.println("Ping device failed to initialize!");
    delay(2000);
  }
  Serial.println("Ping2 initialized successfully.");
}

void loop(void) {
  DateTime now;

  // delay for the amount of time we want between readings
  delay((LOG_INTERVAL - 1) - (millis() % LOG_INTERVAL));
  
  digitalWrite(greenLEDpin, HIGH);
  
  // log milliseconds since starting
  uint32_t m = millis();
  logfile.print(m);           // milliseconds since start
  logfile.print(", ");    
#if ECHO_TO_SERIAL
  Serial.print(m);         // milliseconds since start
  Serial.print(", ");  
#endif

  // fetch the time
  now = RTC.now();
  // log time
  logfile.print(now.unixtime()); // seconds since 1/1/1970
  logfile.print(", ");
  logfile.print('"');
  logfile.print(now.year(), DEC);
  logfile.print("/");
  logfile.print(now.month(), DEC);
  logfile.print("/");
  logfile.print(now.day(), DEC);
  logfile.print(" ");
  logfile.print(now.hour(), DEC);
  logfile.print(":");
  logfile.print(now.minute(), DEC);
  logfile.print(":");
  logfile.print(now.second(), DEC);
  logfile.print('"');
#if ECHO_TO_SERIAL
  Serial.print(now.unixtime()); // seconds since 1/1/1970
  Serial.print(", ");
  Serial.print('"');
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);
  Serial.print('"');
#endif // ECHO_TO_SERIAL

  if (ping.update()) {
    int distance = ping.distance();
    int confidence = ping.confidence();

    logfile.print(", ");
    logfile.print(distance);
    logfile.print(", ");
    logfile.print(confidence);
#if ECHO_TO_SERIAL
    Serial.print(", ");
    Serial.print(distance);
    Serial.print(", ");
    Serial.print(confidence);
#endif // ECHO_TO_SERIAL
  }
  
  logfile.println();
#if ECHO_TO_SERIAL
  Serial.println();
#endif // ECHO_TO_SERIAL

  digitalWrite(greenLEDpin, LOW);

  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  
  // blink LED to show we are syncing data to the card & updating FAT!
  digitalWrite(redLEDpin, HIGH);
  logfile.flush();
  digitalWrite(redLEDpin, LOW);
}

Hi @cl6767 -
I’d recommend starting out with Arduino code for each function, testing it, and moving on when you get the expected result. You could also try the provided Arduino sketch to verify the hardware is working with your Arduino Uno.

Hi @cl6767, welcome to the forum :slight_smile:

I haven’t looked into the hardware you’re using, but in case it’s relevant it’s possible for different Arduino libraries to have a timer conflict if they try to use the same hardware timer for different purposes.

As @tony-white mentioned, testing functionalities one at a time (unit testing) is a useful way of building up confidence together with your implementation, and if you determine that your features work correctly independently then testing them together (integration testing) will help to determine whether the feature implementations are clashing with each other.

Hi @tony-white and @EliotBR -
I appreciate both of your responses. After playing around with the project some more, I believe that the conflict was with SoftwareSerial (for the Ping2) and SD.h that I am using for the Adafruit data logger. Whenever I include both libraries the program seems to bug out.

The solution for me was to switch to the Teensy platform (the 4.1 also has a micro SD module so there was no need for a shield). Everything works perfectly fine now!

1 Like