New boards Wishlist
Hardware testing
We often do not have this board ourselves. Community testing helps establish what actually works. A successful report is evidence for the maintainer to review, not an automatic compatibility claim.
Board details & configuration
- Model
- Elecrow CrowPanel advance 2.8 hmi esp32 ai display 320x240
- Chip, RAM and flash
- ESP32-S3, 512KB SRAM, 8M PSRAM,16M Flash
- Display and touch
- 2.8, 320x240, ft63x6, IC ST7789
- Already tried
- I've done this configuration via ESP Home: esphome: name: crowpaneloffice friendly_name: CrowPanelOffice build_flags: - "-DBOARD_HAS_PSRAM" on_boot: priority: -10 then: - delay: 3s - lambda: |- ESP_LOGI("boot", "Setting initial image URLs from sensors"); - component.update: my_display esp32: board: esp32-s3-devkitc-1 framework: type: esp-idf advanced: execute_from_psram: true sdkconfig_options: CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y CONFIG_ESP32S3_DATA_CACHE_64KB: y CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y CONFIG_SPIRAM_RODATA: y psram: mode: octal speed: 80MHz spi: clk_pin: GPIO42 mosi_pin: GPIO39 i2c: sda: GPIO15 scl: GPIO16 frequency: 400kHz scan: true touchscreen: - platform: ft63x6 id: panel_touch address: 0x38 display: my_display update_interval: 50ms on_touch: then: - lambda: |- ESP_LOGI("touch", "tap: x=%d y=%d raw_x=%d raw_y=%d", touch.x, touch.y, touch.x_raw, touch.y_raw); // Handle bottom taskbar navigation directly from the reported touch coordinates. if (touch.y >= 150 && touch.y <= 239) { // Touch X is significantly left-shifted on this panel; compensate for easier icon targeting. int nav_x = touch.x + 58; if (nav_x < 0) nav_x = 0; if (nav_x > 319) nav_x = 319; int target_page = -1; if (nav_x <= 63) { target_page = 0; } else if (nav_x <= 127) { target_page = 1; } else if (nav_x <= 191) { target_page = 2; } else if (nav_x <= 255) { target_page = 3; } else { target_page = 4; } ESP_LOGI("display", "Taskbar touch candidate: x=%d adj_x=%d y=%d -> page %d", touch.x, nav_x, touch.y, target_page); const uint32_t now = millis(); if (now - id(last_page_switch_time) < 350) { ESP_LOGD("display", "Taskbar touch ignored (debounce), last switch was %u ms ago", now - id(last_page_switch_time)); return; } if (id(display_page) != target_page) { id(last_page_switch_time) = now; id(display_page) = target_page; id(my_display).update(); ESP_LOGI("display", "Taskbar touch switched to page %d", target_page); } else { ESP_LOGI("display", "Taskbar touch matched current page %d; no switch needed", target_page); } } else { ESP_LOGD("display", "Touch outside taskbar band: x=%d y=%d", touch.x, touch.y); } calibration: x_min: 0 x_max: 239 y_min: 0 y_max: 319 transform: swap_xy: true mirror_x: true mirror_y: false display: - platform: mipi_spi id: my_display model: ST7789V cs_pin: GPIO40 dc_pin: GPIO41 reset_pin: GPIO3 dimensions: width: 240 height: 320 color_order: bgr invert_colors: true rotation: 270 data_rate: 20MHz spi_mode: MODE0 draw_rounding: 1 lambda: |- const auto COLOR_WHITE = Color(255, 255, 255); const auto COLOR_BLACK = Color(0, 0, 0); const auto COLOR_RED = Color(255, 0, 0); const auto COLOR_GREEN = Color(0, 255, 0); const auto COLOR_BLUE = Color(0, 0, 255); const auto COLOR_YELLOW = Color(255, 255, 0); const auto COLOR_ORANGE = Color(255, 165, 0); auto color_off = COLOR_WHITE; auto color_on = COLOR_BLACK; The touch is a bit off it seems though.
- Configuration status
- working
View shared configuration
esphome:
name: crowpaneloffice
friendly_name: CrowPanelOffice
build_flags:
- "-DBOARD_HAS_PSRAM"
on_boot:
priority: -10
then:
- delay: 3s
- lambda: |-
ESP_LOGI("boot", "Setting initial image URLs from sensors");
- component.update: my_display
substitutions:
ha_base_url: "http://homeassistant.local:8123"
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
advanced:
execute_from_psram: true
sdkconfig_options:
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y
CONFIG_ESP32S3_DATA_CACHE_64KB: y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
CONFIG_SPIRAM_RODATA: y
psram:
mode: octal
speed: 80MHz
logger:
level: INFO
logs:
http_request: ERROR
captive_portal:
http_request:
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
on_client_connected:
then:
- script.execute: force_ha_entity_refresh
ota:
- platform: esphome
password: "7e86936b45b72df03857d2d2a5df92ff"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Crowpaneloffice Fallback Hotspot"
password: "xxxxxxxxxxxx"
spi:
clk_pin: GPIO42
mosi_pin: GPIO39
i2c:
sda: GPIO15
scl: GPIO16
frequency: 400kHz
scan: true
touchscreen:
- platform: ft63x6
id: panel_touch
address: 0x38
display: my_display
update_interval: 50ms
on_touch:
then:
- lambda: |-
ESP_LOGI("touch", "tap: x=%d y=%d raw_x=%d raw_y=%d", touch.x, touch.y, touch.x_raw, touch.y_raw);
// Handle bottom taskbar navigation directly from the reported touch coordinates.
if (touch.y >= 150 && touch.y <= 239) {
// Touch X is significantly left-shifted on this panel; compensate for easier icon targeting.
int nav_x = touch.x + 58;
if (nav_x < 0) nav_x = 0;
if (nav_x > 319) nav_x = 319;
int target_page = -1;
if (nav_x <= 63) {
target_page = 0;
} else if (nav_x <= 127) {
target_page = 1;
} else if (nav_x <= 191) {
target_page = 2;
} else if (nav_x <= 255) {
target_page = 3;
} else {
target_page = 4;
}
ESP_LOGI("display", "Taskbar touch candidate: x=%d adj_x=%d y=%d -> page %d", touch.x, nav_x, touch.y, target_page);
const uint32_t now = millis();
if (now - id(last_page_switch_time) < 350) {
ESP_LOGD("display", "Taskbar touch ignored (debounce), last switch was %u ms ago", now - id(last_page_switch_time));
return;
}
if (id(display_page) != target_page) {
id(last_page_switch_time) = now;
id(display_page) = target_page;
id(my_display).update();
ESP_LOGI("display", "Taskbar touch switched to page %d", target_page);
} else {
ESP_LOGI("display", "Taskbar touch matched current page %d; no switch needed", target_page);
}
} else {
ESP_LOGD("display", "Touch outside taskbar band: x=%d y=%d", touch.x, touch.y);
}
calibration:
x_min: 0
x_max: 239
y_min: 0
y_max: 319
transform:
swap_xy: true
mirror_x: true
mirror_y: false
display:
- platform: mipi_spi
id: my_display
model: ST7789V
cs_pin: GPIO40
dc_pin: GPIO41
reset_pin: GPIO3
dimensions:
width: 240
height: 320
color_order: bgr
invert_colors: true
rotation: 270
data_rate: 20MHz
spi_mode: MODE0
draw_rounding: 1
lambda: |-
const auto COLOR_WHITE = Color(255, 255, 255);
const auto COLOR_BLACK = Color(0, 0, 0);
const auto COLOR_RED = Color(255, 0, 0);
const auto COLOR_GREEN = Color(0, 255, 0);
const auto COLOR_BLUE = Color(0, 0, 255);
const auto COLOR_YELLOW = Color(255, 255, 0);
const auto COLOR_ORANGE = Color(255, 165, 0);
auto color_off = COLOR_WHITE;
auto color_on = COLOR_BLACK;
// Helper to print text with word-wrap at widget boundary
auto print_wrapped_text = [&](int x, int y, int max_w, int line_h, esphome::font::Font *font, Color color, TextAlign align, const char* text) {
if (!text || max_w <= 0) return;
int cx = x;
int cy = y;
std::string line;
std::string word;
const char* p = text;
while (*p) {
// SANITIZATION: Treat newlines, carriage returns, and tabs as spaces for flow
bool is_space = (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t');
if (is_space) {
if (!word.empty()) {
int ww, wh, wbl, wx;
font->measure(word.c_str(), &ww, &wx, &wbl, &wh);
int lw = 0, lx;
if (!line.empty()) { font->measure(line.c_str(), &lw, &lx, &wbl, &wh); int sw, sx, sbl, sh; font->measure(" ", &sw, &sx, &sbl, &sh); lw += sw; }
if (lw + ww > max_w && !line.empty()) {
it.print(cx, cy, font, color, align, line.c_str());
cy += line_h;
line = word;
} else {
if (!line.empty()) line += " ";
line += word;
}
word.clear();
}
} else {
word += *p;
}
p++;
}
if (!word.empty()) {
int ww, wh, wbl, wx;
font->measure(word.c_str(), &ww, &wx, &wbl, &wh);
int lw = 0, lx;
if (!line.empty()) { font->measure(line.c_str(), &lw, &lx, &wbl, &wh); int sw, sx, sbl, sh; font->measure(" ", &sw, &sx, &sbl, &sh); lw += sw; }
if (lw + ww > max_w && !line.empty()) {
it.print(cx, cy, font, color, align, line.c_str());
cy += line_h;
line = word;
} else {
if (!line.empty()) line += " ";
line += word;
}
}
if (!line.empty()) {
it.print(cx, cy, font, color, align, line.c_str());
}
};1 owner has volunteered to test.
Sign in to volunteer
Discussion 0
Add a commentStart the conversation
Share an example, ask a question or explain how you would use this.