Help with Nextion Display for college student

Is there anyone on here competent enough to tutor a college student on interfacing Nextion to Arduino Mega?

I need two buttons, a gauge, three timers, and a fault screen. I do not think it should be as complicated as I am trying to make it. I already have my arduino code working and an HMI screen made as well as all components working. Just need help getting started with the communications between the two.

Will post all code if there is anyone willing to help.

Thank you all. This forum is a life savor.

Your topic has been moved to a more suitable location on the forum. Introductory Tutorials is for tutorials that e.g. you write, not for questions. Feel free to write a tutorial once you have solved your problem :wink:

If you follow the methods I demonstrate in that tutorial I will help you if you get stuck. Note that for my code to work properly the rest of your code must be non blocking.

Forgive my ignorance, I come from PLC's and Automation. What is it that you mean my non blocking?

The processor can only do one thing at a time, so if you want multiple things to (appear to) happen at the same time you have to write code that does a tiny bit of each thing at a time then moves on to the next thing. All my code is written this way so if you study any of my code you see examples of it. The most common example on this forum of blocking code is delay(), if you write delay(1000) then for 1 second nothing else can happen, your program sits there doing nothing useful. Use of delay comes up frequently as it is, perhaps, the most often made mistake by beginners. Delay() is insidious because people put, for example, delay(10) and nothing bad happens because 10ms of nothing happening doesn't usually cause a problem in most programs. However, more and longer delays eventually lead to questions like 'my program is not very responsive, why is this?'. By the time someone asks this they have written something long and complicated and they will probably have to start again. Read the questions and answers in the programming section of the forum, read any of my example code in my tutorials and read:

Using millis for timing
Demonstration for several things at the same time
Finite state machine tutorial

I've never used a PLC but from the little bits I've read about them I think the problem of non-blocking code is addressed in the PLC firmware so you don't see it in ladder logic. The problem is still there, it's just been taken care of for you by the designers of the PLC.

Agreed! I sure do miss my ladder logic and will never take it for granted again. The interface between a specific PLC and its HMI counter part is so simple. As long as they are connected, all I have to to do is call the variable and boom! Its done. For example, one of the simpler things I am trying to do here is simply display a analog value from my Arduino. Now I already have that value being serially printed through the serial monitor but I am struggling to get started on displaying that same value in a number box with my Nextion. I have read your code and many others but I am struggling at understanding the commands.

Sadly, I have used delays. I did a debounce sequence with millis() but have not got to doing it with my relays start ups. The relays control 10 different motors and starting all 10 simultaneously will result in the Nextion going dark for a moment so I delayed each by 500mS. My intentions is to go back once I get the HMI working and fix it, but time is my enemy at the moment with graduation only seven weeks away and I am not even sure if I am calling out the communications correct. I am unsure which nextion library I am supposed to use. I do have a full on HMI design that is functioning as well as my arduino code that if working for all attached hardware. I just need the two to connect now.

Thank you for your time.

Don't.
Number boxes are a waste of time.
Use a text box and send the number as text, there are plenty of examples in my demonstration code.

I do not use any Nextion library, the official one no one seems to like. I wrote my own methods around the Nextion instruction set. By 'supposed to use' are you saying your teachers / lecturers / whatever you call them insist on a library?

#include <EasyNextionLibrary.h>
#include <trigger.h>
#include "Nextion.h"
#include <Bounce2.h>

NexButton b4 = NexButton(0, 6, "b4"); // ALL ON
NexButton b5 = NexButton(0, 7, "b5"); // ALL OFF



//Digital Inputs
const int Air_Pressure_OK = 22;
const int Coarse_Sys_Button = 24;
const int Mill_Sys_Button = 25;
const int Mold_Sys_Button = 26;
const int Auger_Switch = 27;
const int Coarse_Half_Limit = 28;
const int Coarse_Full_Limit = 29;
const int Powder_Full_Limit = 30;

//Analog In
const int Current_Sensor_Read = A15;
int Sensitivity = 188;
int Current_Read_Value = 0;
int offsetVoltage = 25000;
double ReadVoltage = 0;
double RealCurrent = 0;

//Digital Outputs
const int Alarm_Strobe = 42;
const int Pulsers_On_LED = 43;
const int Coarse_Blower_Relay = 44;
const int Coarse_Al_Relay = 45;              //Al is air lock//
const int Transfer_Blower_Relay = 46;
const int Millshop_Blower_Relay = 47;
const int Millshop_Al_Relay = 48;
const int Molder_Blower_Relay = 49;
const int Molder_Al_Relay = 50;
const int Coarse_Powder_Al = 51;
const int Coarse_Top_Al = 52;
const int Auger_Relay = 53;



