Only SOME switches don't react as expected

hi, thank to everybody for giving me advice regarding my 16 switch MIDI-Footswitch .

i've run into the next issue.

what I tried to achieve with this code is: have each switch go through different states: first press: record, second: playing, third: stopped, then toggle between play/stop.
if it's playing or stopped: Recording if pressed for more than 0.7 seconds.

and IT WORKS! i think...
but NOT with switches connected to 6, 9, 10 and 13.
they always start with „Playing“ and I can't figure out why.

Any Guesses?

String schalter [] = {"LO1", "LO2", "LO3", "LO4", "PB1", "PB2", "PB3", "PB4", "SO1", "SO2", "SO3", "SO4", "FX1", "FX2", "CLR", "S16"};
bool schalterA [16];

unsigned long timers [16];
unsigned long longClick = 700;

byte looperStati [16];

void looperDown (int i){
      timers[i] = millis();
      //Serial.println(timers[i]);
} 

void looperUp (int i){
  if ((millis() - timers[i]) < longClick) {
    if (looperStati[i] == 0) {
        Serial.print (schalter[i]);
        Serial.println (" Recording");
        looperStati[i]++;
      }
    else if (looperStati[i] == 1) {
        Serial.print (schalter[i]);
        Serial.println (" Playing");
        looperStati[i]++;
    }
    else if (looperStati[i] == 2) {
        Serial.print (schalter[i]);
        Serial.println (" Stopped");
        looperStati[i]++;
    }
     else if (looperStati[i] == 3) {
        Serial.print (schalter[i]);
        Serial.println (" Playing");
        looperStati[i]++;
    }
    else if (looperStati[i] == 4) {
        Serial.print (schalter[i]);
        Serial.println (" Stopped");
        looperStati[i] = 3;
    }
   }

if (((millis() - timers[i]) >= longClick) && looperStati[i] >= 3) {
      Serial.print (schalter[i]);
      Serial.println (" Recording");
      looperStati[i] = 1;
      }      
}

void setup() {
  for(int i=0; i<16; i++){
    pinMode(i+5, INPUT_PULLUP);
    schalterA[i] = digitalRead(i+5);
    looperStati[i] = 0;
    }
  
  Serial.begin(9600);
}

void loop() {


  for (int i = 0; i < 16; i++)
  {
    bool inputVal = digitalRead(i + 5);
    if (schalterA[i] != inputVal)
    {
      schalterA[i] = inputVal;
      //Serial.println(schalter[i]);

      if (inputVal)
        looperUp (i);
      else
        looperDown (i);
    }
  }   
}

thanks a lot
thomas (tired and puzzled)

What board are you using and what is connected to it apart from (I assume) 16 pins to ground via buttons?

I used wokwi, my new favorite time waster and right away notice that unless I make the pushbuttons bounce-less, the code misbehaves.

And when debounced, I don't get the sequence you describe, or I have to read it more carefully or you have to explain a bit more about the sequence.

Are the switches all the same kind? And do you have them wired as @ninora and the rest of us assume?

At a glance (and nice use of arrays) there isn't anything eight away obvious why some would work and others not.

Thank you for posting in tags, and something we don't need MIDI and a DAW to test on!

I used a MEGA, I also ask what are you running this on?

a7

I redid your if/else thing as a switch/case, which for me makes it easier to read. If I didn't make a mistake it should be logically identical, it seems to (mis)behave the 'xact same way.

I added to you printed text so it is easier to see what is recording, playing &c.

The read button is debounced, the green button is not.

HTH

a7

hi ninora, I'm using a teensy 4.0.
i connected 16 pushbuttons with Resistors and Condensors (seemingly the right way an right values..)
I do not get any bouncing (like on/off a couple of times with only one press)
and the Setup worked flawless with a different code...

Hi Alto, do I understand your post correctly:

If debounced, every switch behaves as intended?

btw, i'm using a teensy 4.0

Ok, things are getting even weirder.
If i interchange the physical Buttons, the error remains.
i.e. pin 6 still always starts with „Playing“, not „Recording“.

And to make things even worse:
when I disconnect the teensy from my MAC and reconnect (aka power off an on again)
ALL Switches start with PLAYING.
When I just reset with the built in Button, they start with RECORDING with the usual exception of 6, 9, 10, 13.

hurray.

Where? Why? Maybe capacitors? Even that is not needed.
Just connect the pins to a pushbutton that is connected to ground on the other side.

capacitors... sorry.
the Capacitors/Resistors are supposed to a hardware debounce.
without them I get multiple „on/offs“ per press.

Well every switch the same; if it's what you want, then you good.

And I see that you have some kind of hardware resistor-capacitor denouncing learned the hard way, so again looks like you good.

Didja take a peek at the wokwi simulator version I linked above, and also your logic recast as a switch/case?

If you are looking to up game programming switch/case is very easy to add to your tool kit. And as I said, it makes the flow in exact this circumstance easier to read. And write, you may find.

'a7

Look at the ezButton library.

#include <ezButton.h> // ezButton library

ezButton button(7); // create Button object that attach to pin 7;

void setup() {
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
}

