Description
What MCU/Processor/Board and compiler are you using?
- BOARD: SAMD51 - Adafruit Metro M4 w/ Airlift Lite
- DISPLAY: Adafruit 480x320 Breakout (HX8357)
- COMPILER: PlatformIO/VS Code, lv_arduino, Arduino Environment, Windows 10
What do you want to achieve?
- Learn the library so I can effectively add quality screened UIs to MCU projects\products.
What have you tried so far?
- Using the stated board and display, I was able to create a project that runs the slider example based from the STM32_TFT_eSPI_Slider example.
Code to reproduce
#include <Arduino.h>
#include <SPI.h>
#include <lvgl.h>
#include <Wire.h>
#include "TouchScreen.h"
#include <Adafruit_HX8357.h>
#define LED_PIN 2
#define YP A2 // must be an analog pin, use "An" notation!
#define XM A1 // must be an analog pin, use "An" notation!
#define YM A5 // can be a digital pin
#define XP A4 // can be a digital pin
#define TS_MINX 240
#define TS_MINY 315
#define TS_MAXX 840
#define TS_MAXY 760
#define TFT_CS 13
#define TFT_DC 12
#define STMPE_CS 32
#define TFT_RST 11
#define TFT_ROTATION 1 // Landscape orientation
//Ticker tick; /* timer for interrupt handler */
Adafruit_HX8357 tft(TFT_CS, TFT_DC, TFT_RST);
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];
lv_obj_t * slider_label;
int screenWidth = 480;
int screenHeight = 320;
TouchScreen touch = TouchScreen(YM, XP, YP, XM, 300);
/* By Bodmer in https://github.com/Bodmer/TFT_eSPI/issues/581
faster and more efficient than previous one: */
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.writePixels(&color_p->full, w * h, true, true);
tft.endWrite();
lv_disp_flush_ready(disp);
}
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
{
int16_t touchX, touchY;
bool touched = false;
//bool touched = touch.getXY(touchX, touchY); // bool TFT_eTouch<T>::getXY(int16_t& x, int16_t& y)
TSPoint p = touch.getPoint();
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
if (p.z > touch.pressureThreshhold) {
touched = true;
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print("\tPressure = "); Serial.println(p.z);
}
touchX = p.x;
touchY = p.y;
if(!touched)
{
return false;
}
if(touchX>screenWidth || touchY > screenHeight)
{
// Serial.println("Y or y outside of expected parameters..");
// Serial.print("y:");
// Serial.print(touchX);
// Serial.print(" x:");
// Serial.print(touchY);
}
else
{
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
/*Save the state and save the pressed coordinate*/
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
/*Set the coordinates (if released use the last pressed 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 printEvent(String Event, lv_event_t event)
{
Serial.print(Event);
Serial.printf(" ");
switch(event) {
case LV_EVENT_PRESSED:
Serial.printf("Pressed\n");
break;
case LV_EVENT_SHORT_CLICKED:
Serial.printf("Short clicked\n");
break;
case LV_EVENT_CLICKED:
Serial.printf("Clicked\n");
break;
case LV_EVENT_LONG_PRESSED:
Serial.printf("Long press\n");
break;
case LV_EVENT_LONG_PRESSED_REPEAT:
Serial.printf("Long press repeat\n");
break;
case LV_EVENT_RELEASED:
Serial.printf("Released\n");
break;
}
}
void slider_event_cb(lv_obj_t * slider, lv_event_t event)
{
//printEvent("Slider", event);
if(event == LV_EVENT_VALUE_CHANGED) {
static char buf[4]; /* max 3 bytes for number plus 1 null terminating byte */
snprintf(buf, 4, "%u", lv_slider_get_value(slider));
lv_label_set_text(slider_label, buf); /*Refresh the text*/
int16_t value = lv_slider_get_value(slider);
value = map(value, 0, 100, 0, 255);
//analogWriteFrequency(2000); // Set PMW period to 2000 Hz instead of 1000
analogWrite(LED_PIN, value);//8-bit by default
}
}
void setup() {
Serial.begin(115200); /* prepare for possible serial debug */
pinMode(LED_PIN, OUTPUT);
lv_init();
tft.begin(); /* TFT init */
tft.setRotation(1);
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 = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.buffer = &disp_buf;
lv_disp_drv_register(&disp_drv);
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
//Set the theme..
// lv_theme_t * th = lv_theme_night_init(210, NULL); //Set a HUE value and a Font for the Night Theme
// lv_theme_set_current(th);
lv_obj_t * scr = lv_cont_create(NULL, NULL);
lv_disp_load_scr(scr);
/* Create simple label */
lv_obj_t *label = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(label, "PB6 LED DIMMER");
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, -50);
/* Create a slider in the center of the display */
lv_obj_t * slider = lv_slider_create(lv_scr_act(), NULL);
lv_obj_set_width(slider, screenWidth-75); /*Set the width*/
lv_obj_set_height(slider, 40);
lv_obj_align(slider, NULL, LV_ALIGN_CENTER, 0, 0); /*Align to the center of the parent (screen)*/
lv_obj_set_event_cb(slider, slider_event_cb); /*Assign an event function*/
/* Create a label below the slider */
slider_label = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(slider_label, "0");
lv_obj_set_auto_realign(slider, true);
lv_obj_align(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
}
void loop() {
lv_task_handler(); /* let the GUI do its work */
delay(5);
}
Questions:
I must preface these questions with the following: 1) I’m not a traditionally trained engineer (no college degree in engineering). I’m just a self taught weekend warrior who’s strong with Python and can make my way around a C\C++ Arduino sketch. 2) C/C++ outside of the Arduino IDE or PlatformIO is a bit foreign to me. 3) I suck at math and general graphics related topics (buffer, double buffer, triple buffer, vsync, etc.) I can learn this stuff eventually.
Arduino Questions:
- When will the lv_arduino project be updated to v7?
- in the lv_arduino (v6) examples, there is a my_touchpad_read function that allows me to get the touched point X/Y from my input device (through indev_drv.read_cb = my_touchpad_read). This worked for me after calibrating my input device. After trying to drop in the v7 library into my project ignoring the lv_arduino library) my touch device no longer works. I notice a lack of (or I just missed it) an equivalent my_touchpad_read function in the lv_examples (v7). Where has this functionality been moved too? How can I make my Arduino project recognize input?
- The above code works (slider widget slides from touch input) with the lv_arduino v6. But not when I try to use the standard lvgl v7 library. I can see the slider change styles to a more modern slider when I change to v7. I get no compile errors with v7, I’m just not getting any touch input.
MicroPython Questions:
- I see that there is a port to MicroPython. As much as I love Python, I’m concerned that the performance doesn’t compare to C/C++. Is this true? Or can I achieve an equivalent user experience with MicroPython?
- Has MP been updated to v7?
- Would the MP version work under Adafruit’s CircuitPython? I thought (but could be wrong) that you can use all MP under CP, but not the other way around.
Screenshot and/or video
- No Screenshots to show