Nextion Communication Issue

This is probably a question for @PerryBebbington - but I don't want to keep annoying just him.

I've been using his method for serial communication between an ESP32 and a Nextion successfully, though I just started a new project and tried doing the same thing and for some reason my Arduino isn't doing anything with the serial communications.

I checked the Nextion programmer to see that the serial communications were being sent out, they're fine. Tried switching my RX/TX wires around etc, just to rule out something stupid, but I'm thinking it's to do with the ESP32 or my programming.

Hoping someone can take a quick look at what I've got (so far) and see if there's any blatant issues:


Hardware: ESP32 WROOM-32U (devkit C), Nextion NX8048K050_011

Code:

//#include <Arduino.h>
#include "TickTwo.h"

/* ESP32 GPIO */
#include <soc/soc.h>
#include <soc/rtc_cntl_reg.h>
#include <driver/gpio.h>
/* ********** */

/* FILESYSTEM */
#include <vfs_api.h>
#include <FS.h>
#include <FSImpl.h>
#include <SPIFFS.h>
/* ********** */

/* ESP32 WIFI/HTTP *
#include <esp_pm.h>
#include <esp_wifi.h>
#include <esp_wifi_types.h>

#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <HTTPUpdate.h>

#include <ESPNexUpload.h>
* *************** */

//WiFiMulti WiFiMulti;

/* TEMP/HUM SENSOR - DHT11 */
#include <DHTesp.h>
/* *********************** */

#define NEXT_RX 23 // Nextion RX pin
#define NEXT_TX 13 // Nextion TX pin

/* SENSOR DEFS - DHT11 */
DHTesp dhtSensor1;
DHTesp dhtSensor2;
int dhtPin1 = 4;
int dhtPin2 = 12;
TempAndHumidity sensor1Data;
TempAndHumidity sensor2Data;
/* ******************* */
void run_update();
void man_update();
/* TIMERS */
TickTwo timer1(run_update, 1000);
TickTwo timer2(man_update, 1000);
/* ****** */

/* VARS */
enum controls {OFF, RUN, MAN_SEL};
controls cntrl = OFF;
unsigned long timer_1;

float mcuVer = 1.0;
float guiVer = 1.0;
String mcu = "ESP32 WROOM-32U";
String gui = "NEXTION NX8048K050_011";
String splashString_1 = "MCU: v" + String(mcuVer,2) + " | " + "GUI: v" + String(guiVer,2);
String splashString_2 = mcu + " | " + gui;

float set_temp_max;
float set_temp_thresh;
float set_hum_min;
float set_hum_thresh;
float set_hours;

bool heatBOOL = false;
bool humBOOL = false;

float s1_temp;
float s1_hum;
float s2_temp;
float s2_hum;

/* *** */

/* COMM VOIDS */
void changeTxtField(byte boxNo, String text) {
  Serial1.print(F("t"));
  Serial1.print(boxNo);
  Serial1.print(F(".txt=\""));
  Serial1.print(text);
  Serial1.print(F("\""));
  HMICommandEnd();
};
void changeTxtFieldFloat(byte boxNo, float text) {
  Serial1.print(F("t"));
  Serial1.print(boxNo);
  Serial1.print(F(".txt=\""));
  Serial1.print(text);
  Serial1.print(F("\""));
  HMICommandEnd();
};
/* ********** */

void setup() {
    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
    disableCore0WDT();

    Serial.begin(115200);
    Serial1.begin(115200, SERIAL_8N1, 23, 13);
    while (!Serial1) {
      delay(1);
    };
    Serial1.print(F("baud=115200"));
    HMICommandEnd();
    Serial1.print(F("bauds=115200"));
    HMICommandEnd();

    SPIFFS.begin(true);

    /* Power Pins (DHT11) */
    pinMode(2, OUTPUT);
    digitalWrite(2, HIGH);
    pinMode(15, OUTPUT);
    digitalWrite(15, HIGH);
    /* ****************** */
    /* Sensor Setup */
    dhtSensor1.setup(dhtPin1, DHTesp::DHT11);
    dhtSensor2.setup(dhtPin2, DHTesp::DHT11);
    /* ************ */

    /* Core Handling */
    
    TaskHandle_t c1_CNTRL;
    TaskHandle_t c2_SCRN;

    xTaskCreatePinnedToCore(c1_CNTRL_c,"Controller",10000,NULL,1,&c1_CNTRL,0);
    delay(200);
    xTaskCreatePinnedToCore(c2_SCRN_c,"Screen",10000,NULL,2,&c2_SCRN,1);
    delay(200);
    /* ************ */

    timer_1 = millis();
    
};


