The Sunday Blog: Talking to your Nextion HMI
Part 1: Serial communication basics
I have heard your suggestions, encouragements, and critics. The last two Sunday blog series were dedicated to (future) advanced users and we did our best to push the limits of what a Nextion HMI can do in autonomous mode (without any MCU, i.e. Arduino, connected). We will with these new episodes help the beginners with their hands-on. With our Nextion HMIs, it’s like everywhere in life: It’s always about communication. Let’s see and explore how that works in detail!
The early history of serial communication
Everything started in antique times, when people were looking for a way to communicate over long distances. Shouting and yodeling worked well in the mountains, where the echoes helped to increase the distance between sender and receiver. In the deserts of the Middle East, generic trombones, made of a ram’s horn and called “shofar” in the ancient testament, were used. In other parts of the world, systems using mirrors to create flashes from sunlight or smoke signals were used.
The discovery of electricity gave a boost to distant communication: The first electrical comm device was the telegraph where the sender would action a key to close an electrical circuit. The receiver, connected to the same circuit over a long, long cable would then hear a sound from a buzzer when the circuit was closed. Timed actioning of the key, using long and short pulses allowed to transmit text messages using the Morse code which was invented by Samuel Morse for this purpose. Most probably, he was inspired by the sequences of short and long tones of the biblical shofar blasts, which allowed allowed to transit different messages (tekiah, shevarim, teruah).
In the very early days of electricity, the telegraph, although being a huge step forward since it was independent of environment noise, weather conditions and so on, had its weak points: The electrical connections over long distances were not always reliable and thus, the sender could not always be sure that the receiver would get the message. Very soon, a simple but efficient way of line monitoring was born: The active low state. That means that if there was no transmission, the voltage on the cable was on. The telegraphist’s key would then pull it down to ground. Thus, when no communication happened, you could always check the line integrity, just by detecting the presence of the default voltage.
Since telegraphy allowed to communicate through different time zones, it could not made sure that there was always someone listening to the buzzer “at the other end”. But smart engineers found quickly a solution: They replaced the buzzer by a solenoid which would press a pencil on a slowly advancing paper roll which allowed to find a hardcopy of the transmission without someone listening all the time.
People who played already around with Morse code understand that it’s not very ergonomic and difficult to read. But since in the meantime, the mechanical and then the electrical typewriter had been invented, allowing to write quicker and clearer than by hand, the French telegraphy engineer Emile Baudot had a great idea: Add another electrical motor and control disks to the typewriter and use it for encoding the key presses into a series of electrical pulses when sending, or for decoding pulses into a key press when receiving. The very first electromechanical shift register was born and led to the construction of the teletype machine. A 5bit code which allowed to transmit the 26 characters of the alphabet plus some punctuation and the famous “new line” signal was used and got the name of its inventor, the Baudot code.
Teletype machines in the US transmitted initially 60 bits per second, European ones 50 bits per second. This allowed the use of synchronous motors for a precise encoding/decoding timing, controlled by the common mains frequency of 60Hz, resp. 50Hz. The unit for measuring the transmission rate in bits per second is “baud”, also called after M Baudot.
Since historically, there was only one cable for data transmission, there was the need to integrate some control signals into the transmission, for example indicating the beginning of a character and its end, so that the electromechanical decoder would have time to get the motor on norm speed and reset the control disks and to know when a full character was transmitted to action the corresponding typewriter key. This is achieved through additional bits before and after each character, the so-called start and stop bits. A rudimentary and optional error control was also sometimes added, the famous parity bit which is the precursor of today’s common checksum. These, together with the information bits, form what is called a frame: one start bit (logical high = voltage low), a certain number of information bits, optionally a parity bit, one or more stop bits.
Teletype machines (which were also used as printers for the very first computers) used one start bit, 5 data bits, no parity, and two stop bits. The short description of this framing is 5N2. The start bit being always the same, it is not explicitly mentioned. Later, when the same serial communication standard was also used to communicate between a computer and its peripherals, other framings like 7N2 for ASCII or 8N1 for extended ASCII were defined and applied. The parity bit was rarely used but in rough electrical environments where noise and voltage spikes could trouble the communication.
The RS-232/485 Standard
Computers became quicker and quicker, and had more and more peripherals. In the meantime, the serial encoding and decoding was done in an electronic way which took away the need for synchronizing with the slow mains frequency. Thus, in 1960, the first release of the RS-232 standard was established. It used different wires and pins for transmitting and receiving, and it required bipolar (RS-232) and differential signals (RS-485) to increase the noise immunity, allow higher speeds and solve the problem of ground loops. Additional and optional signals were defined, like RTS (the sender is ready to send something) and CTS (the receiver got the RTS signal and answers “It’s ok for me, go on”), and many more. That’s why in the 1980s, a serial connection went through a 25pin Sub-D connector, or if you were lucky having only the minimum of needed signals, a 9-pin Sub-D connector.
Serial communication in the PC domain…
In the consumer PC world, RS-232 does not longer play an important role. The USB (Universal Serial Bus) standard allows higher and variable speed, identification and negotiation between devices, using smaller and easier to handle connectors and much more. Most modern consumer PCs have not longer any classic serial ports. If you really need one, for example to connect your Nextion HMI for programming and debugging, there are cheap USB to serial adapters like FTDI232 or CP2102 available.
… and in the embedded domain
In the world of microcontrollers, the classic serial communication plays still an important role. While some older MCUs like the Arduino UNO have only one port which is needed for programming and debugging. More advanced boards like for example the Arduino Mega have 4, and the Teensy 3.5/3.6 even 6 of these. In all cases, the integrated serial ports have FIFO buffers which can take a certain number of incoming bytes without fearing to miss one in case the loop() doesn’t pass by in time and consume what’s already there which eliminates the need of additional control signals.
On the other side, since all MCUs operate at TTL level (either 5V or 3.3V), we have again the requirement of a common ground, so that a full bidirectional serial communication requires always 3 lines: RX, TX and GND. That works pretty well over short distances with baud rates up to 1 Megabaud. If longer distances are needed, or if you see the communication troubled from an electrical noisy environment, you can always add an interface IC like the MAX232 to translate the TTL levels into true bipolar or differential signals which allow then to go with cable lengths over several meters.
Derivatives (just for info)
Although this standard is or can be universal, at different speeds and lengths, it had some flaws for specific applications: First, the sender and the receiver have to be set up in advance for using the same baud rate and the same framing. Second, there is always some communication overhead (the start and stop bits) which means that to transmit a 8bit value using 8n1 takes 10bits and the corresponding time.
This is not longer a problem at the high baud rates which can be used nowadays, but it was still in the 1980s. That’s why some alternative protocols came to market, which were mostly intended to speed up the data transfer between ICs on the same PCB and thus work only over very short distances, at the expense of using more lines, i.e. for separate clock and control signals, thus eliminating the need for start and stop bits (SPI, I2S), or with several data lines in parallel (QSPI), and adding the capability to address multiple devices on the same data bus (I2C with an additional address byte, SPI with multiple CS signals).
And our Nextion HMI?
The principle is called KISS (Keep It Simple and Safe). That’s why we use the serial communication at TTL level for the Nextion HMI. Since in opposite to a classic unintelligent LCD display, we don’t have to address every single pixel of the display (and refresh it all the time), but we send and receive only short command sequences in ASCII format, communication speed is not an issue. Most Nextion HMIs support baud rates up to 921,600 baud which is much quicker than most MCUs can send or receive. Another point is interoperability: While not all MCUs have integrated I2C or SPI transceivers, even most cheapest and smallest 8pin MCUs have a serial port, or can, as a last resort, emulate one in software.
Now that we know the basics, we’ll have our MCU and the Nextion HMI talking together from the next episode on. “But why?”, you’ll ask, “There are libraries for that”, you’ll say. That’s true. But none of the known libraries cover all types of MCUs and support all components and attributes of the Nextion firmware.
A library is only good as long as it works for you. But when things don’t work as expected, you’ll need to look into that black box. Or if you are just curious, or if you think that things can be improved, stay tuned. We’ll explore all that. Step.by.step.