|
|
View previous topic :: View next topic |
Author |
Message |
ThanhDan
Joined: 07 Jun 2022 Posts: 19
|
DFPlayer using PIC16F887 |
Posted: Mon Jun 13, 2022 5:35 am |
|
|
Hi, I'm using PIC16F887 to play music with DFplayer, I could make the DFplayer play short mp3 of length 5 seconds or so by setting delay_ms(5000) but for a full song I would have to, theoretically, set the delay time to match its length... which is not working too well for me. I have to wait exactly the amount of delay time I set before the DFplayer starts and it doesn't even deliver a full song. Here's my code, please give me guidance.
Code: |
#include <16f887.h>
#use delay(clock = 8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,DISABLE_INTS)
#fuses INTRC_IO,NOWDT,NOMCLR,PROTECT,PUT,NOCPD,NOWRT,NOCPD,NOIESO,NOFCMEN,NOBROWNOUT
unsigned int8 send_buf[10];
void send_data(unsigned int8 cmd, unsigned int8 feedback, unsigned int16 data);
void init();
void main(){
init();
send_data(0x06,0,6);
while(true)
{
send_data(0x08,0,1);
delay_ms(5000);
}
}
void init(){
setup_oscillator(OSC_8MHZ);
}
void send_data(unsigned int8 cmd, unsigned int8 feedback, unsigned int16 data){
unsigned int8 i;
unsigned int16 n;
send_buf[0] = 0x7E;
send_buf[1] = 0xFF;
send_buf[2] = 0x06;
send_buf[3] = cmd;
send_buf[4] = feedback;
send_buf[5] = (unsigned int8)(data >> 8);
send_buf[6] = (unsigned int8)(data);
n = 0;
for(i = 1; i <= 6; i ++){
n += send_buf[i];
};
n = - n;
send_buf[7] = (unsigned int8)(n >> 8);
send_buf[8] = (unsigned int8)(n);
send_buf[9] = 0xEF;
for(i = 0; i < 10; i ++){
printf("%c",send_buf[i]);
};
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19508
|
|
Posted: Mon Jun 13, 2022 6:01 am |
|
|
Don't pause.
Poll the unit.
There is an output pin 'Busy', that tells you when the unit is busy!. Wire
this to your PIC, and wait for this to go off.
It goes low when the unit is playing. By far the easiest way.
You can do it in software. The read_status command could be sent every
1/10th second (say), and the value this returns changes when the track
has finished.
Quote: |
Returned Data Status
7E FF 06 42 00 01 01 xx xx EF - A track in USB flash drive is being played
7E FF 06 42 00 02 02 xx xx EF - A track in SD card is paused playing
7E FF 06 42 00 01 00 xx xx EF - A track in USB flash drive is stopped playing
7E FF 06 42 00 10 00 xx xx EF - Module in sleep
|
Busy is easier.
Is this a DFPlayer, or the 'mini'?.
I know the mini automatically sends:
7E FF 06 3C 00 00 yy xx xx EF, where 'yy' is the track number, when it
finishes playing the track, so this can be used to know when this happens.
The data sheet says:
Quote: |
3.3.2 .Returned Data of Track Finished Playing
U-Disk finish playback 1st track 7E FF 06 3C 00 00 01 xx xx EF
U-Disk finish playback 2nd track 7E FF 06 3C 00 00 02 xx xx EF
TF card finish playback 1st track 7E FF 06 3D 00 00 01 xx xx EF
TF card finish playback 2nd track 7E FF 06 3D 00 00 02 xx xx EF
Flash finish playback 1st track 7E FF 06 3E 00 00 01 xx xx EF
Flash finish playback 2nd track 7E FF 06 3E 00 00 02 xx xx EF
|
So I think both units do this. They say you should wait 100mSec after
this is received before asking it to play another track. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Mon Jun 13, 2022 7:35 am |
|
|
quick look..
Add 'ERRORS' to the USE RS232 'options'....
Delete 'Protect' to the fuses...
Add comments at end of lines of code. costs nothing, helps in debugging, like the line n= - n; , which looks really 'weird' to me...... |
|
|
ThanhDan
Joined: 07 Jun 2022 Posts: 19
|
|
Posted: Mon Jun 13, 2022 10:59 am |
|
|
Ttelmah wrote: | Don't pause.
Poll the unit.
There is an output pin 'Busy', that tells you when the unit is busy!. Wire
this to your PIC, and wait for this to go off.
It goes low when the unit is playing. By far the easiest way.
You can do it in software. The read_status command could be sent every
1/10th second (say), and the value this returns changes when the track
has finished.
Quote: |
Returned Data Status
7E FF 06 42 00 01 01 xx xx EF - A track in USB flash drive is being played
7E FF 06 42 00 02 02 xx xx EF - A track in SD card is paused playing
7E FF 06 42 00 01 00 xx xx EF - A track in USB flash drive is stopped playing
7E FF 06 42 00 10 00 xx xx EF - Module in sleep
|
Busy is easier.
Is this a DFPlayer, or the 'mini'?.
I know the mini automatically sends:
7E FF 06 3C 00 00 yy xx xx EF, where 'yy' is the track number, when it
finishes playing the track, so this can be used to know when this happens.
The data sheet says:
Quote: |
3.3.2 .Returned Data of Track Finished Playing
U-Disk finish playback 1st track 7E FF 06 3C 00 00 01 xx xx EF
U-Disk finish playback 2nd track 7E FF 06 3C 00 00 02 xx xx EF
TF card finish playback 1st track 7E FF 06 3D 00 00 01 xx xx EF
TF card finish playback 2nd track 7E FF 06 3D 00 00 02 xx xx EF
Flash finish playback 1st track 7E FF 06 3E 00 00 01 xx xx EF
Flash finish playback 2nd track 7E FF 06 3E 00 00 02 xx xx EF
|
So I think both units do this. They say you should wait 100mSec after
this is received before asking it to play another track. |
Yeah I am using the mini, but for my application, I only need it to play 1 song, as simple as that. How is using the "busy pin" going to help if it sends only information on when the track has already finished playing. I get how it helps with the transition between songs but I only need to play one.
I think my problem lies in void send_data |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19508
|
|
Posted: Mon Jun 13, 2022 11:16 am |
|
|
It can't take another command, till it has finished the one that is playing
So just wait for the line to go high, before you next call the send_data
command. |
|
|
ThanhDan
Joined: 07 Jun 2022 Posts: 19
|
|
Posted: Mon Jun 13, 2022 11:47 am |
|
|
Ttelmah wrote: | It can't take another command, till it has finished the one that is playing
So just wait for the line to go high, before you next call the send_data
command. |
Thanks for your rapid response, Yes I understand that "the line" (pin 16/ busy pin) going high means that the DFplayer is free, it has finished playing the previous track but my DFplayer doesn't even play anything and the busy pin never went low. This is my revised code, I checked with the pdf to build this code, please have a look, it's quite simple.
Code: |
#include <16f887.h>
#use delay(clock = 8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,DISABLE_INTS)
#fuses INTRC_IO,NOWDT,NOMCLR,PUT,NOCPD,NOWRT,NOCPD,NOIESO,NOFCMEN,NOBROWNOUT
unsigned int8 send_buf[10];
void send_data(unsigned int8 cmd, unsigned int8 feedback);
void volume(unsigned int8 cmd, unsigned int8 feedback);
void init();
void main(){
init();
volume(0x06,0);
delay_ms(5000);
send_data(0x03,0);
delay_ms(5000);
}
void init(){
setup_oscillator(OSC_8MHZ);
}
void volume(unsigned int8 cmd, unsigned int8 feedback){
unsigned int8 i;
send_buf[0] = 0x7E; // Start byte
send_buf[1] = 0xFF; // Version
send_buf[2] = 0x06; // Len
send_buf[3] = cmd; // Command, see 3.2
send_buf[4] = feedback; // Feedback, always 0 => 0
send_buf[5] = 0x00; // High byte (DH), para 1
send_buf[6] = 0x0F; // Low byte (DL), para 2
send_buf[7] = 0xFF; // checksum highbyte
send_buf[8] = 0xD5; // checksum low byte
send_buf[9] = 0xEF; // end
for(i = 0; i < 10; i ++){
printf("%c",send_buf[i]);
};
}
void send_data(unsigned int8 cmd, unsigned int8 feedback){
unsigned int8 i;
send_buf[0] = 0x7E; // Start byte
send_buf[1] = 0xFF; // Version
send_buf[2] = 0x06; // Len
send_buf[3] = cmd; // Command, see 3.2
send_buf[4] = feedback; // Feedback, always 0 => 0
send_buf[5] = 0x00; // High byte (DH), para 1
send_buf[6] = 0x01; // Low byte (DL), para 2
send_buf[7] = 0xFF; // checksum highbyte
send_buf[8] = 0xE6; // checksum low byte
send_buf[9] = 0xEF; // end
for(i = 0; i < 10; i ++){
printf("%c",send_buf[i]);
};
}
|
|
|
|
ThanhDan
Joined: 07 Jun 2022 Posts: 19
|
|
Posted: Mon Jun 13, 2022 11:51 am |
|
|
Ttelmah wrote: | It can't take another command, till it has finished the one that is playing
So just wait for the line to go high, before you next call the send_data
command. |
Hi, thanks for your rapid response. Yes, I understand that the line (busy pin, pin 16) goes high when Dfplayer has finished playing the current song and only then can I send_data to play a new song and there should be a 100ms interval between the events but my Dfplayer doesn't even play anything and the busy pin never went low. Here's my revised code I built using the DF mini pdf, please have a look, it's quite simple
Code: |
#include <16f887.h>
#use delay(clock = 8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,DISABLE_INTS)
#fuses INTRC_IO,NOWDT,NOMCLR,PUT,NOCPD,NOWRT,NOCPD,NOIESO,NOFCMEN,NOBROWNOUT
unsigned int8 send_buf[10];
void send_data(unsigned int8 cmd, unsigned int8 feedback);
void volume(unsigned int8 cmd, unsigned int8 feedback);
void init();
void main(){
init();
volume(0x06,0);
delay_ms(5000);
send_data(0x03,0);
delay_ms(5000);
}
void init(){
setup_oscillator(OSC_8MHZ);
}
void volume(unsigned int8 cmd, unsigned int8 feedback){
unsigned int8 i;
send_buf[0] = 0x7E; // Start byte
send_buf[1] = 0xFF; // Version
send_buf[2] = 0x06; // Len
send_buf[3] = cmd; // Command, see 3.2
send_buf[4] = feedback; // Feedback, always 0 => 0
send_buf[5] = 0x00; // High byte (DH), para 1
send_buf[6] = 0x0F; // Low byte (DL), para 2
send_buf[7] = 0xFF; // checksum highbyte
send_buf[8] = 0xD5; // checksum low byte
send_buf[9] = 0xEF; // end
for(i = 0; i < 10; i ++){
printf("%c",send_buf[i]);
};
}
void send_data(unsigned int8 cmd, unsigned int8 feedback){
unsigned int8 i;
send_buf[0] = 0x7E; // Start byte
send_buf[1] = 0xFF; // Version
send_buf[2] = 0x06; // Len
send_buf[3] = cmd; // Command, see 3.2
send_buf[4] = feedback; // Feedback, always 0 => 0
send_buf[5] = 0x00; // High byte (DH), para 1
send_buf[6] = 0x01; // Low byte (DL), para 2
send_buf[7] = 0xFF; // checksum highbyte
send_buf[8] = 0xE6; // checksum low byte
send_buf[9] = 0xEF; // end
for(i = 0; i < 10; i ++){
printf("%c",send_buf[i]);
};
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Mon Jun 13, 2022 11:57 am |
|
|
haven't read the MP3 datasheet but...maybe it doesn't like your 'checksums', and refuses to play ?? |
|
|
ThanhDan
Joined: 07 Jun 2022 Posts: 19
|
|
Posted: Tue Jun 14, 2022 12:19 am |
|
|
temtronic wrote: | haven't read the MP3 datasheet but...maybe it doesn't like your 'checksums', and refuses to play ?? |
Yeah it's written in the pdf how to find all other bytes and their meanings except for the checksums, I mean what are those? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Jun 14, 2022 4:46 am |
|
|
Thanks to PCM P, I read, well quickly, the datasheet.
Interesting that the device doesn't NEED the checksum !
You have 2 options.
1) use the checksum, so you have to calculate it and send 2 extra bytes.
2) do not use it. Saves calculation and sending the 2 bytes.
For now, try #2. It's easier, cleaner, faster. If it work 100 times out of 100, keep using it.
'Checksums' are a method to confirm that the data sent between devices is correct. Simple ones, like this are easy to code but can fail,depending on the data,rare though.
As stated in the manual, if using an RC 'clock' it's best to use the checksum option. However in your case the devices are next to each other and speed is slow, so I don't think you'll have problems. |
|
|
ThanhDan
Joined: 07 Jun 2022 Posts: 19
|
|
Posted: Tue Jun 14, 2022 9:34 am |
|
|
Hi, thank you all so much for helping, I succeeded, turns out I had the file name wrong (I put 001.mp3 when it should have been 0001.mp3), thanks to PCM P datasheet and temtronic's suggestion, I fixed the bugs. I checked with Proteus' virtual terminal to make sure that the UART message being sent is correct and it was so there was only one thing to fix )
You guys are pros way out of my league and probably won't need this but here's the code
Code: |
#include <16f887.h>
#use delay(clock = 8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,DISABLE_INTS)
#fuses INTRC_IO,NOWDT,NOMCLR,PUT,NOCPD,NOWRT,NOCPD,NOIESO,NOFCMEN,NOBROWNOUT
unsigned int8 send_buf[8];
void play_1(unsigned int8 cmd, unsigned int8 feedback);
void volume_max(unsigned int8 cmd, unsigned int8 feedback);
void init();
void main(){
init();
volume_max(0x06,0);
delay_ms(5000);
play_1(0x03,0);
}
void init(){
setup_oscillator(OSC_8MHZ);
}
void volume_max(unsigned int8 cmd, unsigned int8 feedback){
unsigned int8 i;
send_buf[0] = 0x7E; // Start byte
send_buf[1] = 0xFF; // Version
send_buf[2] = 0x06; // Len
send_buf[3] = cmd; // Command, see 3.2
send_buf[4] = feedback; // Feedback, always 0 => 0
send_buf[5] = 0x00; // High byte (DH), para 1
send_buf[6] = 0x1E; // Low byte (DL), para 2
//! send_buf[7] = 0xFF; // checksum highbyte
//! send_buf[8] = 0xD5; // checksum low byte
send_buf[7] = 0xEF; // end
for(i = 0; i < 8; i ++){
printf("%c",send_buf[i]);
};
}
void play_1(unsigned int8 cmd, unsigned int8 feedback){
unsigned int8 i;
send_buf[0] = 0x7E; // Start byte
send_buf[1] = 0xFF; // Version
send_buf[2] = 0x06; // Len
send_buf[3] = cmd; // Command, see 3.2
send_buf[4] = feedback; // Feedback, always 0 => 0
send_buf[5] = 0x00; // High byte (DH), para 1
send_buf[6] = 0x01; // Low byte (DL), para 2
//! send_buf[7] = 0xFF; // checksum highbyte
//! send_buf[8] = 0xE6; // checksum low byte
send_buf[7] = 0xEF; // end
for(i = 0; i < 8; i ++){
printf("%c",send_buf[i]);
};
}
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|