void HMICommandEnd() {
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);
};


/* *** */
void IRAM_ATTR controller() {
  switch(cntrl) {
    case OFF:
                //none
                vTaskDelay(1);
    break;
    case RUN:
                timer1.update();
                vTaskDelay(1);
    break;
    case MAN_SEL:
                timer2.update();
                vTaskDelay(1);
    break;
  };
};
/* *** */

/* *** */
void HMI_read() {

  static uint8_t HMI_read_data[10];
  static uint8_t HMI_read_data_i;
  static uint8_t a5count;
  uint8_t readSerial;

  while (Serial1.available() > 0) {
    readSerial = Serial1.read();
    if (readSerial == 0xa5) {
      ++a5count;
      if (a5count > 2) {
        a5count = 0;
        HMI_read_data_i = 0;
      }
    }
    else {
      a5count = 0;
    };

    HMI_read_data[HMI_read_data_i] = readSerial;
    if (HMI_read_data_i == 5) {

      switch (HMI_read_data[1]) {
        case 0:
          switch (HMI_read_data[2]) {
            case 0:
              Serial.println("Splash Page");
              changeTxtField(1, splashString_1);
              changeTxtField(2, splashString_2);
              loadSettings();
            break;
          };
        break;
        case 1:
          switch (HMI_read_data[2]) {
            case 0:
              Serial.println("Main Menu");
              cntrl = OFF;
              break;
            case 1:
              switch (HMI_read_data[3]) {
                case 0:
                  Serial.println("3rd case ex.");
                  break;
                case 1:
                  Serial.println("3rd case ex.");
                  break;
              }
             break;
          }
          break;
          case 2:
              Serial.println("Running Page");
              timer1.start();
              cntrl = RUN;
              changeTxtField(12, String(set_temp_max,2) + " C");
              changeTxtField(13, String(set_hum_min,2) + "%");
              changeTxtField(14, String(set_temp_max,2) + " hrs");
          break;
          case 3:
              switch (HMI_read_data[3]) {
                case 0:
                  Serial.println("Manual Run Page");
                  heatBOOL = false;
                  humBOOL = false;
                  timer2.start();
                  cntrl = MAN_SEL;
                  break;
                case 1:
                  Serial.println("Manual Heat Op BTN");
                  if (heatBOOL == false) {heatBOOL = true;};
                  if (heatBOOL == true) {heatBOOL = false;};
                  break;
                case 2:
                  Serial.println("Manual Humidity Op BTN");
                  if (humBOOL == false) {humBOOL = true;};
                  if (humBOOL == true) {humBOOL = false;};
                  break;
              };
          break;
          case 4:
              Serial.println("Config Page");
          break;
          case 5:
              Serial.println("Keyboard Page");
          break;
    };
    ++HMI_read_data_i;
    if (HMI_read_data_i > 9) {
      HMI_read_data_i = 9;
    }
  }
};
};
/* *** */



void getSensorData() {
  sensor1Data = dhtSensor1.getTempAndHumidity();
  sensor2Data = dhtSensor2.getTempAndHumidity();
  s1_temp = sensor1Data.temperature;
  s1_hum = sensor1Data.humidity;
  s2_temp = sensor2Data.temperature;
  s2_hum = sensor2Data.humidity;
};

void run_update() {
  getSensorData();
  changeTxtField(8, String(s1_temp,2) + " C");
  changeTxtField(9, String(s1_hum,2) + "%");
  changeTxtField(10, String(s2_temp,2) + " C");
  changeTxtField(11, String(s2_hum,2) + "%");
};
void man_update() {
  getSensorData();
  changeTxtField(15, String(s1_temp,2) + " C");
  changeTxtField(16, String(s1_hum,2) + "%");
  changeTxtField(17, String(s2_temp,2) + " C");
  changeTxtField(18, String(s2_hum,2) + "%");
};

