Knob image (file) placement is wrong

I finally got a simple image in to use as a pointer knob for an arc (25 pixels square, think square with a pointy “roof”).

It “works”, it rotates around with the original knob on the arc, but it’s offset. It’s like the arc with the new knob is bigger and placed to the right of the original arc. So when the original arc knob is at 270 degrees, the point just touches the original knob. When it’s at 0 degrees, it’s off to the right by about 50 pixels (and maybe 25 or so when at 90 degrees).

Nothing I do seems to have much (desired) effect. I can move the image left or right of the knob, but nothing that would correct this issue.

I created the image in Gimp. When you look at the image there, the zero point is the upper left corner of the image (with the point pointing downward). I’m sure that has something to do with it, but A) I don’t really know how to set that, not without having a larger file with blank space in which I can move the pointer. But still, the size is only 25 pixels, and the offset seems to be larger, so it looks like there’s something else going on.

Also, if I create and modify an object in say “create main gui”, do I also have to apply the same modifications is it’s call back? I wouldn’t think so, but the “object” is in two places, and nothing I’m doing has much effect on anything, so I though I’d ask to be sure.

Suggestions?
Thanks,

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).

Hi @OldMicroGuy

Can you provide your arc_event_cb function too please?

I can. I didn’t post it, because the pointer(knob) placement is wrong before it even makes a callback. (second photo is the default setting of 75 or so)
The call back does work, it rotates it around like it should, just in “arc” that the knob is on, is placed wrong.
Pretty sure this is what was working, to be honest, I’ve tried so much stuff, like adding styles in the callback… I’ve just ripped everything out and starting over again, with nothing but an arc, 6 lines and I’ll start from there.

static void arc_event_cb(lv_event_t * e) {
lv_obj_t * arc = lv_event_get_target_obj(e);
// lv_obj_t * arc = lv_event_get_code(e);
lv_obj_t * custom_knob = (lv_obj_t *)lv_event_get_user_data(e);
// lv_obj_align(custom_knob, LV_ALIGN_CENTER, -70, 0);
lv_obj_center(custom_knob);
lv_arc_align_obj_to_angle(arc, custom_knob, 0);
lv_arc_rotate_obj_to_angle(arc, custom_knob, (lv_arc_get_value(arc)));
}

I’m pretty sure that lv_pct() is doing the same thing, just not sure what. Like maybe using a wrong “default” screen or something.

Thanks,

So far, i’m making progress, until I use
lv_arc_rotate_obj_to_angle(arc, img_knob, (lv_arc_get_value(arc)));

The pointer gets placed on the arc, just not rotated at the correct angle. So I use the rotate command, and it gets offset. Like the rotate command wants a different object, but I don’t have another.

I found it… The root cause is me being a bonehead. The secondary cause is AI being an even bigger bone head.
:
The proper command is : lv_arc_rotate_obj_to_angle(arc, custom_knob, 0);

NOT : lv_arc_rotate_obj_to_angle(arc, custom_knob, (lv_arc_get_value(arc)));

The issue is that “arc_rotate” was rotating the pointer, but with an OFFSET = to the rotation. (so, more rotation = more offset…)

I was reading the command as rotate the knob, to the arc, using the arc’s value.

Good grief.