Community project

ESP32 Interactive Controller

Photo of ESP32 Interactive Controller
Generated with AI

hawa.adusei

Published September 21, 2026

The ESP32 Interactive Controller brings a touchscreen interface to your projects using the UNIHIKER K10 platform. This compact device combines the powerful ESP32 microcontroller with a built-in display, making it ideal for creating interactive dashboards, control panels, and visual applications.

This guide provides everything needed to get started: a complete parts list, wiring diagram, step-by-step assembly instructions, and ready-to-use firmware based on LVGL graphics library. Simply place the K10 on a clear surface, power it via USB, and begin building custom interfaces with buttons, text, and graphics.

Wiring diagram

Loading diagram…

Assemble it in 2 steps

1. Set the K10 on a clear surface

Place the UNIHIKER K10 where you can clearly see its built-in screen. This conference picture uses the screen already inside the board, so do not connect any extra wires.

  • Keep the screen facing upward so the people and meeting table are easy to see.
  • Do not push wires into the board while it is powered; no extra wiring is needed for this drawing.

2. Power the board by USB

Connect a USB cable from the UNIHIKER K10 to your computer. The cable powers the board and lets Schematik send the conference drawing to it.

  • Use a USB cable that carries data as well as power.
  • Pull the plug by its plastic or metal connector, not by the cable itself.

Deploy the firmware

#include <Arduino.h>
#include <unihiker_k10.h>
#include <lvgl.h>


// Forward declarations
static void official(lv_obj_t *screen, int x, int y, uint32_t jacket, uint32_t skin, uint32_t hair);

UNIHIKER_K10 k10;

static lv_obj_t *box(lv_obj_t *parent, int x, int y, int w, int h,
                     uint32_t color, int radius = 0) {
  lv_obj_t *item = lv_obj_create(parent);
  lv_obj_remove_style_all(item);
  lv_obj_set_pos(item, x, y);
  lv_obj_set_size(item, w, h);
  lv_obj_set_style_bg_color(item, lv_color_hex(color), LV_PART_MAIN);
  lv_obj_set_style_bg_opa(item, LV_OPA_COVER, LV_PART_MAIN);
  lv_obj_set_style_radius(item, radius, LV_PART_MAIN);
  lv_obj_set_style_border_width(item, 0, LV_PART_MAIN);
  return item;
}

static lv_obj_t *text(lv_obj_t *parent, const char *words, int x, int y,
                      uint32_t color,
                      const lv_font_t *font = &lv_font_montserrat_14) {
  lv_obj_t *label = lv_label_create(parent);
  lv_label_set_text(label, words);
  lv_obj_set_pos(label, x, y);
  lv_obj_set_style_text_color(label, lv_color_hex(color), LV_PART_MAIN);
  lv_obj_set_style_text_font(label, font, LV_PART_MAIN);
  return label;
}

static void official(lv_obj_t *screen, int x, int y, uint32_t jacket,
                     uint32_t skin, uint32_t hair) {
  // A seated conference delegate: head, hair, jacket, tie, and chair.
  box(screen, x + 10, y, 24, 24, skin, 12);
  box(screen, x + 8, y - 3, 28, 9, hair, 5);
  box(screen, x + 4, y + 23, 36, 42, jacket, 5);
  box(screen, x + 20, y + 25, 5, 22, 0xE7C55B, 1);
  box(screen, x, y + 62, 44, 9, 0x4A5A68, 3);
  box(screen, x + 3, y + 69, 6, 20, 0x34424D, 2);
  box(screen, x + 35, y + 69, 6, 20, 0x34424D, 2);
}

void setup() {
  k10.begin();
  k10.initScreen();

  lv_obj_t *screen = lv_scr_act();
  lv_obj_set_style_bg_color(screen, lv_color_hex(0xEAF0F4), LV_PART_MAIN);
  lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, LV_PART_MAIN);

  // Bright conference-room wall, window, and floor.
  box(screen, 0, 0, 240, 320, 0xEAF0F4);
  box(screen, 0, 236, 240, 84, 0xB88463);
  box(screen, 0, 236, 240, 7, 0x8E6249);
  box(screen, 16, 28, 54, 72, 0x9DD4E6, 3);
  box(screen, 20, 32, 46, 64, 0xD8F4FA, 1);
  box(screen, 41, 32, 4, 64, 0xFFFFFF, 0);
  box(screen, 20, 62, 46, 4, 0xFFFFFF, 0);

  // Presentation screen.
  box(screen, 82, 18, 140, 94, 0x4B5664, 4);
  box(screen, 88, 24, 128, 82, 0xFFFFFF, 2);
  text(screen, "COUNCIL MEETING", 100, 33, 0x2C4A63,
       &lv_font_montserrat_14);
  box(screen, 102, 60, 98, 6, 0x5C9BD0, 2);
  box(screen, 102, 72, 72, 6, 0x78B982, 2);
  box(screen, 102, 84, 88, 6, 0xE0A04D, 2);
  box(screen, 148, 112, 6, 18, 0x4B5664, 1);
  box(screen, 124, 128, 55, 5, 0x4B5664, 2);

  // Name plaque and a large conference table.
  box(screen, 77, 144, 86, 23, 0xD9C27C, 3);
  text(screen, "OFFICIALS", 88, 148, 0x3E4A52, &lv_font_montserrat_14);
  box(screen, 10, 211, 220, 34, 0x774B37, 7);
  box(screen, 14, 211, 212, 9, 0xA56C49, 5);
  box(screen, 26, 242, 12, 51, 0x5B382B, 2);
  box(screen, 202, 242, 12, 51, 0x5B382B, 2);

  // Microphones and papers on the table.
  box(screen, 57, 194, 3, 19, 0x293C4A, 1);
  box(screen, 51, 191, 15, 5, 0x293C4A, 2);
  box(screen, 178, 194, 3, 19, 0x293C4A, 1);
  box(screen, 172, 191, 15, 5, 0x293C4A, 2);
  box(screen, 101, 199, 31, 10, 0xFFFDF5, 1);
  box(screen, 105, 202, 23, 2, 0x7B94A2, 1);

  // Five people gathered for the meeting.
  official(screen, 12, 130, 0x557EAB, 0xE8B28B, 0x4A3029);
  official(screen, 55, 135, 0x8A667E, 0xBF805D, 0x342C2B);
  official(screen, 99, 132, 0x4D737A, 0xF0BE99, 0x6A493B);
  official(screen, 143, 135, 0x6B799E, 0x8E5D43, 0x252525);
  official(screen, 186, 130, 0x6C8A65, 0xE0A37D, 0x74472F);

  // A small potted plant makes the room feel welcoming.
  box(screen, 15, 277, 22, 18, 0xB56842, 2);
  box(screen, 18, 262, 8, 18, 0x57955B, 5);
  box(screen, 26, 258, 9, 22, 0x6CA967, 5);
}

void loop() {
  // This is a still illustration, so it is drawn once rather than refreshed.
  lv_timer_handler();
  delay(5);
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace, diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik