filling bars - logical programming issue

Hello friends!

What i am using: ESP32, Nextion device.

What i am trying to do: Currently i am measuring a voltage signal every second. Now i want to fill a bar (or better bars) with the measured values. For that i created ~25 bars on my Nextion device to be filled. Just imagne 25 bars in a raw. The names of them are j0-j24

My plan is that the latest measured value should fill the rightest bar j24. After a second, this measured value should fill the bar j23 and the freshly latest value should fill bar 24, and so on to the last bar j0. So that i can track the latest 25 measured values.

Notice: To fill the Nextion bar jx on your device, you use: jx.val=value

What i have so far:

Globaly declared:
float plotValues[25];
int z=0;
int barIt=24;

In my 1 second measuring loop:

void writeTextIntoNextion()
{
plotValues[z] = t_input;     //t_input is my measured voltage value


 int i=0;
  for( int t=0;t<=barIt;t++)
  {
    String str = String("j")+String(barIt-t)+String(".val=")+String(plotValues[abs(z+i)]);
    Serial2.print(str);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial.println(str);
    i--;
  }
  z++;
    if(z==25)
    {
      z=0;
    }
}

My problems: My logic must be kinda wrong with the iterators.
1: When the bars getting filled, always to pairs getting filled at the same time
2: when z reached zero and the iterator of z restarts i get odd values and spikes for some bars

Does anyone see where my error is? Or maybe someone has a better and smarter idea how to implement my idea?

Thank you very much

if “z=0” and “i=-1” then “abs(z+i)” is 1. I guess that the actual index you would want is 24 and not 1.

int i = z;
for( int t=0;t<=barIt;t++) {
  String str = String("j")+String(barIt-t)+String(".val=")+String(plotValues[i]);
  if (--i < 0) i = barIt;
}

Thank you for your answer. I keep trying to understand your idea

Seems i am a little bit to stupid (i hope yet) for this:p

Whats my ultimative goal would be:

I have the bars j0-j24.

When i first start measruing, j0 should be filled with the latest value, After that j1 should have the latest value and j0 the previous and so on to j24.
BUT!. After all bars are filled once, the latest value should always be in j24. After 1 second this value should fill j23 and the latest shoudl fill 24 again. So there should every second be a shift of all values to the left.

Kinda fight with this for 2 days now.

Any idea?

What you are doing now is called a circular buffer and that does exately what you want without the need of moving around data for no reason. The only difference is that the "beginning" (first index) of the buffer changes according to the value of "z".

Is there any good reason for always having the latest reading stored as the last element of the array?

No as far as i see it, theres no need that the latest reading is stored in the last array.

I realy just want so visualize the measured values in my "bar-graph"

It is just a question about how to calculate the correct index in the array. You should not mind where the newest reading is actually located.

#define BAR_SIZE 25

int mapCircularBufferIndex(int index, int bufferBegin, int bufferSize)
{
  index += bufferBegin;
  if (index >= bufferSize) index -= bufferSize;
  return index;
}

void loop()
{

  for( int t=0;t<=barIt;t++) {
    String str = String("j")+String(barIt-t)+String(".val=")+String(plotValues[mapCircularBufferIndex(t, z, BAR_SIZE)]);
    ...
  }
}

Simple math…

Thank you very much for your help.

but i am still failing.

What i have so far:

Globaly declared:

float plotValues[24];
int z=0;
int barIt=24;
#define BAR_SIZE 24


int mapCircularBufferIndex(int index, int bufferBegin, int bufferSize)
{
  index += bufferBegin;
  if (index >= bufferSize) index -= bufferSize;
  return index;
}


void writeTextIntoNextion()
{
plotValues[z] = t_input;

for( int t=0;t<=barIt;t++) {
String str = String("j")+String(barIt-t)+String(".val=")+String(plotValues[mapCircularBufferIndex(t, z, BAR_SIZE)]);

Serial2.print(str);
Serial2.write(0xFF);
Serial2.write(0xFF);
Serial2.write(0xFF);

}
z++;
if(z==24)
 {
 z=0;
 } 
}

Problems:
1: When i start the measuring the bar j0 and j24 is filled with the latest value. After 1 second the latest value is j1 and j24, previous j0, After that latest value is j2 and j24, privious j1 and so on.
2: j24 and j0 is always filled with the latest value. but the values are passed like this j0->j1->j2->j3 and so on. I want: j24->j23->22 and so on

Sorry to bother you. i realy try to understand

Thank you

