Register / Login  |  Desktop view  |  Jump to bottom of page

tcMenu Arduinio library » render.setResetCallback only works once (trying to implement a screensaver)

Author: Mr.Robot
03/09/2021 18:37:58
Hi,

I have a question regarding renderer.setResetCallback. I want to use it in order to implement some kind of inactivity splash screen (like a screensaver). So, whenever the user is not pushing a button for a pre specified time, I want the splash screen to appear. Once a button is pressed, the plash screen shall disappear and the inactivity timer / counter shall be restarted. My problem is that the first appearance of the splash screen works fine as well as letting it disappear by a press of a button. The thing is, it never reappears in case the user is inactive subsequently. I am probably misunderstanding the logic behind the render reset and giveBackDisplay. Can you give me hint what I am doing wrong?

Here is my code.

In setup() of main.cpp

// register screensaver
  renderer.setResetIntervalTimeSeconds(SCREENSAVER_START_INTERVAL);
  renderer.setResetCallback([] {
    renderer.takeOverDisplay(Screen::screenSaverCallback);
  });


and the code of the callback method (within the Screen class):

int Screen::takeOverMenuCounter = 0;

void Screen::screenSaverCallback(unsigned int encoderValue, RenderPressMode clicked) {
  // in case this is the first call to the function, display the screensaver splash screen
  if (Screen::takeOverMenuCounter == 0)
    showScreenSaver();

  // in case the A button was pressed, give control back to tcmenu and restart the screensaver intervall timer
  if(clicked) {
    renderer.giveBackDisplay();
    Screen::takeOverMenuCounter = 0;
    renderer.setResetIntervalTimeSeconds(SCREENSAVER_START_INTERVAL);
    renderer.setResetCallback([] {
        renderer.takeOverDisplay(Screen::screenSaverCallback);
    });
  }

  Screen::takeOverMenuCounter++;
}

/*
 * Displays a splash screen as screensaver. Image is loaded from SPIFFS as bmp
 */ 
void Screen::showScreenSaver() {
  gfx.fillScreen(ST77XX_BLACK);
  gfx.setTextColor(ST77XX_BLACK);
  SPIFFS_ImageReader reader;
  reader.drawBMP("/system/splashscreen.bmp",gfx,0,0);
  gfx.setCursor(30, 225);
  gfx.println("<press A to continue>");
}


I also tried the same code without re-setting the timer interval within the callback (line 12) - unfortunately with the same result.

As background info (but probably doesn't matter):
I am using tcmenu on an ESP32 with an ST7789 attached to it.


---
Offtopic:
Since this is my first post some additional words. TcMenu really rocks! It takes a bit to figure out all of its functionality but it is really a time saver in order to implement nice menus. Thanks a lot for having written TcMenu in the first place and maintaining it with high quality documentation!

Author: davetcc
04/09/2021 10:11:23
Thanks for the feedback BTW, always good to know how it's used.

When you give the display back you shouldn't need to register the reset callback, the callback remains active until it's replaced again.

This seems like it's maybe an edge case bug, where the countdown doesn't restart until something is edited. Let me test it myself later today and feedback. If it is a bug, it should be trivial to fix, and can probably go into the 2.2 release BETA that's due imminently.

Author: davetcc
05/09/2021 08:22:26
I've actually tried this locally with the takeOverDisplay example and cannot recreate. It goes to screen saver and then back repeatedly just by clicking to exit the screensaver.

I recommend that you remove the setResetIntervalTimeSeconds and setResetCallback from the if(clicked) block. It is not needed as the values are persistent once set.

I'll try it later on a few other boards, to ensure it's not specific to a board, as I'm doing some testing anyway.

Author: Mr.Robot
05/09/2021 12:40:51
Thank you for your feedback!

I removed setResetIntervalTimeSeconds and setResetCallback from the if(clicked block) as you suggested. Running the code again, it seems that the callback is never called again.

Well, it only seems. After debugging a bit further I owe you an apology. Nothing wrong with your code. The callback is called again. My counter, however, issn't rest to 0 - which is why the splash screen isn't shown again. I have takeOverMenuCounter = 0 in my if(clicked) block but it seems that I am messing something up with all the static functions and variables.

So, sorry for bothering you and thanks for looking into it anyway!

---

Follow up question: Does anyone know a good site / tutorial which gives me some insight on how to use static methods & variables of a class properly? Any suggestions how to fix my code are, of course, welcome as well. smilie

EDIT (a few minutes later):

Well, here we go. Its facepalm time. smilie

image



Have a look at my code and closely watch the takeOverMenuCounter:

void Screen::screenSaverCallback(unsigned int encoderValue, RenderPressMode clicked) {
  // in case this is the first call to the function, display the screensaver splash screen
  if (takeOverMenuCounter == 0)
    showScreenSaver();

  // in case the A button was pressed, give control back to tcmenu and restart the screensaver intervall timer
  if(clicked) {
    renderer.giveBackDisplay();
    takeOverMenuCounter = 0;
  }

  takeOverMenuCounter++;
}


Did you notice that I increase it imidiatly after it is set to zero? That means, whenever the callback is called a second time, the counter is already at 1. Hence the splash screen not appearing again. Here ist the correct code (in case someone is looking for a similar functionality) and it is working like a charm:

void Screen::screenSaverCallback(unsigned int encoderValue, RenderPressMode clicked) {
  // in case this is the first call to the function, display the screensaver splash screen
  if (takeOverMenuCounter == 0) {
    showScreenSaver();
    takeOverMenuCounter++;
  }

  // in case the A button was pressed, give control back to tcmenu
  if(clicked) {
    takeOverMenuCounter = 0;
    renderer.giveBackDisplay();
   } 
}


Author: davetcc
06/09/2021 07:22:16
Great that you found it.

To avoid trying to determine if you are starting up you can use the OO CustomDrawing class:

https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/renderer-take-over-display/#object-oriented-approach-to-display-management

https://www.thecoderscorner.com/ref-docs/tcmenu/html/class_custom_drawing.html

EDIT Side note: Actually, I've tried it now on wide range of boards, and I was also able to find one board / example where the take-over display didn't appear to work properly (MKR example). I'll investigate, it could be completely unrelated. This was actually a problem between the user and the keyboard. I had not added the reset handler!




Register / Login  |  Desktop view  |  Jump to top of page