Troubleshooting Combined SD Card Functionality with Arduino Uno

TL;DR: When testing my code, writing an audio file to an SD card and writing a CSV file to an SD card individually both work. However, when I combine the two functions, it doesn't work. I suspect that the SD card may still be open or writing something when I try to record the audio.

Hi there,

I'm facing an issue with my code that involves multiple functionalities. Here's what I'm trying to achieve: I have a program that displays three questions on an LCD display. The user answers these questions using a keypad. The three answers, along with a timestamp, sensor data (temperature and pressure), are then saved to an SD card in the form of a CSV file. Afterward, a relay is activated, and I want to record sound using a MAX9814 board for two seconds and save it to the SD card.

Here's the problem: when I test the code separately for writing the CSV file to the SD card and recording audio, both functionalities work fine. However, when I combine them together, it doesn't work as expected. I suspect that the SD card may still be open or in the middle of a write operation when I try to record the audio.

I'm using an Arduino Uno with a micro SD card adapter, and the SD card I'm using has a capacity of 32GB. The sensor data is obtained from a BMP280.

I would greatly appreciate any help in identifying the cause of this issue. Thank you in advance!

#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SPI.h>


// LCD Setup
LiquidCrystal_I2C lcd(0x27, 16, 2);  // Set the LCD I2C address and dimensions
// Microphone pin
const int micPin = A3;

// Recording duration
const unsigned long recordingDuration = 2000; // 2 seconds

File audioFile;

// Keypad Setup
const byte ROWS = 4; // Number of rows
const byte COLS = 4; // Number of columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {3, 2, 1, 0};   // Connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4};   // Connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// Relay Setup
const int relayPin = 8;

// SD Card Setup
const int chipSelect = 10;  // Set the chip select pin for the SD card module

// BME280 Sensor Setup
Adafruit_BME280 bme;

// Global Variables
int questionNumber = 1;
String answer1 = "";
String answer2 = "";
String answer3 = "";

// RVK Function
void RVK() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("recording");
  lcd.setCursor(0, 1);
  lcd.print("RVK NIACS");
  delay(2000);  // Display "RVK" for 2 seconds
}

// Function to display the question on the LCD
void displayQuestion(const char* question, int startPos, int endPos) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(question);
  lcd.setCursor(startPos, 0);

  // Clear the previous answer
  lcd.print("  "); // Print two spaces to clear the answer field

  lcd.setCursor(0, 1);
  lcd.print("NIACS");
}

void recordAndSaveAudio() {
  // Create a new audio file
  audioFile = SD.open("recording.wav", FILE_WRITE);
  if (!audioFile) {
    Serial.println("Error creating audio file!");
    while (1);
  }

  // Start recording
  unsigned long startTime = millis();
  unsigned long elapsedTime;

  while (1) {
    // Calculate elapsed time
    elapsedTime = millis() - startTime;

    // Check if recording duration is reached
    if (elapsedTime >= recordingDuration) {
      // Close the audio file
      audioFile.close();

      Serial.println("Recording finished!");
      break;
    }

    // Read audio sample from the microphone
    int sample = analogRead(micPin);

    // Write the audio sample to the SD card
    audioFile.write(sample & 0xFF);          // Write the lower 8 bits
    audioFile.write((sample >> 8) & 0xFF);   // Write the upper 8 bits
  }
  

}

// Function to save the data to the SD card
void saveData(const char* filename, const String& answer1, const String& answer2, const String& answer3, float temperature, float humidity, float pressure) {
  File dataFile = SD.open(filename, FILE_WRITE);  // Open the file in write mode
  if (dataFile) {
    unsigned long currentMillis = millis();  // Get the current timestamp
    dataFile.print(currentMillis);
    dataFile.print(",");
    dataFile.print(answer1);
    dataFile.print(",");
    dataFile.print(answer2);
    dataFile.print(",");
    dataFile.print(answer3);
    dataFile.print(",");
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.println(pressure);
    dataFile.close();  // Close the file
  } else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Error1 saving file!");
    delay(2000);  // Display error message for 2 seconds
  }
 
}