void loadSettings() {
  File setDir = SPIFFS.open("/settings.txt", "r");
  if (!setDir) {
    Serial.println("Couldn't Load Settings");
  }
  Serial.println("=======Load Settings=======");

  for (int i = 1; i < 7; i++) {
    String s = setDir.readStringUntil('\n');


    if (i == 1) {
      set_temp_max = s.toFloat();
      Serial.println("MAX TEMP = ");
      Serial.println(set_temp_max);
    };

    if (i == 2) {
      set_temp_thresh = s.toFloat();
      Serial.println("TEMP THRESHOLD = ");
      Serial.println(set_temp_thresh);
    };

    if (i == 3) {
      set_hum_min = s.toFloat();
      Serial.println("MIN HUMIDITY = ");
      Serial.println(set_hum_min);
    };

    if (i == 4) {
      set_hum_thresh = s.toFloat();
      Serial.println("HUMIDITY THRESHOLD = ");
      Serial.println(set_hum_thresh);
    };

    if (i == 5) {
      set_hours = s.toFloat();
      Serial.println("RUN TIME (HOURS) = ");
      Serial.println(set_hours);
    };

  };
  setDir.close();
};


void writeSettings() {
  File setDir1 = SPIFFS.open("/settings.txt", "w");
  if (!setDir1) {
    Serial.println("Couldn't Load Settings");
  };
  Serial.println("=======Save Settings=======");

  for (int i = 1; i < 7; i++) {

    if (i == 1) {
      setDir1.print(set_temp_max);
      setDir1.print('\n');
    };

    if (i == 2) {
      setDir1.print(set_temp_thresh);
      setDir1.print('\n');
    };

    if (i == 3) {
      setDir1.print(set_hum_min);
      setDir1.print('\n');
    };

    if (i == 4) {
      setDir1.print(set_hum_thresh);
      setDir1.print('\n');
    };

    if (i == 5) {
      setDir1.print(set_hours);
      setDir1.print('\n');
    };

  };
  setDir1.close();
};






void loop() {vTaskDelete(NULL);};

void c1_CNTRL_c( void * pvParameters ) {
  for (;;) {
    controller();
    vTaskDelay(1);
  };
};

void c2_SCRN_c( void * pvParameters ) {
  for (;;) {
    HMI_read();
    vTaskDelay(1);
  };
};

I have some libraries commented out just because I'm not using them yet, it's a work in progress.

I'm not using nextion, do they use 115200 bauds by default?

Side note: I saw this:

boot will fail if pin 12 is pulled high. This might create an issue.

Hello Joel, welcome back!
I'm not annoyed. I enjoyed helping you with your project :grinning:

Come on JT! You know they are called 'functions!'. I expect complete beginners to call them 'voids', not someone with your experience! :frowning:

You can't change the Nextion baud rate like that, assuming it's at the default of 9600 how is it going to ever receive a message sent at 115200? There a comment about baud rate in Using Nextion displays with Arduino - #4 by PerryBebbington

Perry

I copied the code over from something old since I lost the hard drive with my recent work on it, don't judge me too harshly. But the baud settings in the HMI were set to match regardless. I dropped all that and went back to 9600, still no good.

The power supply I've been using to these things is pretty shoddy, wondering if that could be an issue? I'm sort of just running them both off independent USB power. The breakout board I was using for the ESP was making the serial connection shoddy, the uploads were failing here and there - though when I pulled the ESP off the board, the uploads go straight through...so I've ditched that thing.

I dunno, I feel stupid, but nothing is working here - I know the Nextion is sending the serial commands, so it's something to do with the ESP32 or my programming.

My setup baud rates in the ESP is:

Serial.begin(115200);
Serial1.begin(9600, SERIAL_8N1, 23, 13);

and there's no attempts to change it on the Nextion now. Still wondering if perhaps there's a mismatch between the two.

Tip: you can do this:

Serial1.print(F(".txt=\""));
Serial1.print(text);
Serial1.print(F("\"\xFF\xFF\xFF"));

I have written a sketch in the past that tries to capture a Nextion display that has the wrong baudrate. Look at the "Let's get serious" part, that is where I increment the baudrate with small steps.

If you connect the Nextion display to a computer with a usb-serial module, does that work ? If so, then the baudrate is no problem. Set it default at 9600.

My approach is always fix the obvious problems before looking for anything else, if you think the PSU could be the problem then change the PSU for a better one. What does 'shoddy' mean anyway?

Grounds connected together?

What are the 3rd and 4th parameters for? I'm going to guess pin numbers, you should not need to specify pin numbers for a hardware serial port, they are fixed in hardware. Note I am not familiar with the ESP32, does the ESP32 have a serial port on those pins? I have never seen a serial port initialised with 4 parameters.

