First off, I HIGHLY agree with the recommendation to skip the Nextion Arduino Library. It’s not necessary, limiting, resource consuming and honestly makes things much more difficult then using your own setup.
Regarding the startup stuff, it’s too unreliable to depend on consistent startup timings between different screen models/vintages/firmwares and microcontroller hardware/firmware. Simply changing the Nextion Editor version used might impact start up timing or something as simple as initializing a new library on your microcontroller. The right way to do this is by having the Nextion and MCU handshake to properly syncronize.
It’s too unreliable to depend on the Nextion return data “Ready…” response. You could easily miss it if your MCU is also running startup code. Here is how to properly sync of your Nextion and MCU.
On the Nextion, your first page (top in editor) should include the following pre-init code:
sleep=0
bkcmd=0
bauds=115200
dims=100
tm0.tim=200
tm0.en=1
Add a single timer object on this startup page (tm0) with enable set to 0 and the following code:
if(baud!=9600)
{
printh EE // indicates ready and running on Nextion
}
else
{
printh EF // indicates ready but running in Simulator
}
On your microcontroller (assuming Arduino), after your startup code, add the following function:
byte Nextion_Reset() {
// resets/syncs Nextion with MCU
// returns 1 if Nextion module reset
// returns 2 if Nextion simulator reset
// returns 0 if timed out (Nextion not responding)
byte ser;
long timeout=7000+millis();
tft.begin(115200);
ms=millis()-3000;
while(1)
{
if(millis()>timeout) { return 0; } // no response, timeout
if(millis()-ms>=3000) // try reset every 3 seconds
{
ms=millis();
tft.print("\xFF\xFF\xFF");
tft.print("sleep=0\xFF\xFF\xFF");
tft.print("rest\xFF\xFF\xFF");
}
if (tft.available() != 0) // check for tm0 timer signal
{
ser = tft.read();
if(ser==0xEE) { return 1; } // Ready (actual Nextion)
if(ser==0xEF) { return 2; } // Ready (in Simulator)
}
}
}
Your actual Nextion GUI code should start on the second page (page1) and your MCU startup code could end with something like:
byte status=Nextion_Reset();
if(status==1)
{
tft.print("page 1\xFF\xFF\xFF");
StartUp_GUI();
}
if(status==2)
{
tft.print("page simulator\xFF\xFF\xFF");
StartUp_Simulator();
}
while(1) // indicate Nextion comm error (fast flash LED)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
The above will allow both the MCU and Nextion to handshake and neither will proceed without the other ready. Actual code begins on the 2nd Nextion page. It also allows both the Nextion and MCU to determine if it’s running in the Nextion simulator or on an actual Nextion device. The reset routine can be used to reset and resync the Nextion at any point.
You can also add some simple security stuff by utilizing the Page_Exit_Event code tab on the startup page on the Nextion. For example, having “if(xxxx!=) { page 0 }”. This makes it impossible to leave the startup page with a page change unless some requirement is met. You need to also secure the sleep wakeup page so “wup=1/sleep=0/sleep=1” cannot be used as a workaround to gain access to page 1.