void loop() {
  button.loop(); // MUST be at the top of the loop() function

  if(button.isPressed())
    // Do something
}```

I like ezButton, never saw that.

But the OP has solved the debounce problem already, and he also is looking for long press events, which ezButton does not have.

I'd make a bigger proper mess of the whole thing with direct port access and vertical debounce counters. :wink:

a7

The button2 library has short, medium and long press functions, but it's setup is a bit more complex.

had a look at wokwi, looks interesting.
Your code seems to work just fine.
my next step is using ezButton to check if there is any misbehaving of the suspected switches with a different code also

and i will test the whole thing with my stock arduino, maybe....

so, i finished the first stage.
i simply avoid the pins that don't work the way they're supposed to:

String schalter [] = {"LO1", "LO2", "LO3", "LO4", "PB1", "PB2", "PB3", "PB4", "SO1", "SO2", "SO3", "SO4", "FX1", "FX2", "CLR", "S16"};
bool schalterA [16];
bool schalterB [16];

byte pins [] = {0,1,2,3,4,5,7,8,11,12,14,15,16,17,18,19};

byte stati[16];

unsigned long timers [16];
unsigned long longClick = 700;

void looper (int i){
  
  if (schalterA[i] == LOW && schalterB[i]== HIGH) {
      timers[i] = millis();
      Serial.print(stati[i]);
      Serial.println(schalter[i]);
      schalterB[i] = LOW;
      } 
  if (schalterA[i] == HIGH && schalterB[i]== LOW) {
      if ((millis() - timers[i]) < longClick) {
        
        switch (stati[i]) {
        case 0:
        Serial.print (schalter[i]);
        Serial.println (" Recording");
        stati[i] = 1;
        schalterB[i] = HIGH;
        break;
        
        case 1:
        Serial.print (schalter[i]);
        Serial.println (" Playing");
        stati[i] = 2;
        schalterB[i] = HIGH;
        break;
        
        case 2:
        Serial.print (schalter[i]);
        Serial.println (" Stopped");
        stati[i] = 3;
        schalterB[i] = HIGH;
        break;
        
        case 3:
        Serial.print (schalter[i]);
        Serial.println (" Playing also");
        stati[i] = 4;
        schalterB[i] = HIGH;
        break;
        
        case 4:
        Serial.print (schalter[i]);
        Serial.println (" Stopped also");
        stati[i] = 3;
        schalterB[i] = HIGH;
        break;
        }
      }

  if (((millis() - timers[i]) >= longClick) && stati[i] > 2) {
      Serial.print (schalter[i]);
      Serial.println (" Recording");
      schalterB[i] = HIGH;
      stati[i] = 1;
      }      
    }
  }

void playback (int i){
  
  if (schalterA[i] == LOW && schalterB[i]== HIGH) {
      //Serial.print(stati[i]);
      //Serial.println(schalter[i]);
      schalterB[i] = LOW;
      } 
  if (schalterA[i] == HIGH && schalterB[i]== LOW) {
      switch (stati[i]) {
        case 0:
        Serial.print (schalter[i]);
        Serial.println (" Play from Start");
        stati[i] = 1;
        schalterB[i] = HIGH;
        break;
        
        case 1:
        Serial.print (schalter[i]);
        Serial.println (" Stopped");
        stati[i] = 0;
        schalterB[i] = HIGH;
        break;
    }
  }
}
  
void setup() {
  for(int i=0; i<16; i++){
    pinMode(pins[i], INPUT_PULLUP);
    schalterA[i] = HIGH;
    schalterB[i] = HIGH;
    stati[i] = 0;
    }
  
  Serial.begin(9600);
}

void loop() {


for (int i = 0; i < 16; i++){
    schalterA[i] = digitalRead(pins[i]);
  }

for (int i = 0; i < 4; i++){
    looper(i);
    playback(i+4);
  }
}

so I got 4 Loopers and 4 Playbacks
next step:
make one switch the „stop and Erase“ for the Looper that recorded last.
If you don't mind I'll keep you updated.
Thomas
another

Yes, please do.

If you have a moment and any curiosity on par with mine, could you do something very simple to test those pins that don't work configured as inputs?

Maybe just read a pin, and print its value.

Pins should not randomly work or not work.

Is it possible you damaged your board earlier when you knew less about what you were up to, or accidentally? Do you have another board you could test?

It is of slight importance; if you did damage your board, however, it may mean that other pins have been "wounded" and may go dodgy on you during the big performance…

Just sayin'

a7

well, the pins are read properly, I guess.
the weird thing is that pins 6,9,10 & 13 react:
„yes, I have been pressed. and now there is this Variable that has a Value.
well, I don't care, I add 1 to it.

on the Teensy one pin can have multiple functions, maybe there is something wrong deep in the guts of this thing I don't know about yet.

I will use a brand-new Unit one the final Product.
And I will try a stock Arduino uno or Mega if I am able to configure it the way that it is seen a a Midi device by my computer as the teensy is by nature.

You care more than I do, I hope. But are you guessing?

Did you simply read a pin, and print the value? For a "good" pin, to check the code, and for "bad" ones to see if they are bad?

Could you have damaged your board?

Now I am going to guess that there is nothing special about those pins that you wouldn't have to go out of your way to set up, but I do not know the teensy, so.

A practical solution you have found, avoid those pins. Pratical but unsatisfying. :expressionless:

BTW and FWIW, I would be surprised if another Arduino couldn't serve; as I found early on in this or another of your undertakings the teensy comes out of the box with MIDI. Other boards may need a library installed to achieve the same functionality.

a7