Dfplayer help

Hi everybody,

I am trying to get a dfplayer module to work with ESPHome. It seems to be connected and programmed correctly (for example, I get log output like TF Card available when I insert one), but I cannot get it to play any audio.

However, when I manually initiate audio playback (by connecting GND to the dfplayer's IO_2 or IO_1), it does play. So this makes me think that

  • the speaker is connected correctly
  • the size and file system of my SD card is correct
  • the MP3 files have the appropriate encoding

It is connected like this (Wemos D1 Mini powered via USB, but also tried an external power source, no difference):

Wemos D1 Mini dfplayer

The relevant part of my dfplayer.yaml is at the bottom. The defined logger.log message will be displayed when I manually initiate audio playback, so I assume the ESPHome does register things correctly as well. Only initiating playback won’t work. I tried it like this

service: esphome.tester_dfplayer_play
  file: 1 #or file: 001

# ==> [13:24:21][D][dfplayer:032]: Send Command 0x3 arg 0x01
service: esphome.tester_dfplayer_play_folder
  folder: 1 #or 01 or 001
  file: 1 # or 01 or 001

# ==> [13:23:59][D][dfplayer:032]: Send Command 0xf arg 0x101

I tried the esphome.tester_dfplayer_next service as well after manually initiating playback. This does not work, either (even though there are multiple MP3 files on the SD card).

So while I cannot control the dfplayer module successfully via ESPHome, I can communicate with it via UART, as it will display message when inserting/taking out an SD card and when playback has stopped after manually initiating it.

Only using Home Assistant to play/stop/change tracks does not work. Can you please help me fix this problem? Thank you in advance for your ideas :slight_smile:

  tx_pin: D4
  rx_pin: D5
  baud_rate: 9600

      logger.log: 'done!'

  - service: dfplayer_next
      - dfplayer.play_next:
  - service: dfplayer_previous
      - dfplayer.play_previous:
  - service: dfplayer_play
      file: int
      - dfplayer.play: !lambda 'return file;'
  - service: dfplayer_play_loop
      file: int
      loop_: bool
      - dfplayer.play:
          file: !lambda 'return file;'
          loop: !lambda 'return loop_;'
  - service: dfplayer_play_folder
      folder: int
      file: int
      - dfplayer.play_folder:
          folder: !lambda 'return folder;'
          file: !lambda 'return file;'

  - service: dfplayer_play_loop_folder
      folder: int
      - dfplayer.play_folder:
          folder: !lambda 'return folder;'
          loop: true

  - service: dfplayer_set_device_tf
      - dfplayer.set_device: TF_CARD

  - service: dfplayer_set_device_usb
      - dfplayer.set_device: USB

  - service: dfplayer_set_volume
      volume: int
      - dfplayer.set_volume: !lambda 'return volume;'
  - service: dfplayer_set_eq
      preset: int
      - dfplayer.set_eq: !lambda 'return static_cast<dfplayer::EqPreset>(preset);'

  - service: dfplayer_sleep
      - dfplayer.sleep

  - service: dfplayer_reset
      - dfplayer.reset

  - service: dfplayer_start
      - dfplayer.start

  - service: dfplayer_pause
      - dfplayer.pause

  - service: dfplayer_stop
      - dfplayer.stop

  - service: dfplayer_random
      - dfplayer.random

  - service: dfplayer_volume_up
      - dfplayer.volume_up

  - service: dfplayer_volume_down
      - dfplayer.volume_down

So you have D4 connected to the pin marked RX on the dfplayer? And D5 to the pin marked TX?

I tried D4 to tx D5 to rx as well as D4 to rx and D5 to tx. Neither let me control the device.

The connections you have in your first post are not reflected in your yaml code.

I tried both variants. The yaml code I posted is the original version I am using and the connections have changed during testing.

Is it wrong to assume that the connections are correct at the moment because I receive feedback about inserting/removing the sd card? If rx and tx were connected the wrong way, I would not have gotten that log message at all…?

Sorry if the table in my initial post is incorrect, I am experimenting with this and it represented the current state, not the initial (which did match the yaml code). However, as I said, I tried both versions, and neither one worked (except that one would display the log about the sd card and the other wouldn’t - but other than that, there was no playback, skipping tracks, etc.). I thought this meant that we can rule out anything about the connection.

Let’s assume the yaml code matches the connection. How would you go from there?

I don’t know what is wrong or right with your settings, but the esphome docs indicates that the ESP pin that you put as tx_pin in the yaml code connects to the pin marked RX on the dfplayer chip.

I would try to bump up logging some more.

EDIT: sounds like you are receiving info from the dfplayer, but not able to send it. Check connections

Perhaps the pin is dead on the D1?
Try other pins

I changed pins now, no difference. Then I re-wired the entire thing, same. THEN I used different wires, and finally I used an entirely different dfplayer module (new and sealed).

I cannot change anything, not volume, not stop playback. Logs say this

[12:27:10][V][dfplayer:074]: Received message cmd: 0x3b arg 0x02
[12:27:10][I][dfplayer:087]: TF Card unloaded
[12:27:11][V][dfplayer:074]: Received message cmd: 0x3a arg 0x02
[12:27:11][I][dfplayer:081]: TF Card loaded
[12:27:26][D][dfplayer:032]: Send Command 0x6 arg 0x64
[12:27:33][D][dfplayer:032]: Send Command 0x7 arg 0x2a
[12:27:37][D][dfplayer:032]: Send Command 0x9 arg 0x02
[12:27:38][D][dfplayer:032]: Send Command 0x9 arg 0x02
[12:27:45][D][dfplayer:032]: Send Command 0x6 arg 0x04
[12:27:48][D][dfplayer:032]: Send Command 0x6 arg 0x64
[12:28:00][V][sensor:062]: 'tester Uptime': Received new state 119.117996

I don’t know if it has anything to do with it, but when I try to reset the module, I get [12:38:10][D][dfplayer:032]: Send Command 0xc arg 0000. According to it’s data sheet, the CMD for Reset Module is 0x0C (instead of 0xC, which the ESP’s log outputs). EDIT: seems like 0x0C and 0xC are the same in hex (12), so this should not matter.

Also: I still get the TF card output:

[12:27:10][V][dfplayer:074]: Received message cmd: 0x3b arg 0x02
[12:27:10][I][dfplayer:087]: TF Card unloaded
[12:27:11][V][dfplayer:074]: Received message cmd: 0x3a arg 0x02
[12:27:11][I][dfplayer:081]: TF Card loaded

However, this time I did not receive the output I expected to receive when playback would finish (according to my yaml, it’d be “Drück mal Play”:

      logger.log: 'Drück mal Play'

Weirdly, I used to get this output. I have tried different pins as well as different cables. I do get log messages one way (if connected correctly), but not the other (wired incorrectly), so I assume my wiring is correct again. Afterall, it is only 4 wires, of which only 2 carry data.

According to the data sheet, the dfplayer module supports up to 5V, so I switched 3V3 with 5V. Everything still works as before (device powers up, will play music when triggered manually, nothing when trying to control via Home Assistant service). Different commands via Home Assistant do work. For example, I have a button to manually reboot the ESPHome device - when I press it, the device will reboot (according to esphome logs tester.yaml). This will not have any impact, music is still playing while the ESP reboots.

Seems like the only thing that you haven’t changed is the D1? If you dont have another D1 maybe a different uart sensor? Uart also has a few options that you could try to change like stop_bits and parity perhaps the df module needs a certain type of input.

Also I didn’t notice which chip but there is this as well.

Thank you!

I tried parity: EVEN and parity: ODD, but just get

[08:29:55][C][dfplayer:125]: DFPlayer:
[08:29:55][E][uart:028]:   Invalid parity: Integration requested parity NONE but you have ODD!

The same thing happens when I try to change stop_bits

[08:32:42][C][dfplayer:125]: DFPlayer:
[08:32:42][E][uart:020]:   Invalid stop bits: Integration requested stop_bits 1 but you have 2!

I upped debugging and ran this

service: esphome.tester_dfplayer_play_folder
  folder: 1
  file: 1


[08:33:12][D][dfplayer:032]: Send Command 0xf arg 0x101
[08:33:12][D][uart_debug:109]: >>> 7E:FF:06:0F:01:01:01:FE:E9:EF

Nothing happens, same when I try to stop playback

[08:34:26][D][dfplayer:032]: Send Command 0x16 arg 0000
[08:34:26][D][uart_debug:109]: >>> 7E:FF:06:16:01:00:00:FE:E4:EF

Then this

service: esphome.tester_dfplayer_set_device_tf
data: {}

Will return

[08:36:42][D][dfplayer:032]: Send Command 0x9 arg 0x02
[08:36:42][D][uart_debug:109]: >>> 7E:FF:06:09:01:00:02:FE:EF:EF

So it seems like it will send, but not receive anything back. However, when I remove and re-insert the card, I get

[08:37:46][W][dfplayer:052]: Expected Version 0xFF, got 0x6
[08:37:46][D][uart_debug:109]: <<< 7E:06:27:00:20:BE:FF
[08:37:47][W][dfplayer:052]: Expected Version 0xFF, got 0x6
[08:37:47][D][uart_debug:109]: <<< 7E:06:27:00:20:BF:FF

I looked at the data sheet for the dfplayer module again and found

Communication Standard: 9600bps (check)
Data bits: 1 (is 5 by default, see below)
Checkout: none
Flow Control: none

I changed my yaml to this

  tx_pin: D4
  rx_pin: D3
  baud_rate: 9600
  # parity: ODD
  stop_bits: 2
  data_bits: 1
    direction: BOTH
    dummy_receiver: false
      bytes: 60
      - lambda: UARTDebug::log_hex(direction, bytes, ':');

When I try to run it, I get Failed config: data_bits: 1 => value must be at least 5.. According to the UART docs, it is 8 by default, so I changed it to 5 for testing. I also set dummy_receiver : true.

I get

[08:43:35][C][dfplayer:125]: DFPlayer:
[08:43:35][E][uart:024]:   Invalid number of data bits: Integration requested 8 data bits but you have 5!

Whatever command I send, it does not seem to get through.

[08:45:41][D][dfplayer:032]: Send Command 0x6 arg 0x0a
[08:45:41][D][uart_debug:109]: >>> 7E:FF:06:06:01:00:0A:FE:EA:EF
[08:45:46][D][dfplayer:032]: Send Command 0x6 arg 0x1c
[08:45:46][D][uart_debug:109]: >>> 7E:FF:06:06:01:00:1C:FE:D8:EF
[08:45:59][D][dfplayer:032]: Send Command 0xe arg 0000
[08:45:59][D][uart_debug:109]: >>> 7E:FF:06:0E:01:00:00:FE:EC:EF
[08:46:05][D][dfplayer:032]: Send Command 0xc arg 0000
[08:46:05][D][uart_debug:109]: >>> 7E:FF:06:0C:01:00:00:FE:EE:EF
[08:46:12][D][dfplayer:032]: Send Command 0xd arg 0000
[08:46:12][D][uart_debug:109]: >>> 7E:FF:06:0D:01:00:00:FE:ED:EF
[08:46:19][D][dfplayer:032]: Send Command 0x4 arg 0000
[08:46:19][D][uart_debug:109]: >>> 7E:FF:06:04:01:00:00:FE:F6:EF

Now after playback has stopped (after manually initiating it), I got this [08:48:06][D][uart_debug:109]: <<< 7E:FF:06:3D:00:00:05:FE:B9:EF:7E:FF:06:3D:00:00:05:FE:B9:EF.

Finally I put a resistor between the ESP and dfplayer module D3 | resistor | tx pin dfplayer. No difference.

I’d venture to say perhaps it is not compatible since data_bits parameter cannot be matched. It’s probably worth while to go on discord and see if any devs are around that can shed some light on the issue. If not open a bug.

I may have missed it in the thread, but have you tried a different esp device? These things sometimes aren’t well made and they can be, frankly, a POS .

Also when I look at projects that have successfully used the dfplayer they have used different pins. EG this one DIY Video Doorbell with Voice Response | ESPHome / ESP32 Camera / DFPlayer Mini uses a D1 mini with

  tx_pin: D6
  rx_pin: D5
1 Like

Wow! I believe it was the pins after all. Using these pins worked! I can control the device through Home Assistant now. Thank you so much.

1 Like