Start a new topic

No library Basic display strange behaviour

Hi team, I should be doing something terrible wrong but I can't find out what it is and will count with your kindly help.


This is what I have:

  1. NX3224T024_011 Display
  2. Hooked up to a nodeMCU (working properly)
  3. Basic HMI (attached) with 3 fields: Text, Value, Picture
  4. Initial Display is this 

    image

  5. After running this basic program 

  

void setup() {
  Serial.begin(9600);
  while (Serial.available()) Serial.read(); 

    //UPDATE NUMBER
    Serial.print("n0.val=");
    Serial.print(123);
    Serial.print("\xFF\xFF\xFF");
    delay(2000);

    // UPDATE TEXT
    Serial.print("t0.txt=Hello World");
    Serial.print("\xFF\xFF\xFF");
    delay(2000);

    // UPDATE PICTURE
    Serial.print("p0.pic=");
    Serial.print(1);
    Serial.print("\xFF\xFF\xFF");
}

void loop() {
} 

 I would expect all 3 fields to be updated accordingly but only the picture field is as can be seen in the resulting picture

image


What am I doing wrong? 

Many thanks in advance!!!

HMI
(66.7 KB)

You are printing the three required 0xFFs - write them.

But why didn't check with library or 500+ threads?

Thanks Patrick for your prompt answer.


  1. I did as you suggested and did not make any difference. By the way makes sense since the picture IS updated even with the 0xFFs being printed instead of writing. 
  2. I find the library too confusing and poorly documented.

Question, could it be a problem about having to wait some time between commands? Or do I need to somehow refresh the screen after sending the commands?

Any other suggestion?

Regards

Sorry, I missed pic was updated


You are disregarding all Nextion Return Data.

  (big section of Tables in Nextion Instruction Set Section 6)

  - as such you are not synchronizing with Nextion.

 

n0.val is being missed do to timing issue sent before ready.

t0.txt is being missed to malformed command

delay() should never be used.


Reason why you wanted to branch out with own code

  and not use Iteadlib?

HI Patrick, thanks again for your prompt answer, please see remarks below:


"...not synchronizing with Nextion"

I get your point (my bad) still how come pic is updated?


"t0.txt is being missed to malformed command "

 What´s wrong with it, it works OK on the simulator. Could you please tell me how should I do it?


"delay() should never be used."

 Why not? what would be the problem?


"Reason why you wanted to branch out with own code

  and not use Iteadlib?"

Unless I'm missing something library is not supported for the nodeMCU (see error below)



image


Nextion sends very informative framed data

 - length of framed data depend on first byte

 - 0x70  String Data varies in length, all other known fixed


When you set you code up to receive this with bkcmd=3

  - you have a bit of extra serial transmissions on wire

  - not that 4 or 9 bytes out of 11520 per sec really effects much

Then you have clean knowledgeable informed communications.


On MCU side,

  Serial.begin(baudrate);

still needs to be initialized before sending commands, done with

  while (!Serial) { }


Nextion

    0x00 0x00 0x00 0xFF 0xFF 0xFF // power up initialization

    0x88 0xFF 0xFF 0xFF // Nextion Ready.

MCU

    bkcmd=3ÿÿÿ

Nextion

    0x01 0xFF 0xFF 0xFF // Command Successful

MCU

    n0.val=123ÿÿÿ

Nextion

    0x01 0xFF 0xFF 0xFF  // Command Successful

MCU

    t0.txt=Hello Worldÿÿÿ

Nextion

    0x1B 0xFF 0xFF 0xFF  // Invalid Variable Operation

MCU

    p0.pic=1ÿÿÿ

Nextion

    0x01 0xFF 0xFF 0xFF  // Command Successful


Now, it doesn't really matter if it is a quick command

      like setting sys0=dpÿÿÿ

   or a long command lasting 6 minutes

      like triggering event code click m0,0ÿÿÿ

Nextion does not send out its pass/fail until finished.


In the IteadLib Arduino Nextion Library

  this is function recvRetCommandFinished()

    - located in NexHardware.cpp


The get command will return either 0x70 or 0x71

   it does not send out a pass but the string or number.

These functions in IteadLib Arduino Nextion Library

     recvRetString() and recvRetNumber()

     

So you see, if you were to follow the Nextion's Data

  you would have that perfect timing not needing delay()

Regardless of Arduino Lib not binary compatible to ESP

  it is text based C style code that provides framework


