AZ Touch ESP example


It means GPIO14 and GPIO27
On schematic it is called T_IRQ and T_CS to tell it apart from Display CS on GPIO5

1 Like

Just found out, that my display was missing touch. I received the wrong version. No it works like a charm. :partying_face:

I had the same thing here with a touch display for the Raspberry. But there was not “touch”. Either its hard to differentiate for the shop to. Or it is a trick.

1 Like

Thank you very much for your inspiration. :wink:

4 Likes

hello,

nice work, can you share the esphome code please?

Thanks

Thanks.

Awesome Spotify Touch Control via ILI9341-Screen

Would you mind sharing your complete code? I do also have a 2.8 inch screen and I am just wondering how this works in the “display” section of esphome since on the homepage there is only considered the 2.4 inch screen.

Hey guys, new to the forums and HA. I have been trying to figure out how to use this touch controller with different display pages. The ‘touchscreen’ component has the option for page_id but this component does not, AFAIK. I’m hoping it does and I’m just not doing it right.

So far I have the 3 day weather across the lower portion of the screen and 8 buttons for controlling various functions in my room (lights and TV’s) in a grid at the top. I added different icons for displaying the state of the devices (on/off only). Then the date and time at the bottom.

What I’m trying to now do is add another page with different info and buttons. I figured out how to do it on the display but I cannot get the touch areas to change with the new display page.

color:
  - id: red
    red: 100%
    green: 0%
    blue: 0%
  - id: my_red
    red: 100%
    green: 3%
    blue: 5%
  - id: blue
    red: 0%
    green: 0%
    blue: 100%
  - id: green
    red: 0%
    green: 100%
    blue: 0%
  - id: yellow
    red: 100%
    green: 100%
    blue: 0%
  - id: white
    red: 100%
    green: 100%
    blue: 100%
  - id: black
    red: 0%
    green: 0%
    blue: 0%
  - id: orange
    red: 100%
    green: 73%
    blue: 0%
  - id: purple
    green: 0%
    red: 80%
    blue: 100%
  - id: grey
    red: 66%
    green: 66%
    blue: 66%
  - id: dkgreen
    red: 0%
    green: 66%
    blue: 0%
  - id: redorange
    red: 90%
    green: 35%
    blue: 0%
  - id: yellowgreen
    red: 52%
    green: 99%
    blue: 0%
  - id: pink
    red: 100%
    green: 0%
    blue: 66%


spi:
  clk_pin: GPIO14
  mosi_pin: GPIO13
  miso_pin: GPIO27


font:
  - file: "dosis.ttf"
    id: font_e
    size: 16
  - file: "dosis.ttf"
    id: font_s
    size: 14
  - file: "dosis.ttf"
    id: font_b
    size: 20
  - file: "raleway.ttf"
    id: font_c
    size: 30
  - file: "dosis.ttf"
    id: font_d
    size: 22
  - file: 'mdi.ttf'
    id: font_icons
    size: 44
    glyphs:
      - "\U000F0590" # cloudy
      - "\U000F0595" # partlycloudy
      - "\U000F0591" # fog      
      - "\U000F0592" # hail
      - "\U000F067E" # lightning-rainy
      - "\U000F0596" # pouring
      - "\U000F0597" # rainy
      - "\U000F0F36" # snowy
      - "\U000F067F" # snowy-rainy
      - "\U000F0599" # sunny
      - "\U000F0F33" # light-rain
      - "\U000F0F34" # flurries
      - "\U000F0598" # light-snow
      - "\U000F0F35" # freezing-drizzle
      - "\U000F0502" # television off
      - "\U000F0594" # star night
      - "\U000F1A4C" # night light
      - "\U000F1051" # led strip on
      - "\U000F18DD" # multiple ceiling lights filled
      - "\U000F0335" # light bulb filled
      - "\U000F0336" # light bulb outline
      - "\U000F12CF" # multiple lights off
      - "\U000F18DE" # multiple ceiling lights outline
      - "\U000F1253" # multiple bulbs filled
      - "\U000F1254" # multiple bulbs outline
      - "\U000F1A4B" # led strip off
      - "\U000F0503" # television on
      - "\U000F0395" # dasboard