Bounce myInputPin1 = Bounce();
Bounce myInputPin2 = Bounce();
Bounce myInputPin3 = Bounce();

//Pin State

byte Coarse_Button_State = LOW;
boolean offDelayTimer_1 = false;

byte Mill_Button_State = LOW;
boolean offDelayTimer_2 = false;

byte Mold_Button_State = LOW;
boolean offDelayTimer_3 = false;

//Times
unsigned long lastDebounce_1;
unsigned long debounceDelay_1 = 5000;
unsigned long lastDebounce_2;
unsigned long debounceDelay_2 = 5000;
unsigned long lastDebounce_3;
unsigned long debounceDelay_3 = 5000;

void setup()
{
  Serial.begin(9600);

  //Set Pin IO
  pinMode(Air_Pressure_OK, INPUT_PULLUP);   
  pinMode(Coarse_Sys_Button, INPUT_PULLUP);  
  pinMode(Mill_Sys_Button, INPUT_PULLUP);   
  pinMode(Mold_Sys_Button, INPUT_PULLUP);   
  pinMode(Auger_Switch, INPUT_PULLUP);
  pinMode(Coarse_Half_Limit, INPUT_PULLUP);
  pinMode(Coarse_Full_Limit, INPUT_PULLUP);
  pinMode(Powder_Full_Limit, INPUT_PULLUP);
  pinMode(Current_Sensor_Read, INPUT);

  myInputPin1.attach(Coarse_Sys_Button);
  myInputPin1.interval(50);
  myInputPin2.attach(Mill_Sys_Button);
  myInputPin2.interval(50);
  myInputPin3.attach(Mold_Sys_Button);
  myInputPin3.interval(50);

  pinMode(Alarm_Strobe, OUTPUT);
  pinMode(Pulsers_On_LED, OUTPUT);
  pinMode(Coarse_Blower_Relay, OUTPUT);
  pinMode(Coarse_Al_Relay, OUTPUT);
  pinMode(Transfer_Blower_Relay, OUTPUT);
  pinMode(Millshop_Blower_Relay, OUTPUT);
  pinMode(Millshop_Al_Relay, OUTPUT);
  pinMode(Molder_Blower_Relay, OUTPUT);
  pinMode(Molder_Al_Relay, OUTPUT);
  pinMode(Coarse_Powder_Al, OUTPUT);
  pinMode(Coarse_Top_Al, OUTPUT);
  pinMode(Auger_Relay, OUTPUT);

  //Set Pin Status
  digitalWrite(Alarm_Strobe, HIGH);
  digitalWrite(Pulsers_On_LED, HIGH);
  digitalWrite(Coarse_Blower_Relay, HIGH);
  digitalWrite(Coarse_Al_Relay, HIGH);
  digitalWrite(Transfer_Blower_Relay, HIGH);
  digitalWrite(Millshop_Blower_Relay, HIGH);
  digitalWrite(Millshop_Al_Relay, HIGH);
  digitalWrite(Molder_Blower_Relay, HIGH);
  digitalWrite(Molder_Al_Relay, HIGH);
  digitalWrite(Coarse_Powder_Al, HIGH);
  digitalWrite(Coarse_Top_Al, HIGH);
  digitalWrite(Auger_Relay, HIGH);
}

