Hot answers tagged

46

My general rule for embedded systems is to only malloc() large buffers and only once, at the start of the program, e.g., in setup(). The trouble comes when you allocate and de-allocate memory. Over a long run session, memory becomes fragmented and eventually an allocation fails due to lack of a sufficiently large free area, even though the total free memory ...


30

While EEPROM.read and EEPROM.write are valid methods, it's like mopping the floor with a toothbrush. Use EEPROM.put and EEPROM.get instead. For example: #include <EEPROM.h> void setup() { Serial.begin(9600); uint addr = 0; // fake data struct { uint val = 0; char str[20] = ""; } data; // commit 512 bytes of ESP8266 flash (for ...


23

As you state, the internal EEPROM has a lifetime of 100,000 write cycles. This isn't a guess - a very significant proportion of ATmega328 will reach this number with no issues. I have tested three processors before, and all reached 150,000 cycles with no issues. It is important to note the failure mode of EEPROM. Most "EEPROM destroyer" projects repeatedly ...


19

I have taken a look at the algorithm used by malloc(), from avr-libc, and there seems to be a few usage patterns that are safe from the point of view of heap fragmentation: 1. Allocate only long-lived buffers By this I mean: allocate all you need at the beginning of the program, and never free it. Of course, in this case, you could as well use static ...


17

Typically, when writing Arduino sketches, you will avoid dynamic allocation (be it with malloc or new for C++ instances), people rather use global -or static- variables, or local (stack) variables. Using dynamic allocation can lead to several problems: memory leaks (if you lose a pointer to a memory you previously allocated, or more likely if you forget to ...


10

I disagree with people who think you shouldn't use it or it is generally unnecessary. I believe it can be dangerous if you don't know the ins and outs of it, but it is useful. I do have cases where I don't know (and shouldn't care to know) the size of a structure or a buffer (at compile time or run time), especially when it comes to libraries I send out into ...


10

I once ran an experiment on an external EEPROM with 1 million max rated cycles. It took about 6 million cycles to become majorly corrupted, and before that it had progressed having sporadic amounts of corruption. When you say you do not change the value, i am assuming you are writing the same data to an address multiple times. This almost certainly would ...


9

Using dynamic allocation (via malloc/free or new/delete) isn't inherently bad as such. In fact, for something like string processing (e.g. via the String object), it's often quite helpful. That's because many sketches use several small fragments of strings, which eventually get combined into a larger one. Using dynamic allocation lets you use only as much ...


9

Short answer: No; From the atmega328's data sheet (though it applies to all AVR's): AVR uses a Harvard architecture – with separate memories and buses for program and data. Instructions in the program memory are executed with a single level pipelining. While one instruction is being executed, the next instruction is pre-fetched from the program ...


9

The Arduino EEPROM library is compatible with the ATTiny range of AVR microcontrollers as the library itself is built on the standard Atmel AVR avr/eeprom.h 'library' so it is compatible with all the AVR microcontrollers. The EEPROM also doesn't take to being written or read to often as EEPROM can wear very quickly. Reading though does not cause much damage ...


9

In flash and eeprom memory an erased value is 255. It's all about how flash memory works. If you want something other than 255 in there you will have to write something other than 255 in there.


8

This is a X->Y problem. Here is a solution for X: Bit 3 of high fuse of the ATmega328p controls if EEPROM memory is preserved through the chip erase. You can change the high fuse setting in boards.txt. Restart the IDE to apply the new setting. The fuses are written when you select the "burn bootloader" option in the Arduino IDE.


8

You are saving a String object in EEPROM, which is useless. A string object does not store the contents of your string. Instead, it just stores: the memory address where the actual contents (the characters) is stored the amount of memory allocated for this contents the number of characters that actually make the string This is what you are storing to, and ...


8

increase is a global variable and will implicitly initialized with the value zero. Then you are reading the EEPROM data into the variable storagedata in setup(). And then in loop() you are increasing increase from zero to one and write that to EEPROM. This value then gets read back into storagedata. So now increase and storagedata have the same value: one. ...


7

The other answer mentioned some general ideas; here are a couple of more-specific notes. • You can direct your writes of single bytes through a routine that reads the EEPROM cell before writing to it, and if its value isn't changing, doesn't write. • For load-leveling, you can divide the EEPROM address space into k buckets, where k =⌊E/(n+1)⌋, with n = ...


