Nextion - Alternativ to Nextion-Waveform?

Hello friends.

I am using a Nextion and with it, the Nextion intern Waveform (xy-plot).
There, i am plotting my measured dataponts.

I have 2 probelms with it:

1: Its not possible to create the x and y axis names
2: more important. When you switch the pages, the plotted datapoints disappear and the plot starts from the begining when u call the page again.

For my project it is essential that the plotted datapoints of my graph arent disappearing when i leave the page and come back, since i wanna see the histroy

So what are my options now?

has anyone faced the same problem like me? What alternatives to the nextion waveform do i have? As far as i know it is not possible to "keep" the datapoints on the Nextion plot when u are switching to an other page.

Thank you

1: Its not possible to create the x and y axis names

Yes, it is. You put a text box on the display where you want the name. If the name never changes then you just pre-define the name in the box. If you want to change the name dynamically you send the required text to the text box when you want to change it.

2: more important. When you switch the pages, the plotted datapoints disappear and the plot starts from the begining when u call the page again.

Indeed. One of the limitations of the design of the Nextion. There is no solution that I know of.

For my project it is essential that the plotted data points of my graph aren't disappearing when i leave the page and come back, since I want to see the history.

The only option is to keep the original data in whatever controller you are using to control the Nextion and send the data when you go to the page with waveform. I have 672 data points representing the outside temperature over the last week at 15 minute intervals, these are sent when I select the page to show them. It also has the names of the days next to the data, with the current day on the right and the previous days along the bottom towards the left, the text is written to 7 text boxes to show the correct day of the week.

thank you for your answer.

Yes i feared that the only way to make such a plot is to store them

I am using an ESP32.

May it possible if you can provide your part of the code for storing your data and sending them to your Nextion when the specific page is open?. i´I am a little bit lost of how to store them dynamicly

thank you

May it possible if you can provide your part of the code for storing your data and sending them to your Nextion when the specific page is open?. i´I am a little bit lost of how to store them dynamical

Not easily, sorry.

The code for the whole project is quiet large and the code for saving the measurements is one bit and for outputting it is in another bit and it all integrates into something much bigger. Sharing bits of it wouldn't make sense and sharing all of it would be a project in itself. I can give you a rough outline though.

First an ESP32 has loads of SRAM, so that won't be a problem. Create an array of whatever size you need to hold all the measurement values for the plot. As the plot can only accept values from 0 to 255 you can use uint8_t. I don't know how many values you need but for my graph I needed 672, so for example:

uint8_t plotValues[672];

Would do for all of them.

You then need to write the values into the array instead of sending them to the display immediately.
When you load the page you need to cycle through the array and send all the values in order to the Nextion.

I don't have an example of this in my tutorial 'using Nextion displays with Arduino', but I'll give some thought to adding one at some point (not a promise!!!).

Hey perry

I somehow mangaed to create the idea that you proposed

Globaly declared:
float plotValues[489];
int z=0;

Here is the function that stores the measuerd data into a array:(This function is in the loop and is called every second)

void writeTextIntoNextion()
{
  float t_input_raw=analogRead(PH_PIN);
  float t_input=mapf(t_input_raw,A1.low_x1,A1.low_y1,A1.low_x2,A1.low_y2);
  A1.input_raw=t_input_raw;
  A1.input=t_input;


  plotValues[z] = t_input;
  z++;
  if(z==100)
  {
    z=0;
  }
  //Waveform
  s0.addValue(0,mapf(t_input,A1.low_x2,A1.low_y2,0,254));  //addValue(chanel,range)
}

For test-purposes i created a button that writes my stored data into my nextion-waveform

void measureManuellPopCallback(void *ptr)
{
  for(int t=0;t<z;t++)
  {
    s0.addValue(0,mapf(plotValues[t],A1.low_x2,A1.low_y2,0,254));
    
    Serial.print(t);
    Serial.print("    plotValues[t]");
    Serial.println(plotValues[t]);
  }
}

It kinda works, but a couple questions remain.

