The main problem that I deal with in a small integrated device redesign (PID controller) is the storage of device parameters. The old solution, which I partially present here, was space-efficient, but awkward to maintain when adding new parameters. It was based on the identifier of the device parameter, which must match the EEPROM address, as in the example below:
// EEPROM variable addresses #define EE_CRC 0 // EEPROM CRC-16 value #define EE_PROCESS_BIAS 1 // FLOAT, -100.00 - 100.00 U #define EE_SETPOINT_VALUE 3 // FLOAT, -9999 - 9999.9 #define EE_SETPOINT_BIAS 5 // CHAR, -100 - 100 U #define EE_PID_USED 6 // BYTE, 1 - 3 #define EE_OUTPUT_ACTION 7 // LIST, DIRE/OBRNU
Each address was hard-coded, and the next address was determined depending on the previous data size (note the uneven distance between the addresses). This was effective because the EEPROM data store was not wasted, but it was difficult to deploy without errors.
In other parts of the code (i.e. the HMI menu, data storage ...), the code will use a list of parameters corresponding to the addresses just indicated, something like the following:
// Parameter identification, NEVER USE 0 (zero) as ID since it NULL // Sequence is not important, but MUST be same as in setparam structure
Then, in code using these parameters, for example, in the following user menu structures, I created elements using my own PARAM type (structure):
struct param { // Parametar decription WORD ParamID; // Unique parameter ID, never use zero value BYTE ParamType; // Parametar type char Lower[EDITSIZE]; // Lowest value string char Upper[EDITSIZE]; // Highest value string char Default[EDITSIZE]; // Default value string BYTE ParamAddr; // Parametar address (in it media) }; typedef struct param PARAM;
Now the list of parameters is built as an array of structures:
PARAM code setparam[] = { {NULL, NULL, NULL, NULL, NULL, NULL}, // ID 0 doesn't exist {ID_ENTER_PASSWORD_OPER, T_PASS, "0", "9999", "0", NULL}, {ID_ENTER_PASSWORD_PROGRAM, T_PASS, "0", "9999", "0", NULL}, {ID_ENTER_PASSWORD_CONFIG, T_PASS, "0", "9999", "0", NULL}, {ID_ENTER_PASSWORD_CALIB, T_PASS, "0", "9999", "0", NULL}, {ID_ENTER_PASSWORD_TEST, T_PASS, "0", "9999", "0", NULL}, {ID_ENTER_PASSWORD_TREGU, T_PASS, "0", "9999", "0", NULL}, {ID_PROCESS_BIAS, T_FLOAT, "-100.0", "100.0", "0", EE_PROCESS_BIAS}, {ID_SETPOINT_VALUE, T_FLOAT, "-999", "9999", "0.0", EE_SETPOINT_VALUE}, {ID_SETPOINT_BIAS, T_CHAR, "-100", "100", "0", EE_SETPOINT_BIAS}, {ID_PID_USED, T_BYTE, "1", "3", "1", EE_PID_USED}, {ID_OUTPUT_ACTION, T_LIST, "0", "1", "dIrE", EE_OUTPUT_ACTION}, {ID_OUTPUT_TYPE, T_LIST, "0", "1", "GrIJA", EE_OUTPUT_TYPE}, {ID_PROCESS_BIAS2, T_FLOAT, "-100.0", "100.0", "0", EE_PROCESS_BIAS2},
...
In essence, each parameter has a unique identifier, and this identifier must correspond to the hard-coded EEPROM address. Since the parameters were not fixed in size, I could not use the parameter ID itself as an EEPROM (or other medium). The EEPROM organization in the above example was a 16-bit word, but it doesn’t matter (more space is wasted on characters, so anyway, I would prefer an 8-bit organization in the future)
Question:
Is there a more elegant way to do this? Some hash tables, a well-known template, a standard solution for such problems? Now EEPROMS is much larger in size, and I would not mind using a fixed parameter size (losing 32 bits for a logical parameter) in exchange for a more elegant solution. It looks like with fixed size parameters, I could use the parameter ID as an address. Is there an obvious flaw in this method that I don't see?
Now I use distributed HW (HMI, I / O and the main controller are separate), and I would like to use a structure in which all devices know about this parameter structure, so for example, remote I / O knows how to scale the input values, and HMI knows how to display and format data, all of them are based only on the identifier of the parameter. In other words, I need one place where all parameters will be defined.
I did my research on Google, very little could be found for small devices that do not contain some databases. I even thought of some XML definition that would create some C code for my data structures, but maybe there was some elegant solution more suitable for small devices (up to 512K Flash, 32K RAM)?