sensor:
  - platform: homeassistant
    id: temphigh
    entity_id: sensor.temphigh
    internal: True
  - platform: homeassistant
    id: templow
    entity_id: sensor.templow
    internal: True
  - platform: homeassistant
    id: precipprob
    entity_id: sensor.precipprob
  - platform: homeassistant
    id: temphigh1
    entity_id: sensor.temphigh1
    internal: True
  - platform: homeassistant
    id: templow1
    entity_id: sensor.templow1
    internal: True
  - platform: homeassistant
    id: precipprob1
    entity_id: sensor.precipprob1
  - platform: homeassistant
    id: temphigh2
    entity_id: sensor.temphigh2
    internal: True
  - platform: homeassistant
    id: templow2
    entity_id: sensor.templow2
    internal: True
  - platform: homeassistant
    id: precipprob2
    entity_id: sensor.precipprob2


text_sensor:
  - platform: homeassistant
    id: bradtv_on
    entity_id: binary_sensor.controllerv2_bradtv_on
    internal: True
  - platform: homeassistant
    id: benchdisp_on
    entity_id: binary_sensor.controllerv2_benchdisp_on
    internal: True
  - platform: homeassistant
    id: bb1_on
    entity_id: binary_sensor.controllerv2_bb1_on
    internal: True
  - platform: homeassistant
    id: uv_on
    entity_id: binary_sensor.controllerv2_uv_on
    internal: True
  - platform: homeassistant
    id: bluemood_on
    entity_id: binary_sensor.controllerv2_bluemood_on
    internal: True
  - platform: homeassistant
    id: ceiling_on
    entity_id: binary_sensor.controllerv2_ceiling_on
    internal: True
  - platform: homeassistant
    id: conditions
    entity_id: sensor.conditions
    internal: True
  - platform: homeassistant
    id: conditions1
    entity_id: sensor.conditions1
    internal: True
  - platform: homeassistant
    id: conditions2
    entity_id: sensor.conditions2
    internal: True

xpt2046:
  id: touchscreen
  cs_pin: GPIO16
  irq_pin: GPIO21
  update_interval: 50ms
  report_interval: 1s
  threshold: 400
  dimension_x: 240
  dimension_y: 320
  calibration_x_min: 3890
  calibration_x_max: 131
  calibration_y_min: 310
  calibration_y_max: 3897

output:
  - platform: ledc
    pin: GPIO22
    id: gpio_22_backlight_pwm

light:
  - platform: monochromatic
    output: gpio_22_backlight_pwm
    name: "ILI9341 Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON

binary_sensor:
# template sensors
  - platform: template
    id: keyclick_key0
    name: "Brad's TV Click"
  - platform: template
    id: keyhold_key0
    name: "Brad's TV Hold"
  - platform: template
    id: keyclick_key1
    name: "Bench Display Click"
  - platform: template
    id: keyhold_key1
    name: "Bench Display Hold"
  - platform: template
    id: keyclick_key2
    name: "Bed Light Click"
  - platform: template
    id: keyhold_key2
    name: "Bed Light Hold"
  - platform: template
    id: keyclick_key3
    name: "Night Mode Click"
  - platform: template
    id: keyhold_key3
    name: "Night Mode Hold"
  - platform: template
    id: keyclick_key4
    name: "UV Click"
  - platform: template
    id: keyhold_key4
    name: "UV Hold"
  - platform: template
    id: keyclick_key5
    name: "Mood Click"
  - platform: template
    id: keyhold_key5
    name: "Mood Hold"
  - platform: template
    id: keyclick_key6
    name: "Ceiling Lights Click"
  - platform: template
    id: keyhold_key6
    name: "Ceiling Lights Hold"
  - platform: template
    id: keyclick_key7
    name: "Dashboard Click"
  - platform: template
    id: keyhold_key7
    name: "Dashboard Hold"
# key0 definition and tests
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key0
    name: "Brad's TV"
    device_class: ''
    x_min: 0
    x_max: 60
    y_min: 0
    y_max: 60
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key0).publish_state(true);
            delay(500);
            id(keyclick_key0).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key0).publish_state(true);
            delay(500);
            id(keyhold_key0).publish_state(false);
# key1 def and test        
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key1
    name: "Bench Display"
    device_class: ''
    x_min: 60
    x_max: 120
    y_min: 0
    y_max: 60
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key1).publish_state(true);
            delay(500);
            id(keyclick_key1).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key1).publish_state(true);
            delay(500);
            id(keyhold_key1).publish_state(false);
# Key2 def and test
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key2
    name: "Bed Light"
    device_class: ''
    x_min: 120
    x_max: 180
    y_min: 0
    y_max: 60
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key2).publish_state(true);
            delay(500);
            id(keyclick_key2).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key2).publish_state(true);
            delay(500);
            id(keyhold_key2).publish_state(false);
