Nextion Page Number to Arduino Mega

I have recently bought a Nextion Enhanced 3.5" display and have been doing some initial testing/learning ready for starting a project.

I am not an experienced programmer but manage to fumble my way through but this issue has cost me 2 days with no results! I have read just about every web page I can find on the topic and have run around in circles.

I have 3 pages in Nextion (attached) and I want to send the current page number to Arduino. My project Arduino code will be controlled by the Nextion page that is displaying (the Nextion can change pages independently of the Arduino hence the need for Arduino to know what page is displaying).

I have followed example in the standard Nextion library (GitHub - itead/ITEADLIB_Arduino_Nextion - CompPage_v0_32.ino).

I have both a push and a pop event attached to page 0 that upon operating causes the variable CurrentPage to change to the page number i.e. 0. This then prints in the debugger. As a further visual prompt I have tried to change the text in Select1.txt_Stage1 to something.

As it stands neither the CurrentPage variable is changing nor the text box updating.

I have tried changing the Nextion preinitialisation event to "sendme" or to "printh 66 01 FF FF FF" but neither is recognised. I also tried checking the "Send Component ID" in the Touch Press/Release events. I have been very thorough in trying things before reverting to here...

#include  "Nextion.h"

int CurrentPage = 9;  // Create a variable to store which page is currently loaded

// declare 1 text box on each page for testing purposes
NexText txt_stage1 = NexText(0, 2, "txt_stage1");
NexText txt_stage11 = NexText(1, 2, "txt_stage11");
NexText txt_StageSel = NexText(2, 2, "txt_StageSel");

// Declare pages:
NexPage Select1 = NexPage(0, 0, "Select1");  // Page added as a touch event ** this nexpage uses the actual page name as I wanted to see if that made a difference
NexPage page1 = NexPage(1, 0, "Select2");  // Page added as a touch event
NexPage page2 = NexPage(2, 0, "NoRecord");  // Page added as a touch event

char buffer[100] = {0};  // copied from other code but it does not do anything yet

// Declare touch event objects to the touch event list: not sure if you need to listen to a text box?  Prob not but put there just incase
NexTouch *nex_listen_list[] =
{
  &Select1,  // Page added as a touch event
  &page1,  // Page added as a touch event
  &page2,  // Page added as a touch event
  &txt_stage1,
  NULL  // String terminated
};  // End of touch event list


// Page change event:
// both push and pop included for page 0 as I cannot work out which is needed
void Select1PopCallback(void *ptr)  // If page 0 is loaded on the display, the following is going to execute:
{
  CurrentPage = 0;  // Set variable as 0 so from now on arduino knows page 0 is loaded on the display
  txt_stage1.setText("hello1");
  dbSerialPrintln("Select1PopCallback");
}  // End of press event

void Select1PushCallback(void *ptr)  // If page 0 is loaded on the display, the following is going to execute:
{
  CurrentPage = 0;  // Set variable as 0 so from now on arduino knows page 0 is loaded on the display
  txt_stage1.setText("hello2");
  dbSerialPrintln("Select1PushCallback");
}  // End of press event

// Page change event:
void page1PopCallback(void *ptr)  // If page 1 is loaded on the display, the following is going to execute:
{
  CurrentPage = 1;  // Set variable as 1 so from now on arduino knows page 1 is loaded on the display
}  // End of press event


// Page change event:
void page2PopCallback(void *ptr)  // If page 2 is loaded on the display, the following is going to execute:
{
  CurrentPage = 2;  // Set variable as 2 so from now on arduino knows page 2 is loaded on the display
}
// End of press event


void setup() {  // Put your setup code here, to run once:

  //Serial.begin(9600);
  //nexSerial.begin(9600);  nexInit does this hence commented out
  nexInit();

  dbSerial.println("setup start"); // debug

  // Register the event callback functions of each touch event:
  // You need to register press events and release events seperatly.
  // Format for press events: <object name>.attachPush(<object name>PushCallback);
  // Format for release events: <object name>.attachPop(<object name>PopCallback);
  Select1.attachPop(Select1PopCallback);  // Page press event
  Select1.attachPush(Select1PushCallback);
  page1.attachPop(page1PopCallback);  // Page press event
  page2.attachPop(page2PopCallback);  // Page press event
  // End of registering the event callback functions

  dbSerial.println("setup end");  // debug
}


void loop() {  // Put your main code here, to run repeatedly:
  nexLoop(nex_listen_list);
  dbSerial.println(CurrentPage);  // debug
}

OK...managed to ZIP the Nextion files.......