So this code can indeed be ported and its concept used.

Dear Patrick I really appreciate your answers but still I can't make it work. Too confusing for me (and I'm not completely illiterate when it comes to Arduino and the like)


Would it be too much to ask you to correct my code to make it work as desired? According to what I have seen on the internet I guess this could be helpful for many other Nextion users like myself.


Many thanks in advance



Answers to Answers:


1) p0.pic is updated because Serial is established

    n0.val sent out before Serial ready MCU side.

    also good practise to send empty command as first

       MCU sending just ÿÿÿ

2) Text values need to be encapsulated with double quotes

     Serial.print("t0.txt=\"Hello World\"");

     Serial.print("\xFF\xFF\xFF");

3) The delay() command is a Halt in Place and Do Nothing command

     this will even prevent interrupts and incoming serial bytes

     Better practise is to create non-blocking loop of millis(x) out

         st=millis()+2000;

         while(millis() < st) { }

     This holds in place without stopping interrupts from triggering.

4)  Consider the benefit of framework informing the MCU

     Error shown is only because of Hardware serial with AVR

     - your code shows you using a Serial on ESP

       so ESP does indeed have a compatible foundation to build on.


But I have to advocate an informed MCU is better than not.

How to send Text has been asked and answered 100+ times already.

I gave more info in the post above.


But such answers when not read

   had you read the previous posts, such as Nextion TTL Serial

   your t0 mistake would have been avoided

   - don't worry, most don't bother reading already.


So I would debate fixing your code is helpful to others

  - it promotes a "can you fix mine too"

    how about mine, can I be next.


I am a Nextion User like your self (been made Forum God)

  - but I am not compensated to debug and develop user code.

