Use Buttons as Toggle Switches using a Mutliplexer

I was able to setup a multiplexer to serial print each indiviual button just fine.

The next step I need to do is now making a logical toggle switch using these same buttons. I have an if statement that checks the state of the button array and attempts to invert that state.

#inputi being the way to detect which button is pressed.

if ( inputi < 1000 && inputStateArray[i] == 0 ){
inputStateArray[i] = 1
}

if ( inputi < 1000 && inputStateArray[i] == 1 ){
inputStateArray[i] = 0
}

But it doesn't work. Any ideas?

Full code below:

//Mux control pins
int s0 = D0;
int s1 = D1;
int s2 = D2;
int s3 = D3;

int Duct1 = D4;
int Duct2 = D5;

//Define Array of 8 items to set state to use for control if button is pressed
byte inputStateArray[] = {0, 0, 0, 0, 0, 0, 0};
//Mux in "SIG" pin
int SIG_pin = A0;

void setup(){
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);

digitalWrite(s0, LOW);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);

Serial.begin(9600);
}

void loop(){

//Loop through and read first 7 values (Y0-Y7)
//Reports back Value at channel 6 is: 346
for(int i = 0; i < 7; i ++){
  //Serial.println(readMux(i));
  int inputi = readMux(i);
  // if input of i is pressed run 
  if ( inputi < 1000 && inputStateArray[i] == 0 ){
    
    Serial.print(i);Serial.print(":");
    Serial.println(inputStateArray[i]);
    inputStateArray[i] = 1;
    Serial.print("Button ");Serial.print(i);Serial.print(" state value is: ");
    Serial.println(inputStateArray[i]);
    }
  

  if ( inputi < 1000 && inputStateArray[i] == 1 ){
    
    Serial.print(i);Serial.print(":");
    Serial.println(inputStateArray[i]);
    inputStateArray[i] = 0;
    Serial.print("Button ");Serial.print(i);Serial.print(" state value is: ");
    Serial.println(inputStateArray[i]);
    }
  
  
      delay(100);
 }
  
  

      // Check Array Items and turn on Duct 
      //Duct 1
      if (inputStateArray[0] = 0){
        digitalWrite(Duct1, LOW);
      }
      if (inputStateArray[0] = 1){
        digitalWrite(Duct1, HIGH);
      }
      //Duct 2
      if (inputStateArray[1] = 0){
        digitalWrite(Duct1, LOW);
      }
      if (inputStateArray[1] = 1){
        digitalWrite(Duct1, HIGH);
      }
}


  int readMux(int channel){
    int controlPin[] = {s0, s1, s2, s3};
    int muxChannel[16][4]={ {0,0,0,0},
    {1,0,0,0},
    {0,1,0,0},
    {1,1,0,0},
    {0,0,1,0},
    {1,0,1,0},
    {0,1,1,0},
    {1,1,1,0},
    {0,0,0,1},
    {1,0,0,1},
    {0,1,0,1},
    {1,1,0,1},
    {0,0,1,1},
    {1,0,1,1},
    {0,1,1,1},
    {1,1,1,1} };
    //loop through the 4 sig
    for(int i = 0; i < 4; i ++){
      digitalWrite(controlPin[i], muxChannel[channel][i]);
      }
     //read the value at the SIG pin
      int val = analogRead(SIG_pin); //return the value
      return val;
      }

which tutorial are you reading to get your code?

Assumption - if a button is not pressed the input is pulled up to Vcc and will be greater than or equal to 1000*. If button is pressed inputi will be less than 1000 and the if() code is executed.

Assumption #2 - Due to forum formatting the array notation doesn't come through properly. All these - inputStateArray - have an implied left bracket-i-right bracket appended.

Your tests are functioning like so :

    if ( inputi < 1000 && inputStateArray[i] == 0 ) {
      inputStateArray[i] = 1;
   }

Immediately following, you test inputStateArray*[/color] again;*
* *    if ( inputi < 1000 && inputStateArray[i] == 1 ) {       inputStateArray[i] = 0;     }* *
The result is that inputStateArray thrashes back and forth while the button is pressed. It won't be stable until the button is released - and after the button is released it'll always be zero by my reckoning.
Change it so inputStateArray_[/color] merely reflects the current state of the selected input . If the button is pressed set inputStateArray*[/color] to 1, otherwise it's 0.
Next, detect the *change of state * of inputStateArray[/color] using IDE -> file/examples/digital/statechangedetection. This will create a (boolean) variable that's true for only one scan of the program when inputStateArray[/color] goes true.
Use the state change variable to toggle** a third variable between false and true and that third (boolean) variable becomes your push-on, push-off switch state.
https://www.pluralsight.com/tech-blog/avoiding-magic-numbers/_

** State change and toggling are both demonstrated in this timer counter state change toggle FSM tutorial

Thank you for your help @dougp. Your assumptions are correct.

When you say

Change it so inputStateArray merely reflects the current state of the selected input. If the button is pressed set inputStateArray to 1, otherwise it's 0.

Are you saying to make and if(){}else{} statement for this? And if so what is the if condition?

If you could make up a mock of what you mean with this and the next two suggestions that would be incredibly helpful!

Start here:

 if ( inputi < 1000 && inputStateArray[i] == 1 ) {
       inputStateArray[i] = 0;
    }

Make up a little test sketch with i a fixed value (within the array bounds). This is just to prove that the code is responding to the switch as desired.

  if ( inputi < 1000) {
    Serial.println(HIGH);
  }
  else {
    Serial.println(LOW);
  }

If you could make up a mock of what you mean with this and the next two suggestions that would be incredibly helpful!

This is what the tutorial is for.

Which Arduino are you using?

Ok I will try that. I am using a NodeMCU

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.