Fuel Consumption-Nextion_v2.zip (818 KB)

(deleted)

Hi. I am also trying to get the Nextion page number on my arduino Mega, using the "sendme" command in each page of the Nextion, but I am not succeeding.
Cold you please provide an example?
Thank you!

If you use the methods set out in 'using Nextion displays with Arduino' you will find included in the example the Nextion sending the page number after a page change for whatever reason.

Thank you for providing the example.

I am trying to integrate it into my code that is using the ITEAD library. However, I am always receiving a zero for HMI_read_data[1], regardless of the page that I select.

(I am changing the pages from the Nextion, using buttons)

Here is the code:

#include <Nextion.h>

void setup() {
  Serial.begin(9600);
  nexInit();
}

void loop() {
  HMI_read();
}

//HMI_read takes the data sent from the Nextion to the serial port and processes it depending on what has been sent
//There are 3 levels of nested switch statements corresponding to the page, the type of object and the index of the object.
void HMI_read() {
  static uint8_t HMI_read_data[10];         //This is a temporary buffer to hold the data from the display. Space for 10 bytes although this demonstration only uses 6 bytes
  static uint8_t HMI_read_data_i;           //This is a count of how many bytes have been received from the display.
  static uint8_t a5count;                   //0xa5 repeated 3 times is used as a start indicator, this is a count of how many times it has been received.
  uint8_t readtemp;                         //This is to hold the last received byte to ensure that it is only read from the receive buffer once.

  while (Serial2.available() > 0) {         //Read every byte in the receive buffer
    readtemp = Serial2.read();
    if (readtemp == 0xa5) {                 //Count the number of times 0xa5 has been received
      ++a5count;
      if (a5count > 2) {
        a5count = 0;
        HMI_read_data_i = 0;
      }
    }
    else {
      a5count = 0;
    }
    HMI_read_data[HMI_read_data_i] = readtemp;

    Serial.print ("Page = ");
    Serial.println(HMI_read_data[1]); //HMI_read_data[1] contains the page the data has come from

    ++HMI_read_data_i;
    if (HMI_read_data_i > 9) {
      HMI_read_data_i = 9;
    }
  }
};

I am trying to integrate it into my code that is using the ITEAD library.

My code is designed to work without the ITEAD library, I can't offer any help in combining them to work together.

However, I am always receiving a zero for HMI_read_data[1], regardless of the page that I select.

Have you put under post initialisation event:

printh a5         //Start
printh a5         //Start
printh a5         //Start
printh 00            //Page
printh 00            //Type
printh 00            //Index
printh 00         //Required page
printh 00            //Padding

On page 0?

printh a5 //Start
printh a5 //Start
printh a5 //Start
printh 01 //Page
printh 00 //Type
printh 01 //Index
printh 01 //Required page
printh 00 //Padding

On page 1? etc?

You have missed from your code:

    if (HMI_read_data_i == 5)....

And everything that follows it. You are trying to display the value of:

 HMI_read_data[1];

Before all the bytes have been received. Only when

HMI_read_data_i == 5

Have all the bytes been received, then you can do something with them.

PerryBebbington:
My code is designed to work without the ITEAD library, I can't offer any help in combining them to work together.

Have you put under post initialisation event:

printh a5         //Start

printh a5        //Start
printh a5        //Start
printh 00            //Page
printh 00            //Type
printh 00            //Index
printh 00        //Required page
printh 00            //Padding



On page 0?
On page 1? etc?

I was using "sendme" on each page, but I realize that "sendme" is sending "66 xx FF FF FF "

I am going to try with that initialization event, and i will add the missing condition at the code.

Thank you very much for your kind support

I was using "sendme" on each page, but I realize that "sendme" is sending "66 xx FF FF FF "

I am going to try with that initialization event, and i will add the missing condition at the code.

It is kind of important that if you use someone else's code then you use all of it, or if you want to modify it then it helps to understand what the various bits do. Just leaving bits out is unlikely to lead to success.

Thank you very much for your kind support

You're welcome :slight_smile:

not sure I have found my answer in the above so I would like to ask the similar question.. I have several pages and I use hotspots to move from page to page. I also want to know what page I am on. In the simulator I see that the output has a structure like this " 65 00 05 01 FF FF FF" What I have been able to discern is that the "05" is the page I have gone to and the "00" is the page I came from.
What serial commands will I use to parse this?

My application is this.

If going from page 0 to page 4. I want to populate a variable x with 540 and a variable y with 1 for direction. (driving a stepper)

if going from page 4 to page 0 I want to populate a variable x with 540 and a variable y with 0 for direction.

