Start a new topic

Conditional button action

i want to make my button conditional, so the action will only be done when pin 2 is high. So my step will not slide in when it is already in. 

I tried a lot of thing, but it doesn't work. It still slides out. How to fix this?

 

  

void b2PopCallback(void *ptr) // button to put electrical step in
{
    NexButton *btn = (NexButton *)ptr;
    stepStatus = digitalRead(2);
    if (stepStatus = HIGH);
    {memset(buffer, 0, sizeof(buffer));
    digitalWrite(9, HIGH);
    delay (1000);
    digitalWrite(9, LOW);
    Serial.println("Step out");  
    t0.setText("STEP IS IN");
    p0.setPic(4);}
    }

  


 


You might want to swap your button b2 in your Nextion HMI for a dual-state button.

This will allow for the in 0 and out 1 to be tracked on the Nextion side as the request,

and then in your Arduino code, update the button for dual-state and track your bt0.val


Then you pair an arduino variable with your Nextion request.

Ultimately, your Arduino will need the logic to prevent user from stripping gears.

Treat the state of the Nextion button as a requested action

 - but only act if it is safe to do so

   - after any action, update the Nextion display with the actual value


I prefer to have two buttons instead of one dual state button. my complete code and files are here: Camperputer

i just want to make the action of the button conditional with a high pin2.

okay I am going to take a guess here that the semicolon on line 5

 - terminates your if condition and block of code,

     and therefore was not running as conditional based on pin2 being HIGH


void b2PopCallback(void *ptr) // button to put electrical step in
{
    NexButton *btn = (NexButton *)ptr;
    stepStatus = digitalRead(2);
    if (stepStatus = HIGH)    // <== semicolon removed
    {
        memset(buffer, 0, sizeof(buffer));
        digitalWrite(9, HIGH);
        delay (1000);
        digitalWrite(9, LOW);
        Serial.println("Step out");  
        t0.setText("STEP IS IN");
        p0.setPic(4);
    }
}

 


Unfortunatly that doesn't change the result.

I also serial printed the stepStatus and it changes from 1 to 0 as it should, when connected to the ground or 5V, when it floats it is mostly 0.

The t0 and p0 will change always, but the pin 9 stays low all the time.

Here is my complete code: 

/*
Camperputer
With my camputer i want to control:
-the electrical step (button in and out)
-interior light (PWM controlled LED strip)
-auxilary heater (digital potmeter and power on/off)
With my camputer i want to display:
-temperature inside and outside
-voltage batteries (2x)
-wall connection (220 on/off)
-clean water levels (2x load sensors)
-waste water level (load sensors or ping sensors)
-display technical data (vehicle dimensions, weight, tyre pressure, oil specs, etc.)
 
To control the omnistep (5 sec in of out) with button b0 and b1
To control the PWM interior light with slider h0.

*/

#include "NexButton.h"
#include "NexSlider.h"
#include "NexText.h"
#include "NexPicture.h"
#include "NexCrop.h"
int brightness = 0;   //integer for interior led
int wallPower = 0;    //integer for getting wallpower 220 connected
int stepStatus = 0;   //integer for getting step status

/* objects
* i.e. declare a button object [page id:0,component id:1, component name: "b0"].
*/
NexButton b2 = NexButton(3, 2, "b2");
NexButton b3 = NexButton(3, 3, "b3");
NexSlider h0 = NexSlider(2, 3, "h0");
NexText t0 = NexText(3, 5, "t0");
NexPicture p0 = NexPicture(3, 4, "p0");
NexCrop q0 = NexCrop(1, 6, "q0");

char buffer[10] = {0};

NexTouch *nex_Listen_List[] = 
{
    &b2,
    &b3,
    &h0,
    &t0,
    &p0,
    &q0,
    NULL
};

/**
 * Button to return the response.
 * 
 * @param ptr - the parameter was transmitted to pop event function pointer. 
 * 
 */



void b2PopCallback(void *ptr) // button to put electrical step in
{
    NexButton *btn = (NexButton *)ptr;
    stepStatus = digitalRead(2);
    if (stepStatus = HIGH)
      {
        memset(buffer, 0, sizeof(buffer));
        digitalWrite(9, LOW);
        delay (1000);
        digitalWrite(9, LOW);
        Serial.println("Step in");  
        t0.setText("STEP IS IN");
        p0.setPic(4);
      }
     }
    
   void b3PopCallback(void *ptr) // button to put electrical step out
{
    NexButton *btn = (NexButton *)ptr;
    memset(buffer, 0, sizeof(buffer));
    digitalWrite(8, HIGH);
    delay (1000);
    digitalWrite(8, LOW);
    Serial.println("Step out");     
    t0.setText("STEP IS OUT"); 
    p0.setPic(5);
    }
     
  void h0PopCallback(void *ptr) // Slider to set interior light (0-255 PWM)
{
    uint32_t number = 0;
    char temp[10] = {0};
    
    dbSerialPrintln("h0PopCallback");

    h0.getValue(&number);
    brightness = number;
    analogWrite(7, brightness);
    Serial.println("Set interior light");  
} 

