A Different Approach With Nextion

Introduction: A Different Approach With Nextion

In my first project with Arduino Nano connected to Nextion touch display, I had written a long series of commands to be communicated to Nextion via the serial port and this is inevitable if we need to send totally independent commands, in random moments.

I also have to admit that I spent more time in 'fighting' with Libraries than anything else. So I gradually came to work totally without the heavy ITEAD libraries.

I soon realized that I had no urgency to communicate to Nextion the changes to the attributes of visual objects, but I prefer to wait until I collected them and send them to Nextion as a whole, when I got a complete group.

I will try to explain myself better.

When in my project composed of 16 textual indications I want to turn some of them on or off, I do it by taking advantage of the 'bco' attribute that for switch on, passes (for example) from dark gray to white (if in a black rectangle), and vice versa to switch off.

In my application I found it useless to send 16 commands to the serial port in 16 different moments, one for each 'bco' of the 16 signals.

I prefer instead that Arduino collect which signals must be 'on' (HIGH) and which ones must be 'off' (LOW) in a 16-bit register, where each bit corresponds to one of the 16 signaling of Nextion.

After updating each bit of the register, I transmit its value to Nextion, a single message that contains a collective information concerning 16 elements.

In this way the communication from Arduino and Nextion is considerably reduced because in that single message transmitted on the serial to Nextion, information is collected that otherwise would have required the transmission of 16 messages.

True, it is not always necessary to update all reports, but I am sure that to do otherwise would waste more time.

Naturally each bit contained in the integer received by Arduino, the Nextion display will have to associate it to the desired attribute.

This means that code must be written in the Nextion display, but it is not to be frightened: if I succeeded ...

Then there is a double advantage: Arduino will have a lighter code and will be less engaged in serial communication with Nextion.

Nextion after receiving the data in a single message, will use them much more quickly than if it were to wait for 16 messages. The turning on or off of 16 signals will therefore be almost contemporaneous with respect to the most usual mode, in which the time for an unknown number of messages elapses between the execution of the command for the first signaling and the command for the last signaling.

In the Nextion display I created this system in the classic way, that is, turning a 'mask' register each time allows you to examine each of the 16 bits. When the bit examined is HIGH, the signal associated with that bit lights up on the display and turns off when a bit is LOW.

The 'negative' aspect of this system is that the code written in the Nextion display is less convenient to be documented than the Arduino code. Furthermore, the Nextion code risks being scattered over various objects. Care must be taken to document what you do right away.

I use Notepad ++ to write the code which I then copy into the Nextion object which is almost exclusively in tm0 of page 0.

The syntax of the Nextion language has numerous limitations, but it manages to overcome them or to get around them with a minimum of effort and to try to see the problems from points of view that are also unusual.

As an example, I report the way in which Arduino writes the register to be transmitted, written by me in the most elementary way possible.

Step 1: How the Register Is Transmitted

String message = "ArduinoCode.ino";	//	SketchName
#include <SoftwareSerial.h>			// Software Serial Libray
SoftwareSerial SRSerial(A4, A5);	// RX, TX Nextion Display

const int RDY = 2 ;			// pinIDE  2 pinBoard  5 - RDY
const int PWR = 3 ;			// pinIDE  3 pinBoard  6 - PWR
const int DRV = 4 ;			// pinIDE  4 pinBoard  7 - DRV
const int MAS = 5 ;			// pinIDE  5 pinBoard  8 - MArcia Sinistra
const int MAD = 6 ;			// pinIDE  6 pinBoard  9 - MArcia Destra
const int TST = 7 ;			// pinIDE  7 pinBoard 10 - FLT
const int FLT = 8 ;			// pinIDE  8 pinBoard 11 - FLT
const int EME = 9 ;			// pinIDE  9 pinBoard 12 - EME
const int FER = 10 ;		// pinIDE 10 pinBoard 13 - FER
const int COK = 11 ;		// pinIDE 11 pinBoard 14 - Debugging Communication Fail !!!
							// pinIDE 12 pinBoard 15 - n.c.
const int LED = 13 ;		// LED on board Arduino
const int KTS = A0 ;		// pinIDE A0 pinBoard 19 - TST Relay
const int KCO = A1 ;		// pinIDE A1 pinBoard 20 - Communication Ok Relay
const byte termin = 255 ;	// Nextion message terminator (255,255,255)
long FRZ;					// pause
long FRWD = 0 ;				// freeze reception Nextion Comm OK
word InpReg = 0x0000;		// where Inputs are stored
int val = 0 ;				// generic (readInputs)
int Logic = 1 ;				// Logic, will revert (or not) the Inputs

