How to store value entered on Nextion Number field, then display that value on the same field after power down

Hello people!

I am using a Mega 2560 Arduino. It is powered with a regulated 5V power supply and not via USB.

I have a Nextion display with this page:
PID

I'm using the EasyNextionLibrary for Nextion and have set up the buttons with triggers.
It's basically a PID controller, PV (n1 field in Red) displays value in real time of a temperature sensor.
SP (n3 field in Green) is the desired set temperature that turns ON or OFF a heater.

The EEPROM only get updated if the b21 SET button is pressed.

When you touch the n3 field, a numeric keypad opens where you enter your desired set value temperature. Now, I want this n3 value to be stored on the EEPROM so that it is saved and displayed on this field on boot-up.

I have the following sketch that stores the n3 value on the EEPROM, this work as I can serial.print this value to confirm that it has been saved.


#include "EasyNextionLibrary.h"  // Include EasyNextionLibrary
#include <EEPROM.h>
#include <Thermocouple.h>
#include <MAX6675_Thermocouple.h>
#include <SmoothThermocouple.h>
#define SCK_PIN 3
#define CS_PIN 4
#define SO_PIN 5
/**
  Smoothing factor of a temperature value.
*/
#define SMOOTHING_FACTOR 5
Thermocouple* thermocouple = NULL;

EasyNex myNex(Serial1);  // Create an object of EasyNex class with the name < myNex >
                         // Set as parameter the Hardware Serial you are going to use

/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int address16 = 16;
byte value16; // Value stored for PID variable


void setup() {
  myNex.begin(115200);   // Nextion Display begin the object with a baud rate of 115200
  Serial.begin(115200);  // Use to see commands on the Serial Monitor

  Thermocouple* originThermocouple = new MAX6675_Thermocouple(SCK_PIN, CS_PIN, SO_PIN);
  thermocouple = new SmoothThermocouple(originThermocouple, SMOOTHING_FACTOR);
  
  value16 = EEPROM.read(address16);
  int PID = value16;
  myNex.writeNum("n3.val", PID); 
}


void loop() {
  myNex.NextionListen();  // This function must be called repeatedly to response touch events
  delay(300);

   // Reads temperature
  const double celsius = thermocouple->readCelsius();
  // Output Temperature on Nextion n1 text field
  myNex.writeNum("n1.val", celsius); 
        
 Serial.println(value16); // Diplays EEPROM value16

}


 // PID Buttons Page 1

void trigger10() {
    /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0A
   * Every time the button is pressed, the trigger10() function will run
   * and the code inside will be executed once
   */
  int PID; // What is stored on Value16 and displayed on n3
  PID = myNex.readNumber("n3.val");   // Store to PIDTemp the value of text box n3;
  int val16 = PID; 
  EEPROM.update(address16, val16);
  delay(10);
  value16 = EEPROM.read(address16);
  PID = value16;
  myNex.writeNum("n3.val", PID); 
}

void trigger11() {
    /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0B
   * Every time the button is pressed, the trigger11() function will run
   * and the code inside will be executed once
   */
  Serial.println("Clear button pressed");
}

void trigger12() {
    /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0C
   * Every time the button is pressed, the trigger12() function will run
   * and the code inside will be executed once
   */
  Serial.println("Down button pressed");
  //myNex.writeNum("n3.val") +1;
}

void trigger13() {
    /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0D
   * Every time the button is pressed, the trigger13() function will run
   * and the code inside will be executed once
   */
  Serial.println("Up button pressed");
  //myNex.writeNum("n3.val") -1;
   
}

The problem is that if I cut the 5V power and turn power back on, the saved value is only redisplayed on the n3 field when I plug back the USB while Arduino IDE with the sketch is open.

Can anyone help me fix this so that the EEPROM value gets display on the n3 field after boot-up?

Also, I'd like the UP button (b24) to increase the value that is displayed on n3 field by 1 every time it is triggered (void trigger13) and the DOWN button (b23) to decrease the value that is displayed on n3 field by 1 every time it is triggered (void trigger12).

Cheers,

byte value16;  // Value stored for PID variable
    int PID;                           // What is stored on Value16 and displayed on n3
    PID = myNex.readNumber("n3.val");  // Store to PIDTemp the value of text box n3;
    int val16 = PID;
    EEPROM.update(address16, val16);
    delay(10);
    value16 = EEPROM.read(address16);
    PID = value16;

value16 is a single byte variable but val16 is a multibyte int variable, as is PID
I would suggest that you make them all the same type of variable to ensure that you know that the data is stored and read correctly as a first step

So how do I do that, I'm a newbie...
Do I have to change

byte value16;  // Value stored for PID variable

to something else?

Thanks

I suggest that you declare the variables as int and use EEPROM.get() to read back the variable from EEPROM

That may not be your main problem but it should be fixed

Ok changed

byte value16; // Value stored for PID variable

to

int value16; // Value stored for PID variable

The values of the variables are below 255, any advantages in using EEPROM.get() vs EEPROM.read() ?

I don't know how to use EEPROM.get() ???

EEPROM.read() reads a single byte so you cannot read an int fron EEPROM using this function

EEPROM.get() reads a variable of any type and automatically reads the correct number of bytes needed and puts them into the variable in the correct order

See https://docs.arduino.cc/learn/built-in-libraries/eeprom/