1: How did you create the numbers on your y axis? Is every number a textfield in your nextion?
2: When you open the page with your plot, how long does it take to write all datapoints to your waveform-plot? Even with my 100 datapoints right now, its takes ~ 1.5 seconds to print them into my plot? So with your 680 datapoints it must take almost 10 seconds to write them into your nextion plot? >Can you confirm?

Thank you very much!

one last quesion.

How did you trigger the "writing into plot event" , that when the page of the plot is opened

OK, good.

Why have you defined plotValues with 489 elements then only use 100 of them?

The y axis numbers are on the background image, the one with the Northern Lights, they could just as easily be text boxes with numbers in them.

The x axis text and the x axis numbers (min and max temperature for the day) are text boxes to which I send the appropriate text.

Yes, the page takes about 6 seconds at 19200 baud. Using addt should speed things up as would a higher baud rate, both things for future work when I feel like doing it.

I don't see anywhere in your code that you send to the waveform. Is that because you are using the Nextion libraries, about which I know next to nothing?

Looking ahead to something that's not essential but which I think you should learn. Look at 'using Nextion displays with Arduino' part 4. look at the code in Nextion additional features. In the tab _01_Middle there is the function HMI_serial_print(), which manages the sending of data to the correct page. You will see that it starts with

  if (Serial.availableForWrite() > row_length) {
//...
}

This is because serial is slow and becomes blocking if the buffer gets full, preventing anything else from happening until everything has been sent. Where you have a for loop, like you have, that sends a lot of data to the serial port it will become blocking until all the data has been sent. If you follow through from HMI_serial_print() to the functions it calls you will see each function only sends one line of data at a time then returns. Next time around loop() it sends the next line of data, if there is any to send. This makes the code sending to the Nextion non-blocking. In the demonstration this is particularly relevant for page 1, the scrolled list, which has a lot of data and would be blocking it I tried to send all the data in one go in a for loop. This is similar to what you are trying to do with the waveform.

How did you trigger the "writing into plot event" , that when the page of the plot is opened

I'm not sure what you are asking.
Open the page, the plot is blank. From the Nextion instruction set 'add' allows you to send data to the waveform. Am I correct that you are using the Nextion libraries? If so, I can't help as I don't know them.

If you are asking how I draw the scale on the graph I send a click followed by an unclick to a hidden button on the page. Behind the button is a bit of code that draws the scale.

Hey Perry.

Over the last days i tried to get my "filling of the waveform" working.

There are still some questions.

Your wrote:

Using addt should speed things up as ...

I am little confused how to get it work with addt.
addt 3, 0, 10

What i know: The third parameter for the "addt" command is "qty", the number of bytes that will follow. So how i understood it: After the addt command, the nextion is in an kind of mode to recive data in a hex format. So now the Nextion is ready to recive 10 numbers in hex.

My problem now:

My datapoints are stored in plotValues[t]. Now i have to convert every stored data into hex or what?. Here i have my function that writes my data with "add" into the waveform:

....
  for(int t=0;t<z;t++)
  {
    String str = String("add 3,0,")+String(int(plotValues[t]));
    Serial2.print(str);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial.println(str);
  }

As far as i see it, the add function allows only int and no float. Can you confirm?
When i use this: String str = String("add 3,0,")+String(plotValues[t]); without the int() function, my nextion isnt drawing anything

how would you modify it now for the "addt" function?

for(int t=0;t<z;t++)
  {
    String str = String("addt 3,0,")+String(t);
    Serial2.print(str);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
  }

As far as i get it, after this line, the NExtion is ready to recive the data in Hex. But how i am gonna do this? Waht are my next steps?

Thank you very much Perry!

What i know: The third parameter for the "addt" command is "qty", the number of bytes that will follow. So how i understood it: After the addt command, the nextion is in an kind of mode to recive data in a hex format. So now the Nextion is ready to recive 10 numbers in hex.

I have not myself used addt, it is on my list of things to experiment with. Your description seems right to me.

My datapoints are stored in plotValues[t]. Now i have to convert every stored data into hex or what?

