MicroHTR (Part 7)

Part 1, 2, 3, 4, 5, 6, 7, 8

P1170300s

Although this post relates with the MicroHTR application, its content deals mainly with the human interface which makes it available for autonomous usage, I mean without the need of a computer attached to the Arduino board for setting parameters and getting access to real time information. This human interface features two main components: 16 x 2 characters LCD for displaying information and a rotary encoder (with push-button) for navigation through menu items. Both code components belong to the PlainLCD and PlainENC libraries. So far the target application must include some code for achieving the expected human interface. And here they are explained in details.

From the header part of the sketch (before the setup() function):

Include the libraries we just talked about just before

#include <PlainENCi.h> /* Encoder library */
#include <PlainLCD.h> /* LCD library */

Additional libraries are required for the specific heating process

#include <PlainEEPROM.h> /* EEPROM library */
#include <PlainTMP0x.h> /* TMP0x sensors library */
#include <PlainPWM.h> /* PWM library */
#include <PlainPID.h> /* PID library */

Then come some constants. Next ones must be left as is

/* Menu types */
#define MNU_TYP_HEADER 0x00
#define MNU_TYP_MOD_VALUE 0x01
#define MNU_TYP_FXD_VALUE 0x02
#define MNU_TYP_FLD_BACK 0x03

And then come the constants used as menu captions, thus the CAP prefix that I choose. In the beginning, keep these names unchanged:

/* Captions */
#define CAP_PARAM "PARAMETERS"
#define CAP_EXIT "EXIT"
#define CAP_RETURN "RETURN"

Then, you will be free to use any caation constants for each menu item, such as:

/* Application related constants */
#define CAP_SP "SET POINT"
#define CAP_KP "KP"
#define CAP_KI "KI"
#define CAP_KD "KD"
#define CAP_INT "INTERVALS"
#define CAP_STATISTICS "STATISTICS"
#define CAP_MAX_TEMP "TEMP. MAX."
#define CAP_MIN_TEMP "TEMP. MIN."
#define CAP_RESET "RESET"
#define CAP_SETTINGS "SETTINGS"
#define CAP_STATISTICS "STATISTICS"

The come an important variable type, the mnuItem which consists in:

struct mnuItem { 
	uint8_t menuType; /* One of MNU_TYP_x */
	int16_t minValue; /* min value */
	int16_t maxValue; /* max value */
	uint8_t nextMenuIndex; /* Next menu item */
	uint8_t lastMenuIndex; /* Must be set to 0 as default */
	char *caption;  /* Pointer to menu caption */
};

Let’s go through the structure

  • menuType is as per one of the MNU_TYP_x types:
    • MNU_TYP_HEADER : is a header line, it means that no change will be applied to any value
    • MNU_TYP_MOD_VALUE : is a value line, it means that the related value may be changed and display by means of encoder steps
    • MNU_TYP_FXD_VALU : is a value line, but no changes will occur to this value; this type enables scrolling through variables
    • MNU_TYP_FLD_BACK : is a fold back menu item which resumes exploration to a predefined menu index.
  • minValue has various meaning depending on the menuType:
    • MNU_TYP_HEADER: is always 0 as we always start counting from 0 in base 0
    • MNU_TYP_MOD_VALUE: is the lower bound of the value. This value is a signed 16 bits integer (-32768 to 32767). For fractional values, use a multiplying factor. MicroHTR contains various examples.
  • maxValue has various meaning depending on the menuType:
    • MNU_TYP_HEADER: is the number of related sub menus expressed in base 0. If this value equals 5, this means that there are 6 related sub menus.
    • MNU_TYP_MOD_VALUE: is the upper bound of the value. This value is a signed 16 bits integer (-32768 to 32767). For fractional values, use a multiplying factor. MicroHTR contains various examples.
  • nextMenuIndex tells the index to go to (base 0) when pressing the validation push-button
  • lastMenuIndex is used by the menu driver code, leave it X or any value.
  • caption is the related LCD caption

