Start a new topic

Serial overrun and buffering

I'm noticing that I can easily overrun the serial input buffer on the nextion with the result that it does not render things correctly. Anyone know what the size of the input buffer is?

I think on the Nextion side the STM32 hardware buffer for a USART is 12 bytes (as in 96 bits).

Does Nextion use the USART driver (there are no RTS/CTS lines, only RX/TX), so it could be bit-banged, in which case, the size of the buffer is unknown.  The Nextion documentation describes the device as TTL, so that suggests less than USART in capabilities.  It is unknown if the STM has DMA activated, or if this is handled by Nextion's own firmware interrupts.

It is also unknown what your baud rate is set to on your host side, and on the Nextion side.  It is unknown what you are sending command wise, and what processing you have going on.  What type of host are you using, etc.

Depending on your commands, what delay is required for the Nextion to complete your requested task and return.  You could be overloading the Interrupts on the STM by firing off too things off at once.

iTead's documentation states

Note 1: It’s suggested to send an empty instruction before the connect instruction.

Note 2: Delay (1000000/baud rate)+30ms between each attempt.

If you try 9600bps, you should delay 1000000/9600+30=134ms

Now that was for a specific set of instructions where the Nextion is uninterrupted by other routines and the Nextion is in a state where you have its undivided attention.  I would assume, there would be some needed minimal delay in all other cases, and depending on the task the additional time to allot for it.

Big difference between in time required for

Serial.Write('get va0.val') or Serial.Write('va0.val=23') and a

Serial.Write('page 0') that refreshes the current page with background images needing to be loaded, cropping needing to be done, and all the other pre/post initialization events, setting sliders, that in setting them, cause timers to be enabled that will go off and do their own processing. 

