cancel
Showing results for 
Search instead for 
Did you mean: 

TouchGFX gauge not smooth

dvp
Associate II

Hello, I have an issue with my touchGFX gauge. First, let me explain what I want to do and how I currently do it.

 

What I want is receiving data from the CANbus which is a command for the gauge to which position the needle needs to point (same as a car). These commands are direct and if I write it directly to the GUI it jumps positions. It needs to move smooth to that position. 

What I have now is:

I receive CAN message with an interrupt. The received CAN message I put in a FreeRTOS queue.

From a CanTask I extract the data from the CAN message that is relevant to me and is put in a other queue (aziQueue).

In the Model.cpp tick funtion I first had this:

if (osMessageQueueGetCount(aziQueueHandle) > 0)
{
    if (osMessageQueueGet(aziQueueHandle, &aziTarget, NULL, osWaitForever) == osOK)
    {
        azi = (uint16_t)filter(aziTarget);
        modelListener->aziUpdate(azi);
    }
}

 

This was blocking the GUI, because the CAN message was send every 100ms on the bus so it slowed down the GUI update. (I need to update the gauge every thick with small steps until it reaches the command form the CAN message to make it smooth).

Now I have this as a test if it would work instead of using a queue that blocks the ticks:

volatile uint16_t aziTarget = 0;

 

In the Screen1View.cpp I have this function where I update the gauge:

void Screen1View::updateAziGauge(int azi)

 I tried both of these update functions:

gauge1.updateValue(azi, 10);

gauge1.setValue(azi);

 Still no smooth movement.

Do I miss something?

My display is 60Hz. I think that my filter is fine. Every thick it calculates the next step. 

float Model::filter(float fAzimuth)
{
	static float sfX_part = 0.0;
	static float sfY_part = 0.0;

    float fAzimuthDegrees = fAzimuth / 100.0;

    float fMovingAverageFactorOld = 1.0 - (1.0 / (float)AZIMUTH_MOVING_AVERAGE_FACTOR); //Example: when factor is 10, old value will be multiplied by 0.9
    float fMovingAverageFactorNew = 1.0 - fMovingAverageFactorOld;                      //And new value by 0.1

    sfX_part = (fMovingAverageFactorOld * sfX_part) + (fMovingAverageFactorNew * cos((fAzimuthDegrees * M_PI) / 180.0));
    sfY_part = (fMovingAverageFactorOld * sfY_part) + (fMovingAverageFactorNew * sin((fAzimuthDegrees * M_PI) / 180.0));

    float fAzimuthDegreesAveraged = (atan2(sfY_part, sfX_part) * 180.0) / M_PI;

    if (fAzimuthDegreesAveraged < 0.0)
    {
        fAzimuthDegreesAveraged += 360.0;
    }

    return fAzimuthDegreesAveraged * 100.0;
}

Some suggestions? 

4 REPLIES 4
dvp
Associate II

After further inspection, it seems that TouchGFX is limited in terms of gauge step resolution. In the attached image, you can see my current gauge settings. When I manually increase the value, the needle also stutters and jumps. Is this a common issue, or is there a configuration I need to adjust?

dvp
Associate II

Update:

I got it working smooth wit a Texture Mapper instead of a gauge. Is this the right solution/way to do this?

JohanAstrup
ST Employee

Hello @dvp.

From your description, it seems like you manually control the animation with the filter function. Unless you really want fine-grained control, I think this is an overly complicated approach. When you use the updateValue() function, you can specify a duration measured in ticks. If you want a smoother animation, you should increase this duration.
In either TouchGFX Designer, in the "Animation" section of the gauge properties pane, or by calling setEasingEquation() on the gauge object, you can specify an easing equation for the animation.

Is it correctly understood that a new value is received every 100 ms? If the gauge value is updated every 100 ms, there are only ~six ticks to animate the needle position. Now, I do not know if the value changes significantly, but it is not possible to achieve a very smooth animation in six ticks if the delta value is very large.

The gauge needle is effectively a texture mapper, so there is no difference there. The gauge widget is just an extra layer on top of the texture mapper to simplify the implementation.

Can you share a video of how it currently looks with the gauge?


Best regards,
Johan

Here is a video where the left is a gauge which updates with:

gauge1.updateValue(aziValue, 100);

For this I removed my own filtering so it reads the value from CAN data and sets it to the gauge. It also has a cubic ease out animation set.

 

The gauge on the right is a texture mapper also without my own filtering which uses this:

aziFeedback.setupAnimation(AnimationTextureMapper::Z_ROTATION, newRad, 125, 0, EasingEquations::cubicEaseOut);