Preferences and struct

I'm trying to store these settings so I can load them on start up.
I'm using an ESP32, so I believe I need to use preferences.h

As you can see I have different data types,
The struct works fine.
However the prefs.put and prefs.get both require a data type like (prefs.putInt).
is it possible to store a struct containing mixed data types.

struct settings{
  int onbefor;
  int offabove;
  bool  automatic;
  bool cent;
};
settings save1 = {10, 18, true, false};```



Any help welcome.
Thanks.

'struct' declares a data type. So you should be able to load/store 'settings' types. But you may have to explore the available prefs functions to find a more generic method to do that.

arduino-esp32/Prefs2Struct.ino at master · espressif/arduino-esp32 · GitHub

thanks for the reply. I have looked at the examples, however this example uses all the same data types uint8_t Fixed width integer . and uses prefs.putBytes

Yes, you will use .putBytes() and .getBytes()

#include <Preferences.h>
Preferences prefs;

void setup()
{
  Serial.begin(115200);
  struct settings
  {
    int onbefor;
    int offabove;
    bool automatic;
    bool cent;
  };
  settings save1 = { 10, 18, true, false };
  settings retrieve1 = { 0, 0, 0, 0 };

  prefs.begin("Settings");  //namespace
  prefs.putBytes("Settings", &save1, sizeof(save1));
  prefs.getBytes("Settings", &retrieve1, sizeof(retrieve1));

  Serial.println(retrieve1.onbefor);
  Serial.println(retrieve1.offabove);
  Serial.println(retrieve1.automatic);
  Serial.println(retrieve1.cent);
}
void loop() {}

1 Like

Thanks that works, and it's a lot clearer than the example sketch.
I have just looked up sizeof and understand that, but can you explain what the ampersand & does.

Look at the function descriptions for putBytes() and getBytes() here.

https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/preferences.html

For example

,putBytes() stores a variable number of bytes against a given key in the currently open namespace.

size_t putBytes(const char* key, const void* value, size_t len);

& is the "address-of" operator. In the case of its use in the .putBytes function it is a pointer to the address of the values you want to store as bytes. You tell the putBytes() function to go to a certain address in memory, and then place the subsequent number of bytes specified by length into the non volatile storage space.

prefs.putBytes("Settings", &save1, sizeof(save1));

Thank you for taking the time to help me.
sorry to bother you again. Knowing why some code is written the way it is, will help me write better code in the future, instead of just copy and pasting without understanding.
With that in mind.
Why do we point to the address of the the variable, and not just use the variable?

Why do we point to the address of the the variable, and not just use the variable?

You are getting into the issue of how functions are written and how values are passed into functions: passing by reference and passing by value. I would suggest you use Google to find one of the many tutorials on the subject and see what you can understand.

The Preferences.h library functions of putBytes() and getBytes() are written in a way such that they accept parameters by reference. Most functions that can accept some large block of data are written in this fashion because it more efficient.

Indeed, if you try and change how you pass the values of the struct to the function, the compiler will show an error. Try it.

//prefs.putBytes("Settings", &save1, sizeof(save1));
  prefs.putBytes("Settings", save1, sizeof(save1));

No, they are written to accept the address of something.

While this references something, it is not a reference (in C++ context).

The "call by reference" naming stems from a time before C++,
when true references just did not exist.

Also because C is designed to be "close to the hardware". All conventional CPU's use addresses to access variables. All computer languages have to produce machine code to handle variables, but many of them "hide" the address mechanism. The hardware centric philosophy of C promotes the direct use of addresses by providing mechanisms to handle them directly.

Thus addresses can be incremented, decremented, calculated, stored, retrieved, passed and returned from functions. These operations are very efficient due to the tight coupling with CPU architecture.

yes I already did to see if I could work out what it was doing. :thinking:
one last question I promise.
when you look at the function description, can you see strait away what is needed. what can you see that that I can't.
Thanks again for everyone's contributions on this topic. and if you ever need advice on anything to do with garden fences, give me a shout.

when you look at the function description, can you see strait away what is needed. what can you see that that I can't.

size_t putBytes(const char* key, const void* value, size_t len);

As previously noted, pointers point to the address of a variable. Typically, pointers will be typed. For example int* or float* point to the address of an integer or a floating point number in memory. The void* just means that it can point to the address any type of variable.

I think the understanding that const void* value as a function parameter means you use &value in the call of that function just comes from more experience with pointers and the syntax used with them. I'd guess that lots of looking for examples with Preferences.h and structures was also involved.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.