Again, do not change it before you are familiar with the use of menus. And now comes the big part: your menu structure! This is no more than a vector of menu items, one for each menu level. Next comes the menu structure of MicroHTR that I will explain in more details:

struct mnuItem vMnuItems[] = 
{ 
/* {type, min, max, next, last, caption}*/
 {MNU_TYP_HEADER, X, X, X, X, CAP_FIRMWARE}, 
 {MNU_TYP_HEADER, 0, 2, 2, X, CAP_PARAM},
 /* Main menu */
 {MNU_TYP_HEADER, 0, 5, 5, X, CAP_SETTINGS},
 {MNU_TYP_HEADER, 0, 3, 11, X, CAP_STATISTICS},
 {MNU_TYP_FLD_BACK, X, X, 0, X, CAP_EXIT},
 /* Settings */
 {MNU_TYP_MOD_VALUE, MIN_SP, MAX_SP, 2, X, CAP_SP}, 
 {MNU_TYP_MOD_VALUE, MIN_KP, MAX_KP, 2, X, CAP_KP}, 
 {MNU_TYP_MOD_VALUE, MIN_KI, MAX_KI, 2, X, CAP_KI}, 
 {MNU_TYP_MOD_VALUE, MIN_KD, MAX_KD, 2, X, CAP_KD}, 
 {MNU_TYP_MOD_VALUE, MIN_INT, MAX_INT, 2, X, CAP_INT}, 
 {MNU_TYP_FLD_BACK, X, X, 1, X, CAP_RETURN},
 /* Statistics */
 {MNU_TYP_FXD_VALUE, MAX_TEMP, MIN_TEMP, 3, X, CAP_MIN_TEMP},
 {MNU_TYP_FXD_VALUE, MAX_TEMP, MIN_TEMP, 3, X, CAP_MAX_TEMP},
 {MNU_TYP_MOD_VALUE, 0, 1, 3, X, CAP_RESET},
 {MNU_TYP_FLD_BACK, X, X, 1, X, CAP_RETURN} 
};

So let’s explore the menu structure staring from line 0 (base 0).

{MNU_TYP_HEADER, X, X, X, 0, CAP_FIRMWARE} translates this way:

  • menuType says that this is a header or navigation information only level
  • minValue is X as it is passive
  • maxValue  is X as it is passive
  • nextMenuIndex  is X as it is passive
  • lastMenuIndex is X because it is managed by the menu driver itself
  • caption is what ever you want, my choice was to display the application name

If you press the encoder push-button, then the menu driver will jump to line 1 (base 0) which is

{MNU_TYP_HEADER, 0, 2, 2, X, CAP_PARAM}

and reads this way:

  • menuType says that this is a header or navigation information only level
  • minValue is 0 as for all sub menu headers (because we always start counting from 0 in base 0 mode)
  • maxValue  is 2 (base 0)as there are 3 related sub-menus
  • nextMenuIndex  is 2 as the menu index to go to in case of validation is at line 2  (base 0)
  • lastMenuIndex is X because it is managed by the menu driver itself
  • caption is what ever you want to display on the first line of the LCD, in this case  “PARAMETERS” stands for the type of information in this sub-menu. The second line of the LCD contains the caption from the first sub-menu item, which is “SETTINGS”.

Turning the encoder knob clockwise will scroll through all captions from this sub-menu: “STATISTICS” and “EXIT”. No farther move is allowed as we reach the maximum counts as per maxValue. However, it is possible to explore the sub-menu backward when turning the encoder knob counter-clockwise.

Now, say that the LCD displays “PARAMETERS” and “SETTINGS”, which happens when the menu driver points to line 1 (base 0). Then press the encoder push-button.The menu driver now points to line 2 (base 0) that we read this way:

  • menuType says that this is a header or navigation information only level
  • minValue is 0 as for all sub menu headers (because we always start counting from 0 in base 0 mode)
  • maxValue  is 5 (base 0)as there are 6 related sub-menus
  • nextMenuIndex is 5 as the menu index to go to in case of validation is at line 5  (base 0)
  • lastMenuIndex is X because it is managed by the menu driver itself
  • caption is what ever you want to display on the first line of the LCD, in this case  “SETTINGS” stands for the type of information in this sub-menu. The second line of the LCD contains the caption from the first sub-menu item, which is “SET POINT”.