void setup() {
  Serial.begin(9600); // Initialize the serial communication

  lcd.begin(16, 2);
  lcd.backlight();

  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);

  // Initialize the SD card
  if (!SD.begin(chipSelect)) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SD Card initialization failed!");
    delay(2000);  // Display error message for 2 seconds
    while (1);  // Stop the program
  }

  // Initialize the BME280 sensor
  if (!bme.begin(0x76)) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("BME280 initialization failed!");
    delay(2000);  // Display error message for 2 seconds
    while (1);  // Stop the program
  }
}

void loop() {
  char key = keypad.getKey();

  switch (questionNumber) {
    case 1:
      displayQuestion("Cannister?: ______", 11, 18);
      break;
    case 2:
      displayQuestion("Row?: ______", 5, 12);
      break;
    case 3:
      displayQuestion("Level?: ______", 7, 14);
      break;
    default:
      break;
  }

  if (key) {
    if (key == '#') {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Answer received!");
      delay(1000);  // Display answer received message for 1 second

      questionNumber++;

      if (questionNumber > 3) {
        
        questionNumber = 1;  // Reset the question number for the next iteration

        lcd.clear();

        // Read BME280 sensor data
        float temperature = bme.readTemperature();
        float humidity = bme.readHumidity();
        float pressure = bme.readPressure() / 100.0; // Convert pressure to hPa

        // Save data to CSV file
        char filename[] = "data.csv";
        if (!SD.exists(filename)) {
          // If the file doesn't exist, create it and write the header
          File dataFile = SD.open(filename, FILE_WRITE);
          if (dataFile) {
            dataFile.println("timestamp,cannister,row,level,temperature,humidity,pressure");
            dataFile.close();  // Close the file
          } else {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Error creating file!");
            delay(2000);  // Display error message for 2 seconds
          }
        }

        // Save the data to the file
        saveData(filename, answer1, answer2, answer3, temperature, humidity, pressure);

        // Reset the answer variables
        answer1 = "";
        answer2 = "";
        answer3 = "";
        
        delay(2000); // wait to make sure we are done saving
        digitalWrite(relayPin, HIGH);  // Activate the relay
        delay(50); // Activation time of the relay
        digitalWrite(relayPin, LOW);  // Deactivate the relay
        recordAndSaveAudio();
        delay(2000);
        RVK();  // Call the RVK function
      }
    } else if (isdigit(key) || key == '.') {
      if (questionNumber == 1) {
        if (answer1.length() < 2) {
          answer1 += key;
        } else {
          answer1[0] = answer1[1];
          answer1[1] = key;
        }

        lcd.setCursor(11, 0);
        lcd.print(answer1);
      } else if (questionNumber == 2) {
        if (answer2.length() < 2) {
          answer2 += key;
        } else {
          answer2[0] = answer2[1];
          answer2[1] = key;
        }

        lcd.setCursor(11, 0);
        lcd.print(answer2);
      } else if (questionNumber == 3) {
        if (answer3.length() < 2) {
          answer3 += key;
        } else {
          answer3[0] = answer3[1];
          answer3[1] = key;
        }

        lcd.setCursor(11, 0);
        lcd.print(answer3);
      }

      delay(200);  // Delay to display the pressed digit
    }
  }
}

I read only the TLDR - but I think On a UNO you probably don’t have enough memory to have two files open at the same time. (512 bytes buffer for each file). Ensure you close a file before opening the next one (your saveData function opens the file but does not close it)

hey i tried working with you suggestion, but they are already closed in the original code. i even tried to have the variables be local in their respective functions to save on the buffer size. but it still wont work

#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SPI.h>

// LCD Setup
LiquidCrystal_I2C lcd(0x27, 16, 2);  // Set the LCD I2C address and dimensions
// Microphone pin
const int micPin = A3;

// Recording duration
const unsigned long recordingDuration = 2000; // 2 seconds

// Keypad Setup
const byte ROWS = 4; // Number of rows
const byte COLS = 4; // Number of columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {3, 2, 1, 0};   // Connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4};   // Connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// Relay Setup
const int relayPin = 8;

// SD Card Setup
const int chipSelect = 10;  // Set the chip select pin for the SD card module

// BME280 Sensor Setup
Adafruit_BME280 bme;

// Global Variables
int questionNumber = 1;
String answer1 = "";
String answer2 = "";
String answer3 = "";

