Jump to content

Meter and Dial Widgets


Greg

Recommended Posts

Hello Greg,

There are currently no existing rotary widgets and our ToDo list doesn't contain them either. However, if the demand is there we can obviously get something going.
Actually you can do this yourself as it's rather straight forward: You don't have to create a new widget. Instead, you use the existing slider or progressbar widget with a custom rendering routine.
Unlike with other (embedded) GUI libraries, widgets in µGFX are distinguished by their attributes and by the way they behave - not by the way the look like. A rotary dialg / meter consists of a minimum, a maximum and a current value - that's exactly what the slider and the progressbar widgets do. The look of a widget can be completely customized through a custom rendering routine. The custom rendering routine basically overrides the paint() function of a widget and allows you to draw the widget however you like using any of the available functions from the GDISP module.
You can find further information about custom rendering routines and an easy-to-understand example here: http://wiki.ugfx.org/index.php/Creating_a_custom_rendering_routine

If you have more advanced needs it's possible to write your own widget. Sadly we don't have a guide for that yet (it's on the ToDo list!). However, the vast amount of existing widgets together with the /demos/modules/gaudio/oscilloscope demo provide enough different examples. Together with the inline documentation of the widget struct members you should be able to write a custom widget within no time. After all a widget is nothing but a custom struct that you define (the widget object) and the widget VMT (virtual method table, which is essentially a struct of function pointers) which is predefined and documented by the GWIN module. You register your functions to create, destroy and draw your widget along with the functions to handle mouse events and so on in that VMT struct. The GWIN module will automatically call them and provide you with the normalized coordinate parameters and so on.
This might sound a bit complex at first but it's really straight forward once you got into it :)

Please do not hesitate to ask any questions. We are happy to help wherever we can!

Link to comment
Share on other sites

Thanks Joel

Bu I am not to that level of programming ability as yet, I am self taught and an old fellow.

I was wishing for it to be part of the uGFX studio eventually.

I originally and stupidly purchased most of the Mikroelektronika compilers and Visual TFT to attempt to build instrument panels for cars that my son and I were rebuilding.

But Mikroelektronika only support hardware that they sell and If you want to support other stuff then GCC and uGFX is your only affordable option as a hobbyist .

Sorry for being so ignorant but I have bigger ideas than capabilities which drives me to learn but limits my success .

Any how I love ugfx and I am going to attempt to study your post and make it happen.

We have built a Rusefi ECU which is awesome and the code is written using chibios and uses an STM32 discovery board. I want to eventually create an instrument panel to hook up to it and monitor the ECU signals.

Thanks Heaps for your answer.

Kind regards

Greg.

Link to comment
Share on other sites

Hello Greg,

Thank you for your feedback regarding Mikroelektronika. We often hear stories like that. Giving the user the ability to use any platform with any compiler is definitely our main goal. We currently just lack the man power to make the actual software become as extensive as that from competitive products.
I'm not seeing where you're being ignorant at all ;)

I am writing a custom widget for a customer right now. I'll ask him if it's okay if I use some of the code to write a tutorial on the wiki similar to the one for the custom rendering routine. Maybe a bit more extensive and verbose.
Edit: He said that it's okay. I will try to write the basic part of the tutorial up within the next two days.

I know Rusefi ECU as I am/was very active on the ChibiOS forum as well. It's definitely a very interesting project and I am following it silently ever since it started.

Please do not hesitate to ask any question. We are happy to help wherever we can and I am absolutely sure that you are capable of creating a custom widget. The difficult part is understanding how the software is structurized, which function calls which and so on. The actually programming part isn't that hard and your level of motivation is definitely a big bonus too.

Link to comment
Share on other sites

  • 1 month later...

Hi Joel

I have read through the custom rendering widget example and can now see roughly how to apply the widget but as for creating rotating needle , I am lost.

I first thought of using the draw arc function with 2 overlapping arcs to blank each other out except for the needle section but this would just create scrappy needle like the Nextion display one.

Ideally if ugfx had a rotate function that could rotate a needle graphic with a transparent background over an image of a gauge then it would be easy.

But I don't see any rotate functions.

Also If someone does successfully create a custom rendered Gauge Widget, is it then possible to ad these to uGFX  Studio?

Thanks Joel

Sorry for being so ignorant.

Edited by Greg
Link to comment
Share on other sites

The GMISC module provides array/matrix operations including translation, rotation and scaling. These operations can be applied on polygon items. Hence you can draw a needle using a polygon and rotate that using the GMISC functionalities. In fact, there is a demo that shows this: /demos/modules/gdisp/polygons
Let us know if you need any further help / explanations. We are happy to help wherever we can.

