I struggle a bit to create a circularbuffer for my application.
What i want. I continuously measure a pH-value and wanna display them, visual with bars in a xy-diagram.
I want that the current value stands always on the leftest (first) place and and the older value are shifted to the right.
My research showed that a circularbuffer is the right thing. To test it. i first just wanna display the 4 latest values
i store my measured values into an array
plotValues[z]=(sonde_pH.measuredValue);
Now i am stuck. the name of my bars are j0,j1,j2,j3. So the current value should alway be in bar j0.
I need a function that returns the index the following:
0 1 2 3 0
1 ---> 0 ----> 1 ----> 2 ---> 1 and so on
2 3 0 1 2
3 2 3 0 3
Danois90:
NO! When the "int" rolls over it may cause problems.
How will it “roll-over” when you are only ever adding 1?
How does your code prevent this?
How does your code correctly wrap the index (in any case other than adding one to the maximum) when it always sets the index to zero?
I agree if you are adding more than one, then there is a possibility of exceeding the range of an int.
I also agree, at least for buffers which are not exact powers of two, then use of the modulo operator may not be the most efficient.
zwieblum:
Sorry, but no again. If you write wrong code, your code is wrong whatever you do.
I can't write correct code to demonstrate a flaw. The whole point is that it doesn't work. That is standard procedure in cases like this.
Edit - okay, I see the difference. The danger is there, but you've avoided it by constraining the variable - it never exceeds the range of LEN and so never goes negative.
#define LEN 10
int idx;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(1000);
for (unsigned int iter = 32736; iter < 32836; iter++) {
Serial.print(iter);
Serial.print(", ");
Serial.print(idx);
Serial.println();
idx=(idx+1)%LEN;
}
}
void loop() {}
Sometimes people will try something like:
int counter;
...
idx = (counter++)%LEN;
Because that one fails, alarm bells go off anytime anything looks similar.
However, the execution speed and code size overhead for '%' greatly exceed a simple range test and adjustment. It also obfuscates the logic, where the range test and adjustment is self-explanatory.
I have modified my previous post. The modulus operator will work, but I would always avoid it where possible because there is no hardware division available in AVR's. Division is emulated with a series of instructions and when you use modulus you will first have to emulate a division and then perform a multiplication (which btw. may also be emulated) of the result before subtracting that result from a value in order to get the modulus result: Not very effective. A simple and effective one-liner would be:
Thank you for all the answers. unfortunly it seems i am to dumb right now.
Thats the function i made to get my right index
int mapCircularBufferIndex(int index, int bufferBegin, int bufferSize)
{
index -= bufferBegin;
if (index >= bufferSize) index = bufferSize;
return abs(index);
}