I have a class defined as below, it's basically a simple ring buffer, with some methods for getting useful statistics from the data held in the buffer.
enum BalanceMsgType{
BAL_MSG_NOT = 0,
BAL_MSG_READING = 1,
BAL_MSG_SPECIAL = 2,
BAL_MSG_ERROR = 3
};
typedef struct MeasuredMass{
float mg;
unsigned long time;
bool steady;
BalanceMsgType type;
};
class RingBuffer{
private:
unsigned int _size = 0;
unsigned int _pos = 0;
MeasuredMass *_array;
void LinearRegression(){
//... left out for simplicity
}
public:
float lin_reg_m = 0;
float lin_reg_c = 0;
float lin_reg_r = 0;
float est_current_mg = 0;
//methods
RingBuffer(unsigned int size){
_size = size; //forgetting to put this line ->div0-> >1hr debugging :(
_array = new MeasuredMass[_size];
for (int i = 0; i < _size; i++){
_array[i].mg = 0.0;
}
}
void Add(MeasuredMass in_element){
_array[_pos] = in_element;
_pos = (_pos + 1)%_size;
LinearRegression();
est_current_mg = lin_reg_m*(in_element.time+BALANCE_DELAY) + lin_reg_c;
}
void ReadInOrder(MeasuredMass *pdata){ //Call with
//my_buffer.ReadInOrder(data)
for(int i = 0; i < _size; i++){
pdata[i]=_array[(_pos+i+1)%_size];
}
}
float Sum(){
//...
}
float Mean(){
//...
}
float StdDev(){
//...
}
bool SteadyEnough(float max_sd){
//...
}
};
It compiles fine, and runs nicely in test programs. However, if I include it in larger programs (something like progmem 117404 of 122880 bytes, global vars 13604 of 32768) I get a "Board at COM8 not available" warning when using the Arduino Serial Monitor after uploading to my Fubarino Mini. (Even without actually interacting with those programs beyond creating an instance of the class.) Recent experience tells me this is some kind of crash due to a runtime error.
Fiddling around with the code, I've found that the issue doesn't occur in a version of the library which holds an array of floats instead of my MeasuredMass
. That my MeasuredMass
struct is obviously much larger than a float suggests to me that this is due to some pointer/array overflowy behaviour.
I've also managed to show that if I alter the class such that it uses a fixed length array rather than a pointer to one, the issue disappears.
i.e. RingBuffer's private member MeasuredMass *_array;
becomes MeasuredMass _array[25];
and
RingBuffer(unsigned int size){
_size = size; //forgetting to put this line -> div0 -> >1hr bugtracking
_array = new MeasuredMass[_size];
for (int i = 0; i < _size; i++){
_array[i].mg = 0.0;
}
}
becomes
RingBuffer(){
for (int i = 0; i < _size; i++){
_array[i].mg = 0.0;
}
}
I'd rather maintain the ability to set the size of the ring buffer at runtime (in my case it's set based upon the number of seconds' worth of data requested), so can anyone help me in figuring out how I can achieve this without running into the overflow / memory problems I seem to be having?
Thanks