void loop()
{
  
  myInputPin1.update();
  myInputPin2.update();
  myInputPin3.update();

  if (myInputPin1.fell() && Coarse_Button_State == LOW )
  {
    
    digitalWrite(Coarse_Blower_Relay, LOW );//instant turn on
    delay(500);
    digitalWrite(Coarse_Al_Relay, LOW );
    delay(500);
    digitalWrite(Transfer_Blower_Relay, LOW );
    delay(500);
    digitalWrite(Coarse_Powder_Al, LOW );
    delay(500);
    digitalWrite(Coarse_Top_Al, LOW );
    
    Coarse_Button_State = HIGH;
    Serial.println("Coarse_On");
  }

  else if (myInputPin1.fell()  && Coarse_Button_State == HIGH)
  {
    
    offDelayTimer_1 = true;
    lastDebounce_1 = millis();
  }

  if (offDelayTimer_1)
  {

    if (millis() - lastDebounce_1 >= debounceDelay_1)
    {
      
      digitalWrite(Coarse_Blower_Relay, HIGH );//delay turn off
      digitalWrite(Coarse_Al_Relay, HIGH );
      Coarse_Button_State = LOW;
      Serial.println("Coarse_Off");
      offDelayTimer_1 = false;
      if(Mold_Button_State == LOW && Mill_Button_State == LOW)
      {
          digitalWrite(Transfer_Blower_Relay, HIGH );
          digitalWrite(Coarse_Powder_Al, HIGH );
          digitalWrite(Coarse_Top_Al, HIGH );
      }
      
      
    }

  }
  
  if (myInputPin2.fell() && Mill_Button_State == LOW )
  {
    
    digitalWrite(Millshop_Blower_Relay, LOW );//instant turn on
    delay(500);
    digitalWrite(Millshop_Al_Relay, LOW );
    delay(500);
    digitalWrite(Transfer_Blower_Relay, LOW );
    delay(500);
    digitalWrite(Coarse_Powder_Al,LOW );
    delay(500);
    digitalWrite(Coarse_Top_Al, LOW );
    
    Mill_Button_State = HIGH;
    Serial.println("MillShop_On");
  }

  else if (myInputPin2.fell()  && Mill_Button_State == HIGH)
  {
    
    offDelayTimer_2 = true;
    lastDebounce_2 = millis();
  }

  if (offDelayTimer_2)
  {

    if (millis() - lastDebounce_2 >= debounceDelay_2)
    {
      
      digitalWrite(Millshop_Blower_Relay, HIGH );//delay turn off
      digitalWrite(Millshop_Al_Relay, HIGH );
      if(Coarse_Button_State == LOW && Mold_Button_State == LOW)
      {
          digitalWrite(Transfer_Blower_Relay, HIGH );
          digitalWrite(Coarse_Powder_Al, HIGH );
          digitalWrite(Coarse_Top_Al, HIGH );
      }
      
      Mill_Button_State = LOW;
      Serial.println("MillShop_Off");
      offDelayTimer_2 = false;
    }
  }

  if (myInputPin3.fell() && Mold_Button_State == LOW )
  {
    
    digitalWrite(Molder_Blower_Relay, LOW );//instant turn on
    delay(500);
    digitalWrite(Molder_Al_Relay, LOW );
    delay(500);
    digitalWrite(Transfer_Blower_Relay, LOW );
    delay(500);
    digitalWrite(Coarse_Powder_Al, LOW );
    delay(500);
    digitalWrite(Coarse_Top_Al, LOW );
    
    Mold_Button_State = HIGH;
    Serial.println("Molder_On");
  }

  else if (myInputPin3.fell()  && Mold_Button_State == HIGH)
  {
    
    offDelayTimer_3 = true;
    lastDebounce_3 = millis();
  }

  if (offDelayTimer_3)
  {

    if (millis() - lastDebounce_3 >= debounceDelay_3)
    {
      
      digitalWrite(Molder_Blower_Relay, HIGH );//delay turn off
      digitalWrite(Molder_Al_Relay, HIGH );
      if(Coarse_Button_State == LOW && Mill_Button_State == LOW)
      {
          digitalWrite(Transfer_Blower_Relay, HIGH );
          digitalWrite(Coarse_Powder_Al, HIGH );
          digitalWrite(Coarse_Top_Al, HIGH );
      }
     
      Mold_Button_State = LOW;
      Serial.println("Molder_Off");
      offDelayTimer_3 = false;
    }
  }
       
  if  (digitalRead(Coarse_Half_Limit)== LOW or digitalRead(Auger_Switch)== LOW)
  {
    digitalWrite(Auger_Relay, LOW);
  }
    
  else{
    digitalWrite(Auger_Relay, HIGH);
  }

  if (digitalRead(Coarse_Full_Limit)==LOW or digitalRead(Powder_Full_Limit) == LOW)
  {
    digitalWrite(Alarm_Strobe, LOW);
  }
  else{
    digitalWrite(Alarm_Strobe, HIGH);
  }
  if (digitalRead(Air_Pressure_OK) == LOW)
  {
    digitalWrite(Pulsers_On_LED, LOW);
  }
  else{
    digitalWrite(Pulsers_On_LED, HIGH);
  }
  
  Current_Read_Value = analogRead(Current_Sensor_Read);
  ReadVoltage = (Current_Read_Value)*50000/1024;
  RealCurrent = ((offsetVoltage - ReadVoltage)/Sensitivity);
  delay(1000);
  if(digitalRead(Auger_Relay) == LOW){
   Serial.print(" Current Reading ");
   Serial.print(RealCurrent); 
   Serial.print(" mA");
   Serial.println();
    
  }
  
  
}