it may be a simple case statement of the following.
Serial Step Direction
case String x y
1 65 01 01 01 FF FF FF 790 0
2 65 02 01 01 FF FF FF 540 0
3 65 03 01 01 FF FF FF 1040 0
4 65 04 01 01 FF FF FF 1290 0
5 65 00 02 01 FF FF FF 790 1
6 65 02 02 01 FF FF FF 250 1
7 65 03 02 01 FF FF FF 250 0
8 65 04 02 01 FF FF FF 500 0
9 65 00 04 01 FF FF FF 540 1
10 65 01 04 01 FF FF FF 250 0
11 65 03 04 01 FF FF FF 500 0
12 65 04 04 01 FF FF FF 750 0
13 65 00 05 01 FF FF FF 1040 1
14 65 01 05 01 FF FF FF 250 1
15 65 02 05 01 FF FF FF 500 1
16 65 04 05 01 FF FF FF 250 0
17 65 00 06 01 FF FF FF 1290 1
18 65 01 06 01 FF FF FF 500 1
19 65 02 06 01 FF FF FF 750 1
20 65 03 06 01 FF FF FF 250 1

am I making this more difficult that needed?

There is a very interesting post on How to make Nextion - Arduino communicate.
There is an example on how to navigate between pages and let the Arduino know the page you are on.
There is a simple and well written code with enough comment. This also doesn't use any library.

https://forum.arduino.cc/index.php?topic=634237.0

just take your time to read it and follow the examples.

altitudeap:
not sure I have found my answer in the above so I would like to ask the similar question.. I have several pages and I use hotspots to move from page to page. I also want to know what page I am on. In the simulator I see that the output has a structure like this " 65 00 05 01 FF FF FF" What I have been able to discern is that the "05" is the page I have gone to and the "00" is the page I came from.
What serial commands will I use to parse this?

Hi
The output structure that you see at the simulator is the return code of Nextion protocol No21 on section 7
used from the Touch Event of components when the < Send Component ID > is checked on or on .
It is in hex, hexadecimal format, and starting with 0x65.
Has 7 bytes length: 0x65 0x00 0x01 0x01 0xFF 0xFF 0xFF
First Byte 0x65 is the Format group of Nextion Return Data Touch Event
Second Byte 0x00 is the page number that touch event comes from
Third Byte 0x01 is the component ID
Fourth Byte 0x01 is the event that occurs < 0x01 for Touch Release Event > or < 0x00 for Touch Release Event>.
Next 3 bytes declares the end of the command.
You can find the above at Nextion instruction set:

As you have already understood it very difficult to assign the commands that you want in every Touch Event and much more difficult to read them separately for every event from the Serial and attach the function that you want on Arduino.

You must simplify this a lot, I’m going to help you on this.
First you must develop your own custom protocol so you can handle the commands that you need.

Second, sent to Arduino the command that you want through the Touch Event
Last, just read them.

As I can see your project needs to update 2 variables x and y or Step and Direction.
Let’s make a group command for this and named < Sent Variables >

We may assign the capital letter ‘V’ in this command group to identify it later.
The character ‘V’ is the hex 0x56 (google for Ascii character table).

We are going to use the following Data Format:
<#> <Step_var> < Direction_var >

  • <#> declares that a command is followed
  • declares the number of bytes that will follow (len = 3, is the one Byte < Step_var > and < Direction_var >is the other)
  • declares the group of commands (V = Sent Variables),you can add a different command group later.
  • < Step_var > is the value for the Step variable
  • < Direction_var > is the value for Direction variable

So as example for the case 1 of your project we must sent the number < 790 > as Step and the < 0 > as the Direction
Sending the following from Nextion Touch Event in hex :
< # 3 V 790 0 >

To send this trough Serial, we must write on < Touch Press Event > of the component, in your case the component is on < page1 > and has the ID < 1 >, the following:
< printh 23 03 56 316 00 >
Where the HEX is: <23 = #> <03=3> <56=V> <316=790> <00=0>
And that’s it.

So far, the problem is that you can’t send a number bigger than 255 in a single byte, that means that you can’t sent the <316> on hex = <790> in dec.

To do this we need 2 bytes, a high byte and a low byte and the things start to complicate.

In your project this is not a problem because as I can see the values can be divided with 10 and the result is going to be a number lower than 255,
that you can multiply it with 10 on Arduino code after the Serial reading.

At the end, You must sent: < # 3 V 79 0 >
With writing: < printh 23 03 56 4F 00 > Where is: <23 = #> <03=3> <56=V> <4F=79> <00=0>
You can find the HEX of a DEC number from on line tables or calculators.
Do the same with all the cases BE AWARE: uncheck the < Send Component ID >
Here is the code that you must use from Arduino:

