diff --git a/ESP32_CAM_TOY_CAMERA/PART2/LVGL_TEST/LVGL_TEST.ino b/ESP32_CAM_TOY_CAMERA/PART2/LVGL_TEST/LVGL_TEST.ino new file mode 100644 index 0000000..a3cb3c5 --- /dev/null +++ b/ESP32_CAM_TOY_CAMERA/PART2/LVGL_TEST/LVGL_TEST.ino @@ -0,0 +1,112 @@ +#include +#include + +TFT_eSPI tft = TFT_eSPI(); /* TFT instance */ +static lv_disp_buf_t disp_buf; +static lv_color_t buf[LV_HOR_RES_MAX * 10]; + +#if USE_LV_LOG != 0 +/* Serial debugging */ +void my_print(lv_log_level_t level, const char * file, uint32_t line, const char * dsc) +{ + + Serial.printf("%s@%d->%s\r\n", file, line, dsc); + Serial.flush(); +} +#endif + +/* Display flushing */ +void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) +{ + uint32_t w = (area->x2 - area->x1 + 1); + uint32_t h = (area->y2 - area->y1 + 1); + + tft.startWrite(); + tft.setAddrWindow(area->x1, area->y1, w, h); + tft.pushColors(&color_p->full, w * h, true); + tft.endWrite(); + + lv_disp_flush_ready(disp); +} + +/*Read the touchpad*/ +bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data) +{ + uint16_t touchX, touchY; + + bool touched = tft.getTouch(&touchX, &touchY, 600); + + if(!touched) { + data->state = LV_INDEV_STATE_REL; + } else { + data->state = LV_INDEV_STATE_PR; + + /*Set the coordinates*/ + data->point.x = touchX; + data->point.y = touchY; + + Serial.print("Data x"); + Serial.println(touchX); + + Serial.print("Data y"); + Serial.println(touchY); + } + + return false; /*Return `false` because we are not buffering and no more data to read*/ +} + +void setup() +{ + Serial.begin(115200); /* prepare for possible serial debug */ + + lv_init(); + +#if USE_LV_LOG != 0 + lv_log_register_print_cb(my_print); /* register print function for debugging */ +#endif + + tft.begin(); /* TFT init */ + tft.setRotation(1); /* Landscape orientation */ + + uint16_t calData[5] = { 277, 3584, 252, 3468, 7 }; + tft.setTouch(calData); + + lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10); + + /*Initialize the display*/ + lv_disp_drv_t disp_drv; + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = 480; + disp_drv.ver_res = 320; + disp_drv.flush_cb = my_disp_flush; + disp_drv.buffer = &disp_buf; + lv_disp_drv_register(&disp_drv); + + /*Initialize the (dummy) input device driver*/ + lv_indev_drv_t indev_drv; + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.read_cb = my_touchpad_read; + lv_indev_drv_register(&indev_drv); + + lv_obj_t* btn = lv_btn_create(lv_scr_act(), NULL); + lv_obj_set_pos(btn, 10, 10); + lv_obj_set_size(btn, 100, 50); + lv_obj_set_event_cb(btn, btn_event_cb); + + lv_obj_t* label = lv_label_create(btn, NULL); + lv_label_set_text(label, "Button"); +} + +void btn_event_cb(lv_obj_t* btn, lv_event_t event){ + if(event == LV_EVENT_CLICKED){ + Serial.println("Clicked"); + } +} + +void loop() +{ + + lv_task_handler(); /* let the GUI do its work */ + delay(5); +} diff --git a/ESP32_CAM_TOY_CAMERA/PART2/MyToyCamera_LVGL_Setup/MyToyCamera_LVGL_Setup.ino b/ESP32_CAM_TOY_CAMERA/PART2/MyToyCamera_LVGL_Setup/MyToyCamera_LVGL_Setup.ino new file mode 100644 index 0000000..2573274 --- /dev/null +++ b/ESP32_CAM_TOY_CAMERA/PART2/MyToyCamera_LVGL_Setup/MyToyCamera_LVGL_Setup.ino @@ -0,0 +1,184 @@ +#include "esp_camera.h" +#include +#include +#include +#include + +#define PWDN_GPIO_NUM 32 +#define RESET_GPIO_NUM -1 +#define XCLK_GPIO_NUM 0 +#define SIOD_GPIO_NUM 26 +#define SIOC_GPIO_NUM 27 +#define Y9_GPIO_NUM 35 +#define Y8_GPIO_NUM 34 +#define Y7_GPIO_NUM 39 +#define Y6_GPIO_NUM 36 +#define Y5_GPIO_NUM 21 +#define Y4_GPIO_NUM 19 +#define Y3_GPIO_NUM 18 +#define Y2_GPIO_NUM 5 +#define VSYNC_GPIO_NUM 25 +#define HREF_GPIO_NUM 23 +#define PCLK_GPIO_NUM 22 + +TFT_eSPI tft = TFT_eSPI(); +static lv_disp_buf_t disp_buf; +static lv_color_t buf[LV_HOR_RES_MAX * 10]; + +void setup() { + Serial.begin(115200); + displayInit(); + lvglInit(); + cameraInit(); +} + +void loop() { + showingImage(); + lv_task_handler(); +} + +void cameraInit(){ + camera_config_t config; + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.pin_d0 = Y2_GPIO_NUM; + config.pin_d1 = Y3_GPIO_NUM; + config.pin_d2 = Y4_GPIO_NUM; + config.pin_d3 = Y5_GPIO_NUM; + config.pin_d4 = Y6_GPIO_NUM; + config.pin_d5 = Y7_GPIO_NUM; + config.pin_d6 = Y8_GPIO_NUM; + config.pin_d7 = Y9_GPIO_NUM; + config.pin_xclk = XCLK_GPIO_NUM; + config.pin_pclk = PCLK_GPIO_NUM; + config.pin_vsync = VSYNC_GPIO_NUM; + config.pin_href = HREF_GPIO_NUM; + config.pin_sscb_sda = SIOD_GPIO_NUM; + config.pin_sscb_scl = SIOC_GPIO_NUM; + config.pin_pwdn = PWDN_GPIO_NUM; + config.pin_reset = RESET_GPIO_NUM; + config.xclk_freq_hz = 10000000; + config.pixel_format = PIXFORMAT_JPEG; + config.frame_size = FRAMESIZE_QVGA; //320x240 + config.jpeg_quality = 10; + config.fb_count = 2; + + esp_err_t err = esp_camera_init(&config); + if (err != ESP_OK) { + Serial.printf("Camera init failed with error 0x%x", err); + return; + } +} + +void showingImage(){ + camera_fb_t* fb = esp_camera_fb_get(); + if(!fb || fb->format != PIXFORMAT_JPEG){ + Serial.println("Camera Capture Failed!"); + }else{ + Serial.println("Camera Image to Display Here!"); + TJpgDec.drawJpg(20, 40, (const uint8_t*)fb->buf, fb->len); + } + esp_camera_fb_return(fb); +} + +bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap){ + if( y>= tft.height()) return 0; + tft.pushImage(x, y, w, h, bitmap); + return 1; +} + +void displayInit(){ + tft.begin(); + tft.setRotation(1); + tft.fillScreen(TFT_WHITE); + + uint16_t calData[5] = { 277, 3584, 252, 3468, 7 }; + tft.setTouch(calData); + + TJpgDec.setJpgScale(1); + TJpgDec.setSwapBytes(true); + TJpgDec.setCallback(tft_output); +} + +void lvglInit(){ + lv_init(); + lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10); + + /*Initialize the display*/ + lv_disp_drv_t disp_drv; + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = 480; + disp_drv.ver_res = 320; + disp_drv.flush_cb = my_disp_flush; + disp_drv.buffer = &disp_buf; + lv_disp_drv_register(&disp_drv); + + /*Initialize the (dummy) input device driver*/ + lv_indev_drv_t indev_drv; + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.read_cb = my_touchpad_read; + lv_indev_drv_register(&indev_drv); + + lv_layout(); +} + +static void lv_layout(){ + lv_theme_t* th = lv_theme_material_init(LV_THEME_DEFAULT_COLOR_PRIMARY, LV_THEME_DEFAULT_COLOR_SECONDARY, LV_THEME_MATERIAL_FLAG_DARK, LV_THEME_DEFAULT_FONT_SMALL, LV_THEME_DEFAULT_FONT_NORMAL, LV_THEME_DEFAULT_FONT_SUBTITLE, LV_THEME_DEFAULT_FONT_TITLE); + lv_obj_t* scr = lv_obj_create(NULL, NULL); + lv_scr_load(scr); + + lv_obj_t* btn = lv_btn_create(scr, NULL); + lv_obj_set_pos(btn, 360, 100); + lv_obj_set_size(btn, 100, 100); + lv_obj_set_event_cb(btn, btn_event_cb); + + lv_obj_t* label = lv_label_create(btn, NULL); + lv_label_set_text(label, "Shot"); +} + +void btn_event_cb(lv_obj_t* btn, lv_event_t event){ + if(event == LV_EVENT_CLICKED){ + Serial.println("Clicked"); + } +} + +/* Display flushing */ +void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) +{ + uint32_t w = (area->x2 - area->x1 + 1); + uint32_t h = (area->y2 - area->y1 + 1); + + tft.startWrite(); + tft.setAddrWindow(area->x1, area->y1, w, h); + tft.pushColors(&color_p->full, w * h, true); + tft.endWrite(); + + lv_disp_flush_ready(disp); +} + +/*Read the touchpad*/ +bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data) +{ + uint16_t touchX, touchY; + + bool touched = tft.getTouch(&touchX, &touchY, 600); + + if(!touched) { + data->state = LV_INDEV_STATE_REL; + } else { + data->state = LV_INDEV_STATE_PR; + + /*Set the coordinates*/ + data->point.x = touchX; + data->point.y = touchY; + + Serial.print("Data x"); + Serial.println(touchX); + + Serial.print("Data y"); + Serial.println(touchY); + } + + return false; /*Return `false` because we are not buffering and no more data to read*/ +} diff --git a/ESP32_CAM_TOY_CAMERA/PART2/Touch_Controller_Demo/Touch_Controller_Demo.ino b/ESP32_CAM_TOY_CAMERA/PART2/Touch_Controller_Demo/Touch_Controller_Demo.ino new file mode 100644 index 0000000..9a2b19e --- /dev/null +++ b/ESP32_CAM_TOY_CAMERA/PART2/Touch_Controller_Demo/Touch_Controller_Demo.ino @@ -0,0 +1,46 @@ +//Original Source Code +//Bodmer TFT_eSPI +//https://github.com/Bodmer/TFT_eSPI/blob/master/examples/480%20x%20320/Touch_Controller_Demo/Touch_Controller_Demo.ino + +#include +#include +TFT_eSPI tft = TFT_eSPI(); + +void setup(void) { + uint16_t calibrationData[5]; + + Serial.begin(115200); + Serial.println("starting"); + + tft.init(); + + tft.setRotation(1); + tft.fillScreen((0xFFFF)); + + tft.setCursor(20, 0, 2); + tft.setTextColor(TFT_BLACK, TFT_WHITE); tft.setTextSize(1); + tft.println("calibration run"); + + tft.calibrateTouch(calibrationData, TFT_WHITE, TFT_RED, 15); + for(int i=0; i<5; i++){ + Serial.printf("%d, %d\n", i,calibrationData[i] ); + } + + tft.fillScreen((0xFFFF)); +} + +void loop() { + uint16_t x, y; + static uint16_t color; + + if (tft.getTouch(&x, &y)) { + + tft.setCursor(5, 5, 2); + tft.printf("x: %i ", x); + tft.setCursor(5, 20, 2); + tft.printf("y: %i ", y); + + tft.drawPixel(x, y, color); + color += 155; + } +} diff --git a/README.md b/README.md index 19993e8..670f71f 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Implement your project in an exquisite combination of hardware and software. * [Youtube ESP32 Project](https://www.youtube.com/playlist?list=PLnq7JUnBumAyhSBBp95MsQ5-chBAYheZw) +* [Toy Camera = ESP32CAM + ILI9488 + LVGL7 | Part 2, LVGL Configure #ESP32CAM #TOYCAM][[Video]](https://youtu.be/K4VEvUVOkG0)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_CAM_TOY_CAMERA/PART2) + * [Toy Camera = ESP32CAM + ILI9488 + LVGL7 | Part 1, Live Feed Display #ESP32CAM #TOYCAM][[Video]](https://youtu.be/K5Tr0AjK-Uc)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_CAM_TOY_CAMERA/PART1) * [ESP32 | MPU6050 | MahonyAHRS - Adding BLE module(ft. String vs Float)][[Video]](https://youtu.be/lpnG7K0-E88)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/Esp32_MPU6050_MahonyARHS)