Ping2 and SD card module

Hello. I am trying to log depth data straight from my ping 2 (using altsoftwareserial) to an sd card using an sd card module.

I am able to get the ping to work by itself, as well as the sd card module by itself, but not together. It seems like there might be a timing conflict between softwareserial and SPI. any idea on how to get around this? I will attach my code below. Thanks.
Wiring:
Ping TX (white) - arduino pin 8
Ping RX (green) -arduino pin 9
CS-4
SCK-13
MOSI-11
MISO-12

vcc of both are connected to external 5V power supply, GND of ping, sd card module, external power supply, arduino GND all connected together.

#include <SD.h>
#include <SPI.h>
#include "ping1d.h"
#include <AltSoftSerial.h>

// AltSoftSerial for Ping1D communication (Uses pins 8 and 9 on Arduino Uno)
AltSoftSerial altSerial;  // Create AltSoftSerial object for Ping1D sensor
Ping1D ping { altSerial };

// SD card chip select pin
const int chipSelect = 4;

// File object for reading and writing
File myFile;

void setup() {
  // Start Serial communication for debugging
  Serial.begin(9600);
  Serial.println("Initializing system...");

  // Initialize SD card
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("SD card initialization failed!");
    while (1);  // Halt execution if SD card fails to initialize
  }
  Serial.println("SD card initialized!");



  // Initialize AltSoftSerial for Ping1D sensor communication
  altSerial.begin(9600);
  Serial.println("AltSoftSerial initialized!");

  // Initialize Ping1D sensor
  Serial.print("Initializing Ping1D sensor...");
  while (!ping.initialize()) {
    Serial.println("Retrying Ping1D initialization...");
    delay(2000);  // Retry every 2 seconds
  }
  Serial.println("Ping1D sensor initialized!");
}

void loop() {
  // Update Ping1D sensor data
  if (ping.update()) {
    float distance = ping.distance();  // Get distance reading
    int confidence = ping.confidence(); // Get confidence level

    // Print data to Serial Monitor
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.print(" mm, Confidence: ");
    Serial.println(confidence);
    
    // Log data to SD card
    myFile = SD.open("depthData.txt", FILE_WRITE);
    if (myFile) {
      myFile.print("Distance: ");
      myFile.print(distance);
      myFile.print(" mm, Confidence: ");
      myFile.println(confidence);
      myFile.close();  // Ensure data is saved
    } else {
      Serial.println("Error opening depthData.txt!");
    }
    
  }

  delay(1000);  // Wait 1 second before next reading
}

Hi @iribraheim26 -
Generally software serial is not a good idea. You didn’t share what microcontroller you used - generally more than one UART port is available on most modern options.

hello,
I am using an Arduino UNO R3

Hi @iribraheim26 -
The delay(1000) is likely causing some issues, as it is blocking any code execution for a whole second (this is quite a long time for a microcontroller.) Reworking your code to be “non-blocking” may help. Here is chatGPT’s suggestion.- give it a try! The print statements should make debugging easier, and my only suspicion that remains is the altsoftwareserial library itself - maybe the standard softwareserial library would work better?

Here’s a non-blocking version of your Arduino Uno R3 code that eliminates delays and blocking operations using the millis() function for timing and a state-based approach.

Key improvements:

  1. Non-blocking Timing: Replaces delay(1000) with a millis()-based approach.
  2. State-based Execution: Ensures sensor updates and SD writes happen asynchronously.
  3. Avoids SD Card Repeated Open/Close: Keeps the file open as long as possible and writes only when necessary.

Fixed Non-Blocking Code

#include <SD.h>
#include <SPI.h>
#include "ping1d.h"
#include <AltSoftSerial.h>

// AltSoftSerial for Ping1D communication (Uses pins 8 and 9 on Arduino Uno)
AltSoftSerial altSerial; // Create AltSoftSerial object for Ping1D sensor
Ping1D ping { altSerial };

// SD card chip select pin
const int chipSelect = 4;

// File object for writing to SD card
File myFile;

// Timing variables
unsigned long previousMillis = 0; 
const unsigned long interval = 1000; // Interval in milliseconds

