eeprom library example

Hi all,
I’m trying to involve the alternative read/write of the avr/eeprom library
http://arduino.cc/playground/Code/EEPROMWriteAnything

I’m using a struct lVector that is 3 long.

#include <avr/eeprom.h>
#include <lVector.h>

lVector someVector;
int address = 2 ;

In setup:

  lVector mV;
  mV.x = 3002 ;
  mV.y = 58796 ;
  mV.z = -326 ;  
  writeEEP_lVector( address , mV );

where writeEEP_lVector refers to

void writeEEP_lVector( int address , lVector value ){
  eeprom_write_block((const void*)&value, (void*)address, sizeof(lVector));
  delay(20);
}

in the loop I make a read:

  if(test){
    eeprom_read_block((void*)someVector, (void*)address, sizeof(lVector));
    delay(20);
    Serial.print("x ") ;
    ....
    delay(20);
    test=false ;
} // end test

Some of the variables used should probably be pointers of their types instead … I’ve tried some changes ( lVector *someVector ; ) and managed to changed the error-messages. It’s the ‘read’ that throws an error.
Can any of you ‘see’ what’s wrong and why?

What error messages? You don't post them, nor your complete code. How about posting all of it so we can reproduce the problem? Or the error messages anyway.

[quote author=Nick Gammon link=topic=112970.msg849384#msg849384 date=1341474317] What error messages? You don't post them, nor your complete code. How about posting all of it so we can reproduce the problem? Or the error messages anyway. [/quote]

hi Nick, I'll have to move the code to another board . . I'll be back

ok, here goes a version of the code:

#include <avr/EEPROM.h>
#include <lVector.h>

int address = 2;
lVector someVector ;
lVector mV;

void setup()
{
  Serial.begin(9600);
  
  mV.x = 3002 ;
  mV.y = 58796 ;
  mV.z = -326 ;
  
  writeEEP_lVector( address , mV );
  delay(20) ; 
}// end setup -----------------------------------

boolean test = true ;
void loop()
{

  if(test){
    readEEP_lVector(  );
    delay(20);

    Serial.print("x ") ;
    Serial.print(someVector.x) ;
    Serial.print(" , y ") ;
    Serial.print(someVector.y) ;
    Serial.print(" , z ") ;
    Serial.println(someVector.z) ; 
    delay(20);    
    test=false ;
  }// end test

}// end loop ------------------------------------------------------

void writeEEP_lVector( int myAddress , lVector value ){
  eeprom_write_block((const void*)&value, (void*)myAddress, sizeof(lVector));
}// end writeEEP_lVector-----------------------------------------

void readEEP_lVector(  ){
  eeprom_read_block((void*)someVector, (void*)address, sizeof(lVector));
}// end readEEP_lVector----------------------------------

the error is

eeprom_read.cpp: In function 'void readEEP_lVector()':
eeprom_read:46: error: invalid cast from type 'lVector' to type 'void*'

To save me searching, can you post lVector.h or at least tell me where to find it?

#ifndef lVector_h
#define lVector_h

#include "Arduino.h"

struct lVector{
    long x ;
    long y ;
    long z ;
} ; //end struct

#endif

The short answer is to change the function to read:

void readEEP_lVector(  ){
  eeprom_read_block((void*)&someVector, (void*)address, sizeof(lVector));
}// end readEEP_lVector----------------------------------

But why is one function (writeEEP_lVector) taking arguments and another (readEEP_lVector) not?

Why not use the EEPROMAnything you mentioned in your first post? Then you don’t need a helper function…

#include "lVector.h"
#include <EEPROM.h>
#include <EEPROMAnything.h>

int address = 2;
lVector someVector ;
lVector mV;

void setup()
{
  Serial.begin(9600);
  
  mV.x = 3002 ;
  mV.y = 58796 ;
  mV.z = -326 ;
  
  EEPROM_writeAnything(address, mV);
  delay(20) ; 
}// end setup -----------------------------------

boolean test = true ;
void loop()
{

  if(test){
    EEPROM_readAnything(address, someVector);
    delay(20);

    Serial.print("x ") ;
    Serial.print(someVector.x) ;
    Serial.print(" , y ") ;
    Serial.print(someVector.y) ;
    Serial.print(" , z ") ;
    Serial.println(someVector.z) ; 
    delay(20);    
    test=false ;
  }// end test

}// end loop ------------------------------------------------------

invalid cast from type 'lVector' to type 'void*'

That's a really big clue as to what was wrong - you were trying to pass the structure, not the structure's address, as Nick pointed out.

[quote author=Nick Gammon link=topic=112970.msg849402#msg849402 date=1341476894] The short answer is to change the function to read:

void readEEP_lVector(  ){
  eeprom_read_block((void*)&someVector, (void*)address, sizeof(lVector));
}// end readEEP_lVector----------------------------------

[/quote] .. yes. But I'm kinda 'blind' on stuff that involves pointers and dereferencing. AWOL, big clue or not .. I did try to pass a pointer (something like lVector * someVector ) and changed the error-output. If it's too big a question, then tell me and I'll go do my homework. You make it sound as something insignificant. Can you point out where I make a hazardous divertion from the example-code?

But why is one function (writeEEP_lVector) taking arguments and another (readEEP_lVector) not?

It would be preferable with arguments, and I tried. The code as is, is the closest thing I can get to the example-code ( .. assuming that the example-code works)

Why not use the EEPROMAnything you mentioned in your first post? Then you don't need a helper function...

I try to limit the number of extra foreign libraries. But if it cann't be any different, I'll take it.

I did try to pass a pointer (something like lVector * someVector ) and changed the error-output.

It isn't too big a question, but unless you post all the code and the error message, it's difficult to point (no pun intended) you in the right direction.

AWOL:
It isn’t too big a question, but unless you post all the code and the error message, it’s difficult to point (no pun intended) you in the right direction.

What’s missing?

I pulled the code out from a larger context, put it into a new sketch and changed the board. The full code is delivered above.

The lVector is stored in a .h file … with the copied code above. Maybe it will work with a local struct.

[edit:]
Here is the changed code …
lVector someVector changed to lVector *someVector ;
and dereferenced : lVector res = &someVector;
I bet it’s the most silly code you’ve seen for a while!

#include <avr/EEPROM.h>
#include <lVector.h>

int address = 2;
lVector *someVector ;
lVector mV;

void setup()
{
  Serial.begin(9600);
  
  mV.x = 3002 ;
  mV.y = 58796 ;
  mV.z = -326 ;
  
  writeEEP_lVector( address , mV );
  delay(20) ; 
}// end setup -----------------------------------

boolean test = true ;
void loop()
{
  if(test){
    readEEP_lVector(  );
    delay(20);
lVector res = &someVector;
    Serial.print("x ") ;
    Serial.print(res.x) ;
    Serial.print(" , y ") ;
    Serial.print(res.y) ;
    Serial.print(" , z ") ;
    Serial.println(res.z) ; 
    delay(20);    
    test=false ;
  }// end test

}// end loop ------------------------------------------------------

void writeEEP_lVector( int myAddress , lVector value ){
  eeprom_write_block((const void*)&value, (void*)myAddress, sizeof(lVector));
}// end writeEEP_lVector-----------------------------------------

void readEEP_lVector(  ){
  eeprom_read_block((void*)someVector, (void*)address, sizeof(lVector));
}// end readEEP_lVector----------------------------------

error:
eeprom_test_001.cpp: In function ‘void loop()’:
eeprom_test_001:26: error: conversion from ‘lVector**’ to non-scalar type ‘lVector’ requested

eeprom_read_block((void*)someVector, (void*)address, sizeof(lVector));

Here, you’re trying to make a pointer ("(void*)") out of a structure (“someVector”).

The compiler doesn’t know how to do that, so it gives you an error message.

The address of “someVector” has the type “pointer to lVector”, but you can’t pass a “pointer to lVector” to the function “eeprom_read_block”, because there is no overload of “eeprom_read_block” that takes that data type as a parameter, so, you need to cast the “pointer to lVector” to be a “void*” which the function does know about.

AWOL: eeprom_read_block((void*)someVector, (void*)address, sizeof(lVector));

Here, you're trying to make a pointer ("(void*)") out of a structure ("someVector").

The compiler doesn't know how to do that, so it gives you an error message.

The code is almost copied directly from it's place in the loop() example-code. Is that code wrong? or where is the difference?

The address of "someVector" has the type "pointer to lVector", but you can't pass a "pointer to lVector" to the function "eeprom_read_block", because there is no overload of "eeprom_read_block" that takes that data type as a parameter, so, you need to cast the "pointer to lVector" to be a "void*" which the function does know about.

Like lVector (void *) someVector ;

gee does that stuff make me feel stupid and blind

The code is almost copied directly from it's place in the loop() example-code.

Can you show the original?

"almost" isn't normally good enough for the uber-pedant that is the compiler.

There is a big difference between a pointer and what it points to.

As an example, say you live at 12 Main Street, Gotham City.

I can write on a bit of paper "12 Main Street, Gotham City" which is your address. But I can't go and live in the bit of paper with the address on it. Many people can write your address on bits of paper. That's fine. None of them are your house.

In this case the function wants the address, not the house.

AWOL,
I just went the test the original.
You can find it on the link in the first post.

#include <avr/eeprom.h>

struct settings_t
{
  long alarm;
  int mode;
} 
settings;



void setup()
{
  Serial.begin(9600); 
  eeprom_read_block((void*)&settings, (void*)0, sizeof(settings));
  Serial.print(settings.alarm) ;
  Serial.print(" , ") ;
  Serial.println(settings.mode) ;
  // ...
}
boolean test=true ;
void loop()
{
  if(test){
    settings.alarm=76 ;
    settings.mode =54 ;
    Serial.print(settings.alarm) ;
    Serial.print(" ,, ") ;
    Serial.println(settings.mode) ;
    eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));
    test=false ;
  }   
}

