Deska ESP32-3248S035 je cenově dostupné, ale překvapivě výkonné řešení pro tvorbu profesionálních grafických rozhraní.

Srdcem desky je dvoujádrový procesor ESP32 (240 MHz), který má více než dostatek výpočetního výkonu na to, aby plynule poháněl moderní grafickou knihovnu LVGL. Díky tomu můžete vytvářet responzivní tlačítka, grafy, posuvníky a animace, které vypadají mnohem lépe než na starých Arduinech, a to vše v jednom kompaktním modulu bez nutnosti pájení kabelů.

I když tato verze využívá starší typ dotyku (rezistivní/tlakový), s dobře napsaným kódem (viz níže) reaguje spolehlivě a je ideální pro ovládací panely.

1. Instalace podpory pro ESP32

Pokud s ESP32 pracujete poprvé, musíte Arduinu říct, co je to za čip.

  1. Otevřete Arduino IDE.
  2. Jděte do SouborVlastnosti.
  3. Do pole Správce dalších desek URL vložte: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  4. Potvrďte OK.
  5. Jděte do NástrojeVývojová deskaManažer desek.
  6. Vyhledejte esp32 a nainstalujte balíček od Espressif Systems

2. Instalace grafických knihoven

Pro oživení displeje použijeme dvě knihovny. Jednu pro hardware (driver) a druhou pro grafiku (tlačítka, okna).

Jděte do NástrojeSprávce knihoven (Ctrl+Shift+I) a nainstalujte:

LovyanGFX (od lovyan03) – verze 1.2.7 nebo novější.
  • Driver pro displeje připojené k ESP32.
lvgl (od kisvegabor) – verze 9.x.
  • Knihovna pro tvorbu uživatelských rozhraní.

3. Vytvoření souboru lv_conf.h

Knihovna LVGL v Arduino IDE vyžaduje existenci konfiguračního souboru na specifickém místě, jinak se program odmítne zkompilovat.

 

  1. Otevřete ve svém počítači složku s knihovnami Arduina. Obvykle: Dokumenty/Arduino/libraries/.
  2. Otevřete složku lvgl.
  3. Najděte soubor lv_conf_template.h a zkopírujte jej (Ctrl+C).
  4. Vraťte se o úroveň výš (zpět do Dokumenty/Arduino/libraries/).
  5. Vložte soubor sem (Ctrl+V), takže bude ležet vedle složky lvgl (ne uvnitř!).
  6. Přejmenujte tento soubor na lv_conf.h.

 

Poznámka: Pro konfiguraci knihovny LVGL byste mohli soubor upravit. Pro naše účely jsou ale výchozí nastavení vhodná.

4. Nastavení desky před nahráváním

Aby se kód nahrál správně, vyberte v menu vedle nahrávací šipky desku "ESP32 Dev Module" a správný sériový port. Pokud sériový port nevidíte, provděpodobně si budete muset doinnstalovat driver pro USB-serial převodník CH340, který je na desce.

#include <LovyanGFX.hpp>
#include <lvgl.h>

// --- NASTAVENÍ PINŮ ---
#define PIN_RED   4
#define PIN_GREEN 16
#define PIN_BLUE  17
#define PIN_BL    27 // Podsvícení

// Logika LED: Active Low (HIGH = Vypnuto, LOW = Zapnuto)
#define LED_OFF   HIGH
#define LED_ON    LOW

// --- OVLADAČ DISPLEJE (LovyanGFX) ---
class LGFX : public lgfx::LGFX_Device {
    lgfx::Panel_ST7796  _panel_instance;
    lgfx::Bus_SPI       _bus_instance;
    lgfx::Touch_XPT2046 _touch_instance;

public:
    LGFX(void) {
        {
            auto cfg = _bus_instance.config();
            cfg.spi_host = HSPI_HOST;
            cfg.spi_mode = 0;
            cfg.freq_write = 40000000;
            cfg.freq_read  = 16000000;
            cfg.pin_sclk = 14; 
            cfg.pin_mosi = 13;
            cfg.pin_miso = 12;
            cfg.pin_dc   = 2;
            cfg.dma_channel = 1; 
            _bus_instance.config(cfg);
            _panel_instance.setBus(&_bus_instance);
        }
        {
            auto cfg = _panel_instance.config();
            cfg.pin_cs           = 15;
            cfg.pin_rst          = -1;
            cfg.panel_width      = 320;
            cfg.panel_height     = 480;
            cfg.invert           = false;
            cfg.rgb_order        = false; 
            cfg.bus_shared       = true; 
            _panel_instance.config(cfg);
        }
        { 
            auto cfg = _touch_instance.config();
            // Kalibrace pro Sunton Resistive
            cfg.x_min      = 200;  
            cfg.x_max      = 3700; 
            cfg.y_min      = 200; 
            cfg.y_max      = 3700; 
            cfg.bus_shared = true; 
            cfg.spi_host = HSPI_HOST;
            cfg.freq = 2500000; 
            cfg.pin_sclk = 14;
            cfg.pin_mosi = 13;
            cfg.pin_miso = 12;
            cfg.pin_cs   = 33; 
            cfg.pin_int  = -1; // Polling mód (nutné!)
            _touch_instance.config(cfg);
            _panel_instance.setTouch(&_touch_instance);
        }
        setPanel(&_panel_instance);
    }
};

