So here is an animation of how a byte transfers via N81 serial (made with v0.46)
Note that TTL is HIGH on idle (rs232c is LOW on idle). Animation is approx 1 bps.
Valid Nextion baud rates are: 2400, 4800, 9600, 19200, 38400, 57600 and 115200.
Before we get into how to send a command over serial in code,
the more important question is What to send over serial.
There are two main types that need to be dealt with
- Text data belonging to a Component's .txt attribute
- Numeric data of Component attributes or system variables
For text data belonging to a Component's .txt attribute
we need to know what component, and is that component global.
- If the component is local, take the .objname in the attribute.
for Text Component t0 t0.txt="Hello"ÿÿÿ needs to be sent.
for Button Component b1 b1.txt="Hello"ÿÿÿ
for Variable va0.txt then va0.txt="Hello"ÿÿÿ
- every .txt attribute is text data and needs double quotes " around its data.
For numeric data belonging to other Component attributes
we again need to know which Component and if it is global
- for local component numeric attributes, numbers need to be in text format.
to set a Number Component n0 value to 123 n0.val=123ÿÿÿ
to set a Text Component t0 background Color .bco to 32 t0.bco=32ÿÿÿ
to set a Waveform grid height to 50 s0.gdh=50ÿÿÿ
So what if the Component is global? what pagename is it on?
for b1 on page main then main.b1.txt="Hello"ÿÿÿ
for t0 on page page3 page3.t0.txt="Hello"ÿÿÿ
for n0 on page page2 page2.n0.val=234ÿÿÿ
for va4 on page page0 page0.va4.txt="Hello"ÿÿÿ
adding the pagename before the global component means it can be accessed
from any page should the HMI user be on a different page.
Without the pagename, the component is only for the current page and if the HMI
user is on a different page - it will try to update the wrong component.
Which Component attributes can be updated over serial?
In the Nextion Editor, if the attribute name is in the color green ... then yes.
If it is not in green, well then no. It can be read, but not updated.
So how do we read a Component's attribute? Use the get command.
Commands in the Nextion Instruction Set
- these also require to be terminated with three 0xFF bytes.
- one space between command and its parameters, no spaces between parameters.
- numeric values need to be in text format
- text data needs to surround the text data with double quotes "
Another advanced point to mention is the page index and component arrays
t0 with .id of 7 on page 3 (number is left of pagename)
this can be alternatively accessed with p.b
likewise n0 with .id of 2 on page 5 (number is left of pagename)
this can be alternatively accessed with p.b
if it is not global but just local the p. is not needed and b is enough
So before you push out text commands, know what needs to be pushed over serial.
♪♫♪ ... Now Push It ... Push It Real Good ... ♪♫♪
Now how to push bytes out over serial is another story ...
This depends heavily on your Programming Language and your Compiler.
and more so on what Library you use for serial communications.
It isn't just enough to say use Serial2.print("page page0ÿÿÿ");
This may work for an Arduino C++ with HardwareSerial on RX2/TX2,
But the embedded world is much much larger than Arduino.
Most microcontrollers have at least one Hardware UART, many have more.
And when hardware UARTs aren't available, then there is bit-banging the
data over serial by Software. On a lower level, the pins used for serial
need to be set, interrupts or polling, buffer sizes, and ... and ... and ...
This is very much dependent on which microprocessor you are using and
is going to be found in your microcontrollers documentation.
Once all the low level stuff has been taken care of, many write out a library
to simplify their programs - this is very dependent upon the programmer.
Did they use write.usart(); or uart1_write(); or Serial.print, or other.
So to make this story short: There just isn't a means to post how-to-serial
that would be correct across 10,000 MCUs, 100 programming languages,
multiple compilers, and who knows how many serial library implementations.
Each having variations and specific requirements per microprocessor.
This stage requires the users to dig in to their microprocessor documentation,
Their compiler documentation for the programming language chosen, and
read the documentation of the specific serial library being used (often found inside
the code). But there is a short cut to be had. The compiler and microprocessor
forums will surely know amongst their thousands of users, where a good serial
library is and how to use it with ample of examples available.
Thanks Patrick, nice thread.
When this hit the forum last night, I got to thinking.....
So just how robust is the Arduino Serial.print() function and how good is Nextions serial based input to the interpreter.
Turns out they're almost bomb proof. I wrote some simple code to do a little testing, and many of you will be quite surprised at the results. I pushed to the MAX and couldn't break it! I'm going to do a short video clip and a write up, and will start a new thread shortly.
[Update:] Steve's thread is located here:
Let's consider a few things about Hardware UART modules.
... and since we don't have the Nextion source to examine
we make a few assumptions based on good practices (assumed)
A Hardware UART module should be able to receive a byte independent by itself.
One of the first steps in configuring a hardware uart is setting the registers with all the information needed: data bits per frame, parity, length of the stop bit, baud, so right from the falling edge of the start bit, the timing is already known.
Most take measures of averaging by oversampling to ensure against line noise. This is also needed to handle the variation between the two crystals used by each end of the communications line so ensure some tolerance is built in. If we dig into some data sheets, we see that there is a variance error rate that needs to be addressed when the baud rate isn't an evenly divisible into the mcu's clock. So, indeed this variance should be already taken into consideration by any mature microprocessor manufacturer.
So when receiving the bits of a byte, it isn't until the entire byte has been loaded into the register that the interrupt occurs to notify the MCU that the byte is now available in the RX register. We know how many bits were to be coming - it is part of the agreed upon protocol to connect, and so part of the configuration we set up in our programs.
Let's consider the timing of such. The STMF030 is usually running with 48 MHz clock, the GD32F103 I assume is configured for a 108MHz clock. Once the interrupt is triggered, the only priority task the interrupt needs to do is get the byte out of the Register and into the software buffer. At 115200 baud, we have one bit width starting from the stop bit - it's the start bit, to get this task done before data would begin to be corrupted by the next incoming bit. So just assuming only one bit width, an F030's 48MHz clock allows around 416 clock cycles to get this task done. On a F103 at 108MHz that's around 937 clock cycles. So plenty of time to get it from the Register and into the buffer. We can also consider that the next byte interrupt will not arrive until another 10 bits go by. This allows for 4160 clock cycles at 48MHz and around 9735 clock cycles at 108MHz between the-byte-has-arrived interrupts.
For transmitting a byte, a similar process occurs. Our programs send a byte from our transmit buffer into the TX register. Here the module will send out each bit (start, data bits, stop bit) according to the configured parameters fairly independently. When the byte has finally been sent and the TX Register is empty, it raises an interrupt to state it is empty (if our TX Empty interrupt is enabled). The only priority task needing to be completed during this interrupt is getting the next byte from the TX Buffer (if any) and loading it into the TX Register. So when we have a Hardware UART module on our MCUs, we see very little time actually being used to handle incoming and outgoing bytes.
Next I examine a Software Serial implementation of this via bit-banging.