How to handle changes to settings during runtime of a embedded c project?

Viewed 243

I'm playing around with an esp32 (c with esp-idf, not with arduino) for a hobby project of mine. I'm currently programming a little drone that I can control with my smartphone. All works well.

But now I need to create system for persistent settings and parameters. For example pid-tuning parameters or what sensors are enabled and more. The general idea was to have a settings file in flash that is read on startup. The settings can then be used in the individual modules of the program. Now I'd also like to change those settings during runtime. For example pid tuning parameters. I don't want to reboot the system only to change a small parameter.

So now my question: How can I handle changes to those settings during runtime?

  • An idea was to have the module periodically ask a special "settings-module" if there are any changes. It would then change its internal settings accordingly. As settings shouldn't change that often I think the overhead of constantly asking for updates is rather unnecessary.

  • A more extreme idea was, to give a pointer to the variable in question to the "settings-module". If any changes have to be made the settings module would change the variable directly.

  • Or maybe a callback system?

The ideas seem feasible but I don't know if there are any best-practices or better options.

Does anyone of you know a name of a technique I can google or maybe an library that provides something similar?

Thanks!

2 Answers

ESP ISF already has 90% of your requirements covered with the non-volatile storage library - string keys, int/string values, wear levelling etc. Just use this to store all your settings and parameters. Read from it every time you want to get a value (unless you go to the sub-millisecond latency land, in which case it's perhaps best to cache the settings in RAM).

Reading a value from NVS can fail (e.g. if the parameter is not stored, the NVS partition got wiped, etc) which would introduce cumbersome error handling into every code block where you read a parameter. A common trick to avoid this error handling is to add a thin wrapper which takes a fallback value of the parameter and returns it every time reading the parameter from NVS fails. Something like this:

uint32_t fetchU32(const char* key, const uint32_t fallback) {
  uint32_t ret;
  if (ESP_OK != nvs_get_u32(g_nvs_hnd, key, &ret)) {
    ret = fallback;
  }
  return ret;
}

Note that you need to be careful when using such wrappers - occasionally a critical parameter value must be found from NVS and not replaced with a fallback blindly.

Adding to what Tarmo suggested, you should also take not there are write limits to the ESP32's NVS. But do take note that the limits are set by what flash you are using.

I am placing this link where they discuss the write limits of the ESP32.

Related