Spotify Now Playing on LCD
🛠️ In ProgressDisplay the currently playing Spotify song on an text LCD
Required Devices
Used Components (9)
Native API
api Communication protocol for connecting ESPHome to Home Assistant and other clients
Global Variables
globals Store persistent values that can be accessed across automations
Light Component
light Base platform for all light types in ESPHome
Logger
logger Control logging output and verbosity for debugging
Over-The-Air Updates (OTA)
ota Update ESPHome firmware wirelessly over the network
Script
script Create reusable automation sequences
Substitutions
substitutions Define reusable variables for ESPHome configurations
Home Assistant Text Sensor
homeassistant Import text and string values from Home Assistant entities
WiFi
wifi Configure WiFi connectivity for ESP devices
Project Overview
This project aims to create a simple smart device that displays the currently playing Spotify song on an HD44780 based text LCD. The device will use a D1 Mini board for WiFi connectivity and communication with Spotify integration in Home Assistant. The LCD will show the song title and artist name in real-time.
Features
- 🎵 Display Spotify’s currently playing song title and artist name
- 📡 WiFi-enabled for real-time updates
- 🖥️ Simple text-based interface using an HD44780 LCD
- 🔌 Powered via USB
Reusability Note
Just connect to your Home Assistant and if you have Spotify integration it should work straight away. You will need to update id of your entity.
What You’ll Need
Hardware
- 1x ESP8266 D1 Mini
- 1x HD44780 Character LCD (e.g., 16x2 or 20x4)
- 1x USB cable (data capable)
- 1x Power supply (USB charger, 5V/1A minimum)
- 3D Printed Enclosure
Software
- ESPHome installed
- Home Assistant with configured Spotify integration
- Spotify Developer Account for API access is required but the instructions above are pretty exhautive
Required Home Assistant Entities
This project requires the following entities in Home Assistant. You’ll need to update the substitutions with your own entity IDs:
- Media Player: I’m using Spotify but others might work. Example:
media_player.your_spotify
Main Configuration File
Check out HD44780 Character LCD for wiring, in examples overthere, I am also using D1 mini.
esphome:
name: my-spotify-lcd
esp8266:
board: d1_mini
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret my_spotify_lcd_api
ota:
- platform: esphome
password: !secret my_spotify_lcd_api
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
substitutions:
pin_enable: D1
pin_rs: D2
pin_bl: D3
pin_data0: D8
pin_data1: D7
pin_data2: D6
pin_data3: D5
media_player: media_player.your_spotify
script:
- id: update_media_status
then:
- globals.set:
id: my_boot_in_progress
#finally connected to Home Assistant
value: '0'
globals:
- id: my_boot_in_progress
type: int
restore_value: no
initial_value: '1'
text_sensor:
- platform: homeassistant
id: media_state
entity_id: ${media_player}
internal: true
on_value:
then:
- script.execute: update_media_status
- platform: homeassistant
id: media_title
entity_id: ${media_player}
attribute: media_title
internal: true
on_value:
then:
- script.execute: update_media_status
- platform: homeassistant
id: media_artist
entity_id: ${media_player}
attribute: media_artist
internal: true
- platform: homeassistant
id: media_album
entity_id: ${media_player}
attribute: media_album_name
internal: true
# could be useful for graphics LCD
#- platform: homeassistant
# id: media_picture
# entity_id: ${media_player}
# attribute: entity_picture
# internal: true
# Example configuration entry
display:
- platform: lcd_gpio
dimensions: 16x2
data_pins:
- ${pin_data0}
- ${pin_data1}
- ${pin_data2}
- ${pin_data3}
enable_pin: ${pin_enable}
rs_pin: ${pin_rs}
user_characters:
- position: 0
data:
- 0b00000
- 0b00000
- 0b00000
- 0b01010
- 0b11111
- 0b11111
- 0b01110
- 0b00100
- position: 1
data:
- 0b00000
- 0b11011
- 0b11011
- 0b00100
- 0b00100
- 0b10001
- 0b01110
- 0b00000
lambda: |-
static int current_position_first = -1;
static int current_position_second = -1;
if (id(my_boot_in_progress) > 0){
it.print(0, 0, "Connecting ...");
it.print(0, 1, " \x08\x09\x09\x08 ");
return;
}
const int cols = 16; //8 - 40
const int rows = 2; //2 - 4
auto first_row = id(media_state).state + ": " + id(media_title).state + " \x08\x08 ";
auto second_row = id(media_artist).state + " - " + id(media_album).state + " \x08\x08 ";
if(first_row.length() < cols){
first_row.append(cols - first_row.length(), ' ');
}
if(second_row.length() < cols){
second_row.append(cols - second_row.length(), ' ');
}
current_position_first ++;
current_position_second ++;
if(current_position_first >= first_row.length()){
current_position_first = 0;
}
if(current_position_second >= second_row.length()){
current_position_second = 0;
}
std::rotate(first_row.begin(), first_row.begin() + current_position_first, first_row.end());
std::rotate(second_row.begin(), second_row.begin() + current_position_second, second_row.end());
it.printf(0, 0, "%s", first_row.substr(0, cols).c_str());
it.printf(0, 1, "%s", second_row.substr(0, cols).c_str());
output:
- platform: esp8266_pwm
pin: ${pin_bl}
frequency: 1000 Hz
id: pwm_output
light:
- platform: monochromatic
output: pwm_output
name: "Backlight"
Configuration Breakdown
Substitutions
The configuration uses substitutions to make it easy to adapt to your Home Assistant setup. Update these with your own entity IDs:
substitutions:
pin_enable: D1
pin_rs: D2
pin_bl: D3
pin_data0: D8
pin_data1: D7
pin_data2: D6
pin_data3: D5
media_player: media_player.your_spotify # your media player entity id
All pins above are from D1 mini, if you’re using different GPIOs (and you can use any GPIO) just update them with the ones you are using. If you are using a different board, you’ll need to update this section as well with your board details:
esp8266:
board: d1_mini
Boot Status
The display is showing a boot screen until it connects to Home Assistant (until it gets information about player status).
User Defined Characters
user_characters:
- position: 0
data:
- 0b00000
- 0b00000
...
A heart and a smiley face. They are displayed by using \x08 and \0x09.
Displaying Song Information
The display is then showing a combination of play status, song name, song artist and song album:
- status: song name ❤️❤️
- artist: album name ❤️❤️
And they are scrolling at the speed of the refresh rate of the display (1s by default). The algorithm is super simple (and probably inefficient):
- concatenate strings for each row with little hearts at the end
- if the rows are shorter than 16 characters, pad them to 16
- rotate based on the counters
current_position_* - show just 16 characters
I need to figure out how to make the scrolling smoother.
Display Dimensions
My screen is 16x2 so if you have different dimensions make sure to update configuration and lambda variables. I could not get values for rows and columns from the display object so had to hard code them.
display:
- platform: lcd_gpio
dimensions: 16x2
...
const int cols = 16; //8 - 40
const int rows = 2; //2 - 4
Backlight
Backlight is configured as monochromatic light and will be available in Home Assistant to control brightness.
Limitations and Issues
Initially, if idle, there will be no information about current song. The display just shows idle:.
It should handle better the scenario when there is no information.
Slightly slow refresh. Investigate if there is a way to use all of the available memory on the display to make it smoother.