The µGFX-Studio currently doesn't allows adding custom widgets. However, that feature is now at the very top of the ToDo list. Either the next or the over-next version of the µGFX-Studio will definitely include this feature.
The next four weeks we won't have any time left to work on the Studio, however, after that we will put some serious time into it.

Link to comment
Share on other sites

  • 2 months later...

Hello Greg,

We created a small example of a passive dial widget for you. We hope that this helps you to understand the process.
First of all: I'm not a graphics designer. I created a simple dial face graphic in Inkscape and it took me longer to get that done than writing the rest of the widget code. So please feel free to ignore the dial face image and replace it with something nice looking in your mind:

ugfx_dial.png

The button and the slider below are part of the demo/example program: The button can be used to enable a timer that automatically sweeps the needle over the dial. The slider below can be used to manually set the needle position.

The widget we created is a bare minimum implementation example. We tried to keep the bloat as low as possible so you can focus on how it works without being distracted by "unnecessary" things. That being said, our implementation is anything but efficient and contains numerous limitations. There are many modifications and optimizations that could (and should) be made to improve resource requirements. The most important ones are:

  • The widget expects that the supplied dial face image (last parameter of the dialCreate() function) has the same dimensions as the widget itself.
  • The widget doesn't implement handlers for mouse, keyboard, toggle or dial input events. That means that it's currently a passive widget. Therefore, it could be implemented as a window rather than a widget to save a few more bytes of memory.
  • The Polygon gets "recalculated" each time the widget is being re-rendered. That is not necessary. This can be optimized so that the polygon is only calculated when creating the widget.
  • The entire image is redrawn when the angle of the needle changes. This operation could be optimized by just clearing the area the old needle covered. However, that depends on the dial face graphic. In our example you could just draw the minimum rectangle that contains the old needle using the background color. That wouldn't be possible if the dial face image also has "content" below the needle.
  • The example program uses a PNG encoded image for the dial face. That is anything but efficient on a low-power embedded platform.
  • The current version of uGFX doesn't provide anti-aliasing for arbitrary shapes. Therefore, the needle will look quite "zaggy" in some positions. You can reduce the effect by making the widget large enough.
  • Theoretically it would be possible to use the existing slider or progressbar widget and implement the dial as a custom rendering routine. However, that would impose certain limitations when implementing handling of touch events.
  • You can use fixed instead of floating matrix operations in the drawing function to transform & rotate the needle polygon to improve resource requirements. Along with that, you can use GMISC_NEED_FASTTRIG to use lookup tables for the calculation of the rotation angle rather than using the clib implementations.

We hope that helps. Please don't hesitate to ask if you have any questions. Here you go: 

Link to comment
Share on other sites

Thank you so much Joel

Its perfect as is the example code.

I really appreciate that you kept it simple as I am able to read and understand it.

I am very exited to get it running on my STM 32 discovery board and will be doing it today.

Again thanks heaps.

Link to comment
Share on other sites

No problem Greg, you are very welcome :)
Please don't hesitate to ask if you have any questions. We are happy to help wherever we can.

In the meantime we also created another example widget: A statusbar. That widget actually reads the touchscreen coordinates and sends events. You might want to have a look at that one as well: 

Link to comment
Share on other sites

  • 1 month later...

Oh wow.... I don't know what to say, that is just amazing!
We would love to see more of your project, it really looks very very very very well. Ideally we'd like to put a picture or two of that application in our demos section of the website as nice demos is what we are currently lacking.
Would it actually be possible to get the source or is this a closed-source project? Could you at least share how you implemented the gradients & transparency of those very nice looking arcs?

 

7 hours ago, Greg said:

Did you create this with ugfx or visual TFT ?

That is µGFX. It's just amazing & very impressive to see what people can do with it :) 

Link to comment
Share on other sites

Yes its ugfx, and of course, i will share my code as soon as i think its ready for public.

Just look into this small example, which i am actually using to design the arcs: https://jsfiddle.net/m5o6pagh/
The same works for ugfx if you translate the code, i actually use a modified version of the drawline function to put the pixel. This leads to some double drawing, becouse i use it excessivly to create a closed arc, but i will use the draw arc function soon to avoid this.  To prevent that the numbers or the lines are overdrawn i use a "clipping map". It is just an bool array of the display size which i am using to make a lookup. 

I hope i could give you a small image of the process, i use a lot of gimp, javascript and imagination to design this.

Link to comment
Share on other sites

  • 3 weeks later...
  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...