What MCU/Processor/Board and compiler are you using?
Ubuntu on Raspberry pi 2
What LVGL version are you using?
9
What do you want to achieve?
Ability to blank out touch screen on inactivity and wake up on touch
What have you tried so far?
Considering my application is running on Linux directly painting into the framebuffer, so far i have tried implementing my own screen saver mostly on the Linux system level using setterm blanking:
Tty using setterm is configured to blank the screen after let’s say 1 min
I have a script that monitors events coming from the touch screen that un-blanks the screen when touch is detected
This approach mostly works. The issue is that when screen un-blanks lvgl app does not repaint fully, just some part that was ‘touched’. This also presents a UX issue because the ‘wake up’ touch actually may trigger some action on the screen that user is not intending.
So i thought of few options:
find if there s a way to trigger full repaint of the lvgl app - so far no luck . This would solve the repaint problem but would not solve the unintended click of the user on something. I have also implemented a way to send a signal to the application itself on touch, but again not sure if there is a way to force full repaint.
use lvgl’s inactivity detection and cover the screen with a semi transparent overlay a bit before when the screen gets blanked out. This way, when the screen is touched there is only one action on the screen - click on the overlay, removing which will also repaint the whole screen. ← solves both problems: repaint and unintended actions
Wondering if there are other ways of doing it? Has anyone tried doing screen saver with a similar hardware+ OS setup ? Or may anyone has any other advice.
Another (better?) idea I have is to use my app to drive the screensaver.
Something along these lines:
use lv_disp_get_inactive_time to detect inactivity
when inactivity is detected paint semi-transparent overlay over the screen and note that time
in X number of seconds if is still in inactive mode - execute the system call to power down the screen
add a hook to evdev touch screen callback to unblank the screen and remove inactivity overlay if already inactive and screen off. If touch happens within those X seconds after inactivity is detected, but the screen is still ON - just remove the overlay.
it’s actually pretty easy to do. You would need to make a custom indev callback routine to capture touch input. This would globally catch any touch input and you would be able to decide if the touch gets forwarded to LVGL or not. That would handle the touch issues. That blanking of the display is pretty easy as well. create an object and set it to have black as the background color. Hide this object. during inactive times unhide the object and set it as the top most object. when touch comes in hide the object and set it as the bottom most object. You would make the size of the object the same size as your display.
What I ended up doing was to modify my timer loop in the main to check for inactivity and push the semi-transparent overlay screen over my application. Then, in a few seconds, the screen is ‘blanked out’ using setterm - system blanking actually takes care of shutting down the backlight of the LCD which is a great benefit that would not be available with a black screen-large element. On touch, the LVGL automatically detects ‘activity’ and the next loop iteration in main triggers the reverse process for the above.
Works very well. The overlay approach also signals to the user that the device is soon to go to the ‘sleep’ mode, similar to many other devices that behave same way.
Next, I will be adding more to the sleep to stop spinning the timer loop until a new touch event happens and that’s when intercepting the actual touch even will be very useful.
Again, thanks for your prompt response and suggestions.
What is the best practice to have the custom touch not forward the touch input to LVGL but do trigger to turn off the screensaver?
What I currently try using LVGL from the master branch is first check if there is a touch and then check if the screensaver is on. If so:
Reset the flag indicating that the screensaver is off.
Turn on the display
lv_disp_trig_activity(NULL)
set the state to LV_INDEV_STATE_RELEASED and return
However, LVGL still registers the touch resulting in stopping the screensaver AND touching a button. I guess this is because your finger is still touching the touch screen in the next callback and thus triggering the touch also in LVGL.
See my code below, how should I do this properly?
void TouchRead(lv_indev_t *indev, lv_indev_data_t *data)
{
panel->getLcdTouch()->readData();
bool touched = panel->getLcdTouch()->getTouchState();
if(touched) {
if (screenSaver)
{
screenSaver = false; // If the screen saver is active, turn it off
lv_disp_trig_activity(NULL); // and reset the display activity timer
DisplayOn(); // Turn on the display
data->state = LV_INDEV_STATE_RELEASED; // and ignore the touch event
return;
}
// Screen saver is not active, so process the touch event
TouchPoint point = panel->getLcdTouch()->getPoint();
data->point.x = point.x;
data->point.y = point.y;
data->state = LV_INDEV_STATE_PRESSED;
}
else
{
data->state = LV_INDEV_STATE_RELEASED;
}
}
Indeed it does not work because your finger is still touching the touch screen in the next call back.
The solution below does solve this problem, but it looks very much like a bad hack, what is the proper solution?
void TouchRead(lv_indev_t *indev, lv_indev_data_t *data)
{
panel->getLcdTouch()->readData();
bool touched = panel->getLcdTouch()->getTouchState();
static unsigned long screenSaverStoppedTime = 0;
if(millis() - screenSaverStoppedTime < 100) // Disable touch for 100ms after touch to turn off the screen saver
{
data->state = LV_INDEV_STATE_RELEASED;
return;
}
if(touched) {
if (screenSaver)
{
screenSaver = false; // If the screen saver is active, turn it off
lv_disp_trig_activity(NULL); // and reset the display activity timer
DisplayOn(); // Turn on the display
data->state = LV_INDEV_STATE_RELEASED; // and ignore the touch event
screenSaverStoppedTime = millis();
return;
}
// Screen saver is not active, so process the touch event
TouchPoint point = panel->getLcdTouch()->getPoint();
data->point.x = point.x;
data->point.y = point.y;
data->state = LV_INDEV_STATE_PRESSED;
}
else
{
data->state = LV_INDEV_STATE_RELEASED;
}
}