Start a new topic

Set initial state of NexDSButton

I try to set the initial state of a NexDSButton in function setup (). The button is declared as:  

NexDSButton ndsb1 = NexDSButton (2.1 "bt0");

 Also, we have defined the function:  

void ndsb1PopCallback (void * ptr){....}

 where I receiving message by pressing the button on the screen.

I tried to set the initial state of the button like this: 
void setup(void)
{
nexInit();
ndsb1.attachPop(ndsb1PopCallback, &ndsb1);
ndsb1.setValue(1); //I need to be pressed as default!!!!
}

 but no change in the status button (as pressed) ... What am I doing wrong?

Thank you!

NexDSButton ndsb1 = NexDSButton (2.1 "bt0");  // defined incorrectly or perhaps typo


In your sampling of code is nexListen used, or assumed to be automatic?

1. yes, is a typo error.

2.  

void loop(void)
{
    nexLoop(nex_Listen_List);   
}

 What is the proper way to identify the function parameters: NexDSButton (2.1 "bt0"); ? The first parameter is the current page, the second being the object id and the last one is being objname?

Okay on the typo

- the correct means to identify NexDSButton(2,1,"bt0");

  - this is page number seen at left of page-name in Editor

  - followed by a comma

  - second parameter is component .id attribute,

        a number 1 is first component after page component with .id=1

  - followed by a comma

  - last parameter is the component .objname "bt0"

     - the .object name can be fully qualified as In "page2.bt0"

       (especially useful in the case of page2's bt0 component as a global)


What is the definition of your nex_Listen_List ?

this is entire code:

 

#include "NexText.h"
#include "NexDualStateButton.h"

NexText t1 = NexText(2, 2, "t0");

NexDSButton ndsb1 = NexDSButton(2,1,"bt0");

char buffer[10] = {0};

NexTouch *nex_Listen_List[] = 
{
    &ndsb1,
    NULL
};

const int buzzer  =  2; 

void Buzz()
 {
  digitalWrite(buzzer,HIGH);
  delay(100);
  digitalWrite(buzzer,LOW);
 }
 
void ndsb1PopCallback(void *ptr)
{ 
  if (ptr == &ndsb1)
  {
   Buzz();
   uint32_t dual_state; 
   ndsb1.getValue(&dual_state);
   if(dual_state == 1) {
     t1.setText("1");
   }
   else{
    t1.setText("0");
   }  
  } 
}

void setup(void)
{
  pinMode(buzzer,OUTPUT);
  Buzz();
  nexInit();
  ndsb1.attachPop(ndsb1PopCallback, &ndsb1);
  indsb1.setValue(1);
}

void loop(void)
{
    nexLoop(nex_Listen_List);   
}

 another problem is: in TouchReleaseEvent I try to change the values of a global variable:

 

if(background.releu1.val==0)
{
  background.releu1.val=1;
}else
{
  background.releu1.val=0;
}

but I get the following error:

Error: Invalid Variables:background.releu1.val=1;( Double click to jump to code)

Error: Invalid Variables:background.releu1.val=0;( Double click to jump to code)

Error: Compile failed! 2 Errors, 0 Warnings,


in page background exists that variable and is global. (at if statement doesn't get the error!)


Thank you!

1. I modified the interface and added some variable whose value changes depending on the state of the buttons. I read this value from Arduino - so, case closed!

2. For variables ... had to delete ; from the end. 


I noticed that if I have more NexDSButton and press them very quickly, not transmitted to the Arduino event but the button state (what man sees)  was changed. How can I avoid this behavior? 

Entire code is:

 

#include "NexVariable.h"
#include "NexDualStateButton.h"
#include <EEPROM.h>

uint32_t state1, state2, state3, state4, state5, state6, state7, state8; 

NexDSButton ndsb1 = NexDSButton(1,1,"bt0");
NexDSButton ndsb2 = NexDSButton(1,3,"bt1");
NexDSButton ndsb3 = NexDSButton(1,4,"bt2");
NexDSButton ndsb4 = NexDSButton(1,5,"bt3");
NexDSButton ndsb5 = NexDSButton(1,6,"bt4");
NexDSButton ndsb6 = NexDSButton(1,7,"bt5");
NexDSButton ndsb7 = NexDSButton(1,8,"bt6");
NexDSButton ndsb8 = NexDSButton(1,9,"bt7");


NexVariable releu1 = NexVariable(0, 1, "background.releu1");
NexVariable releu2 = NexVariable(0, 2, "background.releu2");
NexVariable releu3 = NexVariable(0, 3, "background.releu3");
NexVariable releu4 = NexVariable(0, 4, "background.releu4");
NexVariable releu5 = NexVariable(0, 5, "background.releu5");
NexVariable releu6 = NexVariable(0, 6, "background.releu6");
NexVariable releu7 = NexVariable(0, 7, "background.releu7");
NexVariable releu8 = NexVariable(0, 8, "background.releu8");

const int buzzer  =  2; 
char buffer[10] = {0};

NexTouch *nex_Listen_List[] = 
{
    &ndsb1,
    &ndsb2,
    &ndsb3,
    &ndsb4,
    &ndsb5,
    &ndsb6,
    &ndsb7,
    &ndsb8,
    NULL
};

 void Buzz()
 {
  digitalWrite(buzzer,HIGH);
  delay(100);
  digitalWrite(buzzer,LOW);
 }
 
void ndsbPopCallback(void *ptr)
{
  Buzz();

  releu1.getValue(&state1);  
  releu2.getValue(&state2);
  releu3.getValue(&state3);
  releu4.getValue(&state4);
  releu5.getValue(&state5);
  releu6.getValue(&state6);
  releu7.getValue(&state7);
  releu8.getValue(&state8);

  if (ptr == &ndsb1){
    EEPROM.write(0, state1==0?0:255);
  }
  if (ptr == &ndsb2){
    EEPROM.write(1, state2==0?0:255);
  }
  if (ptr == &ndsb3){
    EEPROM.write(2, state3==0?0:255);
  }
  if (ptr == &ndsb4){
    EEPROM.write(3, state4==0?0:255);
  }
  if (ptr == &ndsb5){
    EEPROM.write(4, state5==0?0:255);
  }
  if (ptr == &ndsb6){
    EEPROM.write(5, state6==0?0:255);
  }
  if (ptr == &ndsb7){
    EEPROM.write(6, state7==0?0:255);
  }
  if (ptr == &ndsb8){
    EEPROM.write(7, state8==0?0:255);
  }
}

void setup(void)
{
  pinMode(buzzer,OUTPUT);
  Buzz();
    nexInit();
  
    ndsb1.attachPop(ndsbPopCallback, &ndsb1);
    ndsb2.attachPop(ndsbPopCallback, &ndsb2);
    ndsb3.attachPop(ndsbPopCallback, &ndsb3);
    ndsb4.attachPop(ndsbPopCallback, &ndsb4);
    ndsb5.attachPop(ndsbPopCallback, &ndsb5);
    ndsb6.attachPop(ndsbPopCallback, &ndsb6);
    ndsb7.attachPop(ndsbPopCallback, &ndsb7);
    ndsb8.attachPop(ndsbPopCallback, &ndsb8);
    
    CitesteEEPROM();
}

void CitesteEEPROM()
{
  state1 = EEPROM.read(0)==0?0:1;
  state2 = EEPROM.read(1)==0?0:1;
  state3 = EEPROM.read(2)==0?0:1;
  state4 = EEPROM.read(3)==0?0:1;
  state5 = EEPROM.read(4)==0?0:1;
  state6 = EEPROM.read(5)==0?0:1;
  state7 = EEPROM.read(6)==0?0:1;
  state8 = EEPROM.read(7)==0?0:1;

  releu1.setValue(state1);
  releu2.setValue(state2);
  releu3.setValue(state3);
  releu4.setValue(state4);
  releu5.setValue(state5);
  releu6.setValue(state6);
  releu7.setValue(state7);
  releu8.setValue(state8);
}

void loop(void)
{
    nexLoop(nex_Listen_List);   
}

It is possible to optimize the code so that it no longer occur this annoying behavior?

HMI
(641 KB)

Annoying behavior? No.  Expected behaviour.


You wanted to have the assurance current state is recorded in eeprom

- the eeprom takes time to record

- the end-user button presses are exceeding eeprom timing limitations


And if not exceeding eeprom limitations, then exceeding RX/TX limitations. (discovered later as so)

The Nextion serial should be faster than the eeprom, so Nextion keeps pace and the eeprom falls behind and out of sync.


I have to question which, it becomes a simple mathematics once you consult the manufacturer's specifications

But this should be expected with excessive rapid button presses, even with a keyboard.


But for the sake of optimizations:


Your laziness in not writing individual touch release functions for each button in some effort to save time has cost you in terms of your end-result performance.

And in the HMI code, you order your logic in a way that cost cycles when not necessary.


Button Logic:


IF you can be assured that when someone presses a button that it will end up needing to be and indeed will eventually be released - then you can put the state change for that button in the HMI Touch Pressed Event.  The if statement will take additional cycles than a mere assignment, but not so many to cause your problem.  Doing this change in the Touch Pressed Event will reflect the change before sending the result to the Arduino.  So unless you are uncertain if the button's release is to be imminent, place changes before sending over serial.


The shorter assignment is not an if statement but variable=1-variable or releu1.val=1-releu1.val, but even shorter is none at all and merely use the bt0.val.  I question the Redundancy of using a dual-state button and then having a variable to reflect its state.  The dual-state button is itself boolean and will already set its values to 1 or 0 in its native handing on the Nextion, you should have been assured of such when you observed pressing the dual-state button did indeed change its pictures as required.  The result is stored in its .val attribute.


Excessive Serial:


Using the Send Component ID in the Touch Release Event is captured by the attachPop event in the library.  Again for some reason unknown you again do not trust your code?  Why if you have been informed by the Nextion that the release of the dual-state button has occurred are you requesting even more serial communications to request the values of the redundant variables which results in more serial communications for it to be returned?  Seems there is such a distrust to allow the Nextion and Arduino handle this as you have instructed them to do so.  Atleast you didn't send both the Pressed and the Released events when only one should be necessary.


If you can be assured that the dual-state button press and release has indeed changed its state on the Nextion side which should be obvious from the change in pictures, then on the Arduino side you should have been satisfied that this occurred when the Arduino receives the touch release event that it has been completed.  The Touch Release Nextion Return Codes according to the Nextion is 7 bytes 0x65 0x1 0x01 0x00 0xFF 0xFF 0xFF.  This should be sufficient to allow you to set state1 to not state1.  But as mentioned before, your event handling on the Arduino side, you fail to create an individual events for each of these. 


As a result your handler ndsbPopCallback then requests the values of all eight of the redundant variable values.  This changes the byte count from 7 to much higher.  How much higher?  Your redundant variable fully qualified .objname is 17 letters each (this alone could be reduced and see a performance increase).  But what does the Arduino send across the serial.  When we examine the library code we see it will send get background.releu1.valÿÿÿ ... which is 28 bytes to request the value and according to the Nextion Instruction Set will send back a 0x71 return code of another 8 bytes.  This is 36 bytes plus response time cycles that you perform on all eight variables is 288 plus the original 7 for 295 bytes on every button release.


So assuming there are no changes to the IteadLib Arduino Nextion Library NexHardware.app nexInit() function, you are running your baudrate at 9600 bps.  I see no evidence that suggests you are using a higher baudrate, so let's go with the 9600 for calculation purposes.  9600bps, uses 10 bits for each character - eight bits for the character, 1 for the none parity and 1 for the stop bit.  That yields 960 chars per second, and you are using 295 on each button press.  So we discover that it is not your eeprom that is your bottleneck, it has become the unnecessary overloading of your serial. 


Because you fail to write an event handler for each button press, you have used 295 bytes of serial each press, 960/295 or 3.254 - ALMOST but just over 3 presses per second before your serial starts to become out of sync.  And had you written individual event handlers for each button, the need to send over serial a request for each variable value would be redundant - therefore only the original 7 bytes for the release event notification would be necessary.  960/7 or 137.143 presses per second.


Of course changing your baudrate to 115200 assuming no issues to use the higher serial would provide a 12 fold increase, but some electronics become lossy at the higher baudrates and begin mangling data ... but your issue is indeed solvable by code changes. 


You will need to consult your Arduino MCU documentation and your eeprom documentation to discover what your limits are for these and you can perform the math needed to see where these would bottleneck at - but certainly the additional time required to heat up an eeprom for page flashing on every button press could also become an issue.  eeproms are simply slow devices in comparison to others - but they are chosen to hold values in case of power failures.  Is it necessary to write the changes to eeprom on every single button press, or simply once when the user has committed to the changes and leaves the page2 setup?


Your buzz event including a 100ms delay will also automatically reduce you to a MAX 10 presses per second being handled, a bottleneck that will be reached long before your eeprom. 


Now I don't know if this is a school project, but I can tell you that if it is not, it can certainly be reduced and optimized much further using binary mathematics.  If it is not needed to change the lights on / off with each button press and can wait until the user as selected their choice selections, serial could be reduced below 20 bytes to reflect all eight choices.


PS: I didn't see how the user leaves the page2 setup.

Login or Signup to post a comment