Arduino library for WTV020-SD-16P audio module

HazardsMind:
You may need to change #include <Wprogram.h> to #include <Arduino.h> in the .h and/or .cpp file. To do this you will need a text editor like notepad or notepad++, save it then recompile sketch.

Another thing I've found to work is to Select All and Copy the sketch then start a new sketch in the newer IDE and Paste to that. There may still be some editing needed, of course.

Not saying that's wrong to do, but some of the older sketches don't know to look for either Wprogram.h or Arduino.h, some are just set for Wprogram.h.

I always check anyways.

Start a new sketch, it will already include the files that match the IDE version. Paste in the old sketch as a text copy from clipboard. Debug. Repeat until no bugs. There will be differences and one or more might or might not matter. Usually simple sketches just run the same for me.

You can #include <Arduino.h> // just to be sure whichever way you load the sketch

To what extent does the compiler not include unused functions, etc? IIRC if you only use one function in <string.h> then the rest don't get compiled. If nothing calls <Wprogram.h> then it won't be in the final image.

Hey guys, maybe someone here can help.

I'm using an arduino pro mini. I have everything wired, and I'm getting sound, however I'm getting some funky behavior. Right after it plays a sound, it locks up. (I'm using the example from buildcircuits.com... btw, their schematic has the grounds in the wrong place on the bottom of their breadboard). When I play a sound, the whole thing locks up.

I tried isolating it to a subroutine, and setup up println to debug it all:

void PlayVoiceOne() {
        Serial.println("amp on start ");
        digitalWrite(AMPpin, HIGH);
        delay(1000);
        Serial.println("amp on complete ");
        //delay(50);
        Serial.println("play start");
        wtv020sd16p.playVoice(1);
       // this is where it locks up
        Serial.println("play done");
        //delay(100);
        //wtv020sd16p.stopVoice();
        Serial.println("amp off start");
        digitalWrite(AMPpin, LOW);
        Serial.println("amp off end");
}

Eventually it releases the process, but it even interrupts the void loop(), but I can't figure out why it is freezing. I have the latest version of the library. Any thoughts or ideas would be appreciated. BTW, i'm using the PAM8803 amp inline with this.

~Doc

The sound to play only plays during the delay period then you tell it to stop:

 wtv020sd16p.playVoice(1);
       // this is where it locks up
        Serial.println("play done");
        //delay(100);
        //wtv020sd16p.stopVoice();

100 milliseconds is extremely short of a time. :wink:

Those lines are commented out. The delay was only in there from something else i was trying out. You can ignore them.

Even with that being so you are turning off the amp pin immediately after you start the sound.
You will need a delay to play the sound before turning the amp pin low.
Post the whole code so to see what is happening in full.

I think you're confusing playVoice with asyncPlayVoice. ~~ I appreciate your insight tho, I thought of that already, including giving it a few ms to clear... But I've tried quite a few different delays, and ideas, which is why i'm coming here for advice. ~~
~~I can skip the amp completely, and it still locks up. I'm also using some of the different .wav and .ad4 files from onesky's other post. ~~

Okay, I understand what you were talking about. If i'm not using the library, and I'm just using straight serial commands, then what you're saying makes perfect sense, whereas the library kind of takes care of that for me. I have abandoned the library, and i'm just using the straight serial commands to make this work. Everything seems to be working as expected.

Sorry 'bout that. I just had to do some more reading. Now the best part is to read up on file formats, and trying to get them to work with this chip.

~D

elac:
The sound to play only plays during the delay period then you tell it to stop:

 wtv020sd16p.playVoice(1);

// this is where it locks up
       Serial.println("play done");
       //delay(100);
       //wtv020sd16p.stopVoice();



100 milliseconds is extremely short of a time. ;)

1,600,000 cycles Arduino time.

@ GoForSmoke I guess 100 milliseconds is a while in cycles.
Don't blink you'll miss it!
Wikipedia:

The average length of a blink is 100-400 milliseconds.

@JustDoc Could you post your whole code?
We can only help by what info you give.
With the code you posted

void PlayVoiceOne() {
        Serial.println("amp on start ");
        digitalWrite(AMPpin, HIGH);
        delay(1000);
        Serial.println("amp on complete ");
        //delay(50);
        Serial.println("play start");
        wtv020sd16p.playVoice(1);
       // this is where it locks up
        Serial.println("play done");
        //delay(100);
        //wtv020sd16p.stopVoice();
        Serial.println("amp off start");
        digitalWrite(AMPpin, LOW);
        Serial.println("amp off end");
}

The problem LOOKS to be that you are shutting the amp off as soon as the sound starts.
But you say it "locks up" even without the amp.
Explain a bit better what you mean by "locks up".
You said

Right after it plays a sound, it locks up.

Does it completely play the sound? Or just start to?
If it plays a bit then "locks up" maybe you should read this:
http://forum.arduino.cc/index.php?topic=115411.0
Scroll down to where fungus talks about supplying 3.6v to the module.
Here is a schematic showing how to get the 3.6v:
http://forum.arduino.cc/index.php?action=dlattach;topic=115411.0;attach=42690;image
How are you wired up? Can you show a pic of the connections?
Did you connect it like shown in the second post of this thread?
Aside from your //comments which would lead to error and the fact that you are turning the amp off immediately after the sound starts your function looks ok.
How are you wired up? Can you show a pic of the connections?

edit:Also try this:

void PlayVoiceOne() {
        Serial.println("amp on start ");
        digitalWrite(AMPpin, HIGH);
        delay(1000);
        Serial.println("amp on complete ");
        Serial.println("play start");
       wtv020sd16p.playVoice(0); // Added this
       wtv020sd16p.asyncPlayVoice(1);
       // this is where it locks up
        Serial.println("play done");
        Serial.println("amp off start");
        digitalWrite(AMPpin, LOW);
        Serial.println("amp off end");
}

