DFPlayer Mini MP3 player with ESPHome

Like the docs say

fully supports FAT16 , FAT32 file system, maximum support 32G of the TF card, support 32G of U disk, 64M bytes NORFLASH

I’m trying to get a very basic example going before coding away, and I keep having problems getting dfplayer to run. Here are the nuts and bolts from my config:


# SSD1306 Configs
time:
  - platform: homeassistant
    timezone: America/Los_Angeles
    id: ha_time
mqtt:
  broker: 192....
  username: !secret mqtt_client_user1
  password: !secret mqtt_client_pass1
font:
  - file: "verdana.ttf"
    id: my_fontlg
    size: 18
  - file: "verdana.ttf"
    id: my_fontsm
    size: 14
i2c:
  sda: D1
  scl: D2
display:
  - platform: ssd1306_i2c
    id: my_display
    pages:
      - id: page1
        lambda: |-
          it.strftime(0, 0, id(my_fontlg), "%I:%M:%S %p", id(ha_time).now());
          it.strftime(0, 20, id(my_fontlg), "%a, %b %d", id(ha_time).now());
          it.printf(0, 55, id(my_fontlg), "BckYd: %.1f F", id(backyard_temp).state);
          if (id(button).state) {
            it.line(0, 63, 128, 63);
          } else {
            
          }
      - id: page2
        lambda: |-
          it.strftime(0, 5, id(my_fontlg), "%I:%M:%S %p", id(ha_time).now());
          it.strftime(0, 25, id(my_fontlg), "%m-%d-%Y", id(ha_time).now());
          if (id(button).state) {
            it.line(0, 63, 128, 63);
          } else {
            
          }
    model: "SSD1306 128x64"
    reset_pin: D0
    address: 0x3C
interval:
  - interval: 5s
    then:
      - display.page.show_next: my_display
      - component.update: my_display
# DFplayer configs
uart:
  tx_pin: GPIO2
  rx_pin: GPIO5
  baud_rate: 9600

# Declare DFPlayer mini module
dfplayer:
  on_finished_playback:
    then:
      logger.log: 'Somebody press play!'
      
# Generic configs
binary_sensor:
  - platform: status
    name: "${friendly_name} Status"
    
  - platform: gpio
    pin:
      number: GPIO13
      mode: INPUT_PULLUP
      inverted: true
    name: "${friendly_name} Button"
    id: button
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_press:
      then:
        - switch.turn_on: led
        - dfplayer.set_volume: 25
        - delay: 150ms
        - dfplayer.play_next:
    on_release:
      then:
        - switch.turn_off: led

#status_led:
#  pin: GPIO2
  
sensor:
  - platform: wifi_signal
    name: "${friendly_name} WiFi Signal"
    update_interval: 60s
    
  - platform: mqtt_subscribe
    name: "Backyard Temperature"
    id: backyard_temp
    topic: esphome/backyard_temp
    
switch:
  - platform: gpio
    name: "${friendly_name} LED"
    pin: GPIO2
    id: led
    inverted: true

Hardware wise, everything works when I don’t compile with dfplayer… the wemos, ssd, button, standalone dfplayer, amplifier, and speaker work together on the breadboard. However when I add in the dfplayer programming and wire up the uart, it bootloops and won’t even connect to wifi. I must have an obvious issue in my config. Any help is much appreciated.

My end goal is to make devices around my house to give audio and visual feedback from HA (like saying ‘front door opened’, ‘doorbell rang’, etc… and displaying various temps/humids/etc from ha).

