Nextion display and arduino uno serial issue

Hello all,

I have a project currently that i am sending and receiving data between a nextion display and an arduino i'm not using the library as i don't like it and find it messy so am communicating over serial.

Firstly the display communcates great with the arduino all button pushes work expectidly and the arduino responds fine the issue comes up when i try and send data to the nextion.

So i have some air pressures being sent to the arduino through soft serial and updating the nextion numbers and that all works fine but the issue is when this is happening i am getting serial back to the arduino that shouldn't be there as in no nextion buttons have been pushed etc so its only when the arduino sends serial to the nextion display that this occurs and then when a button is pushed the data takes a twist and goes random characters unexpectedly and no longer functions as intended.

Here is my code currently as you can see have commented out some of the bottom serial from arduino to nextion

#include <SoftwareSerial.h>
SoftwareSerial NextSerial(12,11); //RX,TX
//Button States from Nextion

int TYRBTNST=0;
int COMBTNST=0;
String endChar = String(char(0xfff)) + String(char(0xfff)) + String(char(0xfff));

//Pressure Sensor Pins
int SNSTank=A0;
int SNSTyreFront=A1;
int SNSTyreRear=A2;
int SNSBagL=A3;
int SNSBagR=A4;

// Outputs
int BagLUp=2;
int BagRUp=3;
int TyreFUp=4;
int TyreRUp=5;
int BagLDwn=6;
int BagRDwn=7;
int TyreFDwn=8;
int TyreRDwn=9;
int CompTrigger=10;

// Front and rear target pressures
int TargetFrontPress=0;
int TargetRearPress=0;

// Line and Bag Pressures
int LineFrontPress=0;
int LineRearPress=0;
int BagLPress=0;
int BagRPress=0;
int TankPress=0;

void setup() {

  // Begin Serial
Serial.begin(9600);
delay(1000);
NextSerial.begin(9600);

//Set pins as outputs
pinMode(BagLUp, OUTPUT);
pinMode(BagRUp, OUTPUT);
pinMode(TyreFUp, OUTPUT);
pinMode(TyreRUp, OUTPUT);
pinMode(BagLDwn, OUTPUT);
pinMode(BagRDwn, OUTPUT);
pinMode(TyreFDwn, OUTPUT);
pinMode(TyreRDwn, OUTPUT);
pinMode(CompTrigger, OUTPUT);

// Write all output pins High
digitalWrite(BagLUp, 1);
digitalWrite(BagRUp, 1);
digitalWrite(TyreFUp, 1);
digitalWrite(TyreRUp, 1);
digitalWrite(BagLDwn, 1);
digitalWrite(BagRDwn, 1);
digitalWrite(TyreFDwn, 1);
digitalWrite(TyreRDwn, 1);
digitalWrite(CompTrigger, 0);

// Startup
Serial.println("Startup");
delay(500);
}