Since no one can see how values are filled into the array, no one will be able to answer your question.

hmm and dont know exactly what you mean.

This part in my code: plotValues[z] = t_input; fills the array with the measured values

Could you not just invert the for loop in order to get a reversed order? for(int t=barIt; t>=0; t--) or modify the "mapCircularBufferIndex" to reverse the output?

Start printing out the array at the index of the current entry + 1, if the print index rolls over 23, reset to 0 and continue. For example, if the index of the values array is [8], the oldest value is at index [9], print that on your first print column, the value at index [10] on the second column and so on:

if(++ printIndex >= 23)
  printIndex = 0;

The 24th print on the last column will be values array [8], the latest value.

Hello.

Thank you all for your answers. Unfortunly i am still failing.

But i can forumulate my question now more specific. A good hint was that a circular buffer is the key to sucsess.

What i want:

First i want to fill all bars (24) from left to right after every second with my measured values.
So i made this code:

Globaly declared:
float plotValues[24];
int z=0;
int barIt=25;
bool barstat = 0;

void writeTextIntoNextion()   //This runs in a loop every second
{
plotValues[z] = t_input;       //Here are the measured values stored into my arry
 

if(barstat==0)
 {
   String str = String("j")+String(z)+String(".val=")+String(int(mapf(plotValues[z],0,20,0,100)));
   Serial2.print(str);
   Serial2.write(0xFF);
   Serial2.write(0xFF);
   Serial2.write(0xFF);
  }
 if(++z > 24)
 {
   z=0;
   barstat =1;
  }
}

Now the part where i fail.

Now that every bar is filled, i want, that the rightest bar is filled with the latest value every second and simultan, there is a shift of all values to the left. Since it sounds complicated i wrote down what the code should do. I assume that i only have 4 bars

z=0
j4.val=plotValues[0]
j3.val=plotValues[4]
j2.val=plotValues[3]
j1.val=plotValues[2]
j0.val=plotValues[1]

(after one second)

z=1
j4.val=plotValues[1]
j3.val=plotValues[0]
j2.val=plotValues[4]
j1.val=plotValues[3]
j0.val=plotValues[2]

(after one second)

z=2
j4.val=plotValues[2]
j3.val=plotValues[1]
j2.val=plotValues[0]
j1.val=plotValues[4]
j0.val=plotValues[3]

and so on...

so i am kinda confused, how to handle the indices and my for loop.

So simply formulated. How can i create a for loop that does the above mentioned code

Thank you for the help

Your buffer saves the last 24 values but your code only assumes the presence of 5 values. Either change the size of the buffer to only hold the values you need - or change the code to handle all 24 buffered values.

ok thank you for the hint.

Do you have an idea how to do such a loop?

z=0
j4.val=plotValues[0]
j3.val=plotValues[4]
j2.val=plotValues[3]
j1.val=plotValues[2]
j0.val=plotValues[1]

(after one second)

z=1
j4.val=plotValues[1]
j3.val=plotValues[0]
j2.val=plotValues[4]
j1.val=plotValues[3]
j0.val=plotValues[2]

(after one second)

z=2
j4.val=plotValues[2]
j3.val=plotValues[1]
j2.val=plotValues[0]
j1.val=plotValues[4]
j0.val=plotValues[3]

thank you

Manuel_o:
Do you have an idea how to do such a loop?

Yes, of course I do. In fact, you have already received an answer to that question.

Thanks for the help. But unfortunly i still fail, even with the help of your privious posts.

I still cant manage to create a function that gives me the correct iteration that i need

I orientated my tries on your function. I tried all kind of variations. i dont know why i dont get it.
actuallyit isnt that difficult. I dont know..

int mapCircularBufferIndex(int index, int bufferBegin, int bufferSize)
{
  index += bufferBegin;
  if (index >= bufferSize) index -= bufferSize;
  return index;
}

I still fail to create this:(3 indices for test-purpose)

z=0 z=1 z=2 z=3 z=0

plotValues(0) plotValues(1) plotValues(2) plotValues(3) plotValues(0)
plotValues(3) plotValues(0) plotValues(1) plotValues(2) plotValues(3)
plotValues(2) plotValues(3) plotValues(0) plotValues(1) plotValues(2)
plotValues(1) plotValues(2) plotValues(3) plotValues(0) plotValues(1)

Maybe you can give me a hint?

thank you very much

Looks correct, newest value (z) first and then reverse through the buffer.

Thank you. it worked!

Karma+