This is the pertinent code that I have. I tried to distill everything down to nothing but a screen, the actual arc and an image for the knob.
There is code for a button, but that was just to see where the button gets placed (in the center of the arc). There’s also a few lines of code that’s commented out, mostly stuff I tried, but it either didn’t work or didn’t seem to do anything.
It’s acting just like the issue I had using lv_pct(XX) to place an object instead of an actually X/Y coord number. It looks just like the same offset that lv_pct() had. So I’m guessing it’s related, and maybe somehow something to do with a “screen” it’s using. But I just can’t find it.
I even went back to lvgl version 9.0 to see if maybe it was a bug, but this does the same thing.
(this is not everything, but should be everything that matters, code like “touch_read” are not here.
LV_IMAGE_DECLARE(pointer_south); // Name matches the C file’s variable name
void setup()
{ … (some setup, like serial…)
lv_init();
// Register print function for debugging
lv_log_register_print_cb(log_print);
// Start the SPI for the touchscreen and init the touchscreen
touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
// Set the Touchscreen rotation in landscape mode
// Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);
touchscreen.setRotation(Touch_Rotation); // TouchRotation = 1
// (as per raw data read) Z point = 0 = LowerLeft, 1 = UpperLeft, 2 = UpperRight, 3 = LowerRight
// Create a display object
lv_display_t * disp;
// Initialize the TFT display using the TFT_eSPI library
// SCREEN_HEIGHT = 320, SCREEN_WIDTH = 480
// disp = lv_tft_espi_create(SCREEN_HEIGHT, SCREEN_WIDTH, draw_buf, sizeof(draw_buf));
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
// disp = lv_display_create(480, 320);
lv_display_set_buffers(disp, draw_buf, NULL, sizeof(draw_buf), LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270); // 0 = , 90 = , 180 = , 270 = upright
lv_display_set_physical_resolution(disp, 480, 320);
lv_display_set_flush_cb(disp, flush_cb);
…(a little more setup like timer)
}
void lv_create_main_gui(void) {
/******************************************************************************************* /
// create main screen obj here
lv_obj_t * screen = lv_obj_create(NULL);
/****************************************************************************************** */
/********************************************************************************************/
// → create the arc here
lv_obj_t * arc = lv_arc_create(screen);
lv_obj_center(arc);
lv_obj_set_size(arc, 265, 265);
lv_arc_set_rotation(arc, 135);
lv_arc_set_bg_angles(arc, 0, 270);
lv_arc_set_value(arc, 75);
lv_screen_load(screen);
/******************************************************************************************* /
// create a test button here
// lv_obj_t * button = lv_button_create(lv_screen_active());
// lv_obj_center(button);
// lv_obj_set_size(button, 70, 70);
//lv_obj_center(button);
// lv_obj_align_to(button, arc, LV_ALIGN_CENTER, 0, 0);
/****************************************************************************************** /
// Create a style for the knob (arc)
static lv_style_t style_knob;
lv_style_init(&style_knob);
/****************************************************************************************** */
// → creat an image widget for the knob
lv_screen_load(screen); // just in case it needed to loaded again after style
lv_obj_t * img_knob = lv_image_create(screen);
lv_image_set_src(img_knob, &pointer_south);
lv_style_set_bg_image_src(&style_knob, img_knob);
// lv_obj_align(img_knob, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_opa(arc, LV_OPA_TRANSP, LV_PART_KNOB);
// lv_obj_set_style_bg_image_src(arc, &img_knob, LV_PART_KNOB | LV_STATE_DEFAULT);
lv_obj_set_style_bg_image_src(arc, &img_knob, LV_PART_KNOB);
// lv_obj_set_style_pad_all(arc, -30, LV_PART_KNOB);
lv_arc_align_obj_to_angle(arc, img_knob, 0);
lv_arc_rotate_obj_to_angle(arc, img_knob, (lv_arc_get_value(arc)));
lv_obj_center(img_knob);
// Set the background image source for the knob
// Apply the style to the knob part (for default and pressed states)
lv_obj_add_style(arc, &style_knob, LV_PART_KNOB | LV_STATE_DEFAULT);
lv_obj_add_style(arc, &style_knob, LV_PART_KNOB | LV_STATE_PRESSED);
lv_obj_add_event_cb(arc, arc_event_cb, LV_EVENT_VALUE_CHANGED, img_knob);
// lv_obj_align_to(img_knob, arc, LV_ALIGN_CENTER, 0, 0);
}
to make it more clear what’s happening, here’s two screen shots. The first one (should) show the pointer is very close to the knob when rotated a little bit (about 10 'oclock. When rotated further (about 5: 'oclock), it moves further away from the knob. instead of BEING the knob). So it looks like, if the new pointer was a circle, it would be placed about 50 pixels or so, to the right of the center of the arc (the red marks in the center, same as using lv_pct())
I’m my wits end, I have run out of things to try. It may be something else you just can’t do, like making that background arc a gradient. I’ve tried everything with that also, and nothing seems to work.
I need two of these, one smaller than the other, one as an indicator and one as an input device. I there’s a work around, I could do that too, but so far I’m not sure how to do that since I’m not sure how the placement is working (not going where I’m telling it to place it).