Nextion: Continuously Send Serial Data to Photon for Press and Hold?

Hi all,

I’m using the simple Nextion Library here.

When I open my serial monitor and press my button I get:

message = "65 0 2 1 ff ff ff "

This button is set for press event and even if I hold it down I only get one:

message = “65 0 2 1 ff ff ff”

then the serial monitor shows nothing or:

message = “”

Is there a way to have message = “65 0 2 1 ff ff ff” keep coming in when I hold down my button?

Thanks!

#include "Nextion.h"
#define nextion Serial1

Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps

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

}

void loop() {
  String message = myNextion.listen(); //check for message
  if (message == "") { // if no message is received...
    Serial.println("Nothing");
  }
    else if (message != ""){//if a message is received...
    Serial.println(message);//...print it out
    }
 }

The press event is a one-time event when you touch a widged for the first time and that event will not reoccure till you release and touch again.
That is the way how the Nextion display works. The host controller has no way to change that behaviour.

Thanks for clarifying ScruffR,

I was also wondering if I could add some code to the Nextion editor itself to make it keep sending the press event serial message when I press and hold the button?

You can write code in the button event window using Nextion instruction set but I’m unfamiliar with this code language.

You could start a timer that keeps sending any code repeatedly when registering the touch event and stop the timer when you catch the release event.

Thanks for the suggestion, here is the new code:

#include <Arduino.h>
#include "Nextion.h"
#define nextion Serial1

Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps

int P = 0;
int Tset = 100;
unsigned long timer1;
unsigned long timer2;

void setup() {
  Serial.begin(9600);
  myNextion.init();
}

void loop() {
  String message = myNextion.listen(); //check for message
  if (message == "65 0 2 1 ff ff ff"){ //Press up button
    timer1 = millis();
    P = 1;
  }
  else if (millis() - timer1 > 2000 && P == 1){
    P = 2;
  }
  else if (P == 2){
    timer2 = millis();
    P = 3;
  }
  else if (millis() - timer2 > 100 && P == 3){
    Tset = Tset + 1;
    myNextion.setComponentText("t0", String(Tset));
    P = 2;
  }

  if (message == "65 0 2 0 ff ff ff"){ //Release Up button
    P = 0;
    timer1 = millis();
    timer2 = millis();
  }
 }

With this code I press and hold for about 2 seconds, then Tset starts increasing rapidly. Great! However when I release the button, it only stops about 50% of the time. That is, half the time I release Tset just keeps increasing rapidly.

So it seems to not be catching the release message == “65 0 2 0 ff ff ff”. Any suggestions?

I actually meant you should have the display use a timer widget.

Here is another interesting command from the library:

#include <Arduino.h>
#include "Nextion.h"
#define nextion Serial1

Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps

//int P = 0;
//int Tset = 100;
int x = 0;
//unsigned long timer1;
//unsigned long timer2;

void setup() {
  Serial.begin(9600);
  myNextion.init();
}

void loop() {
  String message = myNextion.listen(); //check for message
  x = myNextion.getComponentValue("b0"); //Up button, set for press event only
  Serial.println(x);
}

For this code I set the button b0 back to press event only. When I press and hold the button, the serial monitor reads 1 over and over. When I release, the serial monitor reads 0 over and over. Great! I could use this for a button press and hold code.

However like I was saying I open the monitor and see scrolling zeros. And when I press and hold I see scrolling ones. But sometimes the ones appear right away and sometimes they take a few seconds to show up.

I seems that it’s not always catching the myNextion.getComponentValue(“b0”) command. Any thought?

Oh OK I’ll have to look into how those widgets work.

I don't know whether the library you use has evolved from the library I knew back when I ported the Arduino version. But if it still behaves the same any command sent to the device will first flush all the data that may already have arrived from an ongoing transaction.
When calling the getComponentValue() as rapidly as you do above chances are that you are your own enemy there :wink:

Here is a working code that changes Tset up and down. Short presses change Tset by 1. Press and hold rapidly changes Tset. Both up and down buttons are set for press event only in Nextion editor.

Thanks to ScruffR for pointing out that I was calling getComponent too fast. A delay(20) at the end of the code fixed it.

#include <Arduino.h>
#include "Nextion.h"
#define nextion Serial1

Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps

int P = 0;
int R = 0;
int Tset = 109;
int x = 0;
int x_old = 0;
int y = 0;
int y_old = 0;
int a = 0;

unsigned long timer0;
unsigned long timer1;
unsigned long timer2;

void setup() {
  Serial.begin(9600);
  myNextion.init();
  myNextion.setComponentText("t0", String(Tset));
}

void loop() {
  x = myNextion.getComponentValue("b0"); //Up button, set for press event only
  y = myNextion.getComponentValue("b1"); //Down button, set for press event only
  
  //....................(Tset Up Button).......................
  if(x == 1 && x != x_old){ //Short press of Up button
    Tset = Tset + 1;
    myNextion.setComponentText("t0", String(Tset));
  }
  
  x_old = x;
  
  if (P == 0 && x == 1){ //Press and hold Up button
    timer1 = millis();
    P = 1;
  }
  else if(x == 0){
    timer1 = millis();
    P = 0;
  }
  if (millis() - timer1 > 1500){
    Tset = Tset + 1;
    myNextion.setComponentText("t0", String(Tset));
  }
  
  //....................(Tset Down Button).......................
  if(y == 1 && y != y_old){ //Short press of Down button
    Tset = Tset - 1;
    myNextion.setComponentText("t0", String(Tset));
  }
  
  y_old = y;
  
  if (R == 0 && y == 1){ //Press and hold Down button
    timer2 = millis();
    R = 1;
  }
  else if(y == 0){
    timer2 = millis();
    R = 0;
  }
  if (millis() - timer2 > 1500){
    Tset = Tset - 1;
    myNextion.setComponentText("t0", String(Tset));
  }
  
  if (Tset >= 212){ //Upper limit
    Tset = Tset - 1;
  }
  else if (Tset <= 32){ //Lower limit
    Tset = Tset + 1;
  }
  
  delay(20); //necessary to read value of "x" and "y"
 
 }

I’d still offload all that display stuff to the display itself.
The syntax to code the “macros” on the display is not complicated at all.

You’re probably right I’ll do some searching on how to use their syntax.
Do you have and resources or tutorials you’d suggest for this?

thanks

As I said, it’s so straight forward that you won’t really need a tutorial. The only thing you need is the instruction set on their website.

The most simple approach to start with would be something along this line

  • create a new page and add a font, a button control (b0), a number control (n0) and a timer (tm0)
  • set the en attribute of the timer to 0 (disabled by default) and tim to 100 (100ms)
  • add these macros
  1. tm0 Timer Event macro
n0.val++
  1. b0 Touch Press Event
tm0.en=1
  1. b0 Touch Release Event
tm0.en=0

And debug that in the Nextion Editor

I took your advice.

Add a variable widget va0

Up button press code:

tm0.en=1

Up button release code:

tm0.en=0
va0.val=0

Timer code:

va0.val=va0.val+1
if(va0.val==1)
{
  n0.val++
}else if(va0.val>20)
{
  n0.val++
}

Thanks!

1 Like

Hmm, I’m not quite sure what the if() ... else if() combo is supposed to do.
You only increment when (va0.val==1||va0.val>20), right?
Why not write it that way then?

However, if this is meant as an initial delay before ramping up the repeat speed after the initial hit, I’d rather modify the timer interval instead of introducing a new variable.

// button press (initial increment on first hit and first timer fire after 1sec)
n0.val++
tm0.tim=1000
tm0.en=1

// button release
tm0.en=0

// timer (after first timer fire speed up to 10 times per second)
n0.val++
tm0.tim=100

(you could set the timer interval conditionally, but this is shorter and doesn’t really matter when you do it repeatedly :wink: )

1 Like