detect if pin is low while already detecting.

Okay so that title was a little confusing to type. im trying to set up an old controller to have all of its buttons connected to digital pins on the arduino. Im using a nano so i have pullup resistors and everything is working fine onn the hardware side. each button on the controller has a letter assigned to it. When the arduino detects that one of the pins is low then it sends that letter in lowercase over serial. then when it is released it sends the uppercase variant of the same letter. For example. If i press button A the arduino sends 'a' then i wait and let go and then it sends 'A'. i have software on my pc that interfaces with this and it works perfectly but i cant figure out how to check multiple buttons at the same time. currently my code has

if (digitalRead(2) == LOW){
    Serial.write('a');
    while (digitalRead(2) == LOW) {
    delay(1);
    } 
    Serial.write('A');
}

but i cant do this for more than one button at a time. like i cant hold multiple buttons because its stuck in the delay function.

Look at the change in state example in the IDE. https://www.arduino.cc/en/Tutorial/StateChangeDetection

example: when digitalRead(2) goes from HIGH to LOW, you send ‘a’ when digitalread(2) goes from LOW to HIGH, you send ‘A’

Do not use your ‘while . . .’

cant hold multiple buttons because its stuck in the delay function.

So don't use delay(), or while for that matter.

Put the input pins in an array and read them with a for loop. Use the principle shown in the StateChangeDetection example to detect when an input change state and whether it has been pressed or released, but extend it to hold the previously read states in an array.

larryd: Look at the change in state example in the IDE. https://www.arduino.cc/en/Tutorial/StateChangeDetection

example: when digitalRead(2) goes from HIGH to LOW, you send ‘a’ when digitalread(2) goes from LOW to HIGH, you send ‘A’

Do not use your ‘while . . .’

Thank you very very much this helps tons!

Note: for slow push button switches, scan them ~50ms.

//*************************************
//is it time to check the switches?
if (currentMillis - SwitchMillis >= 50)
{
//code here runs every 50 ms
SwitchMillis = millis(); //re-initilize Timer

//go and check the switches
checkSwitches();   
}
//****************** c h e c k S w i t c h e s ( ) *********************
//switches are checked every 50 milli seconds
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void checkSwitches() 
{
  //re-usable for all the switches 
  boolean thisState;   

  //check if Switch1 has changed state
  thisState = digitalRead(Switch1);
  if (thisState != lastSwitch1State)
  { 
    //update the Switch1 state
    lastSwitch1State = thisState; 

    //this switch position has changed so do some stuff
    //"LOW condition code"
    //has switch gone from HIGH to LOW?
    if(thisState == LOW)                         
    {
      //Do HIGH to LOW stuff here
    }
    else
    {
      //Do LOW to HIGH stuff here
    }


  } //END of Switch code

  //***************************************** 
  // similar code for other switches goes here
  //***************************************** 

} //END of checkSwitches()

I use the Ubi De Feo debounce array:

Ubi De Feo Debounce Arrray

from

#define ARRAY_SIZE 8
// array of pins to be debounced
short pinsToDebounce[]={
  2,3,4,5,6,7,8,9
};
// array of pin state
int swStates[]={
  0,0,0,0,0,0,0,0};
// array of previous pin state
int swPrevStates[]={
  0,0,0,0,0,0,0,0};
// array to store the actual state during debounce
int swDebouncedStates[]={
  0,0,0,0,0,0,0,0};
// array to store the previous state during debounce
int swPrevDebounceStates[]={0,0,0,0,0,0,0,0};
// time to debounce
int debounceDelay=100;
// array of previous times the pin has been checked
long prevTimes[]={
  0,0,0,0,0,0,0,0};
 
void setup(){
  Serial.begin(9600);
 
 initSwitches();
}
void loop(){
 readSwitches();
}
 
void initSwitches(){
  for(int i=0;i<ARRAY_SIZE;i++){
    pinMode(pinsToDebounce[i],INPUT);
  }
}
void readSwitches(){
 
  // Serial.print("active switch set ");
  // Serial.println((int)activeSwitchSet);
 
  for(short sw=0;sw<ARRAY_SIZE;sw++){
    volatile int pin=pinsToDebounce[sw];
    volatile int mpPin=pin;
    volatile int pinPosition=sw;
 
    swStates[pinPosition]=digitalRead(pin);
  }
 
  debouncePins();
   checkStateChange();
}
void debouncePins(){
 
  volatile long _millis=millis();
 
  for(short sw=0;sw<ARRAY_SIZE;sw++){
    if(swStates[sw]!=swPrevStates[sw]){
      prevTimes[sw]=_millis;
    }
    if(_millis-prevTimes[sw]>debounceDelay){
      prevTimes[sw]=_millis;
      swDebouncedStates[sw]=swStates[sw];
      /*
      Serial.print("button ");
       Serial.print(sw);
       Serial.print(" is ");
       Serial.println(swDebouncedStates[sw]);
       */
    }
    swPrevStates[sw]=swStates[sw];
  }
 
}
 
void checkStateChange(){
  for(short sw=0;sw<5;sw++){
    if(swPrevDebounceStates[sw]!=swDebouncedStates[sw]){
      /*
      Serial.println("");
      Serial.print("button ");
      Serial.print(sw);
      Serial.print(" ");
      Serial.println(swDebouncedStates[sw]);
      */
      if(swDebouncedStates[sw]==1){
        pinActive(sw);
      }
      if(swDebouncedStates[sw]==0){
        pinInactive(sw);
      }
    }
    swPrevDebounceStates[sw]=swDebouncedStates[sw];
  }
}
 
void printDebStates(){
  Serial.println("%%%%%%%%%%%%%%%%%%%%%%%%");
  for(int i=0;i<ARRAY_SIZE;i++){
    Serial.print(swDebouncedStates[i]);
    Serial.print('*');
 
  }
 
  Serial.println("");
}
void pinActive(int _id){
 
  Serial.print("active pin ");
  Serial.println(pinsToDebounce[_id]);
}
void pinInactive(int _id){
   Serial.print("inactive pin ");
 Serial.println(pinsToDebounce[_id]);
}

it is also available as a library, but the author used “pinActive” & “pinInactive” as conditions indicating HIGH & LOW. I won’t use this in a program because as noted above these are not synonymous terms.