[edit: Nevermind, I figured out it was a pin incompatibility, likely due to the ssd1306 display config needing D0 to be defined for reset, which is a hardware UART pin. So I changed the pins and it’s working as expected:

# Test Wemos D1 Mini board
# Built In LED -> GPIO2
# button -> D7
# DFplayer rx pin -> D5
# DFplayer tx pin -> D6
# oled sda -> D1
# oled scl -> D2
  
# SSD1306 Configs
time:
  - platform: homeassistant
    timezone: "America/Los_Angeles"
    id: ha_time
mqtt:
  broker: 192...
  username: !secret mqtt_client_user1
  password: !secret mqtt_client_pass1
font:
  - file: "verdana.ttf"
    id: my_fontlg
    size: 18
  - file: "verdana.ttf"
    id: my_fontsm
    size: 14
i2c:
  sda: D1
  scl: D2
display:
  - platform: ssd1306_i2c
    id: my_display
    pages:
      - id: page1
        lambda: |-
          it.strftime(0, 0, id(my_fontlg), "%I:%M:%S %p", id(ha_time).now());
          it.strftime(0, 20, id(my_fontlg), "%a, %b %d", id(ha_time).now());
          it.printf(0, 55, id(my_fontlg), "BckYd: %.1f F", id(backyard_temp).state);
          if (id(button).state) {
            it.line(0, 63, 127, 63);
          }
      - id: page2
        lambda: |-
          it.strftime(0, 5, id(my_fontlg), "%I:%M:%S %p", id(ha_time).now());
          it.strftime(0, 25, id(my_fontlg), "%m-%d-%Y", id(ha_time).now());
          if (id(button).state) {
            it.line(0, 63, 127, 63);
          }
    model: "SSD1306 128x64"
    reset_pin: D0
    address: 0x3C
interval:
  - interval: 5s
    then:
      - display.page.show_next: my_display
      - component.update: my_display
      
# DFplayer configs
uart:
  tx_pin: D5
  rx_pin: D6
  baud_rate: 9600

# Declare DFPlayer mini module
dfplayer:
  on_finished_playback:
    then:
      logger.log: 'Somebody press play!'
      
# Binaries
binary_sensor:
  - platform: status
    name: "${friendly_name} Status"
    
  - platform: gpio
    pin:
      number: GPIO13
      mode: INPUT_PULLUP
      inverted: true
    name: "${friendly_name} Button"
    id: button
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_press:
      then:
        - switch.turn_on: led
        - dfplayer.set_volume: 25
        - delay: 150ms
        - dfplayer.play_next:
    on_release:
      then:
        - switch.turn_off: led

#status_led:
#  pin: GPIO2
  
sensor:
  - platform: wifi_signal
    name: "${friendly_name} WiFi Signal"
    update_interval: 60s
    
  - platform: mqtt_subscribe
    name: "Backyard Temperature"
    id: backyard_temp
    topic: esphome/backyard_temp
    
switch:
  - platform: gpio
    name: "${friendly_name} LED"
    pin: GPIO2
    id: led
    inverted: true

Now I’m off to the races with filling out the code.

Hello!
I try to delay the script while the track is playing, but this does not work. Please tell me how to do this.

script:
  - id: play_dfplayer
    then:
      - logger.log: "Start dfplayer"
      - dfplayer.set_volume: 20
      - delay: 150ms
      - dfplayer.play: 15
      - wait_until: dfplayer.is_playing
      - logger.log: "Stop dfplayer"

I think your wait statement will be true every time the script runs. Try this instead:

script:
  - id: play_dfplayer
    then:
      - logger.log: "Start dfplayer"
      - dfplayer.set_volume: 20
      - delay: 150ms
      - dfplayer.play: 15
      - while:
          condition: 
            dfplayer.is_playing
          then:
            delay: 1ms
      - logger.log: "Stop dfplayer"

Unfortunately this will not stop the execution of the script.
Therefore, I now use the following code:

dfplayer:
  on_finished_playback:
    then:
      - script.execute: stop_dfplayer
      
script:
  - id: play_dfplayer
    then:
      - logger.log: "Start dfplayer"
      - dfplayer.set_volume: 20
      - delay: 150ms
      - dfplayer.play: 15
  - id: stop_dfplayer
    then:
      - logger.log: "Stop dfplayer"

But I don’t want to use two scripts, I need my script to wait while the track is playing and continue to run. It is a pity that “wait_unti” l does not work, it would be very convenient.

2 Likes

Ah I see, it seems the script actions are done asynchronous as is normal with esp programming (probably to avoid wifi issues with blocking codes). So your script continues with the while executing ‘in the background’. It works in a lambda though, which indicates esphome has a way of keeping execution ‘inline’ without causing timing issues (a separate async process if you will).

hey @glmnet just wanted to say thanks for the development! I just added an ESP8266 with a DFPlayer mini to Home Assistant and it works flawlessly!

1 Like

Hello,

I have a jq8400-tf-12p and a jq8900-tf. Should those clones be compatible with the dfplayer mini integration in esphome?

Dear glmnet,

May you send me more details instruction about the installation dfplayer? I’m trying to connect DFPlayer mini with ESP32 device but I still get error. Thanks.

Dear JohnAdam,
You can use automation for play something. Just install code from esp home and call service with automations. Add songs in SD card like 1.mp3 2.mp3 and make automations. I did it, works.

Any ideas why a working DFPlayer will suddenly stop playing?

Below are the logs:

[18:58:32][D][binary_sensor:036]: 'doorbell_button': Sending state ON
[18:58:32][D][dfplayer:032]: Send Command 0x3 arg 0x05
[18:58:32][D][light:275]: 'camera_4_button_light' Setting:
[18:58:32][D][light:284]:   State: ON
[18:58:32][V][dfplayer:074]: Received message cmd: 0x41 arg 0000
[18:58:32][V][dfplayer:103]: Ack ok
[18:58:32][D][light:275]: 'camera_4_button_light' Setting:
[18:58:32][D][light:284]:   State: OFF
[18:58:32][D][light:275]: 'camera_4_button_light' Setting:
[18:58:32][D][light:284]:   State: ON
[18:58:33][V][dfplayer:074]: Received message cmd: 0x3f arg 0x02
[18:58:33][I][dfplayer:093]: TF Card available

Thanks for your help

I can’t get it to work with the UART.

I have a memory card with FAT32, and two mp3s that I know works from another DF-player.

esphome:
  name: tv
  platform: ESP8266
  board: esp01_1m
  # includes:
  #   - customGyro.h

# Enable logging
logger:

# Enable Home Assistant API
api:
  services:
  - service: dfplayer_next
    then:
      - dfplayer.play_next:

ota:
  password: ""

wifi:
  ssid: ""
  password: ""
  manual_ip:
    static_ip: 192.168.1.222
    gateway: 10.0.0.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Tv Fallback Hotspot"
    password: "8ERvosrsrUP6"

captive_portal:

uart:
  tx_pin: GPIO9
  rx_pin: GPIO10
  baud_rate: 9600

# Declare DFPlayer mini module
dfplayer:
  on_finished_playback:
    then:
      logger.log: 'Somebody press play!'

i2c:
  sda: GPIO1
  scl: GPIO3
  scan: true
  id: bus_a
  
sensor:
  - platform: mpu6050
    address: 0x68
    update_interval: 2s
    accel_x:
      name: "MPU6050 Accel X"
    accel_y:
      name: "MPU6050 Accel Y"
    accel_z:
      name: "MPU6050 Accel z"
    gyro_x:
      name: "MPU6050 Gyro X"
    gyro_y:
      name: "MPU6050 Gyro Y"
    gyro_z:
      name: "MPU6050 Gyro z"
    temperature:
      name: "MPU6050 Temperature"
      
  - platform: ultrasonic
    trigger_pin: GPIO12
    echo_pin: GPIO14
    update_interval: 1s
    name: "Ultrasonic Sensor"
    on_value_range:
      - below: 50
        then:
          - dfplayer.play_next:

I also tried the GPIO2 and 5 as the docs suggests but that doesn’t work either.

This is all I get in the logs about UART and DF-player:

[11:39:59][C][uart_esp8266:075]: UART Bus:
[11:39:59][C][uart_esp8266:077]:   TX Pin: GPIO9
[11:39:59][C][uart_esp8266:080]:   RX Pin: GPIO10
[11:39:59][C][uart_esp8266:081]:   RX Buffer Size: 256
[11:39:59][C][uart_esp8266:083]:   Baud Rate: 9600 baud
[11:39:59][C][uart_esp8266:084]:   Data Bits: 8
[11:39:59][C][uart_esp8266:085]:   Parity: NONE
[11:39:59][C][uart_esp8266:086]:   Stop bits: 1
[11:39:59][C][uart_esp8266:090]:   Using software serial
[11:39:59][C][logger:189]: Logger:
[11:39:59][C][logger:190]:   Level: DEBUG
[11:39:59][C][logger:191]:   Log Baud Rate: 115200
[11:39:59][C][logger:192]:   Hardware UART: UART0
[11:39:59][C][dfplayer:125]: DFPlayer:

I have tried both TX → RX and TX → TX.

Currently the dF-player has a separate 5 volt 1 A power supply.
When I trigger the service play next, no sound and no LED lights up.

EDIT:

I believe it’s dead.
I tried to ground the pin that should play the first song and it didn’t do anything.

I spent a lot of time trying to make this work. Unfortunately, not all the DF Players boards are the same. There are several that do not work via UART, I bought three different types from different vendors and only one worked.

Really?
But does the boards work using the ground cable on “play” pin?

Got a new one today and it worked great!

Sorry cause I’m bumping this, but…
Does anybody experienced huge delay in command executing? Not just a delay, let me explain.

My setup is esp01s module as “controller” from esphome side and dfplayer as mp3 player. For now, in test phase, I am using separate power supplies - esp01s is supplying power from esp01 USB programmer connected to PC USB port, and dfplayer is supplying power from 5V 2A wall power supply.

I wired GPIO0 and GPIO2 from esp01s to Tx and Rx on dfplayer. Little 8ohms 3W speaker is connected to SPK_1 and SPK_2 on dfplayer. I have some Underworld album on sdcard (Beaucoup Fish :grin: ) songs renamed to 001.mp3, 002.mp3, etc. and have to say these mp3’s are properly encoded for dfplayer, cause if I shorten GND and ADKEY_1 on dfplayer, first song is playing instantly without delay (in surprisingly good quality for this little piece of HW :slight_smile: ).

esp01s part: I compiled yaml example from ESPHome wiki: DF-Player mini — ESPHome , one at the end bottom of page with all services included, and flashed it onto esp01s. Nothing changed in yaml, except I put correct GPIOs for esp01s (GPIO0 and GPIO2). So, I have all these services in HA, play, pause, set volume, etc. and can call them from dev tools.

This is also working from dev tools, I can play the song, pause it, skip to next, etc. but… with huge delay. Actually, this is not an ordinary delay. E.g. if I click the Call Service button and wait, nothing will happen (most of the time nothing will happen, it was successful only once). But if I’m clicking fast repeatedly on Call Service button, 10 or 15 times, service will be executed.

There are no errors in HA log.

I am aware that both pieces of HW are very poor, but does someone experienced similar problem and is there a solution?

I have one spare Sonoff SV laying around and will try later it instead of esp01s, but I’m not sure could this be a problem with esphome controller or with dfplayer itself.

What does the esphome log say? If it is not showing much, pump up the logging.

@nickrout : Heh, little late for logs, I already removed esp01s, connected Sonoff SV and flashed it with yaml from ESPHome wiki, full example with all services, and it is working flawlessly and instantly, so problem solved from my point of view.

If you are really interested in logs from esp01s for your personal curiosity, I can connect it later tonight and catch the logs, but I would skip this if you don’t need it.

Yup, little weak esp01s was problem, but I still like it so much because of size and price.

Actually, for this money and size, dfplayer is working very nice. I will connect this setup with Aqara motion sensor in my bathroom :smile:

One additional question: Is there some way to get some states from dfplayer in HA? I tried to search across the internet, but didn’t found something useful until now.

Thx.