This sketch plays track 1 start through finish for me I just tried it:

#include <Wtv020sd16p.h>

int resetPin = 2;  // The pin number of the reset pin.
int clockPin = 3;  // The pin number of the clock pin.
int dataPin = 4;  // The pin number of the data pin.

/*
Create an instance of the Wtv020sd16p class.
 1st parameter: Reset pin number.
 2nd parameter: Clock pin number.
 3rd parameter: Data pin number.
 */
Wtv020sd16p wtv020sd16p(resetPin,clockPin,dataPin,busyPin);

void setup() {
  //Initializes the module.
  wtv020sd16p.reset();
  delay(100); // needed after reset
  wtv020sd16p.playVoice(0);
  //Plays asynchronously an audio file.
  wtv020sd16p.asyncPlayVoice(1);
}

void loop() {
// Nothing here
}

Elac,

Sorry, I kinda scrapped everything yesterday and started over from scratch. I completely understand what you are talking about now. What was happening is this, When I said it would 'lock up' I meant that it would play the sound, and then it would 'hang' for a very long time. (I put LED indicators before each one of the commands as well as serial print to kinda debug it). The code has a lot of other stuff in there, most of it crap that I was playing with, and I kind of made the decision if i was going to clean all of the junk code and comments out of it, I might as well start over from scratch.

~Doc

Ok, sometimes a fresh start is the best.
Good luck.

I have a problem with this library the way it is written:

void Wtv020sd16p::sendCommand(unsigned int command) {
  //Start bit Low level pulse.
  digitalWrite(_clockPin, LOW);
  delay(2);
  for (unsigned int mask = 0x8000; mask > 0; mask >>= 1) {
    //Clock low level pulse.
    digitalWrite(_clockPin, LOW);
    delayMicroseconds(50);
    //Write data setup.
    if (command & mask) {
      digitalWrite(_dataPin, HIGH);
    }
    else {
      digitalWrite(_dataPin, LOW);
    }
    //Write data hold.
    delayMicroseconds(50);
    //Clock high level pulse.
    digitalWrite(_clockPin, HIGH);
    delayMicroseconds(100);

   //HERE IS MY PROBLEM
    if (mask>0x0001){
      //Stop bit high level pulse.
      delay(2);      
    }


  }
  //Busy active high from last data bit latch.
  delay(20);
}

Won't mask be > 0x0001 for all 16 loops? Won't it delay 2ms + 100us for every pulse to the chip?

Also the data sheet shows the busy line drooping low when the voice goes high. Why is the library looping while busy is high and waiting for busy to go low in the playVoice routine?

void Wtv020sd16p::playVoice(int voiceNumber){  
  sendCommand(voiceNumber);
  _busyPinState=digitalRead(_busyPin);
  while(_busyPinState==HIGH){
    _busyPinState=digitalRead(_busyPin);
  }
}

ljbeng:
I have a problem with this library the way it is written:

  for (unsigned int mask = 0x8000; mask > 0; mask >>= 1) {

Won't mask be > 0x0001 for all 16 loops?

It will start at 0x8000 (high bit set) and work down one bit per loop.
Things like this you can test in a sketch that only has code in setup() to test the one thing you want to see.

It's not the most efficient code with those delays. Do you want to rewrite it?

I see that but look at the last few lines before the for loop is repeated....

    delayMicroseconds(100);

   //HERE IS MY PROBLEM
    if (mask>0x0001){
      //Stop bit high level pulse.
      delay(2);      
    }

the delay(2) will be executed on each loop.

I did have to rewrite this code... in assembly (for an older product with an obsolete ISD chip) . I only call the delay(2) on the last loop when mask==0x0001...(but in assembly)

;*******Clocks in commands to the sparkfun wave player
clockcmmd	setb		a3
		setb		pdisd
		clrb		a4
		mov		temp3,#2		;wait 2ms
		call		waitms
		mov		count,#8
:rrh		clrb		a4
		call		wait50us		;50 us delay
		movb		a3,commandh.7	
		call		wait50us		;50 us delay
		setb		a4					
		call		wait50us		;50 us delay
		call		wait50us		;50 us delay
		rl		commandh
		djnz		count,:rrh
		mov		count,#8
:rrl		clrb		a4
		call		wait50us		;50 us delay
		movb		a3,commandl.7	
		call		wait50us		;50 us delay
		setb		a4					
		call		wait50us		;50 us delay
		call		wait50us		;50 us delay
		rl		commandl
		djnz		count,:rrl
		setb		a3
		mov		temp3,#2		;wait 2ms
		call		waitms
		ret

RL, is that rotate left? I thought it was ROL or RCL (rotate left with carry)
Do you have a complete ASM cheat sheet?

Edited:
Never mind, RL is rotate accumulator left.

ljbeng:
I see that but look at the last few lines before the for loop is repeated....

    delayMicroseconds(100);

//HERE IS MY PROBLEM
    if (mask>0x0001){
      //Stop bit high level pulse.
      delay(2);     
    }




the delay(2) will be executed on each loop.

I don't know what this hardware needs but to do the same as your assembly for a different chip example only needs the
if (mask>0x0001){
to be
if (mask == 0x0001){

The comment says it's for a stop bit so maybe check where stop bits are needed?

It would be nicer if instead of delays the library let go of the code and pick back up when the time was right but that would be a Major Rewrite rather than a small tweak.

If I have only one PlayVoice() call in my script .. I hear nothing .. The Example works without voice Play (0) ..

Can i use Play Voice (0); Play Voice (1) Play Voice (2);

I thought to play voice wait until the song is finished.

Has the library the ability to play wav-files ?