LGFX tft;

// --- PAMĚŤ A VYKRESLOVÁNÍ ---
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480
#define BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10)
static uint16_t draw_buf[BUF_SIZE]; 

void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
    uint32_t w = (area->x2 - area->x1 + 1);
    uint32_t h = (area->y2 - area->y1 + 1);
    if (tft.getStartCount() == 0) tft.endWrite();
    tft.pushImageDMA(area->x1, area->y1, w, h, (uint16_t*)px_map);
    lv_display_flush_ready(disp);
}

// --- ČTENÍ DOTYKU ---
void my_touch_read(lv_indev_t *indev, lv_indev_data_t *data) {
    uint16_t touchX, touchY;
    bool touched = tft.getTouch(&touchX, &touchY);
    if (touched) {
        data->state = LV_INDEV_STATE_PRESSED;
        
        // 1. Osa X je prohozená -> otočit
        data->point.x = SCREEN_WIDTH - touchX;

        // 2. Osa Y je v pořádku -> beze změny
        data->point.y = touchY;

        // Ochrana proti přetečení
        if(data->point.x < 0) data->point.x = 0;
        if(data->point.x >= SCREEN_WIDTH) data->point.x = SCREEN_WIDTH - 1;
        if(data->point.y < 0) data->point.y = 0;
        if(data->point.y >= SCREEN_HEIGHT) data->point.y = SCREEN_HEIGHT - 1;
        
    } else {
        data->state = LV_INDEV_STATE_RELEASED;
    }
}

// --- OBSLUHA TLAČÍTEK ---
static void btn_event_handler(lv_event_t * e) {
    int color_id = (int)(long)lv_event_get_user_data(e);
    
    // Zhasnout vše
    digitalWrite(PIN_RED, LED_OFF);
    digitalWrite(PIN_GREEN, LED_OFF);
    digitalWrite(PIN_BLUE, LED_OFF);

    // Rozsvítit vybranou
    switch(color_id) {
        case 1: digitalWrite(PIN_RED, LED_ON); break;
        case 2: digitalWrite(PIN_GREEN, LED_ON); break;
        case 3: digitalWrite(PIN_BLUE, LED_ON); break;
    }
}

void setup() {
    Serial.begin(115200);
    
    // 1. INIT PINŮ (Vypnuto při startu)
    pinMode(PIN_RED, OUTPUT);   digitalWrite(PIN_RED, LED_OFF);
    pinMode(PIN_GREEN, OUTPUT); digitalWrite(PIN_GREEN, LED_OFF);
    pinMode(PIN_BLUE, OUTPUT);  digitalWrite(PIN_BLUE, LED_OFF);
    pinMode(PIN_BL, OUTPUT);    digitalWrite(PIN_BL, HIGH);

    // 2. INIT DISPLEJE
    tft.init();
    tft.setRotation(0);
    tft.fillScreen(TFT_BLACK);
    
    // --- OPRAVA BAREV ---
    // Prohodí bajty barev (opravuje fialovou místo zelené)
    tft.setSwapBytes(true); 

    // 3. INIT LVGL
    lv_init();
    lv_display_t * disp = lv_display_create(SCREEN_WIDTH, SCREEN_HEIGHT);
    lv_display_set_buffers(disp, draw_buf, NULL, BUF_SIZE * 2, LV_DISPLAY_RENDER_MODE_PARTIAL);
    lv_display_set_flush_cb(disp, my_disp_flush);

    lv_indev_t * indev = lv_indev_create();
    lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
    lv_indev_set_read_cb(indev, my_touch_read);

    // 4. GUI
    lv_obj_t * scr = lv_screen_active();
    
    // ČERVENÁ
    lv_obj_t * btn1 = lv_button_create(scr);
    lv_obj_set_size(btn1, 150, 100);
    lv_obj_align(btn1, LV_ALIGN_TOP_MID, 0, 30);
    lv_obj_set_style_bg_color(btn1, lv_palette_main(LV_PALETTE_RED), 0);
    lv_obj_add_event_cb(btn1, btn_event_handler, LV_EVENT_CLICKED, (void*)1);
    lv_label_set_text(lv_label_create(btn1), "CERVENA");

    // ZELENÁ
    lv_obj_t * btn2 = lv_button_create(scr);
    lv_obj_set_size(btn2, 150, 100);
    lv_obj_center(btn2);
    lv_obj_set_style_bg_color(btn2, lv_palette_main(LV_PALETTE_GREEN), 0);
    lv_obj_add_event_cb(btn2, btn_event_handler, LV_EVENT_CLICKED, (void*)2);
    lv_label_set_text(lv_label_create(btn2), "ZELENA");

    // MODRÁ
    lv_obj_t * btn3 = lv_button_create(scr);
    lv_obj_set_size(btn3, 150, 100);
    lv_obj_align(btn3, LV_ALIGN_BOTTOM_MID, 0, -30);
    lv_obj_set_style_bg_color(btn3, lv_palette_main(LV_PALETTE_BLUE), 0);
    lv_obj_add_event_cb(btn3, btn_event_handler, LV_EVENT_CLICKED, (void*)3);
    lv_label_set_text(lv_label_create(btn3), "MODRA");
}

void loop() {
    lv_timer_handler();
    lv_tick_inc(5);
    delay(5);
}
FB tw

Další podobné články