-4

Update 3 Jan. 2016: I have answered my own question now too.

I need some help formatting my "if" statement in this C++ macro please:

#define updateEEPROMVal(address,val)  if (EEPROM.get(address)!=val) \
                                        EEPROM.put(address,val)

I'm getting pages of errors, so I'm assuming it's a simple formatting problem.

Update Apr. 2020: Jump straight to my answer. My macro was fine (surrounding it with do {} while (false) would have been better of course, but it was fine as-is). I was simply forgetting the 2nd parameter in EEPROM.get() is all. The 2nd parameter is passed by NON-const C++ reference, and at the time I didn't really know what a reference was or how it worked, so I didn't use the .get() method correctly. That's it!

Back to my original question from 2016:

Here's the full context:

//----------------------------------------------------------------------------------------------------------------------------------
//storeXYValsIntoEEPROM
//-store the current global variable x and y low, center, and high values into EEPROM
//----------------------------------------------------------------------------------------------------------------------------------
#define updateEEPROMVal(address,val)  if (EEPROM.get(address)!=val) \
                                        EEPROM.put(address,val)
void storeXYValsIntoEEPROM()
{
  //update EEPROM values *only* if necessary, this way you minimize writes (and wear-and-tear) on the EEPROM, since it is limited to
  //100k writes per cell I believe (see datasheet)
  updateEEPROMVal(0,x_low);
  updateEEPROMVal(2,x_ctr);
  updateEEPROMVal(4,x_high);
  updateEEPROMVal(6,y_low);
  updateEEPROMVal(8,y_ctr);
  updateEEPROMVal(10,y_high);
}

UPDATE: HERE's my error output:

Arduino: 1.6.5 (Windows 8.1), Board: "Arduino Uno"  

Using library IRremote in folder: C:\Gabe\Gabe - RC-extra\Arduino\Sketches\libraries\IRremote (legacy)  

Using library eRCaGuy_ButtonReader in folder: C:\Gabe\Gabe - RC-extra\Arduino\Sketches\libraries\eRCaGuy_ButtonReader (legacy)  

Using library EEPROM in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM   



C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IC:\Gabe\Gabe - RC-extra\Arduino\Sketches\libraries\IRremote -IC:\Gabe\Gabe - RC-extra\Arduino\Sketches\libraries\eRCaGuy_ButtonReader -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM C:\Users\Gabriel\AppData\Local\Temp\build6111239347405487460.tmp\IR_Tx_code5_w_calibration_mode.cpp -o   C:\Users\Gabriel\AppData\Local\Temp\build6111239347405487460.tmp\IR_Tx_code5_w_calibration_mode.cpp.o   

In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:43:30: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     operator const uint8_t() const       { return **this; }  
                              ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:92:26: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     operator const int() const          { return index; }  
                          ^