Unless I have misread your previous posts I think your variable plotValues is an array of floats. Whether you are using add or addt the Nextion is expecting a value between 0 and 255, which is not a float. According to the Nextion instruction set it is indeed expecting a single byte. I suggest you convert your float value to uint8_t then use Serial.write to send it, as Serial.write sends the byte itself, not the value converted to ASCII. You can do this 'on the fly' just prior to sending the data, a byte at a time. Remember that just about any micro-controller can do conversions like this a lot faster than a serial port can shovel the data out. I also suggest that if you are storing the data in plotValues only to be sent to the waveform and not for anything else then it makes sense to store them as an array of uint8_t not floats, as you may as well store them in the form they will be used.

Maybe (not tested)

  uint8_t temp;
  for(int t=0;t<z;t++)
  {
    temp = (uint8_t) plotValues[t];
    Serial2.write (temp);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial.print (temp);
  }

The line you will have to play with is the conversion from float to uint8_t, I don't know it what I have put will work. Note that for sending to the Nextion I put Serial.write, this sends just the byte, and for sending to the serial monitor I used Serial.print, which converts it to ASCII first.

Please share with me what you get working, both to satisfy my curiosity and for the benefit of others reading this in future.

Something as an aside, not directly related to what you have asked me but you need to be aware of and change in future:

Here I have my function that writes my data with "add" into the waveform:

    String str = String("addt 3,0,")+String(t);

Don't use Strings (as in String with a S) they cause memory problems. I don't know the exact details, but a search of this web site should give you lots of information about NOT using String. Use C strings instead, for example this is from my own code for driving a Nextion waveform:
(This is just an excerpt from a bigger function, but it does the same kind of thing you are trying to do).

#define  serial_write_buffer_size 28
  char printbuffer[serial_write_buffer_size];
              if (i < imax) {
                sprintf(printbuffer, "add %1u,%1u,%1u", 1, 0, (unsigned char) round (5 * (temperature_log[0][d] + 15)));
                Serial.print(printbuffer);
                Serial.write(0xff);
                Serial.write(0xff);
                Serial.write(0xff);
                ++i;
              }

Finally, it's nice helping someone who is obviously making an effort rather than expecting someone on here to provide all the answers, finished and working. (Just read some of the other questions and you'll see). For making a decent effort ++Karma;

Hey Perry. thank you for the detailed answer.

This is my state right now:

Here i am colleting my data
I am storing every measured data (t_input) into plotValues[z], Until now, they are float-data.
Since my range of the graph and my measured data are between 4 and 20 i used the addValue function from the Nextion lib. I know that you are not into the lib, but to add normal data into my waveform, it is working ok. So my measrued values between and 4 and 20 are splitted to the values 0 and 252 for the Nextion waveform.

plotValues[z] = t_input;
  z++;
  if(z==100)
  {
    z=0;
  }
  Serial.println(z);

  //Waveform
  s0.addValue(0,mapf(t_input,0,20,0,252));  //addValue(chanel,range)
}

Now to the problem part. I am still struggling with tbe ADDT function

I tried to modify my code with your proposals.

This is the part where i try to write the data manuell into my waveform via addt

....

// Here i initialze with addt the nextion to recive a group of data (here z)

String str = String("addt 3,0,")+String(z);
  Serial2.print(str);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial.println(str);

//Nextion is now ready to recive data
  
uint8_t temp;

  for(int t=0;t<z;t++)
  {
    temp = mapf((uint8_t)plotValues[t],0,20,0,252); 

    Serial2.write (temp);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
    Serial2.write(0xFF);
  }

It is still not working. When i send the data via addt like i wrote above, my graph makes only some big peaks. I checked the values of "temp" -> temp = 63 (input value is 5,62).
So there must stand something like this

Serial2.write (63);
Serial2.write(0xFF);
Serial2.write(0xFF);
Serial2.write(0xFF);

What i belive: We are sending now the temp value via serial.write. The nextion is expecting to recive the value as HEX. Is serial.write sending the data (here, temp) as a HEX code?

I am confused (again).

