SOLVED: Writing to SD card while TMRpcm is playing a .wav file causes problems

I am working on a project that reads data from a serial device and plays .WAV files based on the serial data received. I was having problems with SoftwareSerial, so I used the hardware serial port (pins 0 and 1 on the Uno) to talk to the serial device. Now I can't print debug statements to Serial any longer.

To get debug messages, I write to a log file on the SD card. However, if I try writing to the log file while a .WAV file is playing, the following bad things can happen:

  • crackling/buzzing sounds during playback
  • garbage gets written to the SD card, which can destroy the file system
  • Arduino locks up

The more I write, the sooner something bad happens.

If I don't write to the card, or if I loop until playback is finished before writing, then it works fine.

Questions:

  • Has anyone else noticed this problem?
  • Can anyone confirm that this behavior is expected based on how TMRpcm works?
  • Any suggested workarounds or fixes?

I have attached test code and a couple of sample output files. One demonstrates normal playback (makeItCrash = 0 and I let it run until I got bored), the other shows a crash where garbage was written to the disk (makeItCrash = 50). It looks like the first part of the log file has been linked to or overwritten by the first part of the .WAV file.

Thanks all!

playcrash.ino (1.68 KB)

LASERLOG.TXT (428 Bytes)

Yes you would expect this.
Why not use software serial and a TTL to USB lead for your debug.

Thanks for the reply!

Grumpy_Mike:
Yes you would expect this.

Oh good, I'm not crazy.

Can you give me a quick explanation why this happens? A pointer to the relevant documentation, for instance? It might help me figure out a fix.

Grumpy_Mike:
Why not use software serial and a TTL to USB lead for your debug.

That's on my list of things to try, but I am afraid that adding another interrupt-driven library might cause more mysterious problems.

("I'm just a caveman. Your interrupt-driven routines frighten and confuse me!")

Now that you've validated that this is a real problem, maybe I can work around it by not writing while audio is playing. I can try pausing or stopping playback, or calling TMRpcm.disable(). Which I choose depends on WHY this problem is occurring.

I just tried calling TMRpcm.pause() before and after writing to the card, and it seems to work fine (code is attached). No crashes and no noticeable effect on playback, unless I'm writing huge amounts of data. And if I am, all that happens is a brief pause of the audio.

Thoughts?

Thanks again!

playcrash.ino (1.94 KB)

Can you give me a quick explanation why this happens?

You can only access one file at a time from an SD card. So when you are writing to it you can't be reading from it. You can make it look like you are by having a big buffer to read into and then that keeps things going when you do the writing. But as the memory space is very limited in an Arduino you can't have your buffer as big as you would need to stop this from under running.

I just tried calling TMRpcm.pause() before and after writing to the card, and it seems to work fine

I think you can see from the above explanation why that is.