# Plotting graphs

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

• # Plotting graphs

Hello,

I would need to use and integrate STemWin graphics functions in my project, but I would like to learn how to do this.
The STemWin chapter is a new subject for me, so any information / tutorials / recommandations are greatly appreciated.

Here is my information :
1. Tools : CubeMX + Atollic TrueStudio + STemWin
2. Board : STM32F429I Disc1

Purpose of project :
3. Measuring a value with ADC, then plotting it as a graph using STemWin.

Please feel free to comment if you need further information.

Sue
• Hi,

Take a look to the example below. It is very basic. I create a window and display a graph. How you feed the buffer for the graph is up to you.

### C Source Code

1. #include "DIALOG.h"
2. #include <stdlib.h>
3. #include <string.h>
4. /*********************************************************************
5. *
6. * Typedef
7. *
8. **********************************************************************
9. */
10. typedef struct {
11. U16 * pData;
12. int NumElements;
13. } GRAPH_INFO;
14. /*********************************************************************
15. *
16. * Static data
17. *
18. **********************************************************************
19. */
20. static GRAPH_INFO _GraphInfo;
21. /*********************************************************************
22. *
23. * Static code
24. *
25. **********************************************************************
26. */
27. /*********************************************************************
28. *
30. */
32. return (rand() % 80 + 1) - 40;
33. }
34. /*********************************************************************
35. *
36. * _UpdateData
37. */
38. static void _UpdateData(void) {
39. int i;
40. //
41. // Shift elemts in buffer
42. //
43. for (i = 0; i < _GraphInfo.NumElements - 1; i++) {
44. *(_GraphInfo.pData + i) = *(_GraphInfo.pData + i + 1);
45. }
46. //
48. //
49. *(_GraphInfo.pData + _GraphInfo.NumElements - 1) = _GetADValue();
50. }
51. /*********************************************************************
52. *
54. */
55. static void _cbWinADV(WM_MESSAGE * pMsg) {
56. int yPos;
57. switch (pMsg->MsgId) {
58. case WM_PAINT:
59. //
60. // Clear window with white
61. //
62. GUI_SetBkColor(GUI_WHITE);
63. GUI_Clear();
64. GUI_SetColor(GUI_RED);
65. //
66. // Draw graph
67. //
68. if (_GraphInfo.pData) {
69. yPos = WM_GetWindowSizeY(pMsg->hWin) / 2;
70. GUI_DrawGraph(_GraphInfo.pData, _GraphInfo.NumElements, 0, yPos);
71. }
72. break;
73. default:
74. WM_DefaultProc(pMsg);
75. break;
76. }
77. }
78. /*********************************************************************
79. *
80. * _cbBk
81. */
82. static void _cbBk(WM_MESSAGE * pMsg) {
83. switch (pMsg->MsgId) {
84. case WM_PAINT:
85. GUI_SetBkColor(GUI_BLACK);
86. GUI_Clear();
87. break;
88. default:
89. WM_DefaultProc(pMsg);
90. break;
91. }
92. }
93. /*********************************************************************
94. *
95. * Public code
96. *
97. **********************************************************************
98. */
99. /*********************************************************************
100. *
102. */
104. int xSize;
105. int ySize;
106. WM_HWIN hWin;
107. memset((void *)&_GraphInfo, 0, sizeof(GRAPH_INFO));
108. GUI_Init();
109. WM_MULTIBUF_Enable(1);
110. WM_SetCallback(WM_HBKWIN, _cbBk); // A callback which clears the background for regions without a window
111. //
112. // Get the size of the screen
113. //
114. xSize = LCD_GetXSize();
115. ySize = LCD_GetYSize();
116. //
117. // Create a window which should show the AD value, the value gets drawn in the callback function _cbWinADV()
118. //
119. hWin = WM_CreateWindowAsChild(10, 10, xSize - 20, ySize - 10, WM_HBKWIN, WM_CF_SHOW, _cbWinADV, 0);
120. //
121. // Init a buffer which can hold enough points for the graph
122. //
123. xSize = WM_GetWindowSizeX(hWin);
124. _GraphInfo.pData = malloc(xSize * sizeof(U16)); // Init points with 0
125. memset((void *)_GraphInfo.pData, 0, xSize * sizeof(U16));
126. _GraphInfo.NumElements = xSize;
127. //
128. // Super loop, GUI_Delay() keeps the application alive, returns after 100ms
129. //
130. while (1) {
131. GUI_Delay(100);
132. _UpdateData();
133. WM_InvalidateWindow(hWin);
134. }
135. }
136. /*************************** End of file ****************************/
Display All
Regards,

