I'm building a number of remote sensors and I would like to store
some configuration data for each sensor in the ATMega EEPROM.
I'm using ASK transmitter modules to send the sensor data to a central receiver.
Using the RadioHead ASK driver, this requires the declaration of an RH_ASK instance with various parameters,
e.g RH_ASK rh(speed, rxpin, txpin);
The problem is that the values of txpin etc will be stored in EEPROM & so will not be known until setup() runs.
But if the RH_ASK instance is declared as a local variable in setup() it won't be visible in loop().
Effectively I want to declare a global variable with local parameters.
The only way I could see around this is to declare the RH_ASK instance inside loop():
word txpin, rxpin, speed;
void setup()
{
... read values from EEPROM...
}
void loop ()
{
RH_ASK rh(speed, rxpin, txpin);
...
while(1)
{ real loop() code goes here }
}
So loop() only runs once. But this seems to be fighting the spirit of the setup/loop structure.
Is there a better solution?
Incidentally the sensor is a DHT22, and using Rob Tillaart's DHTLIB library the declaration of the
global DHT instance doesn't require any parameters, so no problems there.
The C++ 'new' operator is your friend. Declare a pointer to your object in global scope, then create the object dynamically by calling the new operator. The new operator allocates the object on the heap and not the stack. So the object persists in all scopes until operator delete is called. The object's properties and methods are accessed using '->' the same way you would access a struct's fields via a pointer.
Rather than using the heap and 600 bytes of program space that only gets called once, you can use the "placement new" operator. It uses a static memory location that you provide. The object will be constructed there.
If you write your initial values using a separate sketch then you can still just use the EEPROM lib, mine just makes things a little simpler to read and write.
// Your class how ever it is defined.
struct RH_ASK{
RH_ASK( uint8_t txpin, uint8_t rxpin, uint8_t speed ){}
};
//----------------------
//My EEWrap library.
#include <EEWrap.h>
uint16_e txpin EEMEM;
uint16_e rxpin EEMEM;
uint16_e speed EEMEM;
RH_ASK rh(speed, rxpin, txpin);
void setup() {}
void loop() {
//Write new values to EEPROM when needed.
txpin = 4;
rxpin = 5;
speed = 6;
}
This is why many classes use a begin() method to set them up, because constructors of static instances
run too early to be useful to do anything but allocate storage.
If you use new be sure to avoid calling it more than once or you'll rapidly run out of RAM on a microcontroller!
This does exactly what I wanted, i.e. declaration of a global variable with parameters stored in EEPROM. (Another sketch loads the personalisation values for each board into EEPROM.)