problem with my code

hello im trying to control 4 relays with my Nextion touch screen and a DSbutton, i got the code to work but its not working correctly. im using a maga 2560 board. when i go and touch the 4 buttons in a row 1234 the relay engage but they dont turn off if i go 4321. i have to go back to button 1 and start from there. can someone tell me what i need to change in the code so they can work independently?

#include "Nextion.h"

/*
 * Declare a dual state button object [page id:0,component id:1, component name: "bt0"]. 
 */
NexDSButton bt0 = NexDSButton(0, 2, "bt0");
NexDSButton bt1 = NexDSButton(0, 3, "bt0");
NexDSButton bt2 = NexDSButton(0, 4, "bt0");
NexDSButton bt3 = NexDSButton(0, 5, "bt0");

char buffer[100] = {0};

/*
 * Register a dual state button object to the touch event list.  
 */
NexTouch *nex_listen_list[] = 
{
    &bt0,
    &bt1,
    &bt2,
    &bt3,
    NULL
};
/*
 * Dual state button component pop callback function. 
 
 */
void bt0PopCallback(void *ptr)
{
    uint32_t dual_state;
    NexDSButton *btn = (NexDSButton *)ptr;
    dbSerialPrintln("b0PopCallback");
    dbSerialPrint("ptr=");
    dbSerialPrintln((uint32_t)ptr); 
    memset(buffer, 0, sizeof(buffer));
/* Get the state value of dual state button component . */
    bt0.getValue(&dual_state);
     if(dual_state){digitalWrite(9, HIGH);
    }
    
    else{digitalWrite(9, LOW);
    }
}
void bt1PopCallback(void *ptr)
{
    uint32_t dual_state;
    NexDSButton *btn = (NexDSButton *)ptr;
    dbSerialPrintln("b1PopCallback");
    dbSerialPrint("ptr=");
    dbSerialPrintln((uint32_t)ptr); 
    memset(buffer, 0, sizeof(buffer));
/* Get the state value of dual state button component . */
    bt1.getValue(&dual_state);
     if(dual_state){digitalWrite(10, HIGH);
    }

    else{digitalWrite(10, LOW);
    }
}
void bt2PopCallback(void *ptr)
{
    uint32_t dual_state;
    NexDSButton *btn = (NexDSButton *)ptr;
    dbSerialPrintln("b2PopCallback");
    dbSerialPrint("ptr=");
    dbSerialPrintln((uint32_t)ptr); 
    memset(buffer, 0, sizeof(buffer));
/* Get the state value of dual state button component . */
    bt2.getValue(&dual_state);
     if(dual_state){digitalWrite(11, HIGH);
    }

    else{digitalWrite(11, LOW);
    }
}
void bt3PopCallback(void *ptr)
{
    uint32_t dual_state;
    NexDSButton *btn = (NexDSButton *)ptr;
    dbSerialPrintln("b3PopCallback");
    dbSerialPrint("ptr=");
    dbSerialPrintln((uint32_t)ptr); 
    memset(buffer, 0, sizeof(buffer));
/* Get the state value of dual state button component . */
    bt3.getValue(&dual_state);
     if(dual_state){digitalWrite(12, HIGH);
    }


    else{digitalWrite(12, LOW);
    }
}
void setup(void)
{    
    /* Set the baudrate which is for debug and communicate with Nextion screen. */
    nexInit();

    /* Register the pop event callback function of the dual state button component. */
    bt0.attachPop(bt0PopCallback, &bt0);
    bt1.attachPop(bt1PopCallback, &bt1);
    bt2.attachPop(bt2PopCallback, &bt2);
    bt3.attachPop(bt3PopCallback, &bt3);
//setting port OUTPUT
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    pinMode(11, OUTPUT);
    pinMode(12, OUTPUT);
//initializing  port 
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    digitalWrite(12, LOW);
    dbSerialPrintln("setup done"); 
}
void loop(void)
{   
    
    nexLoop(nex_listen_list);
}

when i go and touch the 4 buttons in a row 1234 the relay engage but they dont turn off if i go 4321.

it sounds like you want the buttons to toggle the relays on and off -- when a button is pressed, turn the relay on if it is off, and turn it off if it is on

if so, you need to keep track of the relay state.

i don't know if your callbacks indicate whether the button is pressed and released or just pressed.

when pressed, you need to check the current state of the relay, change it and change the relay state variable to reflect it's new state.

perhaps you should define your "dual_state" variable as static, so that it's value is persistent between calls to the call-back function and initialize it's state to indicate the state of the relays after startup

   static uint32_t dual_state = 0;

You display the name of the callback function ahd the address of the button object:

    dbSerialPrintln("b3PopCallback");
    dbSerialPrint("ptr=");
    dbSerialPrintln((uint32_t)ptr);

...but you don't display the value you read back for 'dual_state'. Please add some code to display the dual_state values and show us what is showing up on Serial Monitor.

Since you're using a Nextion display, and the Nextion library.... The VERY first thing you need to do is confirm you're actually receiving all the events from the display. Odds are, you are NOT.

The Nextion library was written by someone who had not the first F-ing clue what he was doing when it came to handling serial communications. It is right up there with the worst pieces of code I've ever seen. It deliberately, and randomly, discards characters, and even entire messages arriving from the display, so you will surely, at some point, find you are NOT receiving messages you should be receiving.

If you look on the Display forum, you will find a thread from about a year ago where I posted an updated version of the library that actually works. In that same thread, you will find information on how another lister (Perry Bebbington) uses Nextions WITHOUT using their library. I strongly suggest you take one approach or the other, or you will surely end up tearing your hair out at some point.

Start here: Nextion Display not communicating with Arduino - #2 by PerryBebbington - Displays - Arduino Forum

Regards,
Ray L.

johnwasser:
You display the name of the callback function ahd the address of the button object:

    dbSerialPrintln("b3PopCallback");

dbSerialPrint("ptr=");
    dbSerialPrintln((uint32_t)ptr);




...but you don't display the value you read back for 'dual_state'. Please add some code to display the dual_state values and show us what is showing up on Serial Monitor.

I'm new to this can you please show me an example of how to add the code to print the info on serial monitor.

gcjr:
it sounds like you want the buttons to toggle the relays on and off -- when a button is pressed, turn the relay on if it is off, and turn it off if it is on

if so, you need to keep track of the relay state.

i don't know if your callbacks indicate whether the button is pressed and released or just pressed.

when pressed, you need to check the current state of the relay, change it and change the relay state variable to reflect it's new state.

perhaps you should define your "dual_state" variable as static, so that it's value is persistent between calls to the call-back function and initialize it's state to indicate the state of the relays after startup

   static uint32_t dual_state = 0;

I tried that and no change. its like I have to have the first DSbutton pressed for the rest of them to tun on. then I have to turn off the first button and the rest will turn off..