Shoddy means I have the screen connected to an FTDI adaptor and USB cable with just the power/ground running to it, TX/RX pins to the ESP32, and the ESP32 powered by another USB cable into the computer. There are two 3.3v draws from the ESP32 all the time with the sensors running, I've never taken the time to learn about power attenuation so it could just be completely baseless.

Actually, I'm not much of a programmer either and my memory hasn't been great since I had a string of health issues, so I can't recall exactly why the pins are specified there either. I'm sort of just building off an old (previously functional) sketch I had from a long time ago and trying to remember how to do this stuff again.

I'll go perform some more experiments, but if you're saying (aside from what you pointed out) that the code looks acceptable, then I'll see about just making a simple test program without all the other crap and core splitting stuff.

Well, I tried a basic test - the HMI is just a single page with a button and a text field. The button sends the following serial command:

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

and the ESP32 code looks like this:

#include <soc/soc.h>
#include <soc/rtc_cntl_reg.h>
#include <driver/gpio.h>

#define NEXT_RX 23
#define NEXT_TX 13

void setup() {
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, 23, 13);
    while (!Serial1) {
      delay(1);
    };

}

void loop() {
  HMI_read();

}

void HMI_read() {

  static uint8_t HMI_read_data[10];
  static uint8_t HMI_read_data_i;
  static uint8_t a5count;
  uint8_t readSerial;

  while (Serial1.available() > 0) {
    readSerial = Serial1.read();
    if (readSerial == 0xa5) {
      ++a5count;
      if (a5count > 2) {
        a5count = 0;
        HMI_read_data_i = 0;
      }
    }
    else {
      a5count = 0;
    };

    HMI_read_data[HMI_read_data_i] = readSerial;
    if (HMI_read_data_i == 5) {

      switch (HMI_read_data[1]) {
        case 0:
          switch (HMI_read_data[2]) {
            case 0:
              Serial.println("Serial Receipt");
              changeTxtField(0, "Serial Send");
            break;
          };
        break;
    };
    ++HMI_read_data_i;
    if (HMI_read_data_i > 9) {
      HMI_read_data_i = 9;
    }
  }
};
};

void HMICommandEnd() {
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);
};

void changeTxtField(byte boxNo, String text) {
  Serial1.print(F("t"));
  Serial1.print(boxNo);
  Serial1.print(F(".txt=\""));
  Serial1.print(text);
  Serial1.print(F("\""));
  HMICommandEnd();
};

Checked the Nextion was sending the data in the HMI editor, it is. Serial monitor on the ESP32 shows no action at all.

I tried removing those extra pin specifications in the Serial1 arguments, all it does is cause the ESP to keep restarting over and over. I can't recall why I did those things honestly, but there seems to have been a purpose. I feel like I'm missing something..

Could you try Serial2 at pins 16 (RX) and 17 (TX) ?
Use Serial2.begin(9600); to use the default.

When you remove those extra arguments from the Serial begin command, the ESP32 just keeps restarting itself for some reason. I'll google around and find out what the purpose behind that is and try the other pins as you suggested, but I have been using 13 and 23 successfully on the same board with a different program so this is all very strange to me.

Sometimes the community makes the interface between Arduino software and the board (ESP8266), sometimes the manufacturer (ESP32), sometimes Arduino is on top of Mbed (Raspberry Pi Pico) and something things change. Sometimes there are different default pins for different build environments. On the same board there could be other default pins depending on using Arduino/community/microPython/Mbed.

Therefor I don't care what worked in the past :person_shrugging:

The ESP8266 and ESP32 try hard to be compatible with Arduino software. In the past some trick with HardwareSerial was required, but if you have updated everything, then a "Serial2.begin(9600)" should be enough to activate Serial2 on pin 16 and 17.
I think that Serial1 is still confusing for the ESP32.

Hello JT,

You've not confirmed that the grounds from the different power supplies are connected, no common ground, nothing working.

I can't really help with the ESP32 serial ports as I don't have an ESP32. ESP8266 would be no problem. Maybe @Koepel will be more help there.

I'm not saying it's OK, I've not tested it, which is the only proper test, without an ESP32 I can't test it properly. I am saying I can't see an obvious problem, but don't take that as me saying it is definitely OK.