//                                   ______________________________________________
                                    //--------CREATED BY SEITANIS THANASIS--------\\
                                   //---------------VERSION 13/9/2019--------------\\
                                  //----------------- www.seithan.com --------------\\
                                 //------ code for Step and Direction variables -----\\

#define Nextion Serial
 // define that Serial will de writed as Nextion (when we write Nextion.print the  compiler read Serial.print)    

 int Step_var = 0 ;       // Variable to store the Step value that we sent from Nextion
 int Direction_var = 0 ; //  Variable to store the direction value that we sent from Nextion

void setup(){

 
  
  Nextion.begin(9600); // starting the serial port at 9600. NEXTION MUST HAVE THE SAME RATE. For this we write at
                         //  first page to the preinitialize event the command @  baud=9600  @ 
                         // NOTE "bauds" will change the default baud rate off 9600 until it changed again
  delay(500);
}


void loop(){

  Nextion_serial_listen();
  
  
 
}


void Nextion_serial_listen() 

{
    if(Nextion.available() > 2){                // Read if more then 2 bytes come (we always send more than 2 <#> <len> <cmd> <id>
        char start_char = Nextion.read();      // Create a local variable (start_char) read and store the first byte on it  
        if(start_char == '#'){                // And when we find the character #
          uint8_t len = Nextion.read();      // Create local variable (len) / read and store the value of the second byte
                                            // <len> is the lenght (number of bytes following) 
          unsigned long tmr_1 = millis();
          boolean cmd_found = true;
            
          while(Nextion.available() < len){ // Waiting for all the bytes that we declare with <len> to arrive              
            if((millis() - tmr_1) > 100){    // Waiting... But not forever...... 
              cmd_found = false;              // tmr_1 a timer to avoid the stack in the while loop if there is not any bytes on Serial
              break;                            
            }                                     
            delay(1);                            // Delay for nothing delete it if you want
          }                                   
                                               
            if(cmd_found == true){            // So..., A command is found (bytes in Serial buffer egual more than len)
              uint8_t cmd = Nextion.read();  // Create local variable (cmd). Read and store the next byte. This is the command group
                                             
              switch (cmd){
                                    
                case 'V': /*or <case 0x56:>  IF 'V' matches, we have the command group "Sent Variables". 
                           *The next byte  according to our protocol is the value for the <Step_var>
                           */
                     Step_var = Nextion.read() * 10 ;  // we read and store the byte at the variable

                     // The next byte  according to our protocol is the value for the <Direction_var>

                     Direction_var = Nextion.read();   // we store and store the byte at the variable
                     



                      Nextion.print("n0.val="); // Those lines is for the debug on Nextion
                      Nextion.print(Step_var);  // they sent the variables at the         
                      NextionEndCommand();      // numeric Component  n0 
                      
                      Nextion.print("n1.val=");    // Those lines is for the debug on Nextion
                      Nextion.print(Direction_var);     // they sent the variables at the     
                      NextionEndCommand();            // numeric Component  n1
                     
                  break;
                
                                
              }
            }
        }  
    }    
}

void NextionEndCommand()
{
    // with this two ways we can sent the 3 bytes so Nextion can understand the end of a command. Choose freerly.
    
  /* Nextion.write(0xff);
     Nextion.write(0xff);
     Nextion.write(0xff); */
  
    Nextion.print("\xFF\xFF\xFF");
  
 
}

nextion_step_direction.ino (5.59 KB)

As I have found some time, I made a .HMI file on Nextion Editor with the cases of your project.

In every button Touch Press Event you can find the < printh > command

By pressing on it, the command goes to Arduino, it stores the variables and Arduino returns the values to n0 and n1 numeric components for debug.

So, the system is working for sure.

If you want more information on Nextion displays, you are welcome to visit my site at:

to the Nextion Tutotial page:

Or you can read the tutorial from this forum:
https://forum.arduino.cc/index.php?topic=634237.0

The zip file < nextion_step_direction.zip > contains the .HMI file for Nextion editor

nextion_step_direction.zip (297 KB)

thank you so much for your help with this project.

@Seithan

one of the best tutorials related to Nextion I've found / seen.
The available libraries have only brought me at the edge of desperation.
The decision to attack the issues handling the communication to Nextion on my own will rely on your tutorial.

Thank you for sharing and for your insights.

Do you plan to dig into the getValue approach to get data from Nextion (numeric fields) to Arduino?