void setup(void)
{
     
    nexInit();
    b2.attachPop(b2PopCallback, &b2);
    b3.attachPop(b3PopCallback, &b3);
    h0.attachPop(h0PopCallback, &h0);
    
//setting port OUTPUT
    pinMode(9, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(7, OUTPUT);
//setting port INPUT
    pinMode(2, INPUT);

}

void loop(void)
{
    nexLoop(nex_Listen_List);
    //stepStatus = digitalRead(2);  
}

 

(Your code indeed pasted twice, I modified it to reflect only one copy)


If I am understanding what you have written:


a) Your in and out variables are changing on the Nextion

b) Your in and out variables are changing in your MCU reported back from your code

c) But you are still not realizing your physical steps performing what you have told them to do?


Is my understanding right or which is not correct.


I will try to clarify my intensions.

On my campervan i have an electrical step that slides in or out. It is hardwired and has a status swith. I want to read the status switch with arduino int 'stepStatus' and display the result on the Nextion with t0 and p0 (this is not yet in the code).

 

If the step is already in, and i push the button b2 to get the step in, it must not do so, because this will damage the steps electrical motor. Therefore i added the if condition to the button b2. 

If the step is not in and therefore ok to slide out when b2 is pressed it must do so by digitalwrite output9 high for a few seconds and update the stepStatus and display the status on the Nextion with changing t0 and p0 to the corresponding stepStatus.


But in the code i have created now, the int stepStatus changes as it should. But the when pressing b2 output9 never changes and the t0 and p0 always change as if there was no if statement.



Okay I understand the intention, I am trying to understand exactly what is working so far.


So currently the electrical step is functioning without Arduino/Nextion help - by use of _____ and status is displayed in switch

 - I am picturing an on/off or in/out switch with some type of led.


A) Arduino must successfully read the existing hardware status in the existing status switch you describe.


A.1) Once Arduino successfully reads existing status: store in Arduino variable int "stepStatus" (report via Debug value of setStatus)

A.2) Once int stepStatus is successfully read (and reported via Debug) .. then update Nextion screen for in or out



B) On the Nextion side button for IN and button for OUT


B.1) Nextion side Button IN logic needs to check if step is already in

B.2) If step is IN then ensure Display is showing IN

B.3) else if step is OUT then ensure Display is showing OUT ... but

B.4.a) send command to Arduino to request to retract step

B.4.b) ensure display is showing "retracting"

B.4.c) WAIT for Arduino to update the status IN only when IN is reached.


C.1) Nextion side Button OUT logic needs to check if step is already out

C.2) If step is OUT then ensure Display is showing OUT

C.3) else if step is IN then ensure Display is showing IN ... but

C.4.a) send command to Arduino to request to extend step

C.4.b) ensure display is showing "extending"

C.4.c) WAIT for Arduino to update the status OUT only when OUT is reached.


Back to Arduino side


When Button_IN attachPop event is triggered, we know this is request to retract

D.1) We have already read the stepStatus in part A.1

D.2.a) check IF Arduino side stepStatus is in ...

D.2.b) IF Arduino side stepStatus is OUT

D.2.c)  trigger motor pin to continue retracting

D.2.d) if step retracting reaches in - stop pin

D.2.e) ensure to update Arduino side stepStatus is now IN

D.2.f) IF Arduino side stepStatus is already IN - do nothing

D.3) Reread stepStatus from A.1

D.4) Update Nextion as to what the status TRULY is



Likewise Button OUT attachPop event is known as request to extend

E.1) We have already read the stepStatus in part A.1

E.2.a) check IF Arduino side stepStatus is out ...

E.2.b) IF Arduino side stepStatus is IN

E.2.c)  trigger motor pin to continue extending

E.2.d) if step extending reaches out - stop pin

E.2.e) ensure to update Arduino side stepStatus is now OUT

E.2.f) IF Arduino side stepStatus is already OUT - do nothing

E.3) Reread stepStatus from A.1

E.4) Update Nextion as to what the status TRULY is


By leaving the update on the Nextion to be completed by the Arduino

