Go Down

Topic: Write and play audio from SD card (Read 669 times) previous topic - next topic

dpoornima

Nov 20, 2017, 04:48 pm Last Edit: Nov 20, 2017, 04:50 pm by dpoornima
Hello,

I am trying to write sensor data to sd card and while the data is being written, if the sensor data is above a particular value, I want to play an audio file which is on the sd card.
Is it possible to play the audio file while simultaneously writing data to the sd card?

Thank you!

PaulS

What hardware are you using to play the audio file? The Arduino doesn't know squat about audio files.

Proper hardware would read enough data from a file, so that you could also write to a different file, with only minimal chances of both the Arduino and the other hardware needing to read from and write to the SD card at the same time. Mostly the Arduino would write to, and the other hardware read from, buffers. Writing to the card, or reading from the card, happens only when the buffer becomes full (a write happens) or empty (a read happens).
The art of getting good answers lies in asking good questions.

dpoornima

#2
Nov 21, 2017, 06:32 pm Last Edit: Nov 21, 2017, 06:35 pm by dpoornima
Quote
What hardware are you using to play the audio file? The Arduino doesn't know squat about audio files.
I have the audio file in the sd card and using the library https://github.com/TMRh20/TMRpcm , I am able to play the audio file on a speaker which is connected to the pin 9 of arduino promini.

I was wondering if its even possible to play the audio file from the sd card ( whenever  the data point exceeds a certain value)  while continuously  writing the sensor data to the card.

PaulS

Quote
I was wondering if its even possible to play the audio file from the sd card ( whenever  the data point exceeds a certain value)  while continuously  writing the sensor data to the card.
So, that library has a file open on the SD card, using 512+ bytes of SRAM. Do you have enough SRAM to open a second file, using another 512+ bytes of SRAM?

How quickly does that library use up the 512 bytes that it reads each time? How often will you fill up the 512 byte buffer that you will be using to write to the file?