NexButton b4 = NexButton(0, 6, "b4"); // ALL ON
I want this button to change the state of all buttons to true.
NexButton b5 = NexButton(0, 7, "b5"); // ALL OFF
I want this button to change the state of all buttons to false, this way the selected timers will be carried out.
I have a physical button for an E-Stop that is tied to the reset pin, but that one does not follow the timer off.

I have number boxes with global numeric pads set to them that I want to adjust these values,

//Times
unsigned long lastDebounce_1;
unsigned long debounceDelay_1 = 5000;
unsigned long lastDebounce_2;
unsigned long debounceDelay_2 = 5000;
unsigned long lastDebounce_3;
unsigned long debounceDelay_3 = 5000;

I have number boxes that I want to simply display this value.
Serial.print(RealCurrent);

And finally, I want to be able to send alarms in certain scenarios.

Now, I am obviously NOT ASKING ANYONE TO DO THIS FOR ME! Just need some help getting started.

Thank you for your help!

Those are 2 different libraries, your choice is:

The official Nextion library, in which case use Nextion.h. I have yet to see anyone on this forum say it's good, mostly they complain how bad it is, and I've yet to see anyone offer any help with it. I certainly can't help you with it.

@Seithan's Easy Nextion Library, I've see a lot of good comments about that and if you can find Seithan he's pretty helpful. However I've not seen him here recently. Seithan if you see this please wave or something. If you want to use it then include EasyNextionLibrary.h

My methods, for which you do not need any library but you do need to understand how my code works. If you use my methods I'll help if you get stuck. Note however that other commitments mean I am not always available in the week.

If only all students thought that way! We get lots of questions from students who clearly don't have a clue and however much they dress it up what they really mean is 'please do my homework for me'. Those generally get rude comments and no help.

OK, your code is not very long. Please consider:

Breaking it into functions, the only thing in loop() should be calls to functions.
Get rid of all delays, you cannot have multiple half second delays and expect other stuff to work. You have places where almost nothing happens for 2 seconds, that kills any program. You need to understand how to do that in non-blocking form using millis().

NO sir! Not me! I bought and paid for this HMI with my own money, and the beauty of coding is my imagination is the limit. That is why I have my own shop set up. I love prototyping. I have some ideas to repurpose this after my project is done for some home items. That means that I need to know how to do it. I grow so tired of the "Just do it this way" or the "That is how it has always been done". I want to know why and how.

** Side note, those who have others do for them, eventually will be caught when they do not know how to do it.**

Anyways, So I am not required to use any library. I was just hoping to minimalize code. More lines equals more debugging. But if I do not need them I will gladly delete. If you seen my picture, for the values, I used number boxes for the values and text boxes for the labels. Should I still use two separate boxes? Just switch the other to a text box, or can I get away with just one text box, and set the label and the value from the arduino?

I understand how to, that was a on the fly adjustment. I have a separate power supply coming, that way the motors will not blank my screen off due to the inrush current of the motors. Technically speaking, up to 5 motors need to turn on simultaneously each time, at which point, there will be no delay.

image
Every Time I try to open your example, this pops up.

Yes, and often they get told that! They don't get very far here.

You need two boxes, one for the label and one for the actual values. Well, OK that's not strictly true but keep it simple for now. You could have one box and send the label along with whatever it is you want to display.

Do you mean 2021-07-03 Arduino Nextion demo 43.HMI ?

I have downloaded from this forum (rather than use my original copy) and it opens OK in the Nextion editor. Have you removed it from the zip file first?

Sorry, did not extract it. Works like a charm.

1 Like

In my tutorial, in reply #4, there is an additional features section. In there I have a basic calculator, the way I have done it might be relevant to you as I note you have a keyboard in your Nextion. Note I constructed the keypad from individual buttons.

So I used the internal keyboard attached to the text box simply because the user will only be putting in a number. That number will replace these numbers:

unsigned long debounceDelay_1 = 5000;

unsigned long debounceDelay_2 = 5000;

unsigned long debounceDelay_3 = 5000;

This will allow for the user to change the delays as seen fit for powering down the individual sections.

So starting from the beginning of your code,

you start with enum and list the pages. I am taking it as that is the global scope for those pages so that they may be called out anywhere from there on out?

Yes, global scope makes variables accessible anywhere.

I infer from your question that you are a beginner in C/C++, am I correct?