IR_Tx_code5_w_calibration_mode.ino: In function 'void storeXYValsIntoEEPROM()':
IR_Tx_code5_w_calibration_mode.ino:430:61: error: no matching function for call to 'EEPROMClass::get(int)'
IR_Tx_code5_w_calibration_mode.ino:436:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: note: candidate is:
IR_Tx_code5_w_calibration_mode.ino:436:3: note: in expansion of macro 'updateEEPROMVal'
In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){  
                               ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
IR_Tx_code5_w_calibration_mode.ino:430:61: note:   candidate expects 2 arguments, 1 provided
IR_Tx_code5_w_calibration_mode.ino:436:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: error: no matching function for call to 'EEPROMClass::get(int)'
IR_Tx_code5_w_calibration_mode.ino:437:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: note: candidate is:
IR_Tx_code5_w_calibration_mode.ino:437:3: note: in expansion of macro 'updateEEPROMVal'
In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){  
                               ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
IR_Tx_code5_w_calibration_mode.ino:430:61: note:   candidate expects 2 arguments, 1 provided
IR_Tx_code5_w_calibration_mode.ino:437:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: error: no matching function for call to 'EEPROMClass::get(int)'
IR_Tx_code5_w_calibration_mode.ino:438:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: note: candidate is:
IR_Tx_code5_w_calibration_mode.ino:438:3: note: in expansion of macro 'updateEEPROMVal'
In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){  
                               ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
IR_Tx_code5_w_calibration_mode.ino:430:61: note:   candidate expects 2 arguments, 1 provided
IR_Tx_code5_w_calibration_mode.ino:438:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: error: no matching function for call to 'EEPROMClass::get(int)'
IR_Tx_code5_w_calibration_mode.ino:439:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: note: candidate is:
IR_Tx_code5_w_calibration_mode.ino:439:3: note: in expansion of macro 'updateEEPROMVal'
In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){  
                               ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
IR_Tx_code5_w_calibration_mode.ino:430:61: note:   candidate expects 2 arguments, 1 provided
IR_Tx_code5_w_calibration_mode.ino:439:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: error: no matching function for call to 'EEPROMClass::get(int)'
IR_Tx_code5_w_calibration_mode.ino:440:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: note: candidate is:
IR_Tx_code5_w_calibration_mode.ino:440:3: note: in expansion of macro 'updateEEPROMVal'
In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){  
                               ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
IR_Tx_code5_w_calibration_mode.ino:430:61: note:   candidate expects 2 arguments, 1 provided
IR_Tx_code5_w_calibration_mode.ino:440:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: error: no matching function for call to 'EEPROMClass::get(int)'
IR_Tx_code5_w_calibration_mode.ino:441:3: note: in expansion of macro 'updateEEPROMVal'
IR_Tx_code5_w_calibration_mode.ino:430:61: note: candidate is:
IR_Tx_code5_w_calibration_mode.ino:441:3: note: in expansion of macro 'updateEEPROMVal'
In file included from IR_Tx_code5_w_calibration_mode.ino:27:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note: template<class T> T& EEPROMClass::get(int, T&)
     template< typename T > T &get( int idx, T &t ){  
                               ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM/EEPROM.h:130:31: note:   template argument deduction/substitution failed:
IR_Tx_code5_w_calibration_mode.ino:430:61: note:   candidate expects 2 arguments, 1 provided
IR_Tx_code5_w_calibration_mode.ino:441:3: note: in expansion of macro 'updateEEPROMVal'  
Multiple libraries were found for "IRremote.h"  

 Used: C:\Gabe\Gabe - RC-extra\Arduino\Sketches\libraries\IRremote  

 Not used: C:\Program Files (x86)\Arduino\libraries\RobotIRremote  

no matching function for call to 'EEPROMClass::get(int)'  
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265

3 Answers3

2

Code with do{...}while(0) your macro (and don't forget the semicolon):

 #define updateEEPROMVal(address,val)  do{if (EEPROM.get(address)!=val) \
                                    EEPROM.put(address,val);}while(0)

See also this

Better yet, make that a static inline function (to be put in some header file).

Also, use g++ -C -E source.cc > source.ii to get the preprocessed form, you can look inside it.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
2

There is no need for this. When I wrote the library I made sure it minimizes the wear & tear.

The EEPROM function put() uses the update method on the byte level. You are simply duplicating functionality.

If you have more questions regarding the EEPROM lib, ask on the forum.

I created a thread just for my library: https://forum.arduino.cc/index.php?topic=312645

Chris A
  • 1,475
  • 3
  • 18
  • 22
0

My Answer:

Sorry for the trouble, it turns out I was misusing the EEPROM.get function, and the problem wasn't my macro at all. The EEPROM library get() method is defined: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/EEPROM/src/EEPROM.h#L130, and the documentation here: https://www.arduino.cc/en/Reference/EEPROMGet.

I was simply missing the 2nd argument, accidentally using this:

EEPROM.get(address);

...instead of this:

any_type val_in_EEPROM;
EEPROM.get(address, val_in_EEPROM);

Here are 2 solutions I came up with that work.

1) Using a separate function:

-I prefer this method. It turns out the word "inline" in this case is optional, and makes no difference.
-This method makes my program 7610 bytes, with 472 bytes used for global variables. It takes 162 bytes less memory than option 2 below.

inline void updateEEPROMVal(uint16_t address, uint16_t val)
{
  uint16_t val_in_EEPROM;
  EEPROM.get(address,val_in_EEPROM);
  if (val_in_EEPROM!=val)
    EEPROM.put(address,val);
}

void storeGlobalXYValsIntoEEPROM()
{
  updateEEPROMVal(0,x_low);
  updateEEPROMVal(2,x_ctr);
  updateEEPROMVal(4,x_high);
  updateEEPROMVal(6,y_low);
  updateEEPROMVal(8,y_ctr);
  updateEEPROMVal(10,y_high);
}

2) Using a macro, as follows:

-I prefer the above method.
-This method takes 7772 bytes for program space, and 472 bytes for global variables. It takes 162 bytes more than the above method.

uint16_t val_in_EEPROM;    
#define updateEEPROMVal(address,val)  EEPROM.get(address,val_in_EEPROM); \
                                      if (val_in_EEPROM!=val)            \
                                        EEPROM.put(address,val)
void storeGlobalXYValsIntoEEPROM()
{
  uint16_t val_in_EEPROM;

  updateEEPROMVal(0,x_low);
  updateEEPROMVal(2,x_ctr);
  updateEEPROMVal(4,x_high);
  updateEEPROMVal(6,y_low);
  updateEEPROMVal(8,y_ctr);
  updateEEPROMVal(10,y_high);
}

Thanks for everyone's help!

3) (Updated answer) EEPROM.put(address,val) already does the functionality I'm trying to achieve above to avoid unnecessary wear on the EEPROM, so just use the .put() function by itself, as-is!

See @Chris A's answer here.

Yet again I have failed to fully read the documentation. The EEPROM library Put function documentation here (https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/libraries/EEPROM) says, "This function uses the update method to write its data, and therefore only rewrites changed cells." Therefore, my update code is redundant. I just need to use the "put" function as-is. Refer to the EEPROM library's author's (Chris A) answer here too.

So, I've learned a lot, and here's my final answer:

Get rid of my support function and macro, and just use the put function as-is. It already minimizes EEPROM wear and only writes if the contents are different. Nevertheless, I'll leave my above answers for completeness' sake for those who are looking for what the macro or function solution otherwise would have been.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265