It executes with no error.
but …

  1. I execute once, with one set of values.
  2. Execute again with another set of values. The previous values are supposed to be read at start, but it prints the new values …

Nick, … I have a pretty good idea of what pointer* and to some extend the dereferencing& is, but from there to make any use of it is a leap.

You use the pointer to find something. The same way you use an address to find a house.

2) Execute again with another set of values. The previous values are supposed to be read at start, but it prints the new values ..

Yes, I saw that too. But remember this is what happens:

  • You test it once ... the EEPROM is updated.
  • You change the values and upload the sketch.
  • The sketch starts running the moment it is uploaded and updates the values.
  • You start the serial monitor. But this is the second time the sketch ran. So it shows the new values.

[quote author=Nick Gammon link=topic=112970.msg849508#msg849508 date=1341483915] You use the pointer to find something. The same way you use an address to find a house.

2) Execute again with another set of values. The previous values are supposed to be read at start, but it prints the new values ..

Yes, I saw that too. But remember this is what happens:

  • You test it once ... the EEPROM is updated.
  • You change the values and upload the sketch.
  • The sketch starts running the moment it is uploaded and updates the values.
  • You start the serial monitor. But this is the second time the sketch ran. So it shows the new values.

[/quote]

.. I tried again with a small series of read/writes, and it works. // cann't blame it on the example-code then