// ************************************************************************************
void setup() 
// ************************************************************************************
pinMode(RDY, INPUT_PULLUP);	// 
pinMode(PWR, INPUT_PULLUP);	// 
pinMode(DRV, INPUT_PULLUP);	// 
pinMode(MAS, INPUT_PULLUP);	// 
pinMode(MAD, INPUT_PULLUP);	// 
pinMode(TST, INPUT_PULLUP);	// 
pinMode(FLT, INPUT_PULLUP);	// 
pinMode(EME, INPUT_PULLUP);	// 
pinMode(FER, INPUT_PULLUP);	// 
pinMode(COK, INPUT_PULLUP);	// 
pinMode(KTS, OUTPUT);		// 
pinMode(KCO, OUTPUT);		// 

Serial.begin(9600);			// Standard Serial
SRSerial.begin(9600);		// Nextion  Serial
digitalWrite(LED, LOW);		// OFF
digitalWrite(KTS, LOW);		// Relay Test Start released
}							// end setup

void loop()
// *** Read Touchscreen commands ******************************************************
	RdTouch();						// Read TouchSreen

// +++ every 500 mS Update the Nextion Display ****************************************
	if (FRZ+500 < millis())
	{FRZ = millis();
// *** Update Nextion Display *********************************************************
	readInputs();					// Read 16 Inputs from I/O pins	
	NexUpd();						// Update Nextion Display with InpReg data
}	// end loop -----------------------------------------

void readInputs()
// Write the word InpReg with 16 bit read from the Digital Input Pins
val = digitalRead(RDY);
bitWrite(InpReg, 0, (Logic ^ val));		//.... .... .... ...b
val = digitalRead(PWR);	//
bitWrite(InpReg, 1, (Logic ^ val));		//.... .... .... ..b.
val = digitalRead(DRV);	//
bitWrite(InpReg, 2, (Logic ^ val));		//.... .... .... .b..
val = digitalRead(MAS);	//
bitWrite(InpReg, 3, (Logic ^ val));		//.... .... .... b...
val = digitalRead(MAD);	//
bitWrite(InpReg, 4, (Logic ^ val));		//.... .... ...b ....
val = digitalRead(TST);	//
bitWrite(InpReg, 5, (Logic ^ val));		//.... .... ..b. ....
val = digitalRead(FLT);	//
bitWrite(InpReg, 6, (Logic ^ val));		//.... .... .b.. ....
val = digitalRead(EME);	//
bitWrite(InpReg, 7, (Logic ^ val));		//.... .... b... ....
val = digitalRead(FER);	//
bitWrite(InpReg, 8, (Logic ^ val));		//.... ...b .... ....
val = digitalRead(COK);	//
bitWrite(InpReg, 15, (Logic ^ val));	//b... .... .... .... Communication Fail Sim

}		// end ReadInputs

void NexUpd()
	SRSerial.print(InpReg);			// transmit the value to the Nextion Display
	SRSerial.write(termin);			// 255
	SRSerial.write(termin);			// 255
	SRSerial.write(termin);			// 255