Sven
• Hi Sven,

So, I have created the project using CubeMX 5.0.1 + Atollic TrueStudio + STemWin. In the Graphics / STemWin section, I click the execute button to open GUI Builder and create Framewin c file, then generate the code.
Using Atollic, I have FramewinDLG and GUI_App files. And the code creates the skeleton of graphics on the screen. So far, it is okay.

I have then worked and tried to integrate the code you had given me, so that I can create the graph. But, I have experienced some troubles to know how to integrate the code in my project. And the questions I have now are the following :
1. How should I use the code in my project ?
2. Which part of the code should be placed in the FramewinDLG ? And which code for GUI_App ?
3. What is about the function CreateFramewin ?

Please feel free to comment if you need further or detailed information about it.

I thank you in advance for your technical help and with kind regards,

Sue
Files
• FramewinDLG.txt

• GUI_App.txt

• Hi,

try the code below.

Simply call CreateFramewin() from GRAPHICS_MainTask(). Every 100ms a timer expires and calles the callback function _cbDialog(). Here I react on WM_TIMER and get a new AD value. This value gets set as new point for the data object attached to the graph.

### C Source Code

1. /*********************************************************************
2. * *
3. * SEGGER Microcontroller GmbH & Co. KG *
4. * Solutions for real time microcontroller applications *
5. * *
6. **********************************************************************
7. * *
8. * C-file generated by: *
9. * *
10. * GUI_Builder for emWin version 5.44 *
11. * Compiled Nov 10 2017, 08:53:57 *
12. * (c) 2017 Segger Microcontroller GmbH & Co. KG *
13. * *
14. **********************************************************************
15. * *
16. * Internet: www.segger.com Support: support@segger.com *
17. * *
18. **********************************************************************
19. */
20. // USER START (Optionally insert additional includes)
21. #include <stdlib.h>
22. // USER END
23. #include "DIALOG.h"
24. /*********************************************************************
25. *
26. * Defines
27. *
28. **********************************************************************
29. */
30. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
31. #define ID_GRAPH_0 (GUI_ID_USER + 0x01)
32. // USER START (Optionally insert additional defines)
33. // USER END
34. /*********************************************************************
35. *
36. * Static data
37. *
38. **********************************************************************
39. */
40. // USER START (Optionally insert additional static data)
41. // USER END
42. /*********************************************************************
43. *
45. */
46. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
47. { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 240, 320, 0, 0x0, 0 },
48. { GRAPH_CreateIndirect, "Graph", ID_GRAPH_0, 15, 23, 200, 63, 0, 0x0, 0 },
49. // USER START (Optionally insert additional widgets)
50. // USER END
51. };
52. /*********************************************************************
53. *
54. * Static code
55. *
56. **********************************************************************
57. */
58. // USER START (Optionally insert additional static code)
59. /*********************************************************************
60. *
62. */
64. return (I16)(rand() % 50 + 1);
65. }
66. /*********************************************************************
67. *
68. * _cbBk
69. */
70. static void _cbBk(WM_MESSAGE * pMsg) {
71. switch (pMsg->MsgId) {
72. case WM_PAINT:
73. GUI_SetBkColor(GUI_BLACK);
74. GUI_Clear();
75. break;
76. default:
77. WM_DefaultProc(pMsg);
78. break;
79. }
80. }
81. // USER END
82. /*********************************************************************
83. *
84. * _cbDialog
85. */
86. static void _cbDialog(WM_MESSAGE * pMsg) {
87. // USER START (Optionally insert additional variables)
88. int xSize;
89. WM_HWIN hItem;
90. static GRAPH_DATA_Handle hData;
91. // USER END
92. switch (pMsg->MsgId) {
93. // USER START (Optionally insert additional message handling)
94. case WM_INIT_DIALOG:
95. //
96. // Init a buffer which can hold enough points for the graph
97. //
98. xSize = WM_GetWindowSizeX(pMsg->hWin);
99. hData = GRAPH_DATA_YT_Create(GUI_RED, xSize, NULL, xSize);
100. hItem = WM_GetDialogItem(pMsg->hWin, ID_GRAPH_0);
101. GRAPH_AttachData(hItem, hData);
102. WM_CreateTimer(WM_GetClientWindow(pMsg->hWin), 0, 100, 0);
103. break;
104. case WM_TIMER:
106. WM_RestartTimer((WM_HTIMER)pMsg->Data.v, 0);
107. break;
108. // USER END
109. default:
110. WM_DefaultProc(pMsg);
111. break;
112. }
113. }
114. /*********************************************************************
115. *
116. * Public code
117. *
118. **********************************************************************
119. */
120. /*********************************************************************
121. *
122. * CreateFramewin
123. */
124. WM_HWIN CreateFramewin(void);
125. WM_HWIN CreateFramewin(void) {
126. WM_HWIN hWin;
128. return hWin;
129. }
Display All