# key3 def and tests
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key3
    name: "Night Dimming Timer"
    device_class: ''
    x_min: 180
    x_max: 240
    y_min: 0
    y_max: 60
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key3).publish_state(true);
            delay(500);
            id(keyclick_key3).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key3).publish_state(true);
            delay(500);
            id(keyhold_key3).publish_state(false);
# key4 def and tests
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key4
    name: "UV Light"
    device_class: ''
    x_min: 0
    x_max: 60
    y_min: 60
    y_max: 120
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key4).publish_state(true);
            delay(500);
            id(keyclick_key4).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key4).publish_state(true);
            delay(500);
            id(keyhold_key4).publish_state(false);
# key5 def and tests
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key5
    name: "Blue Mood"
    device_class: ''
    x_min: 60
    x_max: 120
    y_min: 60
    y_max: 120
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key5).publish_state(true);
            delay(500);
            id(keyclick_key5).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key5).publish_state(true);
            delay(500);
            id(keyhold_key5).publish_state(false);
# key6 def and tests
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key6
    name: "Ceiling Lights"
    device_class: ''
    x_min: 120
    x_max: 180
    y_min: 60
    y_max: 120
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key6).publish_state(true);
            delay(500);
            id(keyclick_key6).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key6).publish_state(true);
            delay(500);
            id(keyhold_key6).publish_state(false);
# key7 def and tests
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key7
    name: "All Off"
    device_class: ''
    x_min: 180
    x_max: 240
    y_min: 60
    y_max: 120
    internal: True
    on_click:
      - min_length: 5ms
        max_length: 500ms
        then:
          lambda: |-
            id(keyclick_key7).publish_state(true);
            delay(500);
            id(keyclick_key7).publish_state(false);
      - min_length: 1000ms
        max_length: 10000ms
        then:
          lambda: |-
            id(keyhold_key7).publish_state(true);
            delay(500);
            id(keyhold_key7).publish_state(false);


