{"id":21421474,"url":"https://github.com/bolaerts/esp32-2432s028","last_synced_at":"2026-01-27T00:37:26.717Z","repository":{"id":162180995,"uuid":"585976453","full_name":"BOlaerts/ESP32-2432s028","owner":"BOlaerts","description":"Home Assistant integration using ESPHome on an esp32-2432s028 board, featuring I²C expansion and touchscreen functionalities","archived":false,"fork":false,"pushed_at":"2025-02-26T08:00:41.000Z","size":3579,"stargazers_count":153,"open_issues_count":0,"forks_count":19,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-03-16T20:14:09.937Z","etag":null,"topics":["esp32-2432s028","esphome","i2c","ili9341","spi","xpt2046"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BOlaerts.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-06T15:51:13.000Z","updated_at":"2025-03-14T03:10:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"d0be36ff-a8a4-4994-9b14-4c79e02f34de","html_url":"https://github.com/BOlaerts/ESP32-2432s028","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/BOlaerts/ESP32-2432s028","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BOlaerts%2FESP32-2432s028","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BOlaerts%2FESP32-2432s028/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BOlaerts%2FESP32-2432s028/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BOlaerts%2FESP32-2432s028/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BOlaerts","download_url":"https://codeload.github.com/BOlaerts/ESP32-2432s028/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BOlaerts%2FESP32-2432s028/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28793881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T21:49:50.245Z","status":"ssl_error","status_checked_at":"2026-01-26T21:48:29.455Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp32-2432s028","esphome","i2c","ili9341","spi","xpt2046"],"created_at":"2024-11-22T20:34:54.935Z","updated_at":"2026-01-27T00:37:26.712Z","avatar_url":"https://github.com/BOlaerts.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# ESP32-2432s028\n## Introduction\nThis repository contains some experimental setup for using the esp32-2432s028 develoment board with tft display within Home Assistant.\nOnly a few gpio pins are exposed and usable, but by using I²C you could use a MCP23017 module to add additional ports.\n\n## Hardware\n### Wiring esp32-2432s028 + BME280 sensor\nAll credits for extended pinout explanation go to macsbug, see more on: https://macsbug.wordpress.com/2022/08/17/esp32-2432s028/\n\n\u003cimg src=\"/../main/Pictures/esp32_2432s028_i2c.jpg\" width=\"40%\" alt= \"Schematic\" height=\"40%\"\u003e\n\nFlashing instructions: keep the boot button pressed when you plug in the USB cable/flasher, this will allow to flash the firmware.\n\nRemark: some boards have IO22 next to IO27 on CN1, so a single plug and cable can be used.\n[Credits to Dave W](https://github.com/dbuggz)\n\n## Software\n### SPI\nTwo separate SPI busses are being used for the display and the touchscreen.\n``` yaml\nspi:\n  - id: lcd\n    clk_pin: GPIO14\n    mosi_pin: GPIO13\n    miso_pin: GPIO12\n  - id: touch\n    clk_pin: GPIO25\n    mosi_pin: GPIO32\n    miso_pin: GPIO39\n```\n#### Display\nThe esp32-2432s028 has an ili9341 display that can be used via the lcd SPI bus:\n``` yaml\ndisplay:\n  - platform: ili9xxx\n    model: ILI9341\n    spi_id: lcd\n    cs_pin: 15\n    dc_pin: 2\n    lambda: |-\n      ...\n\n# Former led pin in the display config\noutput:\n  - platform: ledc\n    pin: 21\n    id: former_led_pin\n\n# Define a monochromatic, dimmable light for the backlight\nlight:\n  - platform: monochromatic\n    output: former_led_pin\n    name: \"Display Backlight\"\n    id: back_light\n    restore_mode: ALWAYS_ON\n```\n#### Touchscreen\nTo add touch functionalities, a touchscreen component should be added via the touch SPI bus:\n``` yaml\ntouchscreen:\n  platform: xpt2046\n  spi_id: touch\n  cs_pin: 33\n  interrupt_pin: 36\n  update_interval: 50ms\n  threshold: 400\n  calibration:\n    x_min: 280\n    x_max: 3860\n    y_min: 340\n    y_max: 3860\n  transform:\n    mirror_x: true\n    mirror_y: false\n    swap_xy: false\n\n```\n\n### I2C\nThe default gpio pins for I2C on an ESP32 are GPIO21 and GPIO22. Both of them are exposed in the extended IO connector (P3), but apparently GPIO21 is also used as a led pin in the lcd SPI bus, so it looks as if this gpio pin is somehow useless on the extended IO connector. GPIO35 which is also exposed in the extended IO connector can only be used for input, so also useless for I2C. Luckily there is another connector with GPIO27, which makes it possible to setup an I2C bus.\n``` yaml\ni2c:\n  sda: GPIO27\n  scl: GPIO22\n  scan: true\n  id: bus_a\n```\n### Force LED on back of module to stay off\n``` yaml\n# Define pins for backlight display and back LED1\noutput:\n  - platform: ledc\n    pin: GPIO21\n    id: former_led_pin\n  - platform: ledc\n    id: output_red\n    pin: GPIO4\n    inverted: true\n  - platform: ledc\n    id: output_green\n    pin: GPIO16\n    inverted: true\n  - platform: ledc\n    id: output_blue\n    pin: GPIO17\n    inverted: true\n\n# Define a monochromatic, dimmable light for the backlight\nlight:\n  - platform: monochromatic\n    output: former_led_pin\n    name: \"Display Backlight\"\n    id: back_light\n    restore_mode: ALWAYS_ON\n  - platform: rgb\n    name: LED\n    red: output_red\n    id: led\n    green: output_green\n    blue: output_blue\n    restore_mode: ALWAYS_OFF\n```\n### Demo\n#### YAML\n``` yaml\nsubstitutions:\n  devicename: \"esp32-2432s028\"\n  ssid: Esp32-2432S028 Fallback Hotspot\n  static_ip: 192.168.0.44\n  gateway: 192.168.0.1\n  subnet: 255.255.255.0\n\npackages:\n  wifi: !include common/wifi.yaml\n  \nesphome:\n  name: $devicename\n  build_path: ./build/$devicename\n\nesp32:\n  board: esp32dev\n  framework:\n    type: arduino\n\nlogger:\n\napi:\n\nota:\n  - platform: esphome\n\ncaptive_portal:\n\nspi:\n  - id: lcd\n    clk_pin: GPIO14\n    mosi_pin: GPIO13\n    miso_pin: GPIO12\n  - id: touch\n    clk_pin: GPIO25\n    mosi_pin: GPIO32\n    miso_pin: GPIO39\n\ni2c:\n  sda: GPIO27\n  scl: GPIO22\n  scan: true\n  id: bus_a\n\ncolor:\n  - id: my_red\n    red: 100%\n    green: 0%\n    blue: 0%\n  - id: my_orange\n    red: 100%\n    green: 50%\n    blue: 0%\n  - id: my_yellow\n    red: 100%\n    green: 100%\n    blue: 0%\n  - id: my_green\n    red: 0%\n    green: 100%\n    blue: 0%\n  - id: my_blue\n    red: 0%\n    green: 0%\n    blue: 100%\n  - id: my_teal\n    red: 0%\n    green: 100%\n    blue: 100%\n  - id: my_gray\n    red: 70%\n    green: 70%\n    blue: 70%\n  - id: my_white\n    red: 100%\n    green: 100%\n    blue: 100%\n\nfont:\n  - file: \"Helvetica.ttf\"\n    id: helvetica_48\n    size: 48\n  - file: \"Helvetica.ttf\"\n    id: helvetica_36\n    size: 36\n  - file: \"Helvetica.ttf\"\n    id: helvetica_24\n    size: 24\n  - file: \"Helvetica.ttf\"\n    id: helvetica_12\n    size: 12\n\nimage:\n  - file: \"power-off-button.png\"\n    id: on_off_button\n    type: binary\n  - file: \"radio-station.png\"\n    id: radio\n    type: binary\n\nbinary_sensor:\n  - platform: status\n    name: \"Node Status\"\n    id: system_status\n\n  - platform: touchscreen\n    name: Power\n    x_min: 30\n    x_max: 90\n    y_min: 20\n    y_max: 80\n\n  - platform: touchscreen\n    name: Music\n    x_min: 150\n    x_max: 210\n    y_min: 20\n    y_max: 80\n\ntime:\n  - platform: homeassistant\n    id: esptime\n\ntext_sensor:\n  - platform: template\n    # name: Uptime Human Readable\n    id: uptime_human\n    icon: mdi:clock-start\n    internal: True\n\n  - platform: wifi_info\n    ip_address:\n      # name: ESP IP Address\n      id: ip_address\n\nsensor:\n  - platform: uptime\n    # name: Uptime Sensor\n    internal: True\n    id: uptime_sensor\n    update_interval: 1s\n    on_raw_value:\n      then:\n        - text_sensor.template.publish:\n            id: uptime_human\n            state: !lambda |-\n              int seconds = round(id(uptime_sensor).raw_state);\n              int days = seconds / (24 * 3600);\n              seconds = seconds % (24 * 3600);\n              int hours = seconds / 3600;\n              seconds = seconds % 3600;\n              int minutes = seconds /  60;\n              seconds = seconds % 60;\n              return (\n                (\"Uptime \") +\n                (days ? to_string(days) + \"d \" : \"\") +\n                (hours ? to_string(hours) + \"h \" : \"\") +\n                (minutes ? to_string(minutes) + \"m \" : \"\") +\n                (to_string(seconds) + \"s\")\n              ).c_str();\n\n  - platform: wifi_signal\n    # name: \"WiFi Signal Sensor\"\n    internal: True\n    id: wifi_signal_sensor\n    update_interval: 5s\n\n  - platform: bmp280_i2c\n    temperature:\n      name: \"Temperatuur\"\n      unit_of_measurement: °C\n      accuracy_decimals: 1\n      id: \"bme_temperature\"\n    pressure:\n      name: \"Luchtdruk\"\n      unit_of_measurement: hPa\n      accuracy_decimals: 0\n      id: \"bme_humidity\"\n    address: 0x76\n    update_interval: 30s        \n\ndisplay:\n  - platform: ili9xxx\n    model: ILI9341\n    spi_id: lcd\n    cs_pin: 15\n    dc_pin: 2\n    invert_colors: false\n    lambda: |-\n      int hs = it.get_width() / 2; // Horizontal Spacing = text data horizontal center point\n      int hq = it.get_width() / 4; // text data horizontal center for two vertical lines\n      int vs = it.get_height() / 8; // Vertical Center = text data vertical center point = how many lines\n      int line_gap = 21; // distance of line from center of data text\n      it.rectangle(0,  0, it.get_width(), it.get_height(), id(my_blue));\n      it.rectangle(0, 20, it.get_width(), it.get_height(), id(my_blue));\n      \n      it.strftime(5, 5, id(helvetica_12), id(my_white), TextAlign::TOP_LEFT, \"%H:%M:%S\", id(esptime).now());\n      it.print(hs, 5, id(helvetica_12), id(my_blue), TextAlign::TOP_CENTER, \"${devicename}\"); //print title  \n      \n      if (id(system_status).state) {\n        it.print(it.get_width()-5, 5, id(helvetica_12), id(my_green), TextAlign::TOP_RIGHT, \"Online\");\n      }\n      else {\n        it.print(it.get_width()-5, 5, id(helvetica_12), id(my_red), TextAlign::TOP_RIGHT, \"Offline\");\n      }\n      it.line(0, it.get_height()-20, it.get_width(), it.get_height()-20, id(my_blue)); // line across bottom above footer text\n      it.printf(5, it.get_height()-3, id(helvetica_12), id(my_gray), TextAlign::BOTTOM_LEFT, \"%s\", id(uptime_human).state.c_str());\n      it.printf(hs, it.get_height()-3, id(helvetica_12), id(my_gray), TextAlign::BOTTOM_CENTER, \"%.0fdBm\", id(wifi_signal_sensor).state);\n      it.printf(it.get_width()-5, it.get_height()-3, id(helvetica_12), id(my_gray), TextAlign::BOTTOM_RIGHT, \"%s\", id(ip_address).state.c_str());\n      it.image(hq - 25, 50, id(on_off_button));\n      it.image(3*hq - 25, 50, id(radio));\n\n      it.line(0, vs * 3, it.get_width(), vs * 3, id(my_blue));\n      it.print(hs, vs * 3 + line_gap, id(helvetica_24), id(my_white), TextAlign::CENTER, \"BME280 sensor\");\n      it.line(0, vs * 4, it.get_width(), vs * 4, id(my_blue));\n      it.print(hq, vs * 5, id(helvetica_12), id(my_white), TextAlign::CENTER, \"Temperature:\");\n      it.printf(3*hq, vs * 5, id(helvetica_12), id(my_white), TextAlign::CENTER, \"%.1f°C\", id(bme_temperature).state);\n      it.print(hq, vs * 6, id(helvetica_12), id(my_white), TextAlign::CENTER, \"Pressure:\");\n      it.printf(3*hq, vs * 6, id(helvetica_12), id(my_white), TextAlign::CENTER, \"%.0fhPa\", id(bme_humidity).state);\n\n# Define pins for backlight display and back LED1\noutput:\n  - platform: ledc\n    pin: GPIO21\n    id: former_led_pin\n  - platform: ledc\n    id: output_red\n    pin: GPIO4\n    inverted: true\n  - platform: ledc\n    id: output_green\n    pin: GPIO16\n    inverted: true\n  - platform: ledc\n    id: output_blue\n    pin: GPIO17\n    inverted: true\n\n# Define a monochromatic, dimmable light for the backlight\nlight:\n  - platform: monochromatic\n    output: former_led_pin\n    name: \"Display Backlight\"\n    id: back_light\n    restore_mode: ALWAYS_ON\n  - platform: rgb\n    name: LED\n    red: output_red\n    id: led\n    green: output_green\n    blue: output_blue\n    restore_mode: ALWAYS_OFF\n\ntouchscreen:\n  platform: xpt2046\n  spi_id: touch\n  cs_pin: 33\n  interrupt_pin: 36\n  update_interval: 50ms\n  report_interval: 1s\n  threshold: 400\n  calibration:\n    x_min: 280\n    x_max: 3860\n    y_min: 340\n    y_max: 3860\n  transform:\n    mirror_x: true\n    mirror_y: false\n    swap_xy: false\n\n# Exposed switches.\nswitch:\n  - platform: restart\n    name: ESP32-2432S028 Restart\n```\n#### Screenshot\n\u003cimg src=\"/../main/Pictures/esp32_2432s028_demo.jpg\" width=\"40%\" alt= \"Schematic\" height=\"40%\"\u003e\n\n#### Home Assistant integration\n\u003cimg src=\"/../main/Pictures/esp32_2432s028_home_assistant.jpg\" width=\"80%\" alt= \"Schematic\" height=\"80%\"\u003e\n\n### Enclosure options\n- https://www.thingiverse.com/thing:5680106\n- https://www.thingiverse.com/thing:5905855\n \n### Update 19.07.2023: attempt to make a Home Assistant remote control\nUsing one of the above enclosure options, a 600 MAh 3.7V battery and a MT3608 step-up convertor, I tried to make a Home Assistant remote control.\nConclusion: it works, but unfortunately I didn't manage to keep it working for an acceptable period of time, even with deep sleep implemented.\n\n\u003cimg src=\"/../main/Pictures/esp32_2432s028_remote.jpg\" width=\"40%\" alt= \"Remote control\" height=\"40%\"\u003e\n\n\u003cimg src=\"/../main/Pictures/esp32_2432s028_remote_open.jpg\" width=\"40%\" alt= \"Remote control under the hood\" height=\"40%\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbolaerts%2Fesp32-2432s028","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbolaerts%2Fesp32-2432s028","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbolaerts%2Fesp32-2432s028/lists"}