// RVK Function
void RVK() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("recording");
  lcd.setCursor(0, 1);
  lcd.print("RVK NIACS");
  delay(2000);  // Display "RVK" for 2 seconds
}

// Function to display the question on the LCD
void displayQuestion(const char* question, int startPos, int endPos) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(question);
  lcd.setCursor(startPos, 0);

  // Clear the previous answer
  lcd.print("  "); // Print two spaces to clear the answer field

  lcd.setCursor(0, 1);
  lcd.print("NIACS");
}

void recordAndSaveAudio() {
  // Create a new audio file
  File audioFile = SD.open("recording.wav", FILE_WRITE);
  if (!audioFile) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Error creating audio file!");
    delay(2000);  // Display error message for 2 seconds
    return;
  }

  // Start recording
  unsigned long startTime = millis();
  unsigned long elapsedTime;

  while (1) {
    // Calculate elapsed time
    elapsedTime = millis() - startTime;

    // Check if recording duration is reached
    if (elapsedTime >= recordingDuration) {
      // Close the audio file
      audioFile.close();

      Serial.println("Recording finished!");
      break;
    }

    // Read audio sample from the microphone
    int sample = analogRead(micPin);

    // Write the audio sample to the SD card
    audioFile.write(sample & 0xFF);          // Write the lower 8 bits
    audioFile.write((sample >> 8) & 0xFF);   // Write the upper 8 bits
  }
}

// Function to save the data to the SD card
void saveData(const char* filename, const String& answer1, const String& answer2, const String& answer3, float temperature, float humidity, float pressure) {
  // Open the file in write mode
  File dataFile = SD.open(filename, FILE_WRITE);
  if (dataFile) {
    unsigned long currentMillis = millis();  // Get the current timestamp
    dataFile.print(currentMillis);
    dataFile.print(",");
    dataFile.print(answer1);
    dataFile.print(",");
    dataFile.print(answer2);
    dataFile.print(",");
    dataFile.print(answer3);
    dataFile.print(",");
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.println(pressure);
    dataFile.close();  // Close the file
  } else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Error saving file!");
    delay(2000);  // Display error message for 2 seconds
  }
}

void setup() {
  Serial.begin(9600); // Initialize the serial communication

  lcd.begin(16, 2);
  lcd.backlight();

  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);

  // Initialize the SD card
  if (!SD.begin(chipSelect)) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SD Card initialization failed!");
    delay(2000);  // Display error message for 2 seconds
    while (1);  // Stop the program
  }

  // Initialize the BME280 sensor
  if (!bme.begin(0x76)) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("BME280 initialization failed!");
    delay(2000);  // Display error message for 2 seconds
    while (1);  // Stop the program
  }
}

void loop() {
  char key = keypad.getKey();

  switch (questionNumber) {
    case 1:
      displayQuestion("Cannister?: ______", 11, 18);
      break;
    case 2:
      displayQuestion("Row?: ______", 5, 12);
      break;
    case 3:
      displayQuestion("Level?: ______", 7, 14);
      break;
    default:
      break;
  }

  if (key) {
    if (key == '#') {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Answer received!");
      delay(1000);  // Display answer received message for 1 second

      questionNumber++;

      if (questionNumber > 3) {
        questionNumber = 1;  // Reset the question number for the next iteration

        lcd.clear();

        // Read BME280 sensor data
        float temperature = bme.readTemperature();
        float humidity = bme.readHumidity();
        float pressure = bme.readPressure() / 100.0; // Convert pressure to hPa

        // Save data to CSV file
        char filename[] = "data.csv";
        if (!SD.exists(filename)) {
          // If the file doesn't exist, create it and write the header
          File dataFile = SD.open(filename, FILE_WRITE);
          if (dataFile) {
            dataFile.println("timestamp,cannister,row,level,temperature,humidity,pressure");
            dataFile.close();  // Close the file
          } else {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Error creating file!");
            delay(2000);  // Display error message for 2 seconds
          }
        }

        // Save the data to the file
        saveData(filename, answer1, answer2, answer3, temperature, humidity, pressure);

        // Reset the answer variables
        answer1 = "";
        answer2 = "";
        answer3 = "";
        
        delay(2000); // wait to make sure we are done saving
        digitalWrite(relayPin, HIGH);  // Activate the relay
        delay(50); // Activation time of the relay
        digitalWrite(relayPin, LOW);  // Deactivate the relay
        recordAndSaveAudio();
        delay(2000);
        RVK();  // Call the RVK function
      }
    } else if (isdigit(key) || key == '.') {
      if (questionNumber == 1) {
        if (answer1.length() < 2) {
          answer1 += key;
        } else {
          answer1[0] = answer1[1];
          answer1[1] = key;
        }

        lcd.setCursor(11, 0);
        lcd.print(answer1);
      } else if (questionNumber == 2) {
        if (answer2.length() < 2) {
          answer2 += key;
        } else {
          answer2[0] = answer2[1];
          answer2[1] = key;
        }

        lcd.setCursor(11, 0);
        lcd.print(answer2);
      } else if (questionNumber == 3) {
        if (answer3.length() < 2) {
          answer3 += key;
        } else {
          answer3[0] = answer3[1];
          answer3[1] = key;
        }

        lcd.setCursor(11, 0);
        lcd.print(answer3);
      }

      delay(200);  // Delay to display the pressed digit
    }
  }
}