Try modifying your test code like this:

  while (Serial1.available() > 0) {
    readSerial = Serial1.read();
    Serial.print(readSerial);  // Add this line to print readSerial

So you get an immediate print of whatever the ESP32 serial port receives.

Perry

I replaced all instances of Serial1 with Serial2, changed pins, and removed the extra arguments - you were right in the sense that suddenly the serial definition doesn't need those extra arguments since it stops doing that constant reboot thing now, but unfortunately there's still no sign that any serial communications are being received from the nextion.

I re-downloaded the board manager (I had an Espresif link in there before, now I'm using the GitHub one: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json).

@PerryBebbington I did what you suggested (using Serial2 now like Koepel suggested) and what I get is a constant readout of numbers. I'll paste it, though I don't know if it'll explain much:

125525525525125523925525525525525525525125525525525525525525525525525525525525525525525525525525525525525525525512723725525525525525125525525525525525525325525525523925525525525525522325525525525525525525525525525525523925525525525525525525525512725325525525525525525525525525523925525525525525325525525525512725522325512725525525525525525519125525525525525525525525525525525525525525519125525525523925525525525525525525322325525525525525525525525123725425525525525512725525525524725525525525525525525525525525525525525425525525524725525525525525519125525525525525525525525525525325525525512725525525525525525525525524725525525521523925525519125525525525119125525519125525525525525525522725525525325525525525525525525512325525525525525525525525525525125525525525125525525525525525525525525525523725525525525525525525525525525525525125325525525525523925525525525525525525525523925525525525512725525525525512725525525525522325125525525525523922325525525511125525525522363255255254255255255251255235239255255239255255255247255255255255253191255255239255255255255127255255235255255255255127255255239255251127255127255255255255255255255255251253255255175255255254255255255255251255255255255247255255255255239255255255255255255255255255255255255255123255253127255255255255255255255255255255255255255255255251255251253255127251255255255255255255255255127255255223255255255255255253255255255127255251255255255255123239255255247255255255255255255111247191255251255127255255255255255215255255255127127255251255255255239255255255255255255255255255255255255255255255127255255237127255255255255255255255255255255255255255255255255255255255255255255255255247255127255255255255255255255255255255255255255255255255127255255255127255255255255127251255255255255255255255255255223255255255255255255255247255255255255

I should mention that in that stream of numbers, there doesn't seem to be any change in what's printing there when I press the button on the Nextion.

Progress.
The numbers are mostly 255 repeated, which is 0xff. Don't know where that's coming from.

What about if you use:

   Serial.println(readSerial);  // (Added ln so it prints on a new line each time)

You have STILL not confirmed the grounds!

If you disconnect the Nextion does the printing stop?
Do you a have Mega or a Nano Every? Or anything else simple with a spare serial port?

When the Nextion is disconnected, the serial printout stops...maybe this is a Nextion thing afterall?

Here's the line printouts:

254
255
255
255
247
255
255
255
255
255
191
255
255
127
247
127
255
255
255
239
255
255
223
255
255
255
255
255
255
255
255
251
255
255
255
255
255
255
223
127
255
255
255
255
255
255
253
255
239
191
255
255
255
255
255
255
255
255
255
247
223
255
255
235
255
255
253
255
251
255
255
245
255
255
255
255
255
255
255
255
255
127
255
255
255
255
255
255
255
255
255
255
223
127
251
254
255
251
255
255
255
255
255
255
255
237
255
255
223
111
255
255

I am using an ESP32 WROOM32U DevkitC v4 board, I have a couple more of those around and possibly an Arduino of some sort in this mess of a place. What would that be needed for, just to ensure it's not an ESP thing?

Once more:
Grounds???

Sorry for being stupid, but are you asking me something about the ground connections for the board and Nextion?

I just cleaned the ground pin on the FTDI adapter I'm using and now the constant Serial readout doesn't come through, and I get this response when pressing the button on the Nextion screen:

143

Just a singular line with each button press, but no response otherwise - the program is meant to make a printed response in the serial monitor and send out some text to the Nextion.

Yeeessss!
In reply #6 and reply #12 I asked you to confirm that the grounds between the Nextion and the ESP32 were connected together, as I think you are using a different power supply for each. If they are not it won't work.

I am using two different USB connections to power each yes.

  • I've attached the Nextion to the 5v output of the ESP, so they're both on the same USB power now - same 143 result when I press the button. But I'm a bit more hopeful now, so that's something!