display:
  - platform: ili9341
    model: TFT 2.4
    cs_pin: GPIO26
    dc_pin: GPIO19
    led_pin: GPIO22
    reset_pin: GPIO25
    rotation: 180°
    pages:
      - id: home_page
        lambda: |-
      
          #define xcond 40  // X POS for Day 0 (center)
          #define xcond1 120 // X POS for Day 1 (center)
          #define xcond2 200 // X POS for Day 2 (center)
          #define ycond 142 // Y POS line 1 (center)
          #define ycondb 183 // Y POS line 2 (center)
          #define ycondc 225 // Y POS line 3 (center)
          #define ycondd 277 // Y POS line 4 (center)
          #define yconde 252 // Y POS line 3.5 (center)
      
          //color defs
      
          auto black = Color(0, 0, 0);
          auto yellow = Color(255, 255, 0);
          auto red = Color(255, 0, 0);
          auto green = Color(0, 255, 0);
          auto blue = Color(0, 0, 255);
          auto white = Color(255, 255, 255);
          auto orange = Color(255, 170, 0);
          auto purple = Color(200, 0, 255);
          auto grey = Color(153, 153, 153);
          auto ltgblue = Color(93, 241, 238);
          auto dkyellow = Color(90, 90, 0);
          auto ltblue = Color(134, 164, 218);
          auto ltpink = Color(150, 79, 159);
          auto dkgreen = Color(0, 175, 0);
          auto pink = Color(255, 0, 163);
      
          it.fill(Color::BLACK);  // clr screen to black
      
          // draw background
          // it.filled_rectangle(0, 0, 240, 120, ltgblue); // top behind buttons (has issue with borders combining)
          it.filled_rectangle(0, 294, 240, 26, dkyellow); // bottom behind date
          it.filled_rectangle(0, 121, 240, 172, ltblue);
          // it.filled_rectangle(160, 121, 80, 172, ltblue);
          it.filled_rectangle(80, 121, 80, 172, ltpink);
      
          // drawing of buttons
          it.rectangle(0, 0, 59, 59, red);
          it.rectangle(60, 0, 59, 59, red);
          it.rectangle(120, 0, 59, 59, red);
          it.rectangle(180, 0, 59, 59, red);
          it.rectangle(0, 60, 59, 59, red);
          it.rectangle(60, 60, 59, 59, red);
          it.rectangle(120, 60, 59, 59, red);
          it.rectangle(180, 60, 59, 59, red);
          it.line(1, 59, 238, 59, orange);
          it.line(59, 1, 59, 118, orange);
          it.line(119, 1, 119, 118, orange);
          it.line(179, 1, 179, 118, orange);
          it.line(1, 119, 238, 119, orange);
          it.line(238, 1, 238, 119, orange);
      
          // drawing of button touches and icons (on or off)
          if (id(touch_key0).state) {
            it.filled_rectangle(1, 1, 57, 57, orange);
          } else {
            it.filled_rectangle(1, 1, 57, 57, black);
          }
          if (id(bradtv_on).state == "on") {
            it.printf(30, 30, id(font_icons), id(green), TextAlign::CENTER, "\U000F0503");
          } else {
            it.printf(30, 30, id(font_icons), id(green), TextAlign::CENTER, "\U000F0502");
          }
          if (id(touch_key1).state) {
            it.filled_rectangle(61, 1, 57, 57, orange);
          } else {
            it.filled_rectangle(61, 1, 57, 57, black);
          }
          if (id(benchdisp_on).state == "on") {
            it.printf(90, 30, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0503");
          } else {
            it.printf(90, 30, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0502"); 
          }
          if (id(touch_key2).state) {
            it.filled_rectangle(121, 1, 57, 57, orange);
          } else { 
            it.filled_rectangle(121, 1, 57, 57, black);
          }
          if (id(bb1_on).state == "on") {
            it.printf(150, 30, id(font_icons), id(white), TextAlign::CENTER, "\U000F0335");
          } else {
            it.printf(150, 30, id(font_icons), id(white), TextAlign::CENTER, "\U000F0336");
          }
          if (id(touch_key3).state) {
            it.filled_rectangle(181, 1, 57, 57, orange);
          } else { 
            it.filled_rectangle(181, 1, 57, 57, black);
            it.printf(210, 30, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0594");
          }
          if (id(touch_key4).state) {
            it.filled_rectangle(1, 61, 57, 57, orange);
          } else {
            it.filled_rectangle(1, 61, 57, 57, black);
          }
          if (id(uv_on).state == "on") {
            it.printf(30, 90, id(font_icons), id(blue), TextAlign::CENTER, "\U000F1051");}
          else {
            it.printf(30, 90, id(font_icons), id(blue), TextAlign::CENTER, "\U000F1A4B");
          }
          if (id(touch_key5).state) {
            it.filled_rectangle(61, 61, 57, 57, orange);
          } else {
            it.filled_rectangle(61, 61, 57, 57, black);
          }
          if (id(bluemood_on).state == "on") {
            it.printf(90, 90, id(font_icons), id(blue), TextAlign::CENTER, "\U000F1253");
          } else {
            it.printf(90, 90, id(font_icons), id(blue), TextAlign::CENTER, "\U000F1254");
          }
          if (id(touch_key6).state) {
            it.filled_rectangle(121, 61, 57, 57, orange);
          } else { it.filled_rectangle(121, 61, 57, 57, black);
          }
          if (id(ceiling_on).state == "on") {
            it.printf(150, 90, id(font_icons), id(white), TextAlign::CENTER, "\U000F18DD");
          } else {
            it.printf(150, 90, id(font_icons), id(white), TextAlign::CENTER, "\U000F18DE");
          }
          if (id(touch_key7).state) {
            it.filled_rectangle(181, 61, 57, 57, orange);
          } else {
            it.filled_rectangle(181, 61, 57, 57, black);
            it.printf(210, 90, id(font_icons), id(pink), TextAlign::CENTER, "\U000F0395");
          }

          // place temperature on screen
    
          // if (id(outdoor_temp).has_state()) {
          //   it.printf(4, 64, id(font_b), id(purple), TextAlign::TOP_LEFT, "%.1f°", id(outdoor_temp).state);}
          // it.print(4, 94, id(font_s), id(blue), TextAlign::TOP_LEFT, "Outdoor Temperature");
    

          // draw conditions icon at day0
          if (id(conditions).state == "rainy") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0597");}
          if (id(conditions).state == "heavy rain") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0596");}
          if (id(conditions).state == "light rain") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0F33");}
          if (id(conditions).state == "drizzle") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0F33");}
          if (id(conditions).state == "thunderstorm") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F067E");}
          if (id(conditions).state == "lightning") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F067E");}
          if (id(conditions).state == "clear") {
            it.printf(xcond, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
          if (id(conditions).state == "mostly clear") {
            it.printf(xcond, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
          if (id(conditions).state == "partly cloudy") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0595");}
          if (id(conditions).state == "mostly cloudy") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0595");}
          if (id(conditions).state == "cloudy") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0590");}
          if (id(conditions).state == "light fog") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0591");}
          if (id(conditions).state == "fog") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0591");}
          if (id(conditions).state == "flurries") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F34");}
          if (id(conditions).state == "light snow") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0598");}
          if (id(conditions).state == "snow") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F36");}
          if (id(conditions).state == "heavy snow") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F36");}
          if (id(conditions).state == "freezing drizzle") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F35");}
          if (id(conditions).state == "light freezing drizzle") {
            it.printf(xcond, ycond, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F35");}
          if (id(conditions).state == "freezing rain") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F067F");}
          if (id(conditions).state == "heavy freezing rain") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F067F");}
          if (id(conditions).state == "ice pellets") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions).state == "light ice pellets") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions).state == "heavy ice pellets") {
            it.printf(xcond, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions).state == "pouring") {
            it.printf(xcond, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0596");}
          if (id(conditions).state == "sunny") {
            it.printf(xcond, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
    
    
        
          // draw conditions icon at day1
          if (id(conditions1).state == "rainy") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0597");}
          if (id(conditions1).state == "heavy rain") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0596");}
          if (id(conditions1).state == "light rain") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0F33");}
          if (id(conditions1).state == "drizzle") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0F33");}
          if (id(conditions1).state == "thunderstorm") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F067E");}
          if (id(conditions1).state == "clear") {
            it.printf(xcond1, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
          if (id(conditions1).state == "lightning") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F067E");}
          if (id(conditions1).state == "mostly clear") {
            it.printf(xcond1, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
          if (id(conditions1).state == "partly cloudy") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0595");}
          if (id(conditions1).state == "mostly cloudy") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0595");}
          if (id(conditions1).state == "cloudy") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0590");}
          if (id(conditions1).state == "light fog") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0591");}
          if (id(conditions1).state == "fog") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0591");}
          if (id(conditions1).state == "flurries") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F34");}
          if (id(conditions1).state == "light snow") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0598");}
          if (id(conditions1).state == "snow") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F36");}
          if (id(conditions1).state == "heavy snow") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F36");}
          if (id(conditions1).state == "freezing drizzle") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F35");}
          if (id(conditions1).state == "light freezing drizzle") {
            it.printf(xcond1, ycond, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F35");}
          if (id(conditions1).state == "freezing rain") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F067F");}
          if (id(conditions1).state == "heavy freezing rain") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F067F");}
          if (id(conditions1).state == "ice pellets") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions1).state == "light ice pellets") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions1).state == "heavy ice pellets") {
            it.printf(xcond1, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions1).state == "pouring") {
            it.printf(xcond1, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0596");}
          if (id(conditions1).state == "sunny") {
            it.printf(xcond1, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}



          // draw conditions icon at day2
          if (id(conditions2).state == "rainy") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0597");}
          if (id(conditions2).state == "heavy rain") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0596");}
          if (id(conditions2).state == "light rain") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0F33");}
          if (id(conditions2).state == "drizzle") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0F33");}
          if (id(conditions2).state == "thunderstorm") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F067E");}
          if (id(conditions2).state == "clear") {
            it.printf(xcond2, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
          if (id(conditions2).state == "mostly clear") {
            it.printf(xcond2, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}
          if (id(conditions2).state == "partly cloudy") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0595");}
          if (id(conditions2).state == "mostly cloudy") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0595");}
          if (id(conditions2).state == "lightning") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F067E");}
          if (id(conditions2).state == "cloudy") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0590");}
          if (id(conditions2).state == "light fog") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0591");}
          if (id(conditions2).state == "fog") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0591");}
          if (id(conditions2).state == "flurries") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F34");}
          if (id(conditions2).state == "light snow") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0598");}
          if (id(conditions2).state == "snow") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F36");}
          if (id(conditions2).state == "heavy snow") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F36");}
          if (id(conditions2).state == "freezing drizzle") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F35");}
          if (id(conditions2).state == "light freezing drizzle") {
            it.printf(xcond2, ycond, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0F35");}
          if (id(conditions2).state == "freezing rain") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F067F");}
          if (id(conditions2).state == "heavy freezing rain") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F067F");}
          if (id(conditions2).state == "ice pellets") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions2).state == "light ice pellets") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions2).state == "heavy ice pellets") {
            it.printf(xcond2, ycondc, id(font_icons), id(blue), TextAlign::CENTER, "\U000F0592");}
          if (id(conditions2).state == "pouring") {
            it.printf(xcond2, ycondc, id(font_icons), id(grey), TextAlign::CENTER, "\U000F0596");}
          if (id(conditions2).state == "sunny") {
            it.printf(xcond2, ycondc, id(font_icons), id(yellow), TextAlign::CENTER, "\U000F0599");}


          // print 'precip' above the forcasted precip number
          it.print(xcond, yconde, id(font_e), id(yellowgreen), TextAlign::CENTER, "Precip");
          it.print(xcond1, yconde, id(font_e), id(yellowgreen), TextAlign::CENTER, "Precip");
          it.print(xcond2, yconde, id(font_e), id(yellowgreen), TextAlign::CENTER, "Precip");
      


        
          // print forcast, high, low and precip day0
          it.printf(xcond, ycond, id(font_c), id(my_red), TextAlign::CENTER, "%.0f°", id(temphigh).state);
          it.printf(xcond, ycondb, id(font_c), id(blue), TextAlign::CENTER, "%.0f°", id(templow).state);
          it.printf(xcond, ycondd, id(font_c), id(yellowgreen), TextAlign::CENTER, "%.2f\"", id(precipprob).state);

          // print forcast, high, low and precip day1
          it.printf(xcond1, ycond, id(font_c), id(my_red), TextAlign::CENTER, "%.0f°", id(temphigh1).state);
          it.printf(xcond1, ycondb, id(font_c), id(blue), TextAlign::CENTER, "%.0f°", id(templow1).state);
          it.printf(xcond1, ycondd, id(font_c), id(yellowgreen), TextAlign::CENTER, "%.2f\"", id(precipprob1).state);

          // print forcast, high, low and precip day2
          it.printf(xcond2, ycond, id(font_c), id(my_red), TextAlign::CENTER, "%.0f°", id(temphigh2).state);
          it.printf(xcond2, ycondb, id(font_c), id(blue), TextAlign::CENTER, "%.0f°", id(templow2).state);
          it.printf(xcond2, ycondd, id(font_c), id(yellowgreen), TextAlign::CENTER, "%.2f\"", id(precipprob2).state);


      
          // Date
          it.strftime(120, 315, id(font_d), id(redorange), TextAlign::BASELINE_CENTER, "%c", id(ntp).now());


It wouldn’t let me add the image to previous post. Apparently my S22Ultra doesn’t have enough memory … … …

Hi Brad,
this is the display part of a yaml:

display:
  - platform: ili9341
    model: TFT 2.4
    id: touch_display
    cs_pin: GPIO5
    dc_pin: GPIO4
    #led_pin:
    #  number: 15
    #  inverted: true
    reset_pin: GPIO22

    pages:
    - id: page1
      lambda: |-
        it.print( 0, 80, id(font4), id(my_blue), TextAlign::TOP_LEFT, "\U000F095F");
        if (id(extended_color_light_3).state) {
          it.image( 80,  80, id(steckdose_on));
        } else {
          it.image( 80,  80, id(steckdose));
        }
        // 3 x 4 grid
        it.line( 80,   0,  80, 319);
        it.line(160,   0, 160, 319);
        it.line(  0,  80, 239,  80);
        it.line(  0, 160, 239, 160);
        it.line(  0, 240, 239, 240);

    - id: page2
      lambda: |-
        // 3 x 4 grid
        // it.line( 80,   0,  80, 319);
        // it.line(160,   0, 160, 319);
        // it.line(  0,  80, 239,  80);
        it.line(  0, 160, 239, 160);
        it.printf(120, 240, id(font2), TextAlign::BASELINE_CENTER, "%s", id(my_text).state.c_str());
        // it.line(  0, 240, 239, 240);
        // it.print(10, 0, id(font1), id(my_red), TextAlign::TOP_LEFT, "Hello World!");
        // it.print(10, 80, id(font2), id(my_blue), TextAlign::TOP_LEFT, "Hello World!");
        // it.print(10, 160, id(font3), id(my_yellow), TextAlign::TOP_LEFT, "Hello World!");

Then touch actions:

binary_sensor:
 // here al light_3 is toggled
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key4
    x_min: 80
    x_max: 159
    y_min: 80
    y_max: 159
    on_state: 
      if: 
        condition: 
          binary_sensor.is_on: touch_key4
        then: 
        - homeassistant.service:
            service: light.toggle
            data: 
              entity_id: light.extended_color_light_3
 
 // here the pages are turned, touch_key11 ist is the last square of 12
 // the screen is divided in to 3 x 4 squares
  - platform: xpt2046
    xpt2046_id: touchscreen
    id: touch_key11
    x_min: 160
    x_max: 239
    y_min: 240
    y_max: 319
    on_state:
      if: 
        condition: 
          binary_sensor.is_on: touch_key11
        then: 
        - display.page.show_next: touch_display

But in this case the touch action is always triggered. No matter, what page is on.
To do it right, i have to ask before, which page is displayed? An then trigger the right action according the actual page.
Ich sende später ein Beispiel.

1 Like

hi i can’t figure out how to connect the TFT and the esp32. Can someone help me?
Schermata 2022-08-14 alle 12.25.30
to AZ-Delivery ESP32 DEV KitC V2.
How many wire i would connect?

Hi Giuian, it is difficult to help. I could not find detailled datasheet for this display. It is designed for arduino. Maybe the arduino programm exsample helps you out. You can compare the names of pins and translate it to the esp. The ardunio programm should run also on your esp.
I got only different touch displays.
Sorry,
Christian

Thanks Christian

i have the same screen and there is not mutch information about it. i will buy a other one.

Resurrecting my AZ-Touch project, but I cannot find any code examples for the initial config of the 2.8 screen? See below for the 2.4 screen as provided by Christian…

display:
  - platform: ili9341
    model: TFT 2.4
    id: touch_display
    cs_pin: GPIO5
    dc_pin: GPIO4
    #led_pin:
    #  number: 15
    #  inverted: true
    reset_pin: GPIO22

    pages:
    - id: page1
      lambda: |-
        it.print( 0, 80, id(font4), id(my_blue), TextAlign::TOP_LEFT, "\U000F095F");
        if (id(extended_color_light_3).state) {
          it.image( 80,  80, id(steckdose_on));
        } else {
          it.image( 80,  80, id(steckdose));
        }
        // 3 x 4 grid
        it.line( 80,   0,  80, 319);
        it.line(160,   0, 160, 319);
        it.line(  0,  80, 239,  80);
        it.line(  0, 160, 239, 160);
        it.line(  0, 240, 239, 240);

    - id: page2
      lambda: |-
        // 3 x 4 grid
        // it.line( 80,   0,  80, 319);
        // it.line(160,   0, 160, 319);
        // it.line(  0,  80, 239,  80);
        it.line(  0, 160, 239, 160);
        it.printf(120, 240, id(font2), TextAlign::BASELINE_CENTER, "%s", id(my_text).state.c_str());
        // it.line(  0, 240, 239, 240);
        // it.print(10, 0, id(font1), id(my_red), TextAlign::TOP_LEFT, "Hello World!");
        // it.print(10, 80, id(font2), id(my_blue), TextAlign::TOP_LEFT, "Hello World!");
        // it.print(10, 160, id(font3), id(my_yellow), TextAlign::TOP_LEFT, "Hello World!");

Would very much appreciate any code examples similar to above that relate to setting up the AZ-Touch 2.8 screen.

I also got one with 2.8". I will check this.

Hello Gregonic, you can use the model tft 2.4 as well. They both have resolution of 320 x 240. On the 2.8" display it looks the same, only little bit bigger.

display:
  - platform: ili9xxx
    model: TFT 2.4
    id: touch_display
    cs_pin: GPIO5
    dc_pin: GPIO4
    #led_pin:
    #  number: 15
    #  inverted: true
    reset_pin: GPIO22

GPIOs are for AZ-Touchmod ok.
Put this in your yaml. Otherwise the log gets spammed.

# Enable logging
logger:
  level: DEBUG
  logs: 
    component: ERROR

To explore your touch-coordinates use this:

touchscreen:
  platform: xpt2046
  id: my_touchscreen
  cs_pin: 14
  interrupt_pin: 27
  update_interval: 50ms
  report_interval: 1s
  threshold: 400
  swap_x_y: false
  on_touch:
    - lambda: |-
          ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
              id(my_touchscreen).x,
              id(my_touchscreen).y,
              id(my_touchscreen).x_raw,
              id(my_touchscreen).y_raw
              );

Touch with the pencil all over the place an watch the log at the same time.
The touch-areas i have defined like this:

binary_sensor:
  - platform: touchscreen
    id: touch_key0
    x_min: 0
    x_max: 79
    y_min: 0
    y_max: 79
    on_press:
    - logger.log: "Key0 was touched"

  - platform: touchscreen
    id: touch_key1
    x_min: 80
    x_max: 159
    y_min: 0
    y_max: 79
    on_state:
      - lambda: 'ESP_LOGI("main", "key1: %s", (x ? "touch" : "release"));'

Or like this to turn pages:

  - platform: touchscreen
    id: touch_key11
    x_min: 160
    x_max: 239
    y_min: 240
    y_max: 319
    on_state:
      if: 
        condition: 
          binary_sensor.is_on: touch_key11
        then: 
        - display.page.show_next: touch_display

In that case you must test, which page is displayed, to select the right reaction for that touch area action!

I have added a remote reciver and a DHT-Sensor.

Hi Christian, thank you. I’ve started implementing the setup. Here’s my code…

esphome:
  name: esp6-touch
  friendly_name: esp6-touch

esp32:
  board: nodemcu-32s
  framework:
    type: arduino

# Enable logging
logger:
  level: DEBUG
  logs: 
    component: ERROR

# Enable Home Assistant API
api:
  encryption:
    key: "<REDACTED>="

# component buzzer 
rtttl:
  output: rtttl_out
  on_finished_playback:
    - logger.log: 'Song ended!'

ota:
  password: "<REDACTED>"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp6-Touch"
    password: "<REDACTED"

captive_portal:

# Setup the screen
spi:
  clk_pin: GPIO18
  mosi_pin: GPIO23
  miso_pin: GPIO19

output:
  # buzzer
  - platform: ledc
    pin: GPIO21
    id: rtttl_out

  # backlight
  - platform: ledc
    pin: GPIO15
    id: gpio_15_backlight_pwm
    inverted: true

sensor:
  - platform: dht
    pin: GPIO25
    temperature:
      name: "Touch Temperature"
    humidity:
      name: "Touch Humidity"
    update_interval: 60s

display:
  - platform: ili9xxx
    model: TFT 2.4
    id: touch_display
    cs_pin: GPIO5
    dc_pin: GPIO4
    #led_pin:
    #  number: 15
    #  inverted: true
    reset_pin: GPIO22
    lambda: |-
      it.image(0, 0, id(bg_image));

image:
  - file: "images/background.jpeg"
    id: bg_image
#    resize: 200x200
    type: RGB24

touchscreen:
  platform: xpt2046
  id: my_touchscreen
  cs_pin: GPIO14
  interrupt_pin: GPIO27
  update_interval: 50ms
  report_interval: 1s
  threshold: 400
  swap_x_y: false
  on_touch:
    - lambda: |-
          ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
              id(my_touchscreen).x,
              id(my_touchscreen).y,
              id(my_touchscreen).x_raw,
              id(my_touchscreen).y_raw
              );

The setup I would like is to have an image displaying until someone touches the screen. After the screen is touched I want to present a menu of options.

Unfortunately the code above presents the picture like below… I’ve tried a few things but no success?

Thank you for a great write up!

I am running a 2.8 screen with lots of real estate and would like to have different touch actions on different pages. If my German doesn’t fool me, you wrote that you would get examples later.

Would it be possible to give an example on how you determine on which page the touch action is executed?

Many thanks!
Alles gute
Rob

Hi Rob! It’s true. I remeber :slightly_smiling_face:
If you want different actions depending on which page is displayed.
You first have to test which page is on the display. And then take the correct action.
As described here.
In my example:

display:
  - platform: ili9xxx
    model: TFT 2.4
    id: touch_display
    cs_pin: GPIO5
    dc_pin: GPIO4
    reset_pin: GPIO22

Define pages:

    pages:
    - id: page1
      lambda: |-
        it.print( 0, 80, id(font4), id(my_blue), TextAlign::TOP_LEFT, "\U000F095F");
        if (id(extended_color_light_3).state) {
          it.image( 80,  80, id(steckdose_on));
        } else {
          it.image( 80,  80, id(steckdose));
        }

    - id: page2
      lambda: |-
        it.printf( 120, 100, id(font2), TextAlign::BASELINE_CENTER, "%s", id(my_text).state.c_str());
        it.line(  0, 160, 239, 160);
        it.printf( 120, 200, id(font2), TextAlign::BASELINE_CENTER, "%s", id(media_artist).state.c_str());
        it.printf( 120, 240, id(font1), TextAlign::BASELINE_CENTER, "%s", id(media_title).state.c_str());

Define touchscreen:

touchscreen:
  platform: xpt2046
  id: my_touchscreen
  cs_pin: 14
  interrupt_pin: 27
  update_interval: 50ms
  threshold: 400
  calibration_x_min: 3860
  calibration_x_max: 280
  calibration_y_min: 340
  calibration_y_max: 3860

Define touch areas and actions.
Here touch area 5 on my 3 x 4 grid in portrait alignment.

binary_sensor:
  - platform: touchscreen
    id: touch_key5
    x_min: 160
    x_max: 239
    y_min: 80
    y_max: 159
    on_state:
      if: 
        condition: 
          binary_sensor.is_on: touch_key5
        then: 
          - if:
              condition:
                display.is_displaying_page: 
                  id: touch_display
                  page_id: page2
              then:
                - homeassistant.service:
                    service: input_select.select_next
                    data:
                        entity_id: input_select.scenes_bedroom

… is only executet, if page2 is displayed.

I hope, it helpes!

1 Like