void RdTouch()
byte inByte;							// non serve che sia globale	+++L
  if (SRSerial.available()){			// data coming from Nextion?	+++S
	inByte = SRSerial.read();
    if (inByte>=07 && inByte<=127){		// Is this a valid char?		+++V
	  // Cast the decimal number to a character and add it to the message
    }									// end test valid char			---V
	if (inByte != '+' && inByte != '-'){	//Is it the core data byte?	+++C
/*		if (inByte == '0')	{LdoReg=LdoReg ^ 0x0001;}	// from '0'
		if (inByte == '1')	{LdoReg=LdoReg ^ 0x0002;}		
		if (inByte == '2')	{LdoReg=LdoReg ^ 0x0004;}
		if (inByte == '3')	{LdoReg=LdoReg ^ 0x0008;}
		if (inByte == '4')	{LdoReg=LdoReg ^ 0x0010;}
		if (inByte == '5')	{LdoReg=LdoReg ^ 0x0020;}
		if (inByte == '6')	{LdoReg=LdoReg ^ 0x0040;}
		if (inByte == '7')	{LdoReg=LdoReg ^ 0x0080;}
		if (inByte == '8')	{LdoReg=LdoReg ^ 0x0100;}
		if (inByte == '9')	{LdoReg=LdoReg ^ 0x0200;}
		if (inByte == 'A')	{LdoReg=LdoReg ^ 0x0400;}
		if (inByte == 'B')	{LdoReg=LdoReg ^ 0x0800;}
		if (inByte == 'C')	{LdoReg=LdoReg ^ 0x1000;}
		if (inByte == 'D')	{LdoReg=LdoReg ^ 0x2000;}
		if (inByte == 'E')	{LdoReg=LdoReg ^ 0x4000;}
		if (inByte == 'F')	{LdoReg=LdoReg ^ 0x8000;}	// to 'F' 
		if (inByte=='T') {				// Test Start
			digitalWrite(LED, HIGH);	// ON
			digitalWrite(KTS, LOW);		// Relay Test Start engaged
		if (inByte=='t'){				// Test Stop
			digitalWrite(LED, LOW);		// OFF
			digitalWrite(KTS, HIGH);	// Relay Test Start released

		if (inByte=='K') {
			FRWD=millis();  			// freeze the time of current 'OK Comm'
			digitalWrite(KCO, LOW);		// Relay OK Communication engaged
		}								// end test core data byte		---C

   if (inByte == '-'){					//Is it the end msg? ("-")		+++E
		message="";						// clear the messages variable.
   }   			// end test end byte									---E
 }			// end if MySerialAvailable									---S
	if (millis() > (FRWD+5000))
		digitalWrite(KCO, HIGH);		// Relay OK Communication released (Comm Fail)
	}	// end Watch Dog 5000
}		// end Loop 													---L

I want only to show in which way Arduino send the 16 bit Register to Nextion, without the help of the libraries, but jus respecting the syntax described by ITEAD.
<strong>void NexUpd()</strong>

SRSerial.print(InpReg);   // transmit the 16 collected bits to the Nextion Display

SRSerial.print(InpReg);   // transmit the 16 collected bits to the Nextion Display
  SRSerial.write(termin);   // 255 
 SRSerial.write(termin);   // 255 
 SRSerial.write(termin);   // 255


Step 2: .. But Before ....

Of course the code starts with all the declarations and the setup().

The Inputs are INPUT_PULLUP, so the input switches are normally open and when closed, they apply the GND to the correspondent input.

(This is my first Instructable and I'm sorry to show you my code in this bad way. Please download the file ArduinoCode.PDF that it's very clear.

Let me talk about it more

I have developed my own way to 'tell' to the Nextion display what it must do. Usually the MCU (Arduino in my case) send a message for every single variation to apply to the attribute of any single object.
This methode waste much time to do things not always so urgent to load continuously the Serial Line. I found more convenient that Arduino collect into 16 bit registers the information about the attributes to vary on Nextion. About every 500 mS, my Arduino send to Nextion one message containing the 16 bit contained in each register at time. Obviously in Nextion we need the code that handle what must be execute. This distribution of the task (and the code) let get many other advantages. For example, think how to make blink a light! With my approach it's easy: set a bit into the Arduino register and send it to Nextion. The Nextion twin registers could be updated from Arduino very rarely, because the blink frequency it's independent from the communication; the blink frequency is depending from a Timer object into Nextion and can run with the minimum time base near to 50 mS. So with my method we can blink a light in Nextion at frequency relatively high (suppose 2 Hz), even if my Arduino send messages every 10 seconds, just for an extreme example. This can suggest the opposite problem: how to do if the Communication fail? This isn't the object of this discussion, but I've already resolved this problem with a kind of Watch Dog: one inside the Arduino Code, another into the Nextion code.

The blinking is regulated by Nextion code, where every light follows his proper rules: ON/OFF or GREEN/RED or also changing the written inside (or other more). I could tell some other things about my project but I prefer to wait your questions, before to add too much words not so easy for me to translate well as I would.

Step 3: Editing the Nextion Objects

Here is a part of the code I wrote with Nextion Editor on the tm0 object.

It does not escape our notice that with the 16 bits received from Arduino, the Nextion display does not just turn on and off the signals. For the moment I omit the explanations so as not to complicate understanding.

I'm a beginner and so it's better to download the Nextion code.PDF page instead to read the confused code here down. (I'm sorry this is my first instructable)

If you desire you can download the complete code "HMI" for this my application. The filename of this code is POW1225.HMI. It can run into your Nextion display NX4024T032 but to understand it you have to swim into many objects and look the code inside the small window of the editor. So I think that will more easy to look the main code, written in the file Nextion code.PDF


// Project POW1225.HMI		15 May 2019
// vACC (va0) Accumulator
// vINP (va1) Input Register xxxx xxxx xxxx xxxx
tm0.en=1				// tm0	Start
tm0.tim=50				// tm0	Time base 50 mS

// RDY ***************
vACC.val=vINP.val&0x0001	// Mask
if(vACC.val!=0)			// Test RDY
  tRDY.pco=BLUE			// RED
  tRDY.pco=GRAY			// dark GRAY
// PWR ***************
if(vACC.val!=0)			// Test PWR
  tPWR.pco=GREEN		// light GREEN
  tPON.txt="ON"			// ON
  tPON.pco=GREEN		// light GREEN
  tPWR.pco=GRAY			// dark GRAY 33808
  tPON.txt="OFF"		// OFF
  tPON.pco=GRAY			// dark GRAY 33808
// DRY ***************
if(vACC.val!=0)			// Test DRY
  tDRV.pco=BLUE			// BLUE
  tDRY.pco=BLUE			// BLUE
  tDRV.pco=GRAY			// dark GRAY 33808
  tDRY.pco=GRAY			// dark GRAY 33808
// RUN ***************
if(vACC.val!=0)			// Test RUN
  tRUN.bco=RED			// MARCIA RED	(on)
  tRUN.pco=BLACK		// on BLACK
  tDIR.bco=RED			// DIR RED
  tDIR.pco=BLACK		// on BLACK
  tRUN.bco=32768		// MARCIA GRAY (off)
  tRUN.pco=GRAY			// on GRAY
  tDIR.bco=32768		// DIR dark GREEN 1024
  tDIR.pco=GRAY			// DIR GRAY
  tDIR.txt="---"		// STOP
// LEFT **************
if(vACC.val!=0)			// Test RUN Right
  tDIR.txt="<<<  "		// DIR LEFT
// RIGHT *************
if(vACC.val!=0)			// Test RUN Left
  tDIR.txt="  >>>"		// DIR RIGHT
// BOTH **************
if(vACC.val==24)		// Test RUN both
  tDIR.txt=">>!<<"		// DIR BOTH
// TEST **************
if(vACC.val!=0)			// Test TEST
  tsw tTEST,1			// Enable Touch events
  tTEST.pco=GRAY		// dark GRAY 33808
  tsw tTEST,0			// Disable Touch events
// FAULT *************
if(vACC.val==0)			// Test FAULT
  tFLT.pco=GRAY			// FAULT absent
  tFLT.pco=YELLOW		// FAULT present
// EME ***************
if(vACC.val==0)			// Test EME
  tEME.pco=GRAY			// EME absent
  tEME.pco=RED			// EME present
// FERMO *************
if(vACC.val!=0)			// Test FERMO
  tFER.pco=BLACK		// BLACK
  tFER.bco=GREEN		// GREEN
  tFER.pco=GRAY			// GRAY
  tFER.bco=672			// dark GREEN
// *******************


I want to give my acknowledgements to Gideon Rossouwv because reading his Instructables I have gained quickly part of my objectives. Thank you mr. Gideon Rossouwv

Arduino Contest 2019

Participated in the
Arduino Contest 2019

Be the First to Share


    • Puzzles Challenge

      Puzzles Challenge
    • Lamps Challenge

      Lamps Challenge
    • Rice & Grains Challenge

      Rice & Grains Challenge



    8 months ago

    74 bitWrite(InpReg, 0, (Logic ^ val));//.... .... .... ...b


    Reply 8 months ago

    int Logic = 1 ;// Logic to revert or not the Logic value of the Inputs


    Reply 8 months ago

    When this my project was born, was important to choose if the input contact were carrying Voltage or GND. For this reason I followed this way, to be able to change the value of 'Logic' runtime. Now, you can substitute the 'Logic' variable with a 'Logic' constant equal to 1 or 0, as you need. But if you predict to never change the 'Logic' of the input, you can also simplify the code, doing without meaning the constant (or variable 'Logic'.


    8 months ago

    Logic is not defined in .ino file


    Reply 8 months ago

    Thank you for your interest and for your precious feedback.
    You are right!
    'Logic' is a variable that define if the Digital Inputs are to use as is (Logic = 1) or if the Inputs are to be 'Inverted'.
    The Inputs can works in Direct Logic or in Reverse Logic just changing the default value of the variable 'Logic'.
    Unlucky, in my setup() this variable was been erroneously deleted by me.
    Hope this could be enough. Sorry for my error.
    Do you know how expose my code in a better way than this?
    Instructables has give no help to me for this my obstacle.

    Thank you for all.


    Reply 8 months ago

    Please tell me what you exactly means and help me to be more clear and useful.

    I know that this is not a well explained article, but I don't know how expose the Arduino code as I desire. Even the Nextion code it's not in the best form to show you it.

    Thank you