void setup() {
    // Start Serial communication for debugging
    Serial.begin(9600);
    Serial.println("Initializing system...");

    // Initialize SD card
    Serial.print("Initializing SD card...");
    if (!SD.begin(chipSelect)) {
        Serial.println("SD card initialization failed!");
        while (1); // Halt execution if SD card fails to initialize
    }
    Serial.println("SD card initialized!");

    // Initialize AltSoftSerial for Ping1D sensor communication
    altSerial.begin(9600);
    Serial.println("AltSoftSerial initialized!");

    // Initialize Ping1D sensor
    Serial.print("Initializing Ping1D sensor...");
    while (!ping.initialize()) {
        Serial.println("Retrying Ping1D initialization...");
        delay(2000); // Retry every 2 seconds
    }
    Serial.println("Ping1D sensor initialized!");

    // Open SD file once at startup
    myFile = SD.open("depthData.txt", FILE_WRITE);
    if (!myFile) {
        Serial.println("Error opening depthData.txt!");
    } else {
        Serial.println("Logging started.");
    }
}

void loop() {
    unsigned long currentMillis = millis();

    // Check if it's time to take a new reading
    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis; // Update the timer

        // Update Ping1D sensor data
        if (ping.update()) {
            float distance = ping.distance(); // Get distance reading
            int confidence = ping.confidence(); // Get confidence level

            // Print data to Serial Monitor
            Serial.print("Distance: ");
            Serial.print(distance);
            Serial.print(" mm, Confidence: ");
            Serial.println(confidence);

            // Write data to SD card if it's open
            if (myFile) {
                myFile.print("Distance: ");
                myFile.print(distance);
                myFile.print(" mm, Confidence: ");
                myFile.println(confidence);
                myFile.flush(); // Ensure data is written to SD card
            } else {
                Serial.println("Error: SD file not open!");
            }
        }
    }
}

Key Fixes & Improvements

  1. Replaces delay(1000) with millis():

    • Prevents blocking the loop, making it responsive.
    • Allows other tasks to run asynchronously.
  2. Keeps the SD File Open:

    • Reduces wear on the SD card by avoiding frequent open()/close().
    • Uses flush() to ensure data is saved after each write.
  3. Ensures Non-Blocking Sensor Updates:

    • Uses ping.update() inside the loop without halting execution.
    • Allows the system to stay responsive.

This version ensures that your Arduino does not freeze due to delays or SD card read/write overhead. Let me know if you need further optimizations! :rocket:

Hi Tony,

thanks for your reply. Unfortunately the code did not work. It seems like the ping stops initializing the moment i try to open the sd (SD.open). I am able to initialize the ping successfully (tested with serial print lines), then successfully initialize the SD card reader (using SD.begin(chipSelect), I have also tested this using serial print lines). The code hangs at myFile= SD.open. I tried opening it in the setup too, not in the loop. This seems to be a timing/interrupt issue with the internal header source files. Thanks for your help so far

Hello! I believe I just solved the issue. Since the ping serial communication was interfering with the SPI communication of the SD card module, i changed the ping rx tx pins to the default hardware serial pins (0, 1). This seemed to fix my issue. the only caveat is that i have to remove the ping tx rx wires before i upload the code, but once its uploaded i can reattach them and it wrote continuously to my sd card until I physically removed the sd card. Here is my code :

#include <SPI.h>
#include <SD.h>
#include "ping1d.h"

const int SD_CS = 8;  // Chip Select Pin
static Ping1D ping { Serial };
File myFile;

void setup() {
    Serial.begin(9600);
    if (!SD.begin(SD_CS)) {  
        return;
    }
}

void loop() {
    if (ping.update()) {
        float distance = ping.distance();  // Get depth
        int confidence = ping.confidence();  // Get confidence level

        myFile = SD.open("log.txt", FILE_WRITE);
        if (myFile) {
            myFile.print("Depth: ");
            myFile.print(distance);
            myFile.print(" mm, Confidence: ");
            myFile.println(confidence);
            myFile.close();
        }
    }
    delay(1000);  // Wait 1 second before next reading
}
1 Like