Add a second ESPHome fleet display that shares the existing printer pages.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -84,17 +84,22 @@ printer rotation are outside its current scope.
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
1. Keep `esphome/bambu-printer-display.yaml` and the entire `bambu-display/` folder
|
1. Keep both device files and the entire `bambu-display/` folder together in the
|
||||||
together in the ESPHome configuration directory. The generated package is checked
|
ESPHome configuration directory. `bambu-printer-display.yaml` is the first board
|
||||||
in, so the ESPHome dashboard can compile it without running the generator first.
|
and `bambu-printer-display-2.yaml` is the second. They share `board.yaml` and the
|
||||||
|
generated fleet package, which is checked in, so the ESPHome dashboard can compile
|
||||||
|
either file without running the generator first.
|
||||||
2. Supply the existing `api_encryption_key`, `wifi_iot_ssid` and `wifi_password`
|
2. Supply the existing `api_encryption_key`, `wifi_iot_ssid` and `wifi_password`
|
||||||
entries in that directory's `secrets.yaml`.
|
entries in that directory's `secrets.yaml`.
|
||||||
3. Use ESPHome **2026.9.0 or newer**. Compile and install
|
3. Use ESPHome **2026.9.0 or newer**. Compile and install the matching device file
|
||||||
`bambu-printer-display.yaml` over the board's USB-to-UART bridge for the first
|
over that board's USB-to-UART bridge for the first flash; subsequent installs can
|
||||||
flash; subsequent installs can use encrypted OTA.
|
use encrypted OTA. Flash `bambu-printer-display.yaml` to the first panel and
|
||||||
4. Add **Bambu Printer Display** through Home Assistant's ESPHome integration using
|
`bambu-printer-display-2.yaml` to the second. Each file has its own ESPHome name,
|
||||||
the same API encryption key. The display only subscribes to entities, so it does
|
so both panels can be online together.
|
||||||
not require permission to perform Home Assistant actions.
|
4. Add **Bambu Printer Display** or **Bambu Printer Display 2** through Home
|
||||||
|
Assistant's ESPHome integration using the same API encryption key. Each display
|
||||||
|
only subscribes to entities, so it does not require permission to perform Home
|
||||||
|
Assistant actions.
|
||||||
5. Confirm all pages receive data and verify touch direction and color order on the
|
5. Confirm all pages receive data and verify touch direction and color order on the
|
||||||
physical panel. Entity IDs match the repository's `ha-entities.txt` snapshot;
|
physical panel. Entity IDs match the repository's `ha-entities.txt` snapshot;
|
||||||
renamed or disabled entities in live HA must be corrected/enabled there.
|
renamed or disabled entities in live HA must be corrected/enabled there.
|
||||||
@@ -103,7 +108,7 @@ The USB D+/D− GPIO19/20 pins are used by the board's touch bus. Logging theref
|
|||||||
uses UART0. ESPHome may still warn about these two pins; they are intentional for
|
uses UART0. ESPHome may still warn about these two pins; they are intentional for
|
||||||
this board. If GT911 is not found at `0x5D`, inspect the I²C scan and use its reported
|
this board. If GT911 is not found at `0x5D`, inspect the I²C scan and use its reported
|
||||||
address (some hardware revisions select `0x14`). Backlight is GPIO2; RGB data pins
|
address (some hardware revisions select `0x14`). Backlight is GPIO2; RGB data pins
|
||||||
and timings are explicit in the main YAML rather than borrowed from a 5″ board.
|
and timings are explicit in `board.yaml` rather than borrowed from a 5″ board.
|
||||||
|
|
||||||
The display and LVGL both use **big-endian RGB565**. With `mipi_rgb`'s named
|
The display and LVGL both use **big-endian RGB565**. With `mipi_rgb`'s named
|
||||||
`red`/`green`/`blue` pin groups, its generated bus pin map already exchanges the
|
`red`/`green`/`blue` pin groups, its generated bus pin map already exchanges the
|
||||||
@@ -121,7 +126,9 @@ CLI checks from the repository root:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
esphome config esphome/bambu-printer-display.yaml
|
esphome config esphome/bambu-printer-display.yaml
|
||||||
|
esphome config esphome/bambu-printer-display-2.yaml
|
||||||
esphome compile esphome/bambu-printer-display.yaml
|
esphome compile esphome/bambu-printer-display.yaml
|
||||||
|
esphome compile esphome/bambu-printer-display-2.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Change or expand the fleet
|
## Change or expand the fleet
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# Shared Sunton ESP32-8048S043C board for every fleet display.
|
||||||
|
# Device name and friendly name come from the top-level YAML substitutions.
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
friendly_name: ${friendly_name}
|
||||||
|
min_version: 2026.9.0
|
||||||
|
includes:
|
||||||
|
- bambu-display/dashboard.h
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32-s3-devkitc-1
|
||||||
|
flash_size: 16MB
|
||||||
|
flash_mode: dio
|
||||||
|
cpu_frequency: 240MHz
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
sdkconfig_options:
|
||||||
|
CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
|
||||||
|
CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
|
||||||
|
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y"
|
||||||
|
CONFIG_SPIRAM_RODATA: "y"
|
||||||
|
|
||||||
|
psram:
|
||||||
|
mode: octal
|
||||||
|
speed: 80MHz
|
||||||
|
|
||||||
|
logger:
|
||||||
|
hardware_uart: UART0 # GPIO19/20 are the touch bus, not native USB.
|
||||||
|
|
||||||
|
api:
|
||||||
|
id: ha_api
|
||||||
|
encryption:
|
||||||
|
key: !secret api_encryption_key
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
encryption:
|
||||||
|
key: !secret api_encryption_key
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_iot_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
|
||||||
|
i2c:
|
||||||
|
id: touch_bus
|
||||||
|
sda: GPIO19
|
||||||
|
scl: GPIO20
|
||||||
|
scan: true
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: mipi_rgb
|
||||||
|
id: panel_display
|
||||||
|
model: RPI
|
||||||
|
dimensions: 800x480
|
||||||
|
color_order: RGB
|
||||||
|
# Named RGB data_pins are byte-swapped by mipi_rgb's pin mapping.
|
||||||
|
# Send big-endian RGB565 pixels to match that wiring transformation.
|
||||||
|
byte_order: big_endian
|
||||||
|
de_pin: GPIO40
|
||||||
|
hsync_pin: GPIO39
|
||||||
|
vsync_pin: GPIO41
|
||||||
|
pclk_pin: GPIO42
|
||||||
|
pclk_inverted: true
|
||||||
|
pclk_frequency: 16MHz
|
||||||
|
hsync_front_porch: 8
|
||||||
|
hsync_pulse_width: 4
|
||||||
|
hsync_back_porch: 8
|
||||||
|
vsync_front_porch: 8
|
||||||
|
vsync_pulse_width: 4
|
||||||
|
vsync_back_porch: 8
|
||||||
|
data_pins:
|
||||||
|
red: [GPIO45, GPIO48, GPIO47, GPIO21, GPIO14]
|
||||||
|
green: [GPIO5, GPIO6, GPIO7, GPIO15, GPIO16, GPIO4]
|
||||||
|
blue: [GPIO8, GPIO3, GPIO46, GPIO9, GPIO1]
|
||||||
|
auto_clear_enabled: false
|
||||||
|
update_interval: never
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: gt911
|
||||||
|
id: panel_touch
|
||||||
|
display: panel_display
|
||||||
|
i2c_id: touch_bus
|
||||||
|
address: 0x5D
|
||||||
|
# Polling avoids the GT911 INT pin's boot/address-selection behaviour.
|
||||||
|
update_interval: 20ms
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: ledc
|
||||||
|
id: backlight_output
|
||||||
|
pin: GPIO2
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: monochromatic
|
||||||
|
id: panel_backlight
|
||||||
|
name: Backlight
|
||||||
|
output: backlight_output
|
||||||
|
restore_mode: ALWAYS_ON
|
||||||
|
default_transition_length: 0s
|
||||||
|
|
||||||
|
time:
|
||||||
|
- platform: homeassistant
|
||||||
|
id: ha_time
|
||||||
|
timezone: America/New_York
|
||||||
|
|
||||||
|
lvgl:
|
||||||
|
id: dashboard
|
||||||
|
displays: [panel_display]
|
||||||
|
touchscreens: [panel_touch]
|
||||||
|
buffer_size: 12%
|
||||||
|
color_depth: 16
|
||||||
|
byte_order: big_endian # Must match mipi_rgb's named RGB pin mapping above.
|
||||||
|
bg_color: 0x000000
|
||||||
|
text_color: 0xEEEEEE
|
||||||
|
default_font: montserrat_18
|
||||||
@@ -123,7 +123,7 @@ class FleetTests(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
for tag in ('!secret', '!include'):
|
for tag in ('!secret', '!include'):
|
||||||
Loader.add_constructor(tag, lambda loader, node: loader.construct_scalar(node))
|
Loader.add_constructor(tag, lambda loader, node: loader.construct_scalar(node))
|
||||||
config = yaml.load((HERE.parent / 'bambu-printer-display.yaml').read_text(), Loader=Loader)
|
config = yaml.load((HERE / 'board.yaml').read_text(), Loader=Loader)
|
||||||
display = config['display'][0]
|
display = config['display'][0]
|
||||||
pins = display['data_pins']
|
pins = display['data_pins']
|
||||||
natural = pins['blue'] + pins['green'] + pins['red']
|
natural = pins['blue'] + pins['green'] + pins['red']
|
||||||
@@ -135,6 +135,18 @@ class FleetTests(unittest.TestCase):
|
|||||||
for i, pin in enumerate(driver))
|
for i, pin in enumerate(driver))
|
||||||
self.assertEqual(panel_word, color, f'RGB565 color {color:#06x} is wired incorrectly')
|
self.assertEqual(panel_word, color, f'RGB565 color {color:#06x} is wired incorrectly')
|
||||||
|
|
||||||
|
def test_both_boards_share_one_hardware_package(self):
|
||||||
|
class Loader(yaml.SafeLoader):
|
||||||
|
pass
|
||||||
|
Loader.add_constructor('!include', lambda loader, node: loader.construct_scalar(node))
|
||||||
|
names = set()
|
||||||
|
for filename in ('bambu-printer-display.yaml', 'bambu-printer-display-2.yaml'):
|
||||||
|
config = yaml.load((HERE.parent / filename).read_text(), Loader=Loader)
|
||||||
|
names.add(config['substitutions']['device_name'])
|
||||||
|
self.assertEqual(config['packages']['board'], 'bambu-display/board.yaml')
|
||||||
|
self.assertEqual(config['packages']['fleet'], 'bambu-display/generated.yaml')
|
||||||
|
self.assertEqual(len(names), 2)
|
||||||
|
|
||||||
def test_diagnostic_color_page_is_skipped_during_normal_navigation(self):
|
def test_diagnostic_color_page_is_skipped_during_normal_navigation(self):
|
||||||
package = generate(self.printers)
|
package = generate(self.printers)
|
||||||
page = next(page for page in package['lvgl']['pages'] if page['id'] == 'color_test_page')
|
page = next(page for page in package['lvgl']['pages'] if page['id'] == 'color_test_page')
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Second Sunton ESP32-8048S043C fleet display. Same pages and hardware as
|
||||||
|
# bambu-printer-display.yaml, with its own ESPHome name so both boards can
|
||||||
|
# join Home Assistant. Edit bambu-display/printers.yaml, then run generate.py.
|
||||||
|
substitutions:
|
||||||
|
device_name: bambu-printer-display-2
|
||||||
|
friendly_name: Bambu Printer Display 2
|
||||||
|
|
||||||
|
packages:
|
||||||
|
board: !include bambu-display/board.yaml
|
||||||
|
fleet: !include bambu-display/generated.yaml
|
||||||
@@ -1,121 +1,10 @@
|
|||||||
# Sunton ESP32-8048S043C: 4.3" 800x480 RGB LCD + GT911 capacitive touch.
|
# Sunton ESP32-8048S043C: 4.3" 800x480 RGB LCD + GT911 capacitive touch.
|
||||||
# Edit bambu-display/printers.yaml, then run its generate.py to change the fleet.
|
# Edit bambu-display/printers.yaml, then run its generate.py to change the fleet.
|
||||||
|
# The second board is bambu-printer-display-2.yaml; both include bambu-display/board.yaml.
|
||||||
substitutions:
|
substitutions:
|
||||||
device_name: bambu-printer-display
|
device_name: bambu-printer-display
|
||||||
friendly_name: Bambu Printer Display
|
friendly_name: Bambu Printer Display
|
||||||
|
|
||||||
esphome:
|
|
||||||
name: ${device_name}
|
|
||||||
friendly_name: ${friendly_name}
|
|
||||||
min_version: 2026.9.0
|
|
||||||
includes:
|
|
||||||
- bambu-display/dashboard.h
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
board: esp32-s3-devkitc-1
|
|
||||||
flash_size: 16MB
|
|
||||||
flash_mode: dio
|
|
||||||
cpu_frequency: 240MHz
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
sdkconfig_options:
|
|
||||||
CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
|
|
||||||
CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
|
|
||||||
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y"
|
|
||||||
CONFIG_SPIRAM_RODATA: "y"
|
|
||||||
|
|
||||||
psram:
|
|
||||||
mode: octal
|
|
||||||
speed: 80MHz
|
|
||||||
|
|
||||||
logger:
|
|
||||||
hardware_uart: UART0 # GPIO19/20 are the touch bus, not native USB.
|
|
||||||
|
|
||||||
api:
|
|
||||||
id: ha_api
|
|
||||||
encryption:
|
|
||||||
key: !secret api_encryption_key
|
|
||||||
|
|
||||||
ota:
|
|
||||||
- platform: esphome
|
|
||||||
encryption:
|
|
||||||
key: !secret api_encryption_key
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_iot_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
|
|
||||||
i2c:
|
|
||||||
id: touch_bus
|
|
||||||
sda: GPIO19
|
|
||||||
scl: GPIO20
|
|
||||||
scan: true
|
|
||||||
|
|
||||||
display:
|
|
||||||
- platform: mipi_rgb
|
|
||||||
id: panel_display
|
|
||||||
model: RPI
|
|
||||||
dimensions: 800x480
|
|
||||||
color_order: RGB
|
|
||||||
# Named RGB data_pins are byte-swapped by mipi_rgb's pin mapping.
|
|
||||||
# Send big-endian RGB565 pixels to match that wiring transformation.
|
|
||||||
byte_order: big_endian
|
|
||||||
de_pin: GPIO40
|
|
||||||
hsync_pin: GPIO39
|
|
||||||
vsync_pin: GPIO41
|
|
||||||
pclk_pin: GPIO42
|
|
||||||
pclk_inverted: true
|
|
||||||
pclk_frequency: 16MHz
|
|
||||||
hsync_front_porch: 8
|
|
||||||
hsync_pulse_width: 4
|
|
||||||
hsync_back_porch: 8
|
|
||||||
vsync_front_porch: 8
|
|
||||||
vsync_pulse_width: 4
|
|
||||||
vsync_back_porch: 8
|
|
||||||
data_pins:
|
|
||||||
red: [GPIO45, GPIO48, GPIO47, GPIO21, GPIO14]
|
|
||||||
green: [GPIO5, GPIO6, GPIO7, GPIO15, GPIO16, GPIO4]
|
|
||||||
blue: [GPIO8, GPIO3, GPIO46, GPIO9, GPIO1]
|
|
||||||
auto_clear_enabled: false
|
|
||||||
update_interval: never
|
|
||||||
|
|
||||||
touchscreen:
|
|
||||||
- platform: gt911
|
|
||||||
id: panel_touch
|
|
||||||
display: panel_display
|
|
||||||
i2c_id: touch_bus
|
|
||||||
address: 0x5D
|
|
||||||
# Polling avoids the GT911 INT pin's boot/address-selection behaviour.
|
|
||||||
update_interval: 20ms
|
|
||||||
|
|
||||||
output:
|
|
||||||
- platform: ledc
|
|
||||||
id: backlight_output
|
|
||||||
pin: GPIO2
|
|
||||||
|
|
||||||
light:
|
|
||||||
- platform: monochromatic
|
|
||||||
id: panel_backlight
|
|
||||||
name: Backlight
|
|
||||||
output: backlight_output
|
|
||||||
restore_mode: ALWAYS_ON
|
|
||||||
default_transition_length: 0s
|
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: America/New_York
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
board: !include bambu-display/board.yaml
|
||||||
fleet: !include bambu-display/generated.yaml
|
fleet: !include bambu-display/generated.yaml
|
||||||
|
|
||||||
lvgl:
|
|
||||||
id: dashboard
|
|
||||||
displays: [panel_display]
|
|
||||||
touchscreens: [panel_touch]
|
|
||||||
buffer_size: 12%
|
|
||||||
color_depth: 16
|
|
||||||
byte_order: big_endian # Must match mipi_rgb's named RGB pin mapping above.
|
|
||||||
bg_color: 0x000000
|
|
||||||
text_color: 0xEEEEEE
|
|
||||||
default_font: montserrat_18
|
|
||||||
|
|||||||
Reference in New Issue
Block a user