real time Bell Curve on Nextion display: too much info for serial communication.

Fertje

Active member
For a dynamic bell curve, i'm using a standard formula on the teensy and a line command to the nextion display (maxed on 115200 baud).
It works, but the 'line' command is quite long, and seems to slow things down when one parameter changes.

i'm only passing the changed pixels of the bell curve (2 commands: one to clear the old, and one the put in the new) when turning knobs.
for example:

line 100,199,100,199,BLACK (to clear the old pixel)
line 100,200,100,200,RED (for the new pixel)

I'd rather just pass the parameters (bell center height, bell width and position on x-axis of the bell center) once so the nextion can calculate the bell curve itself because it isn't a hard formula to crunch, but my probem is:

nextion can't handle the exp() function.

this is a simplified example of the formula. The Teensy is obviously fast enough, just the serial communication too slow for so many pixel commands.
exp(-0.5 * (i - freq) *(i-freq)/(Q*Q)) / (5*sqrt(2*M_PI)); (where i is the position on the x axis (eg from 0 to 320).

Any thoughts?
 
Yea, not too difficult.
When you receive the line to be plotted, save the co-ordinates in Nextion Global Variables in Program.s.
I suggest x1,y1,x2,y2. Set these up as some dummy values at the start of the program, easily done automatically in Program.s i.e. int x1=0

I realise that you are sending the "Line" command so it is not easy to extract the actual values.
Instead of sending the sending the line command pack the x1,x2,y1,y2 into a packed integer.
Let's say that the packed data is in integer pd
Send "pd=" followed by the packed variable (in HEX format, less to transmit), and of course the 3 FFs.

Have a timer event on Nextion to file every 50ms.
Sequence in Nextion Timer Event.
if(pd!=0) do the following
1) Clear the old line by plotting using the stored values (x1,x2,y1,y2).
2) unpack the new values and store in x1,x2,y1,y2
3) plot the new line using the values just saved in x1,x2,y1.y2
4) set pd to 0

If you can't afford the time of 50ms per line, the following might be an alternative.
Set up a hotspot called lets say m0.
have the code in the hotspot to handle the drawing
if(pd!=0)
{
do the following
1) Clear the old line by plotting using the stored values (x1,x2,y1,y2).
2) unpack the new values and store in x1,x2,y1,y2
3) plot the new line using the values just saved in x1,x2,y1.y2
4) set pd to 0}

Pack the integer on Teensy, send packed integer to Nextion with Send "pd=" followed by the packed variable (in HEX format, less to transmit), and of course the 3 FFs as before.
Send "Click m0,1" and the 3 FFs to Nextion.

This second option requires sending an extra 13 bytes to nextion but does not have the 50ms between lines.
So in the latter case
pd=0x12345678 + 3 0xFF = 16 + 13 bytes sending line was 2*29 bytes, 29 vs 58
I hope all that makes sense.
 
Thanx Bri,
I have actually tried it with a timer and variables but it got messy because he data got sent faster than the timer. 50ms is quite slow.

Your second option to trigger a click might do the trick, thanks for thinking with me, I’ll let you know the result.
 
It's much faster now, great idea with the click trigger and packed variables.
I found some more improvements:
1. Since it's a bell curve, they are mirrored at the centerpoint of the bell. I only have to send the first half so this saves almost half the data. Only when that point changes i send its location so the nextion can deduct the other half of the bell. (except when part of the bell reaches x=0).

2. I'm sending pixels, so x1=x2 and y1=y2. I only have to send x and y. Saves half of the data again.
 
Great, I'm glad I was able to help.
I have developed a library for the Nextion if you are interested. Really it's a skeletal library with the intention that the user modifies/expands to suit their application.
 
First off, the max baud rate isn't 115200 on the Nextion. It's 921600 and I use this baud rate reliably in a production product. So, start with "baud=921600". Next, regarding the minimum timer delay of 50ms of the Nextion - that's just the lowest value accepted by the Nextion Editor. You can actually switch a timer to a shorter delay at run-time using, for example, "t0.tim=20". Regardless, using the "click" method on a hotspot is a better choice to invoke the line draw routine on the Nextion side versus a repeating timer.

What size screen are you using? You need to use caution packing coordinates because the Nextion uses 4-byte signed integers which means x1,y1,x2 and y2 cannot exceed 255 (1-byte) in order to pack both coordinate positions into on value.

Want the fastest implementation, the lowest possible memory use and protection from serial buffer overflows? Use the following:
-increase the serial baud rate to 921600 (baud=921600)
-use Protocol Reparse Mode (recmod=1)
-instead of using the left side of the screen for the 'x' origin (0 position), have the x origin be the center of the bell (allows packing x coordinate in a single byte)
-on Nextion side, use global system variables sys0, sys1, sya0 and sya1. They're already available (saves memory versus declaring new variables in program.s) and testing has shown that operations using these system variables are quicker than operations using user defined variables. (sya0 and sya1 are undocumented global system variables, feel free to use them).
-on the MCU side send the new X and Y coordinates for the "red" line as raw bytes
- for example, instead of sending "line 100,200,100,200,RED" for the new pixel, send just two bytes '100' and '200'
-on the Nextion side, wait for the new X/Y coordinate data to appear in the serial buffer ("while(usize<2)")
-when usize==2
- move the X/Y values from the serial buffer using "sys0=u[0]" and "sys1=u[1]"
- clear the serial buffer with 'udelete 2'
- if both sys0 and sys1 equal 255 then exit Protocol Reparse Mode (recmod=0) - (MCU simply sends 0xFF 0xFF to cancel the drawing routine and return the Nextion to normal operation)
- clear the old pixel with 'line sya0,sya1,sya0,sya1,BLACK'
- draw the new pixel with 'line sys0,sys1,sys0,sys1,RED'
- backup the new pixel position to sya0/sya1 (sya0=sys0, sya1=sys1)
- notify MCU that draw operation has completed and Nextion ready for next coordinates ('printh FF')
-On MCU side, wait until 0xFF received from Nextion then continue

So instead of sending 58 bytes at 115200 baud (with line commands), you're send 3 bytes at 921600 baud (roughly 150 times faster)
 
Back
Top