Problem switching from enhanced to intelligend (Boot problem)

Hi,

i have a pcb with an arduino uno on it, with a code that works good with a 3,5" enhanced nextion. When i use a 5" intelligent nextion it doesn´t communicate. When i connect the 3,5" enhanced and switch power on and everything works fine, i can unplug the 3,5" and plug in the 5" and everything works. But when i switch the power off and on again, it will not work. I also found out when i switch power on without the 3,5" connected and plug it in after that, it also doesn`t work. I think about a boot problem, does anybody have an idea?

Thank you

Ben

I forgot to tell that i am using an Atmega328p and IteadNextionLibrary

I’d start by losing the nextion library. It’s too easy to just send and receive data without the library :slightly_smiling_face:

Post your initialization code. Ensure the baudrate settings are valid for both displays.

I would not expect either display to work if they are plugged in after the initialization code has run.

I found that the initialization time of a basic 3.5" vs enhanced 3.5" is different, with the enhanced variant taking longer to get ready. From memory it was 180mS vs 230mS (or thereabouts) from power on.

Although I’ve never used the intelligent series, it wouldn’t surprise me if they took even longer to boot and become ready.

Also, I’ve found a TJC4832T135 HMI takes longer to boot than an NX4832T035.
I got sick of being ripped off with Nextion price gouging by Greedy Chinese vendors, so I’ve migrated to TJC.

Try increasing the wait time on the Arduino side if you’re not using proper handshaking upon power-up and simply relying on delays.

You can easily measure the boot time differences with a 2-channel DSO.
Trigger channel is the 5V rail, 2nd channel is the TXD from the HMI.
HMI will send 0x00 0x00 0x00 0xFF 0xFF 0xFF (start up) followed by 0x88 0xFF 0xFF 0xFF (ready).

And yes, there is no need to ever use libraries to communicate with a TJC/Nextion.
It’s easy to send and receive packets from the HMI.

not using the Nextion library sounds like a good idea for further projects. But it is too much work for this project since we don`t have that much time and i am a bad programmer.

My Setup:

#include <arduino.h>
#include <EEPROM.h>
//#include <Nextion.h>
#include "../lib/ITEADLIB_Arduino_Nextion/Nextion.h"
#include "./Basic_Defines.h"
#include "./vars.h"
#include "../lib/ACS712/ACS712.h"
void ShowHideID(int IDtoShow, bool ShowHide)
{
        Serial.print("vis ");
        Serial.print(IDtoShow);
        Serial.print("\x2C");
        Serial.print(ShowHide);
        Serial.write("\xFF\xFF\xFF");
}
/*
float stof(const char* s)
{
  float rez = 0, fact = 1;
  if (*s == '-'){
    s++;
    fact = -1;
  };
  for (int point_seen = 0; *s; s++){
    if (*s == '.'){
      point_seen = 1; 
      continue;
    };
    int d = *s - '0';
    if (d >= 0 && d <= 9){
      if (point_seen) fact /= 10.0f;
      rez = rez * 10.0f + (float)d;
    };
  };
  return rez * fact;
}
*/
#include "./DisplayVars.h"
ACS712  ACS(15, 5.0, 1023, 100);
#include "../lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h"
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, ledpin, NEO_RGB + NEO_KHZ800);
#include "./Functions/led.h"
#include "./Display.h"
void setup()
{
        pinMode(4, OUTPUT);
        digitalWrite(4, HIGH);
        pinMode(13, OUTPUT);
        digitalWrite(13, HIGH);
        pinMode(relaispin, OUTPUT);
        digitalWrite(relaispin,LOW);
        pinMode(luefterpin, OUTPUT);
        pinMode(ledpin, OUTPUT);
        pinMode(pwmpin, INPUT);
        pinMode(duftenable, OUTPUT);
        pinMode(chlorenable,OUTPUT);
        pinMode(duftstepperfehler,INPUT_PULLUP);
        pinMode(chlorstepperfehler,INPUT_PULLUP);
        pinMode(strompin, INPUT);
        pinMode(chlorlevelpin, INPUT);
        pinMode(duftlevelpin, INPUT);
        digitalWrite(duftenable,HIGH);
        digitalWrite(chlorenable,HIGH);
        analogWrite(luefterpin,0);
        pixels.begin();
        Serial.begin(9600);
        #if defined(TEENSY) && TEENSY == 1
                Serial2.begin(115200);
        #endif
        delay(200);
        nexInit();
        RaumGrUp.attachPop(RaumGrUpPopCallback, &RaumGrUp);
        RaumGrDown.attachPop(RaumGrDownPopCallback, &RaumGrDown);
        DuftUp.attachPop(DuftUpPopCallback, &DuftUp);
        DuftDown.attachPop(DuftDownPopCallback, &DuftDown);
        LEDOnBtn.attachPop(LEDOnBtnPopCallback, &LEDOnBtn);
        LEDOffBtn.attachPop(LEDOffBtnPopCallback, &LEDOffBtn);
        //.attachPop(PopCallback, &);
        delay(200);
}     // END SETUP

[admin: edited to include code block for clarity]

My Nextion initialization code is a bit simpler :grinning:

const char* nextionEnd = “\xFF\xFF\xFF”;
Serial1.print(“bauds=921600”);
Serial1.print(nextionEnd);
MilliDelay(50);
Serial1.print(“bkcmd=0”); // Set Nextion to return NO replies to each command
Serial1.print(nextionEnd);
MilliDelay(50);

Nextion page 0 preinit code:
bauds=921600
bkcmd=0 // Set Nextion to return NO replies to each command

It works equally well for Enhanced and Intelligent screens.

All Nextion displays send status messages: 3 times 0x00 followed by 3 times 0xFF (terminator) after powering on, 0x88 followed by 3 times 0xFF after boot is complete. Catching these “signals” and having the Arduino react accordingly is much better practice and a much more robust solution than simply putting delay() with an arbitrary value and hoping or praying that the Nextion will be ready afterwards.
To make everything perfect, I recommend even using sendme command at the end of the post initialize event of each page and catching it on Arduino side to make sure that everything is really loaded before starting interaction.

In my program I’m also initializing several SPI ports, each of which take two seconds (hardcoded in the SPI library), so I’m not too concerned with how long the Nextion takes :grinning_face_with_smiling_eyes:

The delay on the arduino works, thank you for your great answers

Hi there,

i continued to work on this program and again it doesnt work. So instead of the NexInit() i use the code elf suggested, and now i can receive data, but can not write on the nextion. Do you have information where i can learn how to send data to the nextion without using the library?

Try this:
const char * pageMove_bt3_Char = “pageMove.bt3.val=0”;
const char* nextionQuoteEnd = \x22\xFF\xFF\xFF;
const char* nextionEnd = \xFF\xFF\xFF;

///


/// Serial Print
///

///
/// Prints data to USB and Bluetooth serial ports. Only one will be active.
///
/// Text to send
///
void SerialPrint(String text, int decimalPlaces = 0)
{

switch (serialId)
{
	case 0:
	{
		Serial.print(text);
		break;
	}
	case 1:
	{
			Serial1.print(text);
		break;
	}
	case 2:
	{
		Serial2.print(text);
		break;
	}
	case 3:
	{
		Serial3.print(text);
		break;
	}
}

}

someFunction()
{
SerialPrint(pageMove_bt3_Char);
SerialPrint(nextionEnd);
}

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.