Go Down

Topic: Arduino library for WTV020-SD-16P audio module (Read 120079 times) previous topic - next topic

JustDoc

#165
Oct 05, 2013, 06:33 pm Last Edit: Oct 05, 2013, 06:36 pm by JustDoc Reason: 1
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:
Code: [Select]

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

There are areas where untrained people may work effectively and with limited equipment. Our pupil doesn't need a big laboratory to do this, he needs freedom; he needs encouragement.
Edwin G. Land, Polaroid Corp 1957

elac

The sound to play only plays during the delay period then you tell it to stop:
Code: [Select]
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.  ;)
It's all about the skills

JustDoc

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

There are areas where untrained people may work effectively and with limited equipment. Our pupil doesn't need a big laboratory to do this, he needs freedom; he needs encouragement.
Edwin G. Land, Polaroid Corp 1957

elac

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.
It's all about the skills

JustDoc

#169
Oct 06, 2013, 04:17 am Last Edit: Oct 06, 2013, 10:58 pm by JustDoc Reason: 1
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
There are areas where untrained people may work effectively and with limited equipment. Our pupil doesn't need a big laboratory to do this, he needs freedom; he needs encouragement.
Edwin G. Land, Polaroid Corp 1957

GoForSmoke


The sound to play only plays during the delay period then you tell it to stop:
Code: [Select]
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.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

elac

#171
Oct 06, 2013, 01:35 pm Last Edit: Oct 06, 2013, 02:28 pm by elac Reason: 1
@ GoForSmoke I guess 100 milliseconds is a while in cycles.
Don't blink you'll miss it!
Wikipedia:
Quote
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
Code: [Select]
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
Quote
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:
Code: [Select]
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:
Code: [Select]

#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
}

It's all about the skills

JustDoc

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
There are areas where untrained people may work effectively and with limited equipment. Our pupil doesn't need a big laboratory to do this, he needs freedom; he needs encouragement.
Edwin G. Land, Polaroid Corp 1957

elac

Ok, sometimes a fresh start is the best.
Good luck.
It's all about the skills

ljbeng

I have a problem with this library the way it is written:
Code: [Select]

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?

Code: [Select]

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


GoForSmoke


I have a problem with this library the way it is written:
Code: [Select]

  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?
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

ljbeng

I see that but look at the last few lines before the for loop is repeated....
Code: [Select]

    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.

ljbeng

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)

Code: [Select]

;*******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

HazardsMind

#178
Oct 12, 2013, 07:34 am Last Edit: Oct 12, 2013, 07:43 am by HazardsMind Reason: 1
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.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

GoForSmoke


I see that but look at the last few lines before the for loop is repeated....
Code: [Select]

    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.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up