when you compile with all warnings enabled, what do you see at the end of the compilation when it tells you about the program size and SRAM used ?

so i did reduce the programm size to see if that did anything and found that the problem has to do with both functions writing to the sd card.

to recap. I have some simple code that prompts you with three questions and expects three answers. These answers, along with some sensor data, are stored in a CSV file on the SD card. Additionally, a relay is activated and audio is recorded, which also needs to be saved to the SD card.

The problem arises when both saving functions are combined in a single code. An error message stating 'Error saving file!' occurs. Interestingly, this error occurs when the CSV file is being created, even though the audio file hasn't been generated yet. It's puzzling why the CSV writing function, which worked perfectly fine in a separate code, is now causing issues. It seems to fail during the call to the CSV writing function, even before the second file operation is performed.

I attempted to initialize and open the SD card in each function separately, ensuring that it is closed before the other function is called. I even tried creating a new instance for the second operation, but unfortunately, these attempts had no effect on resolving the issue.

Furthermore, when both functions are present in the code and only the CSV writing function is called, the code works without any issues. However, when both functions are included in the code and both are called, the execution stops at the first function.

here is the simplified code now writing to a serial monitor.

#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SD.h>
#include <TMRpcm.h>

// BME280 Sensor Setup
Adafruit_BME280 bme;

// Global Variables
int questionNumber = 1;
String answer1 = "";
String answer2 = "";
String answer3 = "";

// Relay Setup
const int relayPin = 8;
const int mic_pin = A3;
const int sample_rate = 16000;
TMRpcm audio;
int file_number = 0;
bool recording_now = false;

// Function to save the data to the SD card
void saveData(const char* filename, const String& answer1, const String& answer2, const String& answer3, float temperature, float humidity, float pressure) {
  // Initialize the SD card
  if (!SD.begin(10)) {
    Serial.println("SD Card initialization failed!");
    while (1);  // Stop the program
  }

  // Open the file in write mode
  File dataFile = SD.open(filename, FILE_WRITE);
  if (dataFile) {
    unsigned long currentMillis = millis();  // Get the current timestamp
    dataFile.print(currentMillis);
    dataFile.print(",");
    dataFile.print(answer1);
    dataFile.print(",");
    dataFile.print(answer2);
    dataFile.print(",");
    dataFile.print(answer3);
    dataFile.print(",");
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.println(pressure);
    dataFile.close();  // Close the file
  } else {
    Serial.println("Error saving file!");
    delay(2000);  // Display error message for 2 seconds
  }

  // Close the SD card connection
  SD.end();
}

void start_recording() {
  // Opens the SD card
  if (SD.begin(10)) {
    // Combines the necessary info to get a char array of the file name
    char file_nam[20] = "hellothere";
    itoa(file_number, file_nam, 10);
    strcat(file_nam, ".wav");

    // Starts recording and turns LED on
    recording_now = true;
    
    audio.CSPin = 10;
    audio.startRecording(file_nam, sample_rate, mic_pin);
    Serial.println(file_nam);

    // Stops recording after 10 seconds
    delay(10000);
    audio.stopRecording(file_nam);
    file_number++;
    recording_now = false;
    

    // Closes the SD card
    SD.end();
  }
}