I don't mind sharing some of my advanced Nextion knowledge

  but I am indeed not paid to do code (unless you sent and I didn't see)

   

OK Patrick many thanks for your patience with me and sorry for bothering you so much. 


Your answers have helped a lot.


Regards.

With all the lessons learned from Patrick´s help above, the code that follows is a quick, simple & dirty way to start playing with an ESP + Nextion display before getting into more complex/professional (and potentially frustrating) solutions like Serial handshake and or Library inclusion.


Hope it helps somebody


 

void setup() {

  Serial.begin(9600);
  while (!Serial) { }
  while (Serial.available()) Serial.read(); //Flush initializing data from Nextion

    delay (1000); //wait one second for display to initialize

    Serial.write("\xFF\xFF\xFF"); //send empty command to establish communication

    //UPDATE NUMBER
    Serial.print("n0.val=");
    Serial.print("123");//Print the Long back to Nextion
    Serial.print("\xFF\xFF\xFF");
  
    delay(1000);  //wait one second for display to perform previous command

    // UPDATE TEXT
    Serial.print("t0.txt=\"Hello World\"");
    Serial.print("\xFF\xFF\xFF");

    delay (1000);  //wait one second for display to perform previous command

    // UPDATE PICTURE
    Serial.print("p0.pic=");
    Serial.print(1);//Print the Long back to Nextion
    Serial.print("\xFF\xFF\xFF");
}

void loop() {
} 

 

I didn't mean to sound harsh, just a few facts

 - just presenting the opposite side of the debate.


What the Nextion Forum should be used for

    is to discuss and debate what neat things Nextion can do

    what neat things it can be used for.


Review the Nextion MCU conversation

   try to incorporate the informative packets

   it becomes so much better synchronized afterwards.


Generally I work with Pascal for my MCUs.

    When I get time I will break out my ESPs

    ESP-12, ESP-8285 and ESP32s

Perhaps we can get a good full library written that uses

    these concepts/function and contribute it to the community.


As stated scattered in answer posts above but

Let's try not to do quick and dirty

  - quick and dirty is what lead you here.  Hmmm....


[ Fixed Typos, Code moved, code confirmed to now compile]


Thanks Patrick, at the moment the quick&dirty solution is enough for me (I'm at POC stage) but will certainly try your code whenever I need a more robust environment.


Keep helping people like me, you do a great job by doing so.


Best!

 

bool waitfor_ready(void) {
  int done;
  uint32_t quitat;
  uint32_t _ndt;
  byte incoming;
  bool passfail;

  _ndt = 0;
  done = 0;
  passfail = false;
  quitat = millis()+1000; // 1000 ms to timeout at
  while (done==0) {
    if (Serial.available() > 0) {
      incoming = Serial.read();
      _ndt = (uint32_t)(((uint32_t)(_ndt <<16) >>8) + incoming);
      if (_ndt==16777215) {
        // Nextion terminator 0xFF 0xFF 0xFF received
        if(incoming==0x88) {
          done=1;
          // Nextion Ready, exit while
          goto  __return;
          // could have just let loop exit on own
        }
      }
    }
    if(millis() > quitat) {
      // if timeout reached exit while
      goto  __return;
    }
  }
  __return:
    if(done==1) {
      // passed 0x88 0xFF 0xFF 0xFF received
      passfail=true;
    } else {
      // failed due to timeout
      passfail=false;
    }
  return passfail;
}

bool waitfor_passfail(void) {
  int done;
  uint32_t quitat;
  uint32_t _ndt;
  byte incoming;
  bool passfail;

  _ndt = 0;
  done = 0;
  passfail = false;
  quitat = millis()+1000; // 1000 ms to timeout at
  while (done==0) {
    if (Serial.available() > 0) {
      incoming = Serial.read();
      _ndt = (uint32_t)(((uint32_t)(_ndt <<16) >>8) + incoming);
      if (_ndt==16777215) {
        // Nextion terminator 0xFF 0xFF 0xFF received
        done=1;
        // reason now in incoming, exit while
        goto  __return;
        // could have just let while exit on own
      }
    }
    if(millis() > quitat) {
      // if timeout reached exit while
      goto __return;
    }
  }
  __return:
    if(done==1) {
      if(incoming==0x01) {
        // passed 0x01 0xFF 0xFF 0xFF received
        passfail=true;
      } else {
        // failed with other cause
        passfail=false;
      }
    } else {
      // failed due to timeout
      passfail=false;
    }
    return passfail;
}

void setup(void) {
  byte ndt[3] = {255,255,255};
  
  Serial.begin(9600);
  while (!Serial) {
    // wait for MCU Serial to finish initialize before sending
  };
  waitfor_ready();      // implement a wait for bytes 0x88 0xFF 0xFF 0xFF
  Serial.write(ndt,3);  // send empty command - extra, but good practice
  Serial.write("bkcmd=3");  // turn Nextion return data on full
  Serial.write(ndt,3);  // send terminator
  waitfor_passfail();   // implement wait for pass/fail and result
  Serial.print("n0.val=");
  Serial.print("123");
  Serial.write(ndt,3);  // send terminator
  waitfor_passfail();   // implement wait for pass/fail and result
  Serial.print("t0.txt=");
  Serial.write(0x22);   // opening Double Quote for .txt
  Serial.print("Hello World");
  Serial.write(0x22);   // closing Double Quote for .txt
  Serial.write(ndt,3);  // send terminator
  waitfor_passfail();   // implement wait for pass/fail and result
  Serial.print("p0.pic=");
  Serial.print("1");
  Serial.write(ndt,3);  // send terminator
  waitfor_passfail();   // implement wait for pass/fail and result
}

void loop(void) {

}

 

Compiles for ESP-8266:

In this manner

  - MCU waits for its own serial to initialize

  - MCU waits for Nextion Ready 0x88 0xFF 0xFF 0xFF

      (occurring at Nextion power on / reset)
  - MCU sends empty command - effectively ensures Nextion buffer 

      is at a good clean starting point (in case Ready timedout)
      (could have been done conditionally, didn't)

  - MCU sets bkcmd to level 3, and will receive informative packets

  - MCU then in synchronization

          sends command and receives response, send and receive

      as Nextion only sends response on end of command processing

      the MCU is assured to be in synchronization with Nextion's timing.

   - USER avoids many pitfalls associated with serial communications.

         read before serial data has arrived

         read long after data has past timeouts

         read in middle of data stream

   - MCU uses no delay(), no halt in place,

        no missed Interrupts, no lost serial data

    - MCU has no wasted time

        command only takes as long as needed, not full time of timeout.

    - MCU can conditionally branch based on function results

        waitfor_ready() and waitfor_passfail() return bool

        therefore it is possible to have code like

           if (waitfor_passfail()) {

               // action if last command was successful

           } else {

               // action to take when last command failed

           }


I would argue for the additional attention to detail and extra cycles used

   the benefit of more reliable, headache free operation is achieved.

Nextion provides much capabilities, only need to catch and act upon.

Login or Signup to post a comment