Hi. I want to store a time schedule persistently on the spark using built in persistent storage (no other hardware). For now I just need a 24 hour clock where I can turn 15-minute blocks of time on and off. Example:
0900 to 0945 on
0945 to 1000 off
1000 to 0815 on
0815 to 0900 off
Any values should be allowed as long as they’re on the 15 minute marks. I understand how to do this part.
I also understand there are two types of storage we can use. One supposedly has a limited number of rewrites while the other doesn’t list a limit.
I’m honestly not sure about the difference but I’d like advice on where to store this info (possibly listing up to every single 15 minute increment simultaneously to turn something on and off every 15 minutes for a 24 hour period) and what format to store it in. I understand the built in storage is very limited in size (100kb?)
At present, there are two main avenues for persistent storage:
- the built-in EEPROM class: this allows 100 bytes of rewritable storage, with 10,000 rewrites.
- the flashee library, which offers up to 1.5MB of storage, with at least 10,000 rewrites.
To store a on/off value for each 15 mins in 24 hours requires 96 values. So you can certainly use the EEPROM built in library which has space for 100 bytes.
EEPROM.write(quarter, 0 or 1) to set the on/off status in eeprom for any quarter from 0 to 95.
If your needs are simply this, then the built in EEPROM library is the best choice because of the straightforward coding involved, especially if you know Arduino.
The built in EEPROM library has a typical endurance of 10,000 writes. If you think the number of rewrites will be near this limit for the lifetime of the application then let me know and we can look at other alternatives that have a higher number of rewrites.
Dang, @mdma beat me to the punch! If you won’t ever turn off the Core then RAM is also a viable storage.
Hehe! I was waiting here doing nothing for 19 hours just ready to pounce on the first question!
I can’t tell if you’re joking about RAM - is the core stable enough for that?!
But it gets me thinking to a kind of storage in the cloud, one that is available via REST externally and easily coded to in the spark via a simple Spark.xxx() function, and gets around the limitations of 4 variables…
@mdma, I was half serious, half hopeful I believe cloud storage was on @Dave’s radar, just not sure where. For now the flashee option is the best.
For my Fan Controller I store the fans last set state in RAM and never have issues with it being wiped because of a reboot/crash.
My main problem is when I lose power.
Well someone would have to change the schedule 3 times per day every day for 9 to 10 years to run out of 10,000 writes. Eeprom week probably work fine.
As far as variables limit go, why not just call a REST function getVar with a string argument for the var name you want? Then your getVar function can do a switch and return the appropriate value and data type. Kind of long but gives a solution to the 4 variable limit.
Any reason I SHOULDN’T use the eeprom?
Between EEPROM and FLASHEE library, which would be better? Also, what gives these a limit of 10,000 writes? Can that be fixed?
Totally, cloud storage is on our radar, and something I’m excited about. It may or may not already secretly exist in an undisclosed staging environment pending additional testing.
edit: but there is a lot more to add / do before it’ll be ready to roll-out.
The endurance of flash memory is limited to a certain number of erases per page - both EEPROM and flashee use flash memory behind the scenes to emulate eeprom, so both libraries have limited endurance.
The endurance figures are cited as a minimum of 10,000 erases per sector. So if you have a memory with 300 sectors, each sector can be erased 10,000 times before that sector might start degrading.
Both libraries have schemes that can avoid erasing pages for each write, and so are roughtly comparable in terms of endurance. The key difference is the amount of memory available - with EEPROM it’s 100 bytes, with flashee it’s variable, up to 1.5MB.
EEPROM was written to be familiar to arduino developers - it supports reading and writing single bytes at a given address. Flashee aims to make writing numbers and strings easier with streams, which can be convenient when writing lots of different types of data. It saves the user from having to split everything into bytes, and automatically keeps track of the address to write the next item to.
writer.writeString("My name is Fred");
I hope that’s a fair comparison - I’ve tried to be unbiased, but of course full disclaimer, I wrote the flashee library!
@mdma, thanks for the help with this! I’m going to ask a crap ton of questions, of course, because I’m new to C as well as to Spark. I have never dealt with flash memory of any kind before, except for my computer’s SSD and a thumb drive, but those are filesystem formatted.
The first question I pose to you, and anyone else in the community, is:
How do I read the data back out? This is an excerpt from the github README.md.
To store data:
flash->writeString("Hello World!", 0);
This writes the string to the flash memory starting at address 0.
To retrieve data:
flash->read(buf, 0, 13)
I see that you can read data with the read() function, but according to this you have to know how long that data is. What if I store an arbitrary string and I don’t know how long it will be?
Obviously this question does not follow the approach we talked out earlier by using a series of bytes to represent time chunks, but I am also considering just writing time strings to the flash and reading them back to enable total granular control down to the minute.
So, to reiterate, how do I read data back out if I don’t know the exact length of a string? Is there an end of string marker I could look for while looping through each byte individually?
Ok, well I figured out how to use the “streaming” example to read and write strings. I’d still like to know how you’d know how long a string is in the previous example though.
Another question: Is it possible to store a struct in memory using your library? Would I just have to store all the struct member’s data sequentially for each instance of the struct, then read them out into new instances in a FIFO manner?
Good question! Yes, you shouldn’t really have to know the length.
I can add “String” to the writeString() interface (I had intended to do that initially, since using
String is much easier than messing about with char arrays.)
With String added, you wouldn’t need to know how big the string is.
Yes, it’s quite easy to store a struct. If you’re using the streaming interface, it’s like this:
// fill out the struct as you normally would
// ... then later
Writing to the device it’s:
// fill out the struct as you normally would
device->write(&myStruct, sizeof(myStruct), someAddress);
// ... then later on
device->read(&myStruct, sizeof(myStruct), someAddress);
The main difference is that the streaming interface takes care of remembering the current address.
This is a good question - I’ll add the info to the docs!