void loop() {
// Serial Read
if(NextSerial.available()){
String dfd="";
delay(100);
while(NextSerial.available()){
dfd+= char(NextSerial.read()); 
}
// Delete Unwanted Serial
//if(dfd.length()<5) dfd="";
//if(dfd.length()>10) dfd="";
Serial.println(dfd);
    
//Tyre Page
// Tyre Button Enable and Disable
if(dfd.substring(0,8) == "TYRBTNST"){
TYRBTNST = (dfd.substring(8,9).toInt());
Serial.print("Tyre State ");
Serial.println(dfd.substring(8,9).toInt());
} // End Tyre Button Enable & Disable 

//Home Page
// Compressor Button Enable and Disable
if(dfd.substring(0,8) == "COMBTNST"){
// Normally Turns LED ON But not while using serial2 digitalWrite(LED_BUILTIN,dfd.substring(8,9).toInt());
COMBTNST = (dfd.substring(8,9).toInt());
Serial.print("Compressor State ");
Serial.println(dfd.substring(8,9).toInt());
digitalWrite(CompTrigger,dfd.substring(8,9).toInt());
} // End Compressor Enable & Disable

//Bag Control Page
// Left Bag Arrows
// Left Bag Up
if(dfd.substring(0,6) == "BagLUp"){
digitalWrite(BagLUp,dfd.substring(6,7).toInt());
Serial.print("LeftBagUp ");
Serial.println(dfd.substring(6,7).toInt());
} // End Right Up

// Left Bag Down
if(dfd.substring(0,7) == "BagLDwn"){
digitalWrite(BagLDwn,dfd.substring(7,8).toInt());
Serial.print("LeftBagDown ");
Serial.println(dfd.substring(7,8).toInt());
} //End Right Down

// Right Bag Arrows
// Right Bag Up
if(dfd.substring(0,6) == "BagRUp"){
digitalWrite(BagRUp,dfd.substring(6,7).toInt());
Serial.print("RightBagUp ");
Serial.println(dfd.substring(6,7).toInt());
} // End Right Up

// Right Bag Down
if(dfd.substring(0,7) == "BagRDwn"){
digitalWrite(BagRDwn,dfd.substring(7,8).toInt());
Serial.print("RightBagDown ");
Serial.println(dfd.substring(7,8).toInt());
} //End Right Down

// Both Bags
// Both Up
if(dfd.substring(0,6) == "BagsUp"){
digitalWrite(BagLUp,dfd.substring(6,7).toInt());
digitalWrite(BagRUp,dfd.substring(6,7).toInt());
Serial.print("BothBagsUp ");
Serial.println(dfd.substring(6,7).toInt());
} // End bags up

// Both Down
if(dfd.substring(0,7) == "BagsDwn"){
digitalWrite(BagLDwn,dfd.substring(7,8).toInt());
digitalWrite(BagRDwn,dfd.substring(7,8).toInt());
Serial.print("BothBagsDwn ");
Serial.println(dfd.substring(7,8).toInt());
} // End bags down

}// end serial read

//Read Sensor values
// Tank Pressure
TankPress = map(analogRead(SNSTank), 101, 922, 0, 200);

//Tyre Pressures
LineFrontPress = map(analogRead(SNSTyreFront), 101, 922, 0, 200);
LineRearPress = map(analogRead(SNSTyreRear), 101, 922, 0, 200);

// Bag Pressures
BagLPress = map(analogRead(SNSBagL), 101, 922, 0, 200);
BagRPress = map(analogRead(SNSBagR), 101, 922, 0, 200);

// Send Tank Info
//NextSerial.println(String("HomePage.TankPress.val=") + String(TankPress));
//NextSerial.print(endChar);

// Send Bag Info Home Page
NextSerial.print(String("HomePage.LeftBagPress.val=") + String(BagLPress));
NextSerial.write(0xff);
NextSerial.write(0xff);
NextSerial.write(0xff);


// NextSerial.print(String("HomePage.RightBagPress.val=") + String(BagRPress));
// NextSerial.write(0xff);
// NextSerial.write(0xff);
// NextSerial.write(0xff);

// Send Bag Info Airbag COntrol Page
// NextSerial.print(String("AirbagControl.LeftBagPress.val=") + String(BagLPress));
// NextSerial.write(0xff);
// NextSerial.write(0xff);
//NextSerial.write(0xff);

//NextSerial.print(String("AirbagControl.RightBagPress.val=") + String(BagRPress));
//NextSerial.write(0xff);
//NextSerial.write(0xff);
//NextSerial.write(0xff);

Here you can see the 2 different serial monitor outputs.
The first is when the arduino is sending the updated value to nextion

`// Send Bag Info Home Page
NextSerial.print(String("HomePage.LeftBagPress.val=") + String(BagLPress));
NextSerial.write(0xff);
NextSerial.write(0xff);
NextSerial.write(0xff);` 

Nextion error

The second is with this commented out and a single button push both time to show the difference in serial data

// Send Bag Info Home Page
//NextSerial.print(String("HomePage.LeftBagPress.val=") + String(BagLPress));
//NextSerial.write(0xff);
//NextSerial.write(0xff);
//NextSerial.write(0xff);

Nextion No error

I posted the same question about 13 hours ago. lol

Try a 470uF cap across the display as suggested here: Using Nextion displays with Arduino

The cap across the display does not help eliminate the garbage being sent by the display. I did find that the display works perfectly when connecting the display to the computer with an FTDI programmer and running it with the Nextion Software in debug mode.

So the cap on the display didn't help the issue?

I just dont understand why it only throws out random data when its receiving data as when its not receiving data then everything works flawlessly that's why i assumed it must be something i'm doing wrong in code

The cap is for smoothing the unstable 5V coming from the arduino. Still a good idea when powering the display from another power source.

I did fix my issue when I took my code back to the display only without any other inputs.

Yeah i just don't get why its receiving serial garbage when i send it serial but other than that it works flawlessly so the nextion sends perfect serial as expected when it doesnt receive any serial but as soon as a line of serial is sent all hell breaks loose so surely its something in my coding i don't know ill have to investigate i guess

Try this:

if (NextSerial.available() > 0) {

}

This checks if something has been sent.

The capacitor is not intended to stop the display sending garbage over serial, it is intended to reduce the horrible amount of electrical noise the display injects into the power supply. As noted in my tutorial that noise was interfering with a GPS receiver I had on my bench at the same time.

This is wrong as you have an extra 'f' in each character, it should be 0xff. That said I don't see where in your code you use it.

Your code for receiving data from the Nextion has no start or end markers to show where the data starts and / or ends. Nextion use 0xff 0xff 0xff as an end marker and I use 0xa5 as a start marker for data sent from the Nextion to the Arduino. You seem to be relying on timing to do this, you are going to struggle with that approach. See Serial Input Basics - updated for an excellent account of how to do serial data transfer properly. The tutorial is not Nextion specific but the principals it explains are applicable to serial data transfer generally.

I never use Strings (upper case S), only c-strings AKA char arrays. There is a lot of discussion on here about whether or not Strings are safe on microcontrollers. Personally I just stay away from them. As for your code your use of them makes it harder for me to understand.

You've written everything inside the loop function. The is a terrible way to write anything but the simplest code. I suggest you learn to use functions to break your code into manageable chunks. Using functions makes it easier to read and easier to debug. All my sample code is broken down into functions.

If you are getting unexpected data back from a Nextion it is probably the return codes, which indicate that the Nextion is not happy with something you've sent it. See here for more about this: Instruction Set – Nextion

The following code is intended for a Nano Every and receives Nextion data up to the 0xff 0xff 0xff end marker and sends it to the serial monitor. Connect Rx1 of a Nano Every to the data you want to monitor, don't forget the ground. Best to use a 1k resistor in series with the data to stop phantom powering in the event all devices are not powered at the same time.

// Receives data on serial port 1 up to 0xff 0xff 0xff Nextion end marker
// Sends to serial monitor
// Intended for boards with at least 1 spare serial port

const uint16_t bufferSize = 256;
char DataRx[bufferSize];
uint16_t DataIndex = 0;
bool dataReady = false;
bool overflow = false;

const uint16_t baudDefault = 9600;
const uint16_t baudHeating = 57600;
const uint16_t baudHeatingNextion = 38400;

void setup() {
  char fileName[] = __FILE__;
  Serial.begin(115200);
  Serial.println("Serial monitor started");
  //Serial1.begin(baudDefault);
  //Serial1.begin(baudHeating);
  Serial1.begin(baudHeatingNextion); // Use the correct Baud rate for the data you are monitoring, change as required.
  Serial.println("Serial 1 started");
  Serial.println(sizeof(fileName));
  Serial.println(fileName);
  pinMode(13, OUTPUT);
}

void loop() {
  RxData();
  PrintData();
  runLED();
}

void RxData() {
    char RxTemp;
    static uint8_t charCount = 0;
    static uint8_t FFcount = 0;
    while (Serial1.available() > 0) {
        RxTemp = Serial1.read();

        //if ((uint8_t)RxTemp != 0xa5) {
        
        if ((uint8_t)RxTemp != 0xff) {
            DataRx[DataIndex] = RxTemp;
            ++DataIndex;
            if (DataIndex >= bufferSize) {
                DataRx[bufferSize - 1] = 0x00;
                DataIndex = 0;
                dataReady = true;
                overflow = true;
            }
        } else {
            ++FFcount;
            if (FFcount >= 3) {
                FFcount = 0;
                DataRx[DataIndex] = 0x00;
                DataIndex = 0;
                dataReady = true;
            }
        }
    }
}

void PrintData() {
  if (dataReady) {
    dataReady = false;
    if (overflow) {
      overflow = false;
      Serial.print("Buffer overflow: ");
    }
    Serial.println(DataRx);
  }
}

void runLED() {
  uint32_t currentMillis = millis();
  static uint32_t lastMillis;
  const uint32_t interval = 500;
  if (currentMillis - lastMillis >= interval) {
    lastMillis += interval;
    digitalWrite(13, !(digitalRead(13)));
  }
}

Thanks for the response!

Firstly i know writing in the loop isnt the greatest but it is also the simplest for me personally when i start a project thats how i do it as its easier layed out for me. Without understanding the nextion working etc then this would be a little more hard to follow so i completely understand that.

Basically the only parts of info currently that have anything to do with the issues i get are the following which are causing issues which is why im not understanding as i have read of many others sending just this simple code to the nextion and getting no weird results but as mentioned it may be something to do with the if (NextSerial.available() > 0) { }

the top string function was a start at making the code neater so hadn't been implemented so thanks for pointing that out but yes hasn't been used as of yet.

i haven't done any starter markers or end markers but rather the arduino would look for certain length strings and if the string was of certain size and the substring started with certain characters then it would follow that and do something with it it all works flawlessly.

But the only issue in all this code is when i simply add the last line and try and update the nextion value

basically sending the following gives garbage out of the nextion

NextSerial.print(String("HomePage.LeftBagPress.val=") + String(BagLPress));
NextSerial.write(0xff);
NextSerial.write(0xff);
NextSerial.write(0xff);

But im not overly sure why as that to me seems like the correct command to send and it all works on the nextion also so the nextion number called LeftBagPress on the homepage changes its value correctly when sending that code and it changes it many many times a second correctly so its working on the nextion but obviously there is something i am missing with that alone.

That's where i think i need to start what would you replace that section of code with im just not overly sure how else that should be written as it seems that is the main issue as commenting it out everything else works flawlessly but it only starts to play up when sending data from arduino to nextion in that way

I don't know the answer to your question.

I think you need to be very sure that what you are sending is what you think you are sending, and that it is exactly what the Nextion is expecting. If you send as much as 1 character that it doesn't like it will reply with one of the return codes. You need to know what it is sending back and see if it matches one of the codes they list. If it does then that's big clue.

You have included HomePage in what you sent, is that page on the display when you send the data? If not then it will be out of scope and I would assume it will reject it. I have always been very careful to know which page I am on and only ever send data relevant to that page. There is no need to include HomePage, just use:

LeftBagPress.val=

When I first started using Nextion displays I made a lot of use of a serial adaptor on my laptop to monitor the data with PuTTY to see if what I thought I was sending was what was actually being sent (often it wasn't). At the time I was still on a steep learning curve for C and using PIC micro controllers, so didn't have access to Arduino's serial monitor. Since then I bought a load of Nano Everys and use them to monitor serial data for all sorts of things, just take in the data on Serial1 and send it to the serial monitor. Do this and you get surprises when the data is not what you expected. I also built my own mini serial monitor, see Share tips you have come across - #1125 by PerryBebbington

Sure, but now you are bumping up against the limits of doing that. It's a lot easier to debug when code is in nice chunks called 'functions'. You can remove whole blocks to see if removing them makes a difference just by putting // in front of where you call the function. Please, now is the time to put some effort into learning to split your code into functions. The only code in your loop functions should be calls to other functions.

Yes it is called Home.Page and it functions as it updates the value as intended so it is working even though the nextion is spitting something back out and the reason i did it that way so that it won't receive errors when on other pages although i could over complicate it and make the arduino know what page it is on and then stop sending outputs when on those pages etc but it seemed a lot more simple to target the page and value it is on rather than try and make the arduino stop sending certain data when on other pages etc.

I will see what i can do and even completely start again with new code for a basic serial communcation of just sending and receiving data back and forth and see what fixes it but at the moment im at a loss hence why i asked what is wrong with that send command as nothing else in the loop really has anything to do with it so its just those for lines for some reason even though they work flawlessly on updating the values on the nextion display which is why im not overly sure what the issue is as if it didn't like it then i would assume it wouldn't update the value im telling it it but ill keep trying

Thanks anyway

Suggestion for structuring code into separate modules. USE TABS and comment out your test code. (I'm assuming you're using the Windows IDE).
When you write a function, put it in a separate tab. Write a separate setup() and loop(), and add any global data that it might reference. Include Serial begin, and use Serial Monitor to debug your code.
Use this arrangement to create and test your function. When it's ready, and you KNOW it does what is needed, then with a simple set of /**/, you make the main, setup, and data 'disappear' (they become comments), and your function is ready to be used in your program. Any time you have to modify the function, you remove the two comment markers, make your changes and test them, then restore the comments and go back to work on your program.
This will obviously not work in all circumstances, and I'm sure there will be plenty of pontification from some about it being a poor practice, and they'll also go on about all the ways it won't work in some esoteric circumstances, but for a newbie just getting into the game, it's comprehensible, and simple.
This approach will also encourage you to localize your data, so that the function is less coupled to the rest of the program, which is a good thing.

I did have tabs in there and everything organised neatly and layed out and was commenting out full sections as you just suggested but I read someone else had an issue and they deleted tabs and it worked so I went through and deleted every tab as a trial haha didn't solve it so then I just quickly commented out the few lines and it worked so then posted here that's as far as I got with it haha

I guess that's a form of regression?

So just a little update.... After hours of re-coding everything swapping to char arrays and trying many different things it still functioned the exact same worked fine when not sending commands but complete garbage as soon as commands were sent to the nextion. So I decided to pop into the nextion editor and connect up the arduino through the port there.... switched out the soft serial to the standalone serial and it all worked flawlessly both sending and receiving code.

I then desoldered the wires on pins on 11 and 12 of the arduino ( that was linked to rx tx for the nextion display) and connected them to the standard serial pins 0 and1 and bang, worked instantly so i am assuming something is wrong with pins 11 and 12 or at least one of them on my arduino.... but finally not pulling my hair out as much at least anyway

1 Like

There are many suggestions here on the forum that softserial is problematic above 9600 baud, so it wouldn't surprise me if that was at the root of your problem. Anyway, congrats, it's solved and you're on your way!

the weird thing was is i was only using 9600 baud nothing changed in any part of the code or serial setup other than for all commands it was Serial2 and now its just Serial other than that all completely the same and it works perfectly with no missed data no errors or anything haha so werid haha.

Im not sure if there is an issue with pins 11 and 12 for rx and tx ( similar to pin 13 being builtinled) so maybe something there is the issue that i wasn't aware of but yeah making the serial the standard pins 0 and 1 and it works like a charm haha

I see. I had noted your initial 9600, but thought the higher baud rate in Perry's suggestion might have crossed you up.
Anyway, it's just a caution. I consider software serial to be a hazard for those beginning to work with Arduino, as the nuances of it's limitations often aren't even comprehensible at beginner coding skills. You're clearly not there, but it can still be a trap.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.