I/O "States" not Maintaining

Hello, I am still new to the forum so please bear with (and let me know) of any mistakes I may make (I think I got it now, though)!

I am making an automated air system using motorized ball valves controlled by a HMI touchscreen (Nextion 7").

My logic involves "listening" for a specific's buttons id over Serial3 (button being a valve on a map) and changing a bool array's respective value to true/false keeping track of whether the valve is open/closed.

#define numValves 10
bool valve_states[numValves] = {false, false, false, false, false, false, false, false, false, false};
int valve_pins[numValves] = {30,31,32,33,34,35,36,37,38,39};

I realize there are some holes in this approach, i.e if the screen and controller (Arduino Mega) somehow get turned off separately etc. But, just sending the buttons id and state was giving me corrupted serial messages. I figured I could iron this out later...

But my main issue is that the individual states are not "remebering" what they were set to. The first button (id 65 0 2...) will set it's pin high when pressed, but not save the valve_state[0] as true in turn never being able to turn it off. All the others work fine when turning on/off. Their respective I/O will turn High/Low (unlike the first one with the exact same code???) but as soon as you press another valve's button, it will set the previously touched back to false and turn it's I/O off. Only one valve can be turned on at once...

void loop() {
  String message = myNextion.listen(); //check for message
  if(message != ""){ // if a message is received... 
   //Serial.println(message); //...print it out  
    
    if(message == "65 0 2 0 ffff ffff ffff" && valve_states[0] == false){
    valve_states[0] == true;
    digitalWrite(valve_pins[0], HIGH);
    print_states(); 
    } else{
      valve_states[0] == false;
      digitalWrite(valve_pins[0],LOW);
      print_states();
    }

    if(message == "65 0 3 0 ffff ffff ffff" && valve_states[1] == false){
    valve_states[1] = true;
    digitalWrite(valve_pins[1], HIGH);
    print_states();   
    } else {
      valve_states[1] = false;
      digitalWrite(valve_pins[1],LOW);
      print_states();
    }

    if(message == "65 0 4 0 ffff ffff ffff" && valve_states[2] == false){
    valve_states[2] = true;
    digitalWrite(valve_pins[2], HIGH); 
    print_states();  
    } else {
      valve_states[2] = false;
      digitalWrite(valve_pins[2],LOW);
      print_states();
    }

    if(message == "65 0 5 0 ffff ffff ffff" && valve_states[3] == false){
    valve_states[3] = true;
    digitalWrite(valve_pins[3], HIGH); 
    print_states();  
    } else {
      valve_states[3] = false;
      digitalWrite(valve_pins[3],LOW);
      print_states();
    }

    if(message == "65 0 6 0 ffff ffff ffff" && valve_states[4] == false){
    valve_states[4] = true;
    digitalWrite(valve_pins[4], HIGH); 
    print_states();  
    } else {
      valve_states[4] = false;
      digitalWrite(valve_pins[4],LOW);
      print_states();
    }

    if(message == "65 0 7 0 ffff ffff ffff" && valve_states[5] == false){
    valve_states[5] = true;
    digitalWrite(valve_pins[5], HIGH);
    print_states();   
    } else {
      valve_states[5] = false;
      digitalWrite(valve_pins[5],LOW);
      print_states();
    }

    if(message == "65 0 8 0 ffff ffff ffff" && valve_states[6] == false){
    valve_states[6] = true;
    digitalWrite(valve_pins[6], HIGH);
    print_states();   
    } else {
      valve_states[6] = false;
      digitalWrite(valve_pins[6],LOW);
      print_states();
    }    

    if(message == "65 0 9 0 ffff ffff ffff" && valve_states[7] == false){
    valve_states[7] = true;
    digitalWrite(valve_pins[7], HIGH); 
    print_states();  
    } else {
      valve_states[7] = false;
      digitalWrite(valve_pins[7],LOW);
      print_states();
    }

    if(message == "65 0 a 0 ffff ffff ffff" && valve_states[8] == false){
    valve_states[8] = true;
    digitalWrite(valve_pins[8], HIGH); 
    print_states();  
    } else {
      valve_states[8] = false;
      digitalWrite(valve_pins[8],LOW);
      print_states();
    }

    if(message == "65 0 b 0 ffff ffff ffff" && valve_states[9] == false){
    valve_states[9] = true;
    digitalWrite(valve_pins[9], HIGH);
    print_states();   
    } else {
      valve_states[9] = false;
      digitalWrite(valve_pins[9],LOW);
      print_states();
    }
   
 }
}

I know some of you must be shivering in your seats right now, I am by no means a coder and still trying to learn. I am sure there is a much simpler (and CORRECT) way to do this. Any and all help/advice is very much appreciated.

Thanks in advanced!

First of all, the size of your code could be reduced by 1/10, because the only change in "message" is character 6, which increases linearly so it could be converted to an array index (2=0, 3=1, 4=2 etc.). But the reason why your state is reset is because the "else" part of each button's "if" statement will be executed, if "message" does not equal the message for the specific button.

    if(message == "65 0 2 0 ffff ffff ffff" && valve_states[0] == false) {
    valve_states[0] == true;
    digitalWrite(valve_pins[0], HIGH);
    print_states();
    } else{
      valve_states[0] == false;
      digitalWrite(valve_pins[0],LOW);
      print_states();
    }

That should be:

  if (message == "65 0 2 0 ffff ffff ffff")
  {
    if (valve_states[0] == false) {
    valve_states[0] == true;
    digitalWrite(valve_pins[0], HIGH);
    print_states();
    } else{
      valve_states[0] == false;
      digitalWrite(valve_pins[0],LOW);
      print_states();
    }
  }

Thank you both very much!!

I don't know why I didn't think of that... makes a whole lot of sense!

I had thought about trying to loop through all the valves, but my experience with strings has always been light.

So far I got:

char msg_id[numValves] = {"2","3","4","5","6","7","8","9","a","b"};

and

for(int i=0; i<numValves; i++){
     if (message == "65 0 2 0 ffff ffff ffff"){
       if (valve_states[i] == false) {
         valve_states[i] = true;
         digitalWrite(valve_pins[i], HIGH);
         } else{
          valve_states[i] = false;
           digitalWrite(valve_pins[i],LOW);
           }
          }
         }

I'm starting to look into how to change just the 6th character with the array. I do like a challenge! Just a brief explanation of how you would go about that would be awesome!

You could consider something like this:

char getButtonIndex(char c)
{
  const char buttonCodes[numValves] = {"2","3","4","5","6","7","8","9","a","b"};
  for (byte i = 0; i < numValves; i++) if (buttonCodes[i] == c) return i;
  return -1; //Invalid code
}

void loop()
{
  String message = myNextion.listen();
  if (message.length() < 6) return; //Exit if message is invalid too short / empty
  char valve = getButtonIndex(message.charAt(5));
  if (valve == -1) return; //Invalid valve index
  valve_states[valve] ^= 1; //Toggle state
  digitalWrite(valve_pins[valve], valve_states[valve]); //Write new state
  print_states();  
}

Holy cow that's awesome!
Having it applied to something I worked on makes this really easy to understand!

I got some practicing to do before this level of efficiency comes naturally.

Thank you for your help!!!!!! :slight_smile: :slight_smile: :slight_smile:

Just remember this: Being able to use code is not as important as knowing how it works! :wink: