can i save settings? - Page 1
Forum section: electronics / general

author: gatoulisss
author_rank: Contributor
timestamp: January 25, 2021, 12:11:48 pm
content: hello everyone,i need your help, i have a project with a pic mcu (pic16f88 & pic16f628a) which uses battery as power supplier, a reed switch is connected on my pic and makes several settings choices that work on the rest off the program.my question is : is there any way to save this settings so if battery run out or disconnects my mcu will keep the settings i've already done before when i connect new battery?thank you all very much!

author: Siwastaja
author_rank: Super Contributor
timestamp: January 25, 2021, 12:25:48 pm
content: Both PIC16F88 and PIC16F628A contain internal EEPROM memory which can be used to store such settings. I'm sure you can find a tutorial on using EEPROM.

author: Ian.M
author_rank: Super Contributor
timestamp: January 25, 2021, 12:52:07 pm
content: There are however a couple of 'flies in the ointment':The EEPROM has limited write endurance, (e.g. for the PIC16F88, min. 100K, typ. 1M writes per location and a factor of 10 less above 85 deg C), so if your code is particularly badly designed and writes to EEPROM too frequently, you can wear out the EEPROM quite quickly, e.g one write per second is likely to kill it in under a fortnight, and at elevated die temperature *CAN* kill it in as little as a few hours. The usual solution is to either wait a minute or so's timeout after user input before writing the settings, resetting the timeout on each new input so its reasonably certain the user has finished making changes, or explicitly require user confirmation to save settings.Also if BOR isn't enabled and you have any EEPROM write code anywhere in your firmware, there is a risk of EEPROM corruption if the supply voltage falls or dips below the minimum rated Vdd for operation at that clock frequency. This can to some extent be mitigated by setting EEADR/EEADRH to an unused loction when not actually accessing the EEPROM to reduce the risk of a power glitch wiping important data, but the preferred solution is to either enable BOR and PWRT (POR/BOR reset 'hold' delay timer') in the CONFIG bits, or use an external voltage monitor and reset controller IC on /MCLR.A further issue is: if you disable external /MCLR and your code writes to EEPROM within a few hundred ms of powerup, its likely that you'll get EEPROM corruption during the device programming and verify sequence. To avoid it,either don't write to EEPROM without user input or wait ONE second after powerup or reset before permitting any EEPROM writes.

author: gatoulisss
author_rank: Contributor
timestamp: January 25, 2021, 06:24:48 pm
content: this is the part of my code that uses the reed switch, i want to save the hx value witch is the choice of the userhow i could do it? so when for example i replace battery the choice will be kept (im using mikro C )void ep(){delay_ms(50);while (portb.f0==1) { // while reed switch is closeda=a+1;if (a==7){a=0;} //number of different choicesfor (k=1; k<=a; k++){sound_play(2600,80);delay_ms(200);hx=k;} // this is what i want to keepdelay_ms(1000);}

author: Ian.M
author_rank: Super Contributor
timestamp: January 25, 2021, 06:56:09 pm
content: *Please* usecode tagswhen posting inline sourcecode here.I cant be much help anywhere your code diverges from 'vanilla' ANSI C, as I'm not a mikroC user, but it looks like its got an EEPROM library you can use. See:https://download.mikroe.com/documents/compilers/mikroc/pic/help/eeprom_library.htm

author: Foxxz
author_rank: Regular Contributor
timestamp: January 25, 2021, 07:05:19 pm
content: In your code it looks like while the reed switch is closed HX will be changing once every 0.2 seconds or 1.2 seconds at the longest.Maybe wait until the reed switch is open to save the HX value as long as you don't expect power off to occur inside the loop. HX will always be equal to A when the while loop exits.I'm just looking for ways to reduce flash writes when the values settle and writing to flash won't affect your loop timing as that can take some cycles to do.

author: DrG
author_rank: Super Contributor
timestamp: January 25, 2021, 07:05:53 pm
content: If you don't want to use on chip EEPROM, I would add using a 47C04/47L04 EERAM e.g.,https://www.microchip.com/wwwproducts/en/47L04These have both static RAM, which your program writes to, and EEPROM, which is written to upon power down.Advantages: cost .66 cents, available in PDIP, requires a single cap to manage the power down write, claims more than 1,000,000. store cycles, automatic transfer to static ram on power up {your program would read and write the switch setting from SRAM).Disadvantage: requires an I2C interface. Slow, but likely fine for your use. Some scrambling issues as noted, I suppose, but in your project, it could be tolerable.I have used these as a projecteer and like them.

author: gatoulisss
author_rank: Contributor
timestamp: January 25, 2021, 07:18:21 pm
content: when the reed opens the loop stops and the hx keeps the last setting number so at that moment i could save it to EEPROM the problem is that i dont understand how to do this exaclyQuote from: DrG on January 25, 2021, 07:05:53 pmi dont mind use the on chip EEPROM but my problem is that i dont know how to do sohow i could save the hx int value to eeprom??

author: DrG
author_rank: Super Contributor
timestamp: January 25, 2021, 07:41:37 pm
content: Quote from: gatoulisss on January 25, 2021, 07:18:21 pmIt is going to take some programming, for the on-chip EEPROM, this might helphttps://deepbluembedded.com/eeproms-internal-in-pic-microcontrollers/and I am sure there are others if you do some searching. I can't give you a couple of lines to add, it's more than that.The EERAM is probably easier to program. You write to and read from an address in a bit more of a straightforward manner. Have you ever done any programming using I2C or SPI? If yes, you can probably figure it out from the data sheet.Do you have a RTC in this project? You might have another option also.

author: ledtester
author_rank: Super Contributor
timestamp: January 25, 2021, 07:49:53 pm
content: A lot of microcontrollers have brown-out detection. If you put a large enough cap on your power rails it might be possible to quickly save the settings when a brown-out occurs and before you lose power. That would cut down on the number of EEPROM (or EERAM) writes.Adding a battery backup (like a CR2032 cell) to your circuit is another option.

author: Ian.M
author_rank: Super Contributor
timestamp: January 25, 2021, 08:04:27 pm
content: kand thushxfits in a single byte. I've already pointed you at the mikroC internal EEPROM library functions. It could be as simple as:Code:#define HX_EEPROM 1 // Address of stored hx in the EEPROM//....// To store hxEEPROM_Write(HX_EEPROM,hx);EEPROM_Read(0); // Leave EEADR/EEADRH zeroed.//....// To recall hxhx=EEPROM_Read(HX_EEPROM);Of course, if you want EEPROM error detection and possible correction, or wear levelling, it rapidly gets a *LOT* more complex.

author: DrG
author_rank: Super Contributor
timestamp: January 25, 2021, 08:14:30 pm
content: Quote from: Ian.M on January 25, 2021, 08:04:27 pmThis is one place where the EERAM could represent a big advantage. You would be doing those reads and writes to static RAM, which would be much faster (note that I am to lazy right now to go look at the values). Additionally, EEPROM gets automatically written to once during each power down, adding to the "life expectancy".

author: Ian.M
author_rank: Super Contributor
timestamp: January 25, 2021, 08:19:27 pm
content: Yes. The minimum improvement to reduce wear on the internal EEPROM would be only write it if the data has changed. e.g:Code:// To store hxif(hx!=EEPROM_Read(HX_EEPROM)){EEPROM_Write(HX_EEPROM,hx);}EEPROM_Read(0); // Leave EEADR/EEADRH zeroed.I doubt Gatoulisss cares about the speed as his code is sprinkled with calls todelay_ms()for hundreds of ms, so under ten ms to write a byte probably isn't even noticeable.

author: gatoulisss
author_rank: Contributor
timestamp: January 25, 2021, 09:00:40 pm
content: thank you all very much for your enormous help!!so if i add to my code this lines and make it like this it would work?i cant quite understand how to use addresses .. i mean how i could know the address of hx for example?if i want to keep two variables on the eeprom thn the second for example would be #define HX_EEPROM 2 ??Code:#define HX_EEPROM 1void ep(){delay_ms(50);while (portb.f0==1) { // while reed switch is closeda=a+1;if (a==7){a=0;} //number of different choicesfor (k=1; k<=a; k++){sound_play(2600,80);delay_ms(200);hx=k;} // this is what i want to keepdelay_ms(1000);}if(hx!=EEPROM_Read(HX_EEPROM)){EEPROM_Write(HX_EEPROM,hx);}

author: DrG
author_rank: Super Contributor
timestamp: January 27, 2021, 06:21:31 pm
content: Quote from: gatoulisss on January 25, 2021, 09:00:40 pmI am being serious and not trying to condescend or rag on you - Why do you think that would work? Can you explain it?

author: ledtester
author_rank: Super Contributor
timestamp: January 27, 2021, 11:07:28 pm
content: QuoteRead this documentation on the eeprom library calls:https://download.mikroe.com/documents/compilers/mikroc/pic/help/eeprom_library.htmThe calls EEPROM_Read() and EEPROM_Write() each take an eeprom address. If you want to store two variables assign them two different addresses, like 1 and 2.See the example code at the end for examples of reading and writing to different EEPROM addresses.

author: JohnnyMalaria
author_rank: Super Contributor
timestamp: January 27, 2021, 11:53:34 pm
content: I like the path of least resistance even if it costs a little more and uses more physical space.How about a *parallel* EEPROM chip such ashttps://www.digikey.com/en/products/detail/microchip-technology/AT28C64B-15PU/1008529if you can spare an extra half dozen GPIO.I would use the first few bytes to store a pointer to another location and the number of times you've written to it. Then I'd write my hx byte to that location. You can do this a few 10,000 times to a given location before moving to the next. An 8KB chip would therefore allow you to write your hx byte up to 800 million times before the chip reaches near end-of-life.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 28, 2021, 04:04:56 pm
content: When a beginner is struggling to start using theinternalEEPROM which is just two off-the-shelf library functions away, I wouldn't start recommending adding external EEPROM chips, communicating with them, and implementing wear leveling. Start with the internal EEPROM.The easiest way to limit excess write cycles is to make the user press "save settings" or something like that.

author: DrG
author_rank: Super Contributor
timestamp: January 28, 2021, 05:28:06 pm
content: Quote from: Siwastaja on January 28, 2021, 04:04:56 pmConcur and I would add that it is essential that the beginner understands what they really want to happen.Here is the function as it was last presented:Code:#define HX_EEPROM 1void ep() {delay_ms(50);while (portb.f0 == 1) { // while reed switch is closeda = a + 1;if (a == 7) { //number of different choicesa = 0;}for (k = 1; k <= a; k++) {sound_play(2600, 80);delay_ms(200);hx = k; // this is what i want to keep}delay_ms(1000);}if (hx != EEPROM_Read(HX_EEPROM)) {EEPROM_Write(HX_EEPROM, hx);}The 'a' value seems to simply change the choice (hx) range to 1-6 and it will always force the user to make a choice and always save the choice to EEPROM. There may be some issues with the delays (200 ms choice time through the k loop, as mentioned and the 1 sec before re-entering the k loop)The OP has stated "my question is : is there any way to save this settings so if battery run out or disconnects my mcu will keep the settings i've already done before when i connect new battery?" Thanks to that library, the answer is yes and easily, but I'm not sure he thought that through and that is what I was getting at when I asked him to explain why he thought his new code would work.One approach would be something like this:Code:#define HX_EEPROM 1void ep() {delay_ms(50);if (hx = EEPROM_Read(HX_EEPROM)) == 0){while (portb.f0 == 1) { // while reed switch is closeda = a + 1;if (a == 7) { //number of different choicesa = 0;}for (k = 1; k <= a; k++) {sound_play(2600, 80);delay_ms(200);hx = k; // this is what i want to keep}delay_ms(1000);}EEPROM_Write(HX_EEPROM, hx);}}This depends on first writing 0 to the EEPROM location to indicate that a choice has never been saved [yes, there are other ways but the point is there]. The problem is, you only get to ever make ONE choice. This becomes a problem, even if you use a second switch to "save settings" - you have to be able to go through a choice loop to save a new setting (or figure out some way to change settings unless you only want to save settings once, in which case you would hard code the setting by sticking it in EEPROM and eliminate the choosing).Perhaps a better way would be something like this:Code:// had to edit this to break out of the loop when the reed switch is hit (and I still don't like it )void ep() {delay_ms(50);hx = EEPROM_Read(HX_EEPROM);// if the eeprom value is out of bounds start the choice at 1 else start it at the saved hx choiceif (hx < 1) || or (hx > n_CHOICES) {hx = 1;}while (1) {sound_play(2600, 80);delay_ms(200); // of course this could simply be added to the next line delay - but for illustration...delay_ms(1000); // because that is what the original code does at the end of the k loop but it makes more sense hereif (portb.f0 == 1) {break; // exit and save choice to EEPROM}hx++;if (hx > n_CHOICES) {hx = 1;}}if (hx != EEPROM_Read(HX_EEPROM)) {EEPROM_Write(HX_EEPROM, hx); // save a new choice}}Here, the choice loop isstarted at the last saved choice(or the initial value in the EEPROM, or 1 if the initial value is out of bounds - it should ideally be set once). That is a compromise and lets the user get the saved setting quickly (without having to go through the choice loop) but still allows changing the settings.In my experience, the hardest part of coding is figuring out what you want to do.Apologies if I screwed up some syntax or made some other silly mistake; I am not testing or even compiling the code.Hope it helps.