The Sunday Blog: Talking to your Nextion HMI

Part 3: Let your PC talk to your Nextion with Python

In the previous episode, we have learned how using a Nextion HMI makes designing GUIs much simpler and saves most of the time and resources of your MCU, compared to the use of a simple TFT display. We have designed a very simple example GUI, allowing simply to display some text, using the free Nextion Editor, within seconds. Finally, we used the integrated Nextion simulator to test our GUI and to display “Hello world”. Today, we move a step forward, we upload the compiled GUI to our Nextion screen and we’ll set and change the displayed text “from outside”. In case you don’t want to create the GUI yourself, you can download it here: hello.HMI

Open it with the Nextion Editor, compile it, and upload it to your screen.

Connecting your Nextion

While you don’t forcibly need to connect your Nextion to your computer (you can use a SD card) to transfer the compiled firmware onto your Nextion, a serial connection is required to interact. Before we go into detail how this is done using the 4000+ development boards (Arduino, STM, ESPE, Teensy, etc.) out there in the wild, we should first understand how everything works, and do everything “by hand”.

Most modern computers do not have serial ports using TTL level. Thus, we need an adapter from USB to TTL serial like a FTDI232 or a CP2102. As soon as our Nextion gets power, it will show the blue default screen of our GUI:

Setting up the PC to talk to your Nextion

While it is theoretically possible to use a terminal window and send whatever directly to the Nextion over a com port, this approach is not very pedagogic and we should prefer a more contemporary and platform-independent way to communicate. We’ll use Python 3 in a first step since it’s universal (Windows, MacOS, Linux).

Edit: I just learned that in opposite to MacOS and Linux, Python does not come by default with Windows. But since almost every developer gets in touch with Python earlier or later, it’s perhaps the best moment to install it now from https://www.python.org/downloads/windows/. Or if you are on Windows 10, the May 2019 release or newer, you’ll even find it in the Microsoft Store for free. After you did that, it’s almost all the same in all platforms.

First of all, we need to know which com port our OS has attributed to our Nextion. We open a command window and we enter:

python3 -m serial.tools.list_ports

Our PC or Mac will list something similar to this (in macOS and Linux):

/dev/cu.Bluetooth-Incoming-Port
/dev/cu.usbserial-0001
2 ports found

Or in Windows:

COM1
COM3
2 ports found

In case you get an error message instead like “ModuleNotFoundError: No module named ‘serial'”, the Python serial library did not come by default with your Python installation. That can be fixed in the same command window, issuing:

pip3 install pyserial

After which we can launch Python 3 and are greeted by the command prompt :

>>>

Since we want to use serial communication, we’ll tell it to use the serial module, first:

>>> import serial

Then, we have to initialize the serial communication over the selected comm port from the list above:

>>> nexSer = serial.Serial('/dev/cu.usbserial-0001', 9600) //macOS or Linux
>>> nexSer = serial.Serial('COM3', 9600) //Windows

That’s it, now you are ready to send something over.

How to say it

In our first enthusiasm, we try perhaps simply with nexSer.write(‘Hello world’). This will unfortunately fail on several levels. First on the Python side, since our string must be byte-encoded to be sent over serial. Second, if we send simply that string, byte-encoded or not, our Nextion won’t know where to put it. Third, our Nextion won’t understand that the command is complete because we did not add the famous termination bytes, 3 times \xFF.

Defining the terminator

… is an easy task, we just enter

>>> terminator = b'\xff\xff\xff'

which declares the terminator variable and sets it to 0xffffff.

Expressing the command

Remember from last week in the simulator window? If we want to change the value of an attribute of one of our GUI components, the syntax is component.attribute=value. That means that in our case, we have to issue: t0.txt=\”Hello world\” (with escaped double quotes since the whole command is seen as a string).

Byte-encoding the command string
>>> command = str.encode('t0.txt=\"Hello world\"')

Please notice that for most MCUs, especially if you use an Arduino compatible environment, the byte-encoding is not needed, the Serial.print() function does it automatically.

And now, sending:
>>> nexSer.write(command + terminator)

Hooray! If we didn’t make any mistake, Python will answer us with a “23” (the number of bytes written) and or Nextion will look like this:

Since it worked so well, let’s try another thing:

>>> command = str.encode('t0.txt=\"I hear you\"')
>>> nexSer.write(command + terminator)

After we are now trained and experienced in talking to our Nextion “by hand”, we might delegate this to our MCU from next week on. Pre-heat your Arduino already, preferably a Mega since it has multiple serial ports. One is needed for the communication with the IDE and for debugging, a second one is needed for talking to the Nextion. The Arduino UNO has only one port, which means we’ll have to emulate a second one in software which might make things a little more complicated. But we’ll deal with that, too!