3

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!

NikLeberg
  • 65
  • 1
  • 5
  • Do you have a single program or several? If a single program, then load the setting into a structure and have all parts of the program access that structure. Create a function to save that structure to the flash memory. Use a member of the structure being a simple counter that is incremented for each change. Parts of the program can check that counter and compare with their own copy. If different then a change occurred and appropriate action can be taken. – fpiette May 26 '21 at 06:28
  • @fpiette The code is modularized and runs as several tasks that are managed by FreeRTOS. If I understand you correctly, you say to have all settings in a globally accessible struct? Is there a simple way to modularize this a bit? – NikLeberg May 26 '21 at 07:29
  • Are the task running in different threads or is this single thread cooperative multitasking? This is important to manage access to data in a safe way. – fpiette May 26 '21 at 08:37
  • Not directly your problem, but remember that flash memory has a limited number of write cycles. Don't write to frequently or you'll kill the flash memory! Read [this artcile](https://en.wikipedia.org/wiki/Flash_memory). – fpiette May 26 '21 at 08:41

2 Answers2

1

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.

Tarmo
  • 3,728
  • 1
  • 8
  • 25
  • Promisig! The idea with a thin wrapper seems great for my problem. I'll have a look an play around with the nvs_flash a bit. I'd love to mark your answer as **helpful**, but need a few points more for that. :) – NikLeberg May 26 '21 at 11:10
  • Have fun and take into account advice from fpiette - the erase cycles on Flash memory are limited to about 10000 per each sector. If you need to update your parameters often (say more than few times per hour), you can easily wear out a small NVS partition. You can work around this by increasing the size of the NVS partition (so the wear levelling algorithm can spread the work to more sectors), but this solution only scales linearly with the size. It's best to keep data which gets updated often in RAM. – Tarmo May 26 '21 at 11:18
1

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.

PopherTheG
  • 11
  • 2