2025-01-18 11:25 AM - last edited on 2025-01-20 02:59 AM by Andrew Neil
Board STM32H7474I-DISCO, TouchGFX V4.24.2.
If you keep the analog/digital clock examples running (in the evaluatation board) for (say) 10 minutes then the clock on the LCD screen will be more than 15-25 seconds behind your watch. This is a massive delay: 15-25 seconds delay during 600 seconds is not nothing.
Probably reasons (my ideas)
It would be nice to know which statement is right and how to resolve this issue.
I tried to open TouchGFX Academy Tutorial3 example in STMCubeMX and create a new, dedicated timer with 20ms interrupt for the LCD update, but STMCubeMX did not allow to edit any Timer: properties of any enabled timers were empty. I also do not know how I can consume a Timer Interrupt in TouchGFX.Thanks for your help.
Louis
PS: I also would like to mention that TouchGFX Academy/Tutorial 3 increments the minute counter in every second... not in every minute. This is not a big issue but it should be fixed in the tutorial.
Solved! Go to Solution.
2025-01-24 05:03 AM - edited 2025-01-24 05:10 AM
Just sync it periodically with the RTC.
I call this in my screen view handleTickEvent():
//clock
//When every N tick execute C++ code
//Execute C++ code
tm const* timeinfoPtr = nullptr;
static tm timeinfoOld = tm();// {0};
#ifdef SIMULATOR
time_t rawtime;
time(&rawtime);
timeinfoPtr = localtime(&rawtime);
#else
//tm timeinfo={};
//timeinfoPtr = &timeinfo;
timeinfoPtr = getTimeStruct();
#endif
if (timeinfoPtr != nullptr)
{
bool timeChanged = timeinfoPtr->tm_sec!= timeinfoOld.tm_sec||
timeinfoPtr->tm_min != timeinfoOld.tm_min ||
timeinfoPtr->tm_hour != timeinfoOld.tm_hour;
bool dateChanged = timeinfoPtr->tm_mday != timeinfoOld.tm_mday ||
timeinfoPtr->tm_mon != timeinfoOld.tm_mon ||
timeinfoPtr->tm_year != timeinfoOld.tm_year;
timeinfoOld = *timeinfoPtr;
static bool timeInitialized = false;
if (!timeInitialized)
{
timeInitialized = true;
// disable animation the first time to prevent arms from rotating a lot
analogClock1.initializeTime24Hour(timeinfoPtr->tm_hour,
timeinfoPtr->tm_min,
timeinfoPtr->tm_sec);
}
else
{
// analogClock need to be updated more than 1 time per second to allow animation
analogClock1.setTime24Hour(timeinfoPtr->tm_hour,
timeinfoPtr->tm_min,
timeinfoPtr->tm_sec);
}
if (timeChanged)
{
digitalClock1.setTime24Hour( timeinfoPtr->tm_hour,
timeinfoPtr->tm_min,
timeinfoPtr->tm_sec);
}
if(dateChanged)
{
Unicode::snprintf(dateBuffer, DATE_SIZE,
"%04d-%02d-%02d",
timeinfoPtr->tm_year + TM_YEAR_BASE,
timeinfoPtr->tm_mon - TM_MONTH_OFFSET,
timeinfoPtr->tm_mday);
date.resizeToCurrentText();
date.invalidate();
}
}
2025-01-19 10:05 AM
I investigated a bit, and as I expected STM supports the performance measurement. (Thanks for that STM) In STM32H474I-DISCO board' PJ8 = RENDER_TIME and PJ3 = VSYNC_FREQ. These port pins are available on the CN6 ARDUINO connector (easy access). You need a scope and you can mesaure the VSYNC frame rate and the time is necessary to render graphics on the LCD screen.
On the attached 20250119_125653.bmp screenshot the yellow trace is the VSYNC_FREQ = 58.96Hz. It is not 60.0 Hz! This is the reason of the not accurate time measurement. The blue trace the time is necessary to render a label and a floating-point number (system tick increment time) on LCD. To render some text and a float number we need more than 15ms which just fit into the refresh rate. There is no LCD rendering overflow.
On the other screenshot (20250119_130344.bmp) the LCD is updated in every second (yellow). The blue rendering time is running time of the code which checks whether the 1 second (or more) elapsed in the handleTickEvent() interrupt service routine.
Therefore, supposing that if we increment a counter in every TouchGFX's handleTickEvent() interrupt service routine and check whether its value = 60 means 1 second is faulty and cannot be used. For accurate clock we need to keep track the elapsed time (float) and show HH:mm:ss digital clock value from the elapsed time. The only problem is you have to specify the exact VSYNC (system tick) frequency for the app.
Rather than specifying the VSYNC frequency it would be better solution using a dedicated TIMER of the MCU which generates (say) 20ms interrupt and updates the LCD from that interrupt instead of handleTickEvent().
I think if I open the TouchGFX project's IOC file in STM32CubeMX, then I can create an auto repeat timer with enabled interrupt. The question is how I can use the Timer interrupt in TouchGFX?
I have no idea about that.
Louis
2025-01-20 02:53 AM
Hello @Louie88 ,
The tick timer is meant to enable 60 fps, therefore it is not extremely accurate as it is not meant to be used as a real clock.
To a timer interrupt in TouchGFX, you have look at these videos :
Basically, there is 2 ways when you receive your interrupt, either you use a task from your RTOS that will change your time or you just set a value and react to that value in the model.cpp.
Regards,
2025-01-20 02:56 AM
2025-01-20 03:40 AM
Primary problem ... TGFX is ollllld utility and when first example for clock is created on some first board, maybe display and oscilator used on it can use VSYNC and was perfect. But autors dont warning , not use it always.
Result is many next examples and users do same mistake. Stop use this example as working code.
Stop use any timers = for this exist RTC and on networked boards combination with NTP.
2025-01-20 04:34 AM
Hi Gaetan,
I thought the examples are for demonstrating the features not for an accurate product. But should not we (users especially beginners) be warned that the clock is not accurate, it just an example how to implement the GUI and show the time and it is not intended to be an Apple watch?
Thanks for the reply and the links. They seem to be very useful.
If I find the way how the clock works right (accurate time) then I will post. it.
Thanks,
Louis
2025-01-20 04:43 AM
Hi MM..1,
Thanks for your notes. The reason why I implement my own digital clock was to be familiar with TGFX and how I can use the MCU peripherals in TGFX to show date in a nice form. The digital/analog clock app seemed to be perfect pick for this purpose. But when I got 20s delay for 10 minutes, I wanted to understand why it happens, then I wanted to correct it. Yes, I know the MCU has a dedicated RTC but using it in TGFX seemed to be impossible for a beginner with 30+ years practice (with Intel 8051, Silicon Labs Ti, STM MCUs) in embedded systems.
Louis
2025-01-20 05:01 AM
@Louie88 wrote:should not we ... be warned that the clock is not accurate, it just an example how to implement the GUI
Yes, I think so - especially as you're not the first to be caught out by this!
2025-01-21 08:10 AM
Hi guys,
I created 20ms time base by using Timer1 in H7474I-DISCO board:
Clock = 200MHz
Prescaler = 40 000
Counter = 100
Resulting 50Hz Timer1 interrupt.
In main.c from the HAL_TIM_PeriodElapsedCallback() I toggle PK1 port (Available on CN5.3 pin) and I increment lcdUpdateTick variable to show how many times the Timer 1 interrupt happened. The plan is to check if (lcdUpdateTick % 50) = 50 * 20ms = 1 sec, in mainView.cpp somehow and update the clock display.
...
uint32_t lcdUpdateTick = 0;
...
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// Existing system tick code
if (htim->Instance == TIM6) {
HAL_IncTick();
}
// My added code to toggle PK1 pin
if (htim->Instance == TIM1) {
lcdUpdateTick++;
HAL_GPIO_TogglePin(GPIOK, GPIO_PIN_1);
}
}
On scope I got 25.0000Hz, which is right because PK1 is toggled in every interrupt so the 50Hz is divided by 2 = 25Hz, I attached the screenshot.
Now my problem is how can detect this TIMER 1 interrupt in mainView.cpp? I guess I should:
Would you please send me an example how to do this right? (Maybe I wrong and there is better solution for this job...)
Thanks,
Louis
2025-01-21 08:48 AM - edited 2025-01-21 08:57 AM
HW interrupt is in real world delayd based on priority etc. But counter will show valid value, then simply in screenview tick check
if( (lcdUpdateTick/50) != lastshowedsec ) shownewsec...
and this require be
volatile uint32_t lcdUpdateTick = 0;
because is updated in ISR. And in view extern "C" it.
PS> Name it lcdUpdateTick is inappropriate.