The larger the display (7.0" at 800x840 with 768,000 bytes for one background image is much different than small displays (2.4" and 2.8" at 240x320 with 153,600 for its background image).

Polling where the Arduino loops to keep asking the Nextion to check on and report a value verses

Event Driven where nothing happens until an Event (like touch, minute timer) that needs addressing.

Improper baud settings: if one side is timed with a hardware clock, and the other side is bit-banged and relying on oversampling, you will get better results using a fall back baud rate.

So I hoped that somewhat helped with few details to go on.

Long response, thanks for taking the time. I'm running at 115200 baud using an esp8266 running Espruino (javascript). I'm observing that the following sequence breaks (comments added here for illustration):


gockt4.picc=5   # set background of approx 160x120 button
ref gockt4         # make button bg appear
xstr 172,183,136,24,2,0,5,1,0,0,"Next: WED"   # overlay text on button
xstr 172,209,136,24,2,0,5,1,0,0,"0min Well"     # overlay 2nd line on button
gockt5.picc=5   # repeat with next button
ref gockt5
xstr 16,296,136,24,2,0,5,1,0,0,"Next: WED"
xstr 16,322,136,24,2,0,5,1,0,0,"0min Grey"

I have 8 of these buttons on one page. The above sequence breaks after the second button and the xstr commands get skipped. I added a "get hello" command after each button and a loop to wait for "hello" to come back and that fixed this case. So the commands are correct, it's just a matter of flow control.

I hit the same issue in other places of the UI code that are much harder to fix one by one, so I need to update my driver to automatically add an explicit handshake every now and then. If I knew how many bytes of internal serial buffer the nextion had I could use that to decide when to insert a handshake command. Doing it after every command makes things even slower than they already are.

So before rewriting drivers, things to consider, what is your observations at 57600 baud.

The MCU STM32F030C8T6 on the back of the Nextion has 12 bytes if default hardware used,  I will say that in the limited space of that MCU, they hopefully did not waste space to write a new driver for what exists for free space in hardware.  That is my assumption until I discover otherwise.

I am not an Arduino guy, and I am actually looking into the 8266/ ( iTeads 8285 specifically).

But I am thinking there has to be (or should have been) a ACK/NAK in the hardware, to say "okay got your transmission" that writing raw o sockets may not be addressing (hence, the get hello may be addressing and dealing with that.

Did you know two lines on a button can be sent in one command

b0.txt="hello\rWed 12pm"

Line1 and Line2 could be stored in a Nextion variables

at the appropriate time set off a timer to concatenate

My thinking is along the lines of what event are you dealing with, and deal specifically with that event, so does all 8 separate buttons need to be addressed in this one event?

Thanks for the tip with \r. I tried \n but that didn't work and didn't think of \r, haha.

reducing the baud rate isn't going to solve this problem. From my tests with encoding an explicit "hello" ACK after each button update it's pretty clear that sending commands at full speed is more than a factor of 2x or 4x off. Maybe I should start by measuring the execution times of each command using an ACK.Then I could follow the slowest command with a long string to render and make that string longer and longer until it fails. That should tell me how many bytes of buffering the firmware has.

Of course it would be nice if itead actually responded. So far I've had more headaches than anything else with these displays. I don't think i will be buying more...

I don't think the hardware is that bad.  There is a learning curve to the HMI component.

Do you mind if you put your HMI up, and a text file of what it was you were trying to accomplish, maybe I can see some efficiencies to be had.

After some more testing it looks like there's about a 128 character buffer in the serial input. So after a slow operation, it's best not to send more than that or the command sequence will get messed up. Sigh.

So how close is your does this come to documentation?  Where at 115200 baud, the published spec requests a 38.7 ms delay between commands?  Is your average command ~5 chars?

The avg command is certainly much longer. Where do I find this published spec?

Nextion Blog for the Upload Protocol ... timing on all the other commands must be the same over the same serial port.  So using the delay between commands calculation in there


Using your assumption of a 128 byte buffer, my estimate is ~25.6 delay cycles with 5 bytes used in the average command size brings it close to 1 sec.  Assuming the serial buffer was your bottleneck.

The upload protocol, also doesn't have other things happening on the Nextion at the time of the upload.

I did not make any allowances for the time needed between your command and the completion of that command.  

Perhaps you could play around with how many commands per second you get in issuing sys0=23.  I believe the sys0, sys1, and sys2 variables are possibly stored in the registers with no need to perform object lookups.  Looping sys0 to a count from 1 to N would certainly be less of a load than the other commands.  Performing timing on isolated instructions would give a idea of how long each take, until you have your timing chart built out.

The 30ms+ timing you refer to is to allow the auto-baud detection to work, isn't it? Has nothing to do with any interval between regular commands...

I don't believe I have seen anything inside Nextion Instruction Set to suggest auto-baud.

baud or bauds sets the baud rate. 

The Upload Protocol was published publically as a commercial solution, I think if the STM was capable of such an auto-baud the commercial spec would not have had to bother with the baud parameter, no??

Oh, I see, it's the probing the host has to do to find which serial port might have a nextion display. I still fail to see what tells me about normal graphics commands. These will all take different amounts of time.

So, what we users are left with is that through experiment and observation - it is possible to get questions answered, but it is through these experiments and observation that someone has done - lots of work remaining to be done.

What I've implemented now is to always send a 'get "!"' after each command "group" and to wait for the ! to be echoed before sending the next command group. I'm using javascript in my esp8266 and I build up a queue of functions to call to produce the next command group. That ends up using less memory than to queue the command characters because one little closure can produce a couple of commands. Some timings I noticed on an NX4832:

page main; get ! : 115ms

button.picc=5; ref button; xstr ... <20 chars lg font>; get ! : 35-40ms (the button is 160x112)

xstr <9 chars lg font>, get ! : 6ms

xstr <3 chars sml font>, get ! : 0.36ms

I guess someone could run a battery of tests... Seems to me that itead really should add an ACK to all commands and build that into the protocol...

Login or Signup to post a comment