Thank you

I don't know. Some thoughts.

Write a simple sketch that sends 10 values to the Nextion and nothing else, get that working.
Stop using String, it will cause problems later even if it's not the cause of the problem now (look how I do it in my tutorial).
I don't know if what you are sending using String is correct or not as I don't use String for anything so have never learnt to use it.

What I believe: We are sending now the temp value via serial.write. The Nextion is expecting to receive the value as HEX. Is serial.write sending the data (here, temp) as a HEX code?

Serial.write(n); sends the value of n as a byte, as in 8 bits, as in the hex value. Serial.write(63); sends 00111111.

What I think you need is to send however many bytes you have decided to send followed by 3 lots of 0xff.

Do you have another Arduino with a spare serial port? It might be useful to connect the Rx of a spare serial port to the Tx of the port sending to the Nextion, put a bit of code on the second Arduino and have it mirror whatever it receives to its serial monitor, so you can see what exactly is being sent.

I don't know what else to try, sorry.

I think i found the solution

From what i can tell right now, this should work.

 String str = String("addt 3,0,")+String(z);
  Serial2.print(str);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial.println(str);
  delay(100);
  uint8_t temp;

  for(int t=0;t<z;t++)
  {
    temp = mapf(plotValues[t],0,20,0,252);

    Serial2.write (temp);
  }
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial2.write(0xFF);

Thank you Perry!!

Last step now is to get this code triggered, when the page of the waveform is opened.
My plan was to make a small (hiden) button called b2. In my Nextion device i write into the "Postinitalize Event: click b2,1
click b2,0
The Send Component ID of touch and press event is marked

So from the theory, when the page is opened the hidden button b2 will be pushed.

My textfunction:

void b2testPopCallback(void *ptr)
{

  Serial.println("hello");
}

So when i open the waveform-page i should get the hello in my serialcommand. Unfortunly nothing happens.

Is my way corect? From my point of view, this should not be a problem of the nextion-Lib. Because when i push the button by hand on my nextion device, i get the message "hello".

Thank you

ps: i will look into the problems with "Strings".Thank you for the tip

Is my way correct?

Erm...
Not how I would do it. I change pages like this, for example page 0 to page 1:
Button on page 0 has page page 1 under touch release event, which will change the page to page 1. On page 1 under post initialisation event is the the code to send to the Arduino to request the data for the page. That way the request gets sent as soon as the page is ready to receive the data, not before and without any unnecessary delay. Whether this will work with the Nextion libraries I do not know.

hmm i kina know what you mean

So i have my page "main_front". its more or less my homescreen. There, there is my waveform.

You wrote:

post initialisation event is the the code to send to the Arduino to request the data for the page

So what has to be in the postinitialize event on my page "Main_front" to trigger this part of code in my scetch

 String str = String("addt 3,0,")+String(z);
  Serial2.print(str);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial.println(str);
  delay(100);
  uint8_t temp;

  for(int t=0;t<z;t++)
  {
    temp = mapf(plotValues[t],0,20,0,252);

    Serial2.write (temp);
  }
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial2.write(0xFF);

This are the data the nextion "needs".

Damn a hard puzzle

So what has to be in the postinitialize event on my page "Main_front"?

That's where I can't help you because I don't know how the libraries work. The examples in 'using nextion displays with Arduino' use this method. I don't know if it is even possible with the libraries, sorry.

Hey Perry.

I think i found the solution:D

I made a small hiden button on my Nextion. When i open the page i put an click event for this button into the postinitilaze event of the page. Into the button i put under "touch release event" printh 65 02 0B 00 FF FF FF. I just can speak for the Nextion libary. This is the HEX that the button and my ardunio is expecting.

So when i open the page, the button gets clicked and the HEX code is send to my ardunio, and the code of the button will be executed

Thank you so much Perry!

I think i found the solution:D

:slight_smile:

Thank you so much Perry!

You're welcome!

Now do me a favour and become this forum's Nextion Library expert so I don't have to keep telling everyone who prefers the libraries that there is not much support for them here!