Turning the encoder knob clockwise will scroll through all captions from this sub-menu: “KI”, “KP”, “KD”, INTERVALS” and “RETURN”. No farther move is allowed as we reach the maximum counts as per maxValue. However, it is possible to explore the sub-menu backward when turning the encoder knob counter-clockwise.

Now, say that the LCD displays “SETTINGS” and “SET POINT”, which happens when the menu driver points to line 2 (base 0). Then press the encoder push-button. The menu driver now points to line 5 (base 0) that we read this way:

  • menuType says that this menu deals with a changeable value
  • minValue is a user defined constant set in MIN_SP
  • maxValue  is a user defined constant set in MAX_SP
  • nextMenuIndex is 2 as we want to resume to line 2 (base 0) on completion of the parameter setting
  • lastMenuIndex is X because it is managed by the menu driver itself
  • caption is what ever you want to display on the first line of the LCD, in this case  “SET POINT” stands for the type of information in this sub-menu. The second line of the LCD contains the actual value.

Turning the encoder knob clockwise will scroll through all values from  captions from minValue to maxValue  by steps of 1 (or -1), starting from the actual value of the variable.

Let’s take an other case. Say that the LCD displays “SETTINGS” and “RETURN. Then press the encoder push-button.The menu driver now points to line 10 (base 0) that we read this way:

  • menuType says that this is a fold back menu which will drive us back to some other menu index
  • minValue  is X as it is passive
  • maxValue  is X as it is passive
  • nextMenuIndex is 2 as we want to resume to line 2 (base 0)
  • lastMenuIndex is X because it is managed by the menu driver itself

Pressing the encoder push-button will resume to line 2 and the LCD will display “PARAMETERS” and “SET POINT”

There is no major difference between MNU_TYP_MOD_VALUE (changeable values) and MNU_TYP_FXD_VALUE (fixed values), except that the encoder knob will have no effect on the display in fixed value mode.

Well, this is quite an exercise to build this table and this exercise may require few attempts before understanding it fully. Taking into account the programming language I know, this is neither the best nor the worst of the menu builders. Next post will describe how to customize the functions which read, display and write changeable values.

Next post on same subject

 

 

5 Comments

  1. LeandroM says:

    Hello Didier, I’ve been taking time here and there and doing first tests on the ENC library, but it seems it wont work with a DUE board… can you point me on the direction to port the library to a DUE in a way I can contribute to your awesome work?
    (also) I’ve seen some misspells here and there on this post but some couldn’t understand or guess at all…

    take care!

    • Didier says:

      Hi Leandro,
      I do not plan to develop PlainLCD for other boards than the DUE. May I encourage you, and this is a general statement, to start playing with the libraries with a Uno and a 2×16 LCD, get familiar with the code and them move step by step to any other board.
      The reason behind this decision is that almost all my code is compatible. Developing multi-platform compatible code would represent a hell lot of work which is far, far, far from my plans. Unless you would sponsor me, who knows 😉

      • LeandroM says:

        That’s what I would like to: move step by step towards the DUE but so far I haven’t made a library by myself, so I’m ain’t very sure about the road…
        I was wondering as I read your answer, that it all would mean to make all the libraries on the HTR package DUE compatible… tiresome…
        As I am working mostly on this DUE, it really would mean a great opportunity to learn a lot about the differences with a UNO if I get to work on this translation…off course I really only need the ENC library, that would be the first step… It would be straightforward to sponsor you 🙂 but how about I sponsor you to point me to the road so I can benefit from learning about all this, so I can work on some ideas I may be having about a DUE…???
        I’m really not that wealthy so is it possible to think about some kind of trade in terms of work maybe? 😉
        greets

Leave a Reply

You must be logged in to post a comment.