Ok, can I use EEPROM.get if I use EEPROM.update?

The original functions were EEPROM.read() and EEPROM.write(), each of which operate on a single byte and can be used for single byte variables such as byte and char

The EEPROM library was subsequently enhanced and EEPROM.get(), EEPROM.put() and EEPROM.update() were added. Each of them operate on a variable of any type. EEPROM.update() only writes bytes that have changed, thus saving wear on the EEPROM as it can only be used safely for about 100,000 writes to each location.

The get() and put() functions themselves call update() so also save on wear on the EEPROM. I suggest that you use get() and put() for all EEPROM access

Ok I changed the sketch to use EEPROM.put and EEPROM.get instead, but I have the same behavior when cutting power, I only get the value if I plug back the USB cable...

#include "EasyNextionLibrary.h"  // Include EasyNextionLibrary
#include <EEPROM.h>
#include <Thermocouple.h>
#include <MAX6675_Thermocouple.h>
#include <SmoothThermocouple.h>
#define SCK_PIN 3
#define CS_PIN 4
#define SO_PIN 5
/**
  Smoothing factor of a temperature value.
*/
#define SMOOTHING_FACTOR 5
Thermocouple* thermocouple = NULL;

EasyNex myNex(Serial1);  // Create an object of EasyNex class with the name < myNex >
                         // Set as parameter the Hardware Serial you are going to use

/** the current address in the EEPROM  **/
int address16 = 16;
int PID;

void setup() {
  myNex.begin(115200);   // Nextion Display begin the object with a baud rate of 115200
  Serial.begin(115200);  // Use to see commands on the Serial Monitor

  Thermocouple* originThermocouple = new MAX6675_Thermocouple(SCK_PIN, CS_PIN, SO_PIN);
  thermocouple = new SmoothThermocouple(originThermocouple, SMOOTHING_FACTOR);

  EEPROM.get(address16, PID);
  myNex.writeNum("n3.val", PID);
}


void loop() {
  myNex.NextionListen();  // This function must be called repeatedly to response touch events
  delay(500);

  // Reads temperature
  const double celsius = thermocouple->readCelsius();
  // Output Temperature on Nextion n1 text field
  myNex.writeNum("n1.val", celsius);

  Serial.println(PID);  // Diplays EEPROM value16
}


// PID Buttons Page 1

void trigger10() {
  /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0A
   * Every time the button is pressed, the trigger10() function will run
   * and the code inside will be executed once
   */
  PID = myNex.readNumber("n3.val");  // Store to PIDTemp the value of text box n3;
  EEPROM.put(address16, PID);
  delay(10);
  PID = EEPROM.get(address16, PID);
  myNex.writeNum("n3.val", PID);
}

void trigger11() {
  /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0B
   * Every time the button is pressed, the trigger11() function will run
   * and the code inside will be executed once
   */
  Serial.println("Clear button pressed");
}

void trigger12() {
  /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0C
   * Every time the button is pressed, the trigger12() function will run
   * and the code inside will be executed once
   */
  Serial.println("Down button pressed");
  //myNex.writeNum("n3.val") +1;
}

void trigger13() {
  /* Create a button on Nextion
   * Write in the Touch Release Event of the button
   * this command:    printh 23 02 54 0D
   * Every time the button is pressed, the trigger13() function will run
   * and the code inside will be executed once
   */
  Serial.println("Up button pressed");
  //myNex.writeNum("n3.val") -1;
}

Seams that it is related to Serial communication or something!!!

Nextion display uses Serial1...
Monitor uses Serial0
Any idea what is causing this???

I seem to remember there being a problem reading from EEPROM in setup() under some circumstances because EEPROM did not have time to initialise

As an experiment put a delay(1000); in setup() before the EEPROM.get()

Tried but still not working...

It is related to serial communication...

  • If I unplug the USB cable from the PC and restart the Arduino board, the value won't be there.
  • If I unplug the USB cable from the PC, restart the Arduino board then plug the USB, while Arduino IDE is open, value is restored, but only if serial monitor is running. If serial monitor is not running, then it is not restored, if I open serial monitor, then the value is restored.

So it seems that the value is only restore when Arduino IDE is open with the Serial Monitor running.
Nextion display is on Serial1, serial monitor uses Serial0...
Any clues of why???

I think that every time serial monitor is initiated, then the void setup() section is run once, thus pulling the value from the EEPROM.

The problem is that I can't place:

EEPROM.get(address16, PID);
myNex.writeNum("n3.val", PID);

in the void loop() section, because the number field n3 will be updated very fast before I have time to enter the value using the Nextion numeric keypad and hit the set button...

Under what circumstances do you want the value to be read from EEPROM ?

I want the value in the n3 number field to be there on every power ON, so I don't have to enter it everytime...

The problem is that the n3 number field is used to both sent and receive the value from the EEPROM...

Opening the Serial monitor causes the Mega to reset so setup() will, of course, run again. This can almost certainly be prevented by a hardware hack on the Mega

In this case, reset is desirable, because is pull the value from the EEPROM...

Is there a way to reset the serial0 after power is turned ON via coding?

Yep, that would work, if I click on the Arduino Reset button, then value is restored...

What exactly do you mean by "resetting" ?

Ok, if I click on the Arduino Reset button, then value is restored even if no USB is plugged in...