void setup() {
  Serial.begin(9600); // Initialize the serial communication

  pinMode(mic_pin, INPUT);
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);

  // Initialize the BME280 sensor
  if (!bme.begin(0x76)) {
    Serial.println("BME280 initialization failed!");
    while (1);  // Stop the program
  }
}

void loop() {
  if (questionNumber == 1) {
    Serial.println("Enter Cannister:");
  } else if (questionNumber == 2) {
    Serial.println("Enter Row:");
  } else if (questionNumber == 3) {
    Serial.println("Enter Level:");
  }

  while (Serial.available() == 0) {
    // Wait for input from the Serial Monitor
  }

  char key = Serial.read();
  if (key == '#') {
    questionNumber++;
    if (questionNumber > 3) {
      questionNumber = 1;  // Reset the question number for the next iteration

      // Read BME280 sensor data
      float temperature = bme.readTemperature();
      float humidity = bme.readHumidity();
      float pressure = bme.readPressure() / 100.0; // Convert pressure to hPa

      // Save data to CSV file
      char filename[] = "data.csv";
      saveData(filename, answer1, answer2, answer3, temperature, humidity, pressure);

      // Reset the answer variables
      answer1 = "";
      answer2 = "";
      answer3 = "";

      digitalWrite(relayPin, HIGH);  // Activate the relay
      delay(50); // Activation time of the relay
      digitalWrite(relayPin, LOW);  // Deactivate the relay
      delay(2000);
      
      //start_recording();
      //RVK();  // Call the RVK function
    }
  } else if (isdigit(key) || key == '.') {
    if (questionNumber == 1) {
      answer1 += key;
    } else if (questionNumber == 2) {
      answer2 += key;
    } else if (questionNumber == 3) {
      answer3 += key;
    }
  }
}

when compiling this is the memory usage
Sketch uses 25312 bytes (78%) of program storage space. Maximum is 32256 bytes.
Global variables use 1626 bytes (79%) of dynamic memory, leaving 422 bytes for local variables. Maximum is 2048 bytes.

i have now comment out the calling or activation of the ' start_recording' function.

you have SD.begin(10); multiple times. Just have it once in the setup and loose the SD.end() calls

this might end up being a long file name. may be stick to 8.3

    char file_nam[20] = "hellothere";
    itoa(file_number, file_nam, 10);
    strcat(file_nam, ".wav");

the TMRpcm library mentions using sdFat which is a better version than the SD library

they mention also

Audio recording is still being tested and may not perform as expected.

Can you share the output of the compiler (in code tags)? do you get warnings?

i had the sd begin in the setup before and it made no difference, but the saving recoding worked perfectly fine with this library when tested in a stand alone set-up. only when combined with the other saving command , it starts giving problems.

how does it compile?

this is all that follws from the compiling

In file included from C:\Users\user\Documents\Arduino\libraries\TMRpcm/TMRpcm.h:14:0,
                 from C:\Users\user\AppData\Local\Temp\.arduinoIDE-unsaved2023530-18732-5z9rdw.h9cvg\sketch_jun30d\sketch_jun30d.ino:4:
C:\Users\user\Documents\Arduino\libraries\TMRpcm/pcmConfig.h:48:4: warning: "/*" within comment [-Wcomment]
    /* Use the SDFAT library from http://code.google.com/p/sdfatlib/            */
     
C:\Users\user\Documents\Arduino\libraries\SD\src\SD.cpp: In function 'open.constprop':
C:\Users\user\Documents\Arduino\libraries\SD\src\SD.cpp:462:14: warning: 'pathidx' may be used uninitialized in this function [-Wmaybe-uninitialized]
     filepath += pathidx;
              ^
C:\Users\user\Documents\Arduino\libraries\SD\src\SD.cpp:456:9: note: 'pathidx' was declared here
     int pathidx;
         ^
Sketch uses 25312 bytes (78%) of program storage space. Maximum is 32256 bytes.
Global variables use 1626 bytes (79%) of dynamic memory, leaving 422 bytes for local variables. Maximum is 2048 bytes.

I tried to compile for a UNO and got

'class TMRpcm' has no member named 'startRecording'