I tried another line of code.
It compiles and is executable.
Only snag is, that it comes up with the wrong reads.

if you try it, then send a key through the serial monitor and it’ll flip between reads and writes.

#include <avr/eeprom.h>
#include <lVector.h>

lVector someVector ; 

void setup()
{
  Serial.begin(9600);
}
boolean test=true ;
long counter=1;
void loop()
{
  if( Serial.available()>0){
    int gg = Serial.read();
    someVector.x = counter ;
    someVector.y = counter*counter ;
    someVector.z = counter*counter*counter ;
    counter++;
    if(test){
    Serial.println("writes ") ;  
    writeVector( someVector, 0 );
    test=false;
    }
    else{
    Serial.println("reads ") ; 
    readVector(0);
    test=true;
    }
  }
}// end loop

void writeVector( lVector myV, int anAdd){
  Serial.print(myV.x) ;
  Serial.print(" , ") ;
  Serial.print(myV.y) ;
  Serial.print(" , ") ;
  Serial.println(myV.z) ;
  delay(20) ;
  eeprom_write_block((const void*)&myV, (void*)anAdd, sizeof(lVector));
  delay(20) ;
}

void readVector(int anAdd  ){
  void* someV;
  eeprom_read_block(&someV, (void*)anAdd, sizeof(lVector));//&someVector,  (void*)
  delay(20) ;

  lVector *rs =(lVector *) someV;
  lVector tt = *rs ;
  Serial.print(tt.x) ;
  Serial.print(" , ") ;
  Serial.print(tt.y) ;
  Serial.print(" , ") ;
  Serial.println(tt.z) ;
  delay(20) ;
}
void readVector(int anAdd  ){
  void* someV;
  eeprom_read_block(&someV, (void*)anAdd, sizeof(lVector));//&someVector,  (void*)
  delay(20) ;

  lVector *rs =(lVector *) someV;
  lVector tt = *rs ;

What?

No, no. Don't do this. Pass an argument to the function and change that. This looks very much like you experimented for an hour and finally got a compiler error to go away.

Or use what I suggested above (reply #6).