the Arduino becomes in control of the steps

- it can either run the pin or ignore the request to protect the motor.

Arduino must update the Nextion status bits and reset Nextion buttons.


Look over and review the above steps to see these are the parts needed to be completed via code.  If there is something missing, then it needs to be added to your list of what needs to be accomplished.  Then once you have well defined smaller segments - then it becomes easier to code for each defined segment.


I would create a global Variable Nextion side where the Arduino can upload the final status

The Arduino would still update all visual components

- the two buttons for in and out should check this global Nextion side Variable


But the make the Arduino what is in control, it is the only one that can read the actual electric step status.

I found wht my IF statement didn't work properly....

I used :

if (stepStatus = HIGH)

instead of:

if (stepStatus == HIGH)


It is working now how i thought it should work.

And all your above steps are correct.

But...

I don't know what you mean by creating a global variable, isn't stepStatus this global variable?

And i don't know where to start with your step A (reading stepStatus and update actual status on the screen) i tried to write that in the void loop, but thats not working.

if (stepStatus = HIGH) .. one = is an assignment so it sets stepStatus to HIGH

if (stepStatus == HIGH) .. two == is a comparison so it compares stepStatus to HIGH


Creating a global variable in your HMI design

- click the Variable Component, it gets added in a row under your design screen

  - select the variable (probably named va0 at this point)

     - set .objname or leave as is

     - set .vscope from local to global


With this va0 global variable, the Arduino side can send what actual status is

 - the buttons can check against this va0 if step is IN or OUT and

    - decide if anything needs to be sent

    - update the screen elements based on va0 being IN or OUT

    - screen should reflect actual - va0 could be where you place actual.


I can't guide you on step A reading the actual physical hardware for your step

 - but somehow, you need to be able for your Arduino to know state of physical

   - without the Arduino knowing physical state all else leads to motor issue

   - it is more than just knowing if the motor is running

     - which direction, and if stop where from all in to all out is it

     - I assumed your Arduino already had a way to know where steps were physically

 - to update actual status on the Nextion screen is probably a few pieces

    - one would be to send va0.val= to the actual physical state of the steps

        - this allows the Nextion side to see the actual physical state of steps

    - other would be to change the text/pictures to reflect this actual state


Thanks Patrick for your help!

I changed my code and I now have a working 'conditional' button and also the wallpower displays works.

I made a void udatestep and wallconnection that monitors the stepstatus and if the wallconnection is connected. This works, but when i put these voids in the void loop or setup loop i get an error recvRetCommandFinished err . I don't understand why, the program works fine.

 

/*
Camperputer
With my camputer i want to control:
-the electrical step (button in and out)
-interior light (PWM controlled LED strip)
-auxilary heater (digital potmeter and power on/off)
With my camputer i want to display:
-temperature inside and outside
-voltage batteries (2x)
-wall connection (220 on/off)
-clean water levels (2x load sensors)
-waste water level (load sensors or ping sensors)
-display technical data (vehicle dimensions, weight, tyre pressure, oil specs, etc.)
 
To control the omnistep (5 sec in of out) with button b0 and b1
To control the PWM interior light with slider h0.

*/

#include "NexButton.h"
#include "NexSlider.h"
#include "NexText.h"
#include "NexPicture.h"
#include "NexCrop.h"
int brightness = 0;          //integer for interior led
int wallPowerstatus = 0;     //integer for getting wallpower 220 connected
int wallPowernew = 0;        //integer for setting wallpower 220 connected
int stepStatus = 0;          //integer for getting step status
int stepnew = 0;             //integer for setting step status

/* objects
* i.e. declare a button object [page id:0,component id:1, component name: "b0"].
*/
NexButton b2 = NexButton(3, 2, "b2");
NexButton b3 = NexButton(3, 3, "b3");
NexButton b5 = NexButton(1, 7, "b5");
NexSlider h0 = NexSlider(2, 3, "h0");
NexText t0 = NexText(3, 5, "t0");
NexPicture p0 = NexPicture(3, 4, "p0");
NexCrop q0 = NexCrop(1, 6, "q0");

char buffer[10] = {0};

NexTouch *nex_Listen_List[] = 
{
    &b2,
    &b3,
    &b5,
    &h0,
    &t0,
    &p0,
    &q0,
    NULL
};

/**
 * Button to return the response.
 * 
 * @param ptr - the parameter was transmitted to pop event function pointer. 
 * 
 */