How important is it that the audio play glitch-free (that is, with no delays caused by you writing to the card when it needs to read from the card?

The only way to really know is to try it.
The art of getting good answers lies in asking good questions.

dpoornima

#4
Nov 22, 2017, 01:34 am Last Edit: Nov 22, 2017, 01:36 am by dpoornima
I tried it :

I have an audio file (31 KB) (around 2 sec) saved on the sd card. When I collect sensor data, the microcontroller creates a file "DATA00" and writes the sensor data to this file.
The audio plays just once (when the datapoint is above a value) and after playing once, the audio file gets corrupted and the data is not readable anymore.
The microcontroller writes data to the file "DATA00" every 30 ms.

I had an other question too. Can the sd card keep writing data to the DATA file while the audio is being played?
From what I noticed, its not able to do that.

Any suggestions to fix the issue?

PaulS

Quote
Any suggestions to fix the issue?
Yes, but I'll refrain unless you continue to fail to POST YOUR CODE!
The art of getting good answers lies in asking good questions.

dpoornima

Code: [Select]


#include <SPI.h>
#include <SD.h>
#include <TMRpcm.h>         
TMRpcm tmrpcm;
#define FILE_BASE_NAME "Data"
#include <Wire.h>
#include <RTClib.h>
#include <float.h>
#define DS3231_Address 0x68
#define HSCDRRN400MD2A3_I2C 0x28
#define OUTPUT_MIN 1638.4
#define OUTPUT_MAX 14745.6
#define PRESSURE_MIN -400
#define PRESSURE_MAX +400
unsigned long time;
RTC_DS3231 rtc;
int chipSelect = 10;
File file;
int BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char filename[] = FILE_BASE_NAME "00.csv";

//added button library, variables and button function
#include <Bounce2.h>
Bounce button = Bounce(); //instantiate a Bounce object

const byte LedPin = 8;
const byte ButtonPin = 7;
bool logFlag = true;//default status to enable SD writes in Loop
int count = 0;
float sensdata[3] = {0, 0, 0};
void buttonCheck()//debounced function to check if button pressed
{
  button.update();
  if (button.fell())
  {
    if (logFlag == true)
    {
      logFlag = false;
      Serial.println();
      Serial.println("Data Logging in Loop Disabled");
      Serial.println("Press Reset to Enable");
      Serial.println();
    }
  }
}

float calPressure()
{
  float pressure;
  float pressure_mmhg;

  //send a request
  Wire.beginTransmission(HSCDRRN400MD2A3_I2C);
  Wire.write(1);
  Wire.endTransmission();
  // now get the data from the sensor
  delay (5);

  Wire.requestFrom(HSCDRRN400MD2A3_I2C, 4);

  byte a     = Wire.read();
  byte b     = Wire.read();
  byte c     = Wire.read();
  byte d     = Wire.read();
  byte status1 = (a & 0xc0) >> 6;
  int bridge_data = ((a & 0x3f) << 8) + b;
  int temperature_data = ((c << 8) + (d & 0xe0)) >> 5;
  pressure = 1.0 * (bridge_data - OUTPUT_MIN) * (PRESSURE_MAX - PRESSURE_MIN) / (OUTPUT_MAX - OUTPUT_MIN) + PRESSURE_MIN;
  pressure_mmhg = 0.750062 * pressure;
 
  return pressure_mmhg;
}

void setup()
{
  Wire.begin(); // wake up I2C bus
  delay (500);
  Serial.begin(115200);
  Serial.println ("Sketch has started");

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

  pinMode(ButtonPin, INPUT_PULLUP);
  button.attach(ButtonPin);
  button.interval(20);//20 ms debounce interval

  tmrpcm.speakerPin = 9; //11 on Mega, 9 on Uno, Nano, etc

  if (rtc.lostPower())
  {
    Serial.println("RTC lost power,set the time");
    //rtc.adjust(DateTime(2017,8,21,17,10,00));
  }
  delay(10);

  if (!SD.begin(10))
  {
    Serial.println(F("begin failed"));
    return;
  }

  while (SD.exists(filename)) {
    if (filename[BASE_NAME_SIZE + 1] != '9') {
      filename[BASE_NAME_SIZE + 1]++;
    }
    else if (filename[BASE_NAME_SIZE] != '9') {
      filename[BASE_NAME_SIZE + 1] = '0';
      filename[BASE_NAME_SIZE]++;
    }
    else {
      Serial.println(F("Can't create file name"));
      return;
    }
  }
  File file = SD.open(filename, FILE_WRITE);
  digitalWrite(LedPin, HIGH);//indicate file being written
  DateTime now = rtc.now();
  file.print(now.year(), DEC);
  file.print('/');
  file.print(now.month(), DEC);
  file.print('/');
  file.print(now.day(), DEC);
  file.print(',');
  file.print(now.hour(), DEC);
  file.print(':');
  file.print(now.minute(), DEC);
  file.print(':');
  file.print(now.second(), DEC);
  file.println();
  file.print("Time( ms)");
  file.print(',');
  file.print("Presuure (mmhg)");
  file.println();
  file.close();
  digitalWrite(LedPin, LOW);//file write finished
}
void loop()
{
  float Pressure;
  float Sdiff;
  static bool calMax = false;
  static bool calMin = false;
  static float max = 0;
  static float min = 0;
  static int Maxcount = 0;
  static int presentcount = 0;
 

  if (count == 0)
  {
    sensdata[1] = calPressure();
   
    sensdata[1] = (sensdata[1] + calPressure()) / 2;
    ++count;
  }

  else
  {
    sensdata[2] = calPressure();//pressure_mmhg;

    sensdata[2] = (sensdata[2] + calPressure()) / 2;

    Pressure = sensdata[2];
    time = millis();

    if (calMax == false && (sensdata[1] > sensdata[0]) && (sensdata[1] > sensdata[2]))
    {
      calMax = true;
      max = sensdata[1];
     
    }
    else if (calMin == false && (sensdata[1] < sensdata[0]) && (sensdata[1] < sensdata[2]))
    {
      calMin = true;
      min = sensdata[1];
     
    }

    if ( calMax == true && calMin == true)
    {
      calMax = false;//enable finding of next max
      calMin = false;

      Sdiff = max - min;
     



      if (Sdiff >= 20)
      {
        ++Maxcount;
       
        Sdiff = 0;
      }

      if (Maxcount > presentcount )
      {

        if (Maxcount >= 1)
        {

          tmrpcm.play("6.wav");

          Maxcount = 0;
          presentcount++;
         
        }

      }
     
    }
    sensdata[0] = sensdata[1];
    sensdata[1] = sensdata[2];
    sensdata[2] = 0;
  }

  buttonCheck();//update logFlag

  if (logFlag)//logFlag determines write enable
  {
    File file = SD.open(filename, FILE_WRITE);
    if (file)
    {
      digitalWrite(LedPin, HIGH);//indicate file being written
      file.print(time);
      file.print(',');
      file.print(Pressure);
      file.println();
      file.close();
      digitalWrite(LedPin, LOW);//file write finished
    }
  }
}

PaulS

THAT is why I asked you to post your code. It seems that you forgot to mention that you have other devices on the I2C bus.

When I finally found the TMRpcm library, it has a readme file that points to a Wiki that says:
Quote
May interfere with other libraries that rely on interrupts
, like the Wire class.

Quote
This library can be very processor intensive
The misspelled is.
The art of getting good answers lies in asking good questions.

dpoornima

Oh! Looks like I have to figure out another way to do this!
Thank you for pointing it out.

Go Up