yeah you have to do somthing in the config file to get the startRecording working on a uno,

this is the video that explains it class TMRpcm' has no member named 'startRecording' error, arduino uno, nano and lower - YouTube

also if you want to advance with the question you have to enter a number in the serial monit from 1-99 and # after the number, then it will go to the next question

i solved it, i do not know what the problem was but i got it to work for by flipping the order. first doing the audio recording then doing the csv write

#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SD.h>
#include <TMRpcm.h>

// BME280 Sensor Setup
Adafruit_BME280 bme;

// Global Variables
int questionNumber = 1;
String answer1 = "";
String answer2 = "";
String answer3 = "";

// Relay Setup
const int relayPin = 8;
const int mic_pin = A3;
const int sample_rate = 16000;
TMRpcm audio;
int file_number = 0;
bool recording_now = false;

// Function to save the data to the SD card
void saveData(const char* filename, const String& answer1, const String& answer2, const String& answer3, float temperature, float humidity, float pressure) {
  // Initialize the SD card
  if (!SD.begin(10)) {
    Serial.println("SD Card initialization failed!");
    while (1);  // Stop the program
  }

  // Open the file in write mode
  File dataFile = SD.open(filename, FILE_WRITE);
  if (dataFile) {
    unsigned long currentMillis = millis();  // Get the current timestamp
    dataFile.print(currentMillis);
    dataFile.print(",");
    dataFile.print(answer1);
    dataFile.print(",");
    dataFile.print(answer2);
    dataFile.print(",");
    dataFile.print(answer3);
    dataFile.print(",");
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.println(pressure);
    dataFile.close();  // Close the file
  } else {
    Serial.println("Error saving file!");
    delay(2000);  // Display error message for 2 seconds
  }

  // Close the SD card connection
  SD.end();
}

void start_recording() {
  // Opens the SD card
  if (SD.begin(10)) {
    // Combines the necessary info to get a char array of the file name
    char file_nam[20] = "hellothere";
    itoa(file_number, file_nam, 10);
    strcat(file_nam, ".wav");

    // Starts recording and turns LED on
    recording_now = true;
    
    audio.CSPin = 10;
    audio.startRecording(file_nam, sample_rate, mic_pin);
    Serial.println(file_nam);

    // Stops recording after 10 seconds
    delay(2000);
    audio.stopRecording(file_nam);
    file_number++;
    recording_now = false;
    

    // Closes the SD card
    SD.end();
  }
}

void setup() {
  Serial.begin(9600); // Initialize the serial communication

  pinMode(mic_pin, INPUT);
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);

  // Initialize the BME280 sensor
  if (!bme.begin(0x76)) {
    Serial.println("BME280 initialization failed!");
    while (1);  // Stop the program
  }
}

void loop() {
  if (questionNumber == 1) {
    Serial.println("Enter Cannister:");
  } else if (questionNumber == 2) {
    Serial.println("Enter Row:");
  } else if (questionNumber == 3) {
    Serial.println("Enter Level:");
  }

  while (Serial.available() == 0) {
    // Wait for input from the Serial Monitor
  }

  char key = Serial.read();
  if (key == '#') {
    questionNumber++;
    if (questionNumber > 3) {

      digitalWrite(relayPin, HIGH);  // Activate the relay
      delay(50); // Activation time of the relay
      digitalWrite(relayPin, LOW);  // Deactivate the relay
      
      start_recording();
      questionNumber = 1;  // Reset the question number for the next iteration

      delay(2000);
      // Read BME280 sensor data
      float temperature = bme.readTemperature();
      float humidity = bme.readHumidity();
      float pressure = bme.readPressure() / 100.0; // Convert pressure to hPa

      // Save data to CSV file
      char filename[] = "data.csv";
      saveData(filename, answer1, answer2, answer3, temperature, humidity, pressure);

      // Reset the answer variables
      answer1 = "";
      answer2 = "";
      answer3 = "";

      
      
      //RVK();  // Call the RVK function
    }
  } else if (isdigit(key) || key == '.') {
    if (questionNumber == 1) {
      answer1 += key;
    } else if (questionNumber == 2) {
      answer2 += key;
    } else if (questionNumber == 3) {
      answer3 += key;
    }
  }
}

OK - the magic world of libraries...