6

The internal RAM of the Arduino will be reset when you repower the chip, so if you want to keep your data, you need to store it in EEPROM. If you are worried about the limited write/erase cycles, you should estimate how often the data would be updated (i.e. written to EEPROM) and how long you plan the lifetime of the device you build. If 100,000 cycles ...


6

Yes, that is fine. LOW is 0 and HIGH is 1. digitalWrite() sets the output to off if it receives a 0 and on if it receives anything of 1 or more. That means that these are all equivalent: digitalWrite(pin, HIGH); digitalWrite(pin, 1); digitalWrite(pin, 69); It's especially useful when you are examining a variable for, say, a certain bit being set: ...


6

Thanks to Jaromanda X and Juraj for the SPIFFS recommendation. I was able to use this block of SPIFFS code as an example and safely store settings in my project outside of the compiled source. To upload files to my ESP8266, I followed the installation and usage instructions for the ESP8266 filesystem plugin for the standard Arduino IDE. First, I created a ....


6

You can cycle through all the addresses in the EEPROM like a ring buffer. You'll need to reserve a bit so you can binary search for the head of the buffer during startup. You can also reduce how often you write in general especially when the count will increment in bursts, try and wait out those bursts instead of writing on every increment.


5

Testing a single byte write I ran some test code overnight to try to get to the bottom of this. Somewhat surprisingly perhaps, I got up to over 11 million writes before a read-back failed: Current count = 11514199 Writes per minute: 17550 .................... Current count = 11538199 Writes per minute: 17550 .................... Current count = 11562199 ...


5

No. The foundation of a Harvard architecture such as AVR is to only allow code that exists within program space to be executed, and EEPROM is not within program space. It is possible, however, to write a virtual machine that will run from flash. This VM can then read program-become-data from anywhere and take action based on it.


5

The AVR (the microcontroller family traditionally used on Arduino boards) is a Harvard Architecture, meaning that executable code and variables are in two separate memories - in this case flash and SRAM. The executable code never leaves flash memory. When you call a function the return address is usually pushed to the stack - the exception is when the ...


5

Local variables and function parameters are stored on the stack. However, that is not a reason not to use them. Computers are designed to work that way. Stack memory is only in use while a function is active. As soon as the function returns, the memory is freed. Stack memory is a GOOD Thing. You don't want to use recursive functions with lots of levels of ...


5

You can divide EEPROM space into entries and provide each entry with a single "dirty" bit. You could use a separate byte to store it, or reuse a bit from a byte which is not completely used by your data. Suppose you start with EEPROM willed with zeroes, and you decide that the first byte of each entry holds the "dirty" bit in the LSb. When you log ...


5

My best off-the-top-of-my-head figure is 6 bytes. 4 bytes for the timestamp (assuming a 32-bit value). Two byte for -32768 to +32767. Multiply the temperature by 100 to make it into the integer range -5500 to +12599. That then fits comfortably inside a 16-bit signed integer. However, there are other tricks you can use. For instance, if you know the time ...


5

A simple SPI SRAM chip. Available up to 128KB, such as the 23LC1024: http://www.microchip.com/wwwproducts/en/23LC1024


5

Some things I noticed in your code: You are writing everything to the same address (is that intentional?) You are only writing the first 6 six bytes of your arrays (I am pretty sure that is intentional) You are declaring these arrays to be bigger than what you are putting in them (this is again probably intentional, but I am just guessing) So here is an ...


5

The ESP8266 doesn't have any EEPROM. Instead it emulates it using Flash. In order not to wear out your flash you have to "commit" changes to the flash once they have been queued for writing - otherwise they will be lost. Instead of using the Arduino examples you should be using the ESP8266 specific examples included with the ESP8266 EEPROM emulation ...


5

I can think of a few: don't power it on unless you have to; don't write to it unless you have to; write as little data to you as you can - compress the data; only write to it during brown out or power down, ...; level the writes to as many cells as possible - increment the write address with subsequent writes; use a big eeprom; use fram; use sram + battery ...


Only top voted, non community-wiki answers of a minimum length are eligible