Did you hold boot (or bridge IO0 to GND) while connecting the cable to get into flashing mode? I just soldered onto the exposed pads to connect my usb. This way I could flash it with https://web.esphome.io/
I havenât flashed anything to it yet. I want to find how to change the graphics first.
I did find an online tool for designing the graphics. At least I think it is the right LCD for this knob. I havenât tried using it yet.
Also found this YouTube tutorial.
Yeah thatâs their crap design tool. Really awful.
Wrong video I think. This one is what you wanted to point to isnât it?
Buuuuut we are in the esphome section of the forum, so not quite right.
Any chance of your code my friend?
True, but if I can figure out how to flash new code and graphics, connecting to ESPHome shouldnât be too difficult.
Same as flashing any other esphome code I guess. You have a serial connection, use it.
Iâve probably flashed a hundred ESP devices. My stumbling block is which graphics library to use for the display.
If you want ESPHome, then i dont think theres an alternative to displayâŚ
@nickrout - pasted the hardware that needs to be worked out, display screens are from Figma, nothing finished in ESPHome yet, but nothing too hard:
font:
- file: 'fonts/Roboto-Regular.ttf'
glyphs: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ°.:/+- ' #ABCDEFGHIJKLMNOPQRSTUVWXYZ°
id: regular
size: 24
- file: 'fonts/Roboto-Regular.ttf'
glyphs: ' -0123456789°Cecohi' #C
id: huge
size: 80
- file: 'fonts/Roboto-Regular.ttf'
glyphs: ' -0123456789°Cecohi' #C
id: medium
size: 60
- file: "fonts/fa-light.ttf"
glyphs: "\uf06c\uf7ae\uf79a\uf06d\uf1eb\ue137\uf011\ue487\uf293\ue00d\uf015\ue1b0\uf624\ue3b0\ue1a7\uf2dc\ue004\uf775\uf2f1\uf863\uf750\uf017"
display: # 240 x 320
- platform: st7789v
id: ${device_name}_display
model: Custom
width: 240
height: 320
offset_height: 0
offset_width: 0
###
eightbitcolor: true # OR IT BREAKS
### backlight_pin: GPIO35 ## breaks color
update_interval: 20s
cs_pin: GPIO34
dc_pin: GPIO13
reset_pin: GPIO21
on_page_change:
then:
- light.turn_on: ${device_name}_backlight
pages:
- id: page_boot
lambda: |-
int w = it.get_width();
int h = it.get_height();
auto icon = "\ue1a7"; // hand-wave //
auto color = id(gray);
it.print(w/2, h/2 , id(huge), random_color, TextAlign::CENTER, "hi");
it.print(w/2, w, id(symbol), random_color, TextAlign::CENTER, icon);
it.print(w/2, h - 20, id(regular), random_color, TextAlign::CENTER, "nESP");
- id: page_qr_wifi
lambda: |-
int w = it.get_width();
int h = it.get_height();
auto icon = "\uf1eb"; // \uf293 = bluetooth // \uf1eb = wifi
auto color = id(gray);
it.qr_code(w/3.5, h/4, id(qr_hotspot), random_color, 4);
it.print(w/2, w, id(symbol), random_color, TextAlign::CENTER, icon);
it.printf(w/2, h - 20, id(regular), random_color, TextAlign::CENTER, "nESP" );
- id: page_climate
lambda: |-
// canvas
int w = it.get_width();
int h = it.get_height();
int h2 = h / 2;
int w2 = w / 2;
int yheader = h / 3;
int yfooter = h - 20;
int radius = w2;
// font sizes
auto main_font = id(huge);
// text values
std::string huge_text = "x";
auto get_mode = id(hvac_mode).state;
auto get_hvac_action = id(hvac_action).state;
auto get_preset_mode = id(preset_mode).state;
// bools
auto dual = false;
// numeric
float get_target_temp_low = id(target_temp_low).state;
float get_target_temp_high = id(target_temp_high).state;
float get_target_temperature = id(target_temperature).state;
// check for dual mode
if (isnan(get_target_temperature) ){
dual = true;
get_target_temperature = round((get_target_temp_low + get_target_temp_high) / 2);
}
float get_current_temperature = id(current_temperature).state;
float minTemp = 15.0;
float maxTemp = 30.0;
// COLORS
auto color_neutral = id(graydark);
auto color_main = id(graydark);
auto color_accent = color_main;
auto color_background = id(black);
auto linecolor = id(graydarker);
// ICON
auto icon = "\uf624";
// hvac_mode (state)
if ( get_mode == "heat" ){
color_main = id(mode_heat);
icon = "\uf06d"; // fire
}
else if (get_mode == "cool") {
color_main = id(mode_cool);
icon = "\uf2dc"; // snowflake
}
else if (get_mode == "dry") {
color_main = id(mode_dry);
icon = "\uf750"; // droplet-percent
}
else if (get_mode == "fan_only") {
color_main = id(mode_fan);
icon = "\uf863"; // fan
}
else if (get_mode == "heat_cool") {
color_main = id(mode_heat_cool);
icon = "\uf2f1"; // rotate
}
// heat_cool hvac_action options: idle, cooling, heating
if (get_hvac_action == "idle") {
if (get_mode == "heat_cool"){
color_main = id(mode_heat_cool);
}
else if (get_mode == "heat"){
color_main = id(mode_heat);
}
else if (get_mode == "cool"){
color_main = id(mode_cool);
}
else{
color_main = id(mode_idle);
icon = "\uf017"; // clock
}
icon = "\uf017"; // clock
color_accent = id(mode_idle);
}
if ( (get_mode == "off") || (get_hvac_action == "off") ){
color_main = id(graydarker);
color_accent = id(graydark);
linecolor = id(graydarker);
icon = "\uf011"; // power-off
}
// Draw filled circle if not off or idle
if ( (get_hvac_action == "heating") || (get_hvac_action == "cooling") || (get_hvac_action == "drying") || (get_hvac_action == "fan" ) ) {
// stripeLength = stripeLength + w / 40;
radius = radius - w / 40;
it.filled_circle(w2, h2, w2, color_main);
linecolor = id(white);
color_accent = color_main;
it.print(w2, yheader, id(regular), color_background, TextAlign::CENTER, get_hvac_action.c_str() );
}
if (get_preset_mode == "eco") {
huge_text = "eco";
color_main = id(mode_eco);
} else {
char buffer[32];
float value = round(get_target_temperature);
if (value != 0 && !isnan(value) ){
snprintf(buffer, sizeof(buffer), "%.0f", value); // Convert float to a C-style string
huge_text = buffer;
}
}
if ( dual ){
main_font = id(medium);
float value_low = round(get_target_temp_low);
float value_high = round(get_target_temp_high);
std::string separator = " - ";
huge_text = std::to_string((int)value_low) + separator + std::to_string((int)value_high);
}
else {
float value = round(get_target_temperature);
if (value != 0 && !isnan(value) ){
huge_text = std::to_string((int)value);
}
}
// Draw current temperature at bottom
it.printf(w2, yfooter, id(regular), color_neutral, TextAlign::CENTER, "%.0f", get_current_temperature );
// dual gauge mode:
// it.printf(w2, yfooter, id(regular), color_main, TextAlign::CENTER, "%.0f - %.0f", get_target_temp_low, get_target_temp_high);
// invert colors for filled background
if ( (get_hvac_action == "heating") || (get_hvac_action == "cooling") || (get_hvac_action == "drying") || (get_hvac_action == "fan" ) ) {
auto hold = color_accent;
color_accent = color_background;
color_main = color_background;
color_background = hold;
}
// Draw icon
it.print(w2, w, id(symbol), color_main, TextAlign::CENTER, icon);
// draw set at center
it.print(w2, h2 , main_font, color_accent, TextAlign::CENTER, huge_text.c_str() );
Thanks for the homework assignment.
Happy to help, together we might come to a final solution faster - i can finalize the display if someone helps figure out how to make the gpio sensors work reliably⌠I dont think you can use any other graphics âlibraryâ on st7789v⌠together with esphome.
Thank you!
It seems to me that openhasp would be ideal for this. Although it doesnât have a touch screen, the interface of a rotary plus a push button could work with openhasp.
Did anybody have a look at this already?
https://aliexpress.com/item/1005004882568128.html
Information is a little bit sparse but it seems to be a commercial version of Smartknob
I just recently purchased one of these and am looking to do the same thing and would love to help in the development of this.
Have a go, my enthusiasm tanked when the basic left-right-push sensors were out of whack.
Itâs a dead link.
Works for me
Because it has been changedâŚ
Hey, did you get any more information? I might buy that one and give it ago, made the mistake of only ordering the diag cable on another buyâŚ