Regards,
Sven
• Hi Sven,

I thank you very much for your reply and support with my issues. This is nice of you.

So, I started the project with CubeMX + GUI Builder + Atollic, then generated the code. I then copied the code you have given me in the FramewinDLG.c of the project.
The code compiled successfully without error. However, the display screen is the same between before and after the implementation of the last code. Even the background screen did not change its colour to BLUE, as the code written after WM_PAINT in the _cbBK callback routine. I can not attach the picture of the display screen as its size is too big.

So, my questions are the following :
#1. Did I misunderstand something ? Or, did I miss to code something ?
#2. How can I learn this part of the emWIN efficiently, so that I will have a good understanding of the subject ?

Any suggestions or tips are greatly appreciated, as I have got stuck technically with this matter.

I thank you in advance and with kind regards,

Sue
Files
• FramewinDLG.txt

• GUI_App.txt

• Hi,

The callback function _cbBk() is not used, therefore it won't do anything. This was a mistake of mine because _cbBk() was a leftover of the previous example.

But the dialog with the GRAPH widget should work. Try to set a breakpoint into WM_TIMER. If you don't get there you should check the timing functions GUI_X_GetTime() and GUI_X_Delay(). Those functions are most likely located in a file named GUI_X<*>.c and required for any timing related functionalities of emWin.

The code in WM_TIMER takes care about updating the GRAPH widget. If you never end up there the GRAPH widget doesn't change.

One very important point with emWin is Window Manager especially the callback mechanism (more in chapter 18 of the emWin user manual). Every widget (and the dialogs created with the GUIBuilder) is based on the Window Manager. Also, sometimes it can be handy to create a WM-window (WM_CreateWindowAsChild()) instead of a predefined widget.

In my first example I have set up a single WM-window and used it to draw a graph.

So I recommend to take a look into the chapter about the Window Manager and how it works.

Regards,
Sven
• Good morning Sven,

I thank you a lot for your reply, and also for your recommendation. Indeed, I learn and get to know more about emWin and Window Manager on your detailed manual. It helps to better understanding about the subject.

So, here are the steps that I have been taking :
#1. Using GUI Builder to make simple and progressive samples, with the help of the manual.
#2. Taking back the samples you have given me and implement them in my project.

It is a bit difficult for me to say when I would get back to give you the feedback about the samples. I have been working to make all these points to function correctly.

I thank you for your support and see you soon.

With kind regards,

Sue
• Hi Sven,

I hope that you enjoyed your weekend.

So, IT SIMPLY WORKS! And I am a happy guy.

Firstly, I followed your suggestion about the timer and checked those 2 files. Activating the Systick handler had resolved this issue.
Secondly, I made a step-by-step approach to work on the display. And yes, I am now able to display an image and also a window for the graph.
Third step, I implemented your 2nd code in the graph window and can see its graph.
So, that is a good step forward for me and I THANK YOU very much for your helpful support and assistance. That is really great!

These days I have been learning to implement the reading input via ADC, and then display the values on the graph.
And I have this question which is not obvious for me :
#1. Where should I put my codes in the files generated by CubeMX + GUI Builder + STemWin ? The dedicated space for "user code" seems to be very limited.
#2. Where is the super loop for "the user code" ?

With kind regards,

Sue
Files
• GUI_App.txt

• main.txt

• WindowDLG.txt

• Hi,

The super loop is the while loop in GRAPHICS_MainTask() you will never return from it and it calls periodically GUI_Delay(). I would replace the HAL_Delays by GUI_Delays. The two HAL Delay() will cause a pause of 2 seconds. In this pause emWin has no chance to update the screen.

Not sure about the CubeMX procedure to generate code. This is an ST tool and I'm not really familiar with it. Regarding the GUIBuilder. You should place the code between the 'user code' sections.

To be honest, I use the GUIBuilder only to create a starting point for dialogs. The main part is done manually. For a beginner this might be a bit harder, but it gives you way more flexibility.

In most cases I create a dialog with the GUIBuilder and copy paste the required parts into my real application.

Regards,
Sven
• Good morning Sven,

So, your explication confirms my understanding about the super loop and also the several C files generated by CubeMX and GUI Builder.
Using CubeMX 5.0.1 and GUI Builder to start a project, there are main, GUI_App, WindowDLG / FramewinDLG and also other files generated. The super loop in function GRAPHICS_MainTask() is not clearly dedicated for 'user code'. And consequently, when the same project is regenerated with CubeMX, all the codes that are implemented in the super loop are deleted.

I have got one question regarding this :
#1. Is there a method to implement the codes within the super loop that will NOT be deleted ?
My understanding is that adding the 'user section' in this super loop would be necessary and important.

With kind regards,

Sue
• Hi,

CubeMX is not a SEGGER tool. I can't say if there is a place where the user can place code in the super loop. I suggest to contact ST.
But I agree with you that this should be possible.

The GUIBuilder is a SEGGER tool and it shouldn't touch the user code (between the marks) in c-files generated by this tool.

You could get around this by setting up a timer in the dialog. Each time the timer expires you can poll the AD values (not that elegant but should work).

In WM_INIT_DIALOG call this:

WM_CreateTimer(pMsg->hWin, YOUR_TIMER_ID, Period, 0);

Add another case, WM_TIMER, to react on the timer message. In this case do something like this:

Id = WM_GetTimerId((WM_HTIMER)pMsg->Data.v);
if (Id == YOUR_TIMER_ID) {
WM_RestartTimer((WM_HTIMER)pMsg->Data.v, Period);
}

This way you can use the AD value directly within the dialog.

Regards,
Sven
• Hey Sven,

I thank you very much for your reply and also for your recommendation tip about the super loop issues. I am going to work on using the timer to update the values.

The super loop without dedicated 'user section' is situated in GUI_App.c file; and I going to post this in ST forum to resolve the issues.
And I will get back here to let you know the results.

My project has been progressing fine, and I am so happy about it.
So, BIG thank you for supporting my technical issues with STemWin. Your helps are really helpful and precise.

I will certainly come back here in near future as my project goes.....

Have a nice day and with kind regards,

Sue