void b2PopCallback(void *ptr) // button to put electrical step in
{
    NexButton *btn = (NexButton *)ptr;
      if (stepnew == LOW)
      {
        memset(buffer, 0, sizeof(buffer));
        digitalWrite(9, HIGH);
        delay (1000);
        digitalWrite(9, LOW);
        Serial.println("Step in");     
       }
     }
    
   void b3PopCallback(void *ptr) // button to put electrical step out
{
    NexButton *btn = (NexButton *)ptr;
      if (stepnew == HIGH)
      {
        memset(buffer, 0, sizeof(buffer));
        digitalWrite(8, HIGH);
        delay (1000);
        digitalWrite(8, LOW);
        Serial.println("Step out");     
       }
    }

 void b5PopCallback(void *ptr) // button for central doorlocking
{
    NexButton *btn = (NexButton *)ptr;
        memset(buffer, 0, sizeof(buffer));
        digitalWrite(10, HIGH);
        delay (500);
        digitalWrite(10, LOW);
        Serial.println("Doors locked");     
    }
     
  void h0PopCallback(void *ptr) // Slider to set interior light (0-255 PWM)
{
    uint32_t number = 0;
    char temp[10] = {0};
    dbSerialPrintln("h0PopCallback");
    h0.getValue(&number);
    brightness = number;
    analogWrite(7, brightness);
    Serial.println("Set interior light");  
} 


  void wallconnection() // Display if 220V wallpower is connected
  {
    if (wallPowernew == wallPowerstatus)
      {}  //do nothing
      else
      {
      wallPowerstatus = wallPowernew;
          if (wallPowerstatus == HIGH)
            {
              q0.setPic(3);
            }
            else
            {
              q0.setPic(0);
            }
      
      }
  }




  void updatestep()   // Display current stepstatus
  {
     if (stepnew == stepStatus)
      {}  //do nothing
      else
      {
      stepStatus = stepnew;
          if (stepStatus == HIGH)
            {
              t0.setText("STEP IS IN"); 
              p0.setPic(4);
            }
            else
            {
              t0.setText("STEP IS OUT"); 
              p0.setPic(5);
            }
      
      }
  }
void setup(void)
{
     
    nexInit();
    b2.attachPop(b2PopCallback, &b2);
    b3.attachPop(b3PopCallback, &b3);
    b5.attachPop(b5PopCallback, &b5);
    h0.attachPop(h0PopCallback, &h0);
    
//setting port OUTPUT
    pinMode(10, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(7, OUTPUT);
//setting port INPUT
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    
    wallconnection();         // Display if 220V wallpower is connected
    updatestep();             // Display current stepstatus
    
}

void loop(void)
{
    nexLoop(nex_Listen_List);
    stepnew = digitalRead(2);
    wallPowernew = digitalRead(3);
    
    wallconnection();        // Display if 220V wallpower is connected
    updatestep();            // Display current stepstatus
    
 }

 

my understanding of the recvRetCommandFinished err,

is the library trying to receive a Nextion response after your command, or expecting to

this error is on debug serial only, so if the nextion has indeed completed what it was suppose to

I wouldn't worry about it immediately - but keep it on our to look into list


You could try putting a type of uint_32t instead of void and a final line in the procedure/function of return 0; to see if it removes the recvRetCommandFinished.  This would confirm if it is expecting a return value. Somewhere before your project is complete, we will see if we can't figure it out


Progress feels good - huh


I also had to add an delay before my first voids, because the arduino was already performing these voids before the nextion was ready for it, this caused the screen to miss the initial stepstate and wallconnection.

Also two of the recvRetCommandFinished err are now gone.  

void setup(void)
{
     
    nexInit();
    b2.attachPop(b2PopCallback, &b2);
    b3.attachPop(b3PopCallback, &b3);
    b5.attachPop(b5PopCallback, &b5);
    h0.attachPop(h0PopCallback, &h0);
    
//setting port OUTPUT
    pinMode(10, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(7, OUTPUT);
//setting port INPUT
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    
    delay(1500);              // Delay, because screen is not yet started and Arduino sends first voids
    wallconnection();         // Display if 220V wallpower is connected
    updatestep();             // Display current stepstatus
    
}

 

The only thing that isn't working correct now is that if the input 2 or 3 change when the nextion is on another page, the status isn't updated. I don't understand, all my nextion vscopes that must change are on global, i thought that that would be enough?

try this


where you are declaring nextion components like

   NexButton b2 = NexButton(3, 2, "b2");

change the objname to include your pagename

   NexButton b2 = NexButton(3, 2, "pagename.b2");


if page is page3 where the globals b2 is then

   NexButton b2 = NexButton(3, 2, "page3.b2");

Login or Signup to post a comment