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.
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:
Non-blocking Timing: Replaces delay(1000) with a millis()-based approach.
State-based Execution: Ensures sensor updates and SD writes happen asynchronously.
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
Replaces delay(1000) with millis():
Prevents blocking the loop, making it responsive.
Allows other tasks to run asynchronously.
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.
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!
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
}