Switching between 2 or more sketches

Technically, i have a Mega. The inputPin or outputPin can be assign to any pins (for testing purpose). They just need to assign on different pins to the output.

X= 12 pin inputs
Usb=4 pin out
Bnc=2 pin out

Says:
Usb-X: in=1234, out=22,23,24,25
Bnc-X: in=1,2 to X needs to be assigned to different Pin than USB because the X contains 12 Pins.
X= Usb + BNC

More specific:
This is my pin table already assigned to X=12 Pin Master Input:

// X PIN IN   &    PIN OUT
//	22	=	1		    23
//	24	=	2		    25
//	26	=	3	     	27
//	28	=	4	     	29
//	30	=	5	     	31
//	32	=	6	  	    33
//	34	=	7	        35
//	36	=	8	        37
//	38	=	9	        39
//	40	=	10	  	    41
//	42	=	11	  	    43
//	44	=	12	  	    45
//	46	=	Shield      47

Btw, the cool thingy when i added kts_button3. Now i can even test 3 outputs from 3 sketches. (Or even more.. if my 20x4 lcd can handles all text line)
Your code is very easy to understand.

I cannot compile your code. Missing libraries

Very interesting this fail, I have nothing is connected. It showing 2:Pass
looks like I can not have same I/O#1 & I/O#2 pins? Do I have to assign all of them differently both IN&OUT?

int out#1[] = {25, 31};
int in#1[] = {24, 30};
int out#2[] = {23, 31, 39, 41}; 
int in#2[] = {22, 30, 38, 40};

Does this affect that same test?

#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C lcd(0x27, 16, 2);

#define NUM_PINS 4


int outputPins1[] = {35, 36}; // For testing in Wokwi I've wired pins 35 to 37
int inputPins1[] = {37, 38};
int outputPins2[] = {2, 3, 4, 5}; // For testing in Wokwi I've wired pins 2 to 22 and 5 to 25
int inputPins2[] = {22, 23, 24, 25};
int *outputPins;
int *inputPins;
int maxTestPins;
int count;
int voltage;
char results[NUM_PINS] = {'?', '?', '?', '?'};
bool testComplete = false;

#include "KTS_Button.h"
KTS_Button button1(7);
KTS_Button button2(8);


enum States {
  WELCOME = 0,
  TESTING,
  RESULTS,
};

States state = WELCOME;

  template<typename T>
  void LCDPrint(const T &printThis, int row = 0, bool clear = true) {
    if (clear) lcd.clear();
    lcd.setCursor(0,row);
    lcd.print(printThis);
  }
  

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();

  for (int i = 0; i < 2; i++) {
    pinMode(outputPins1[i], OUTPUT);
    pinMode(inputPins1[i], INPUT);
  }

for (int i = 0; i < 4; i++) {
    pinMode(outputPins2[i], OUTPUT);
    pinMode(inputPins2[i], INPUT);
  }

  displayStartup();
  delay(2000);
  displayWelcome();
}

void displayStartup() {
  LCDPrint("Continuity");
  LCDPrint("Tester (2/4-Pin)", 1, false);
}

void displayWelcome() {
  LCDPrint("Left 2-Pin Test");
  LCDPrint("Right 4-Pin Test", 1, false);
}

void resetResults() {
  for (int i = 0; i < NUM_PINS; i++) results[i] = '?';
}

void runTest() {
  LCDPrint("Testing...");

  for (count = 0; count < maxTestPins; count++) {
    digitalWrite(*outputPins + count, HIGH);
    delay(10);

    voltage = digitalRead(*inputPins + count);

    switch (voltage) {
      case HIGH:
        results[count] = 'P';
        break;

      case LOW:
        results[count] = 'F';
        break;

      default:
        results[count] = '?';
    }

    digitalWrite(*outputPins + count, LOW);
    delay(10);
  }
}

void displayResults() {
  if (maxTestPins == 2) {
    LCDPrint((String)"1:" + results[0] + " 2:" + results[1]);
  }
  else if (maxTestPins == 4) {
    LCDPrint ((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3]);
  }

  LCDPrint("Press To Restart", 1, false);
}

void loop() {
  switch (state) {
    case WELCOME:
      if (button1.read() == SINGLE_PRESS) {
        maxTestPins = 2;
        outputPins = outputPins1;
        inputPins = inputPins1;
        state = TESTING;
      }
      if (button2.read() == SINGLE_PRESS) {
        maxTestPins = 4;
        outputPins = outputPins2;
        inputPins = inputPins2;
        state = TESTING;
      }
      break;

    case TESTING:
      resetResults();
      testComplete = false;
      runTest();
      state = RESULTS;
      break;

    case RESULTS:
      if (!testComplete) { 
        displayResults();
        testComplete = true;
      }

      if (button1.read() == SINGLE_PRESS || button2.read() == SINGLE_PRESS) {
        displayWelcome();
        state = WELCOME;
      }
      break;

    default:
      break;
  }
}

Very interesting, actually your 2nd code even better. I understand now after a few tests.
I can share the input & output pin however I want based on my X pin table.
It is the same results, when I connected same pin between 2-pin test & 4-pin test, I should see the results "pass/fail" on those shared pins (because I share the input/output)

Edited: BNC (2pin test) 1:F 2:P even nothing is connected to BNC. But USB only PinIN are connected and None PinOUT is connected.

int outputPins1[] = {25, 31}; // 
int inputPins1[] = {24, 30};  // 
int outputPins2[] = {22, 30, 38, 40}; //
int inputPins2[] = {23, 31, 39, 41};  //

Ah yeah because you're setting the pin 31 and 30 as both an output and an input at the same time. It will be whatever the last change to that pinmode was during setup.

You should be okay using shared pins but only if you share inputs with inputs and outputs with outputs

Agreed! that would makes sense. Btw, in my original code you can tell I have test result "Good/Bad Cable" displayed under 1=P : 2=P . Can I add that extra command on LCD display result? under "Press to test again"

Thanks

Yeah you probably can. You'd basically need to check the results array and they are all 'p' then print pass, else print fail. If you can post your version of the code now with the 20x4 I'll take a look

//LCD
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
const uint8_t i2cAddr = 0x27;
const int rs=0, rw=1, en=2, db4=4, db5=5, db6=6, db7=7, bl=3;
typeof(POSITIVE) blpol=POSITIVE; // backlight polarity level
LiquidCrystal_I2C lcd(i2cAddr, en, rw, rs, db4, db5, db6, db7, bl, blpol);

#define NUM_PINS 4

int outputPins1[] = {25, 31}; 
int inputPins1[] = {24, 30}; 
int outputPins2[] = {22, 52, 38, 40};
int inputPins2[] = {23, 30, 39, 41}; 
int *outputPins;
int *inputPins;
int maxTestPins;
int count;
int voltage;
char results[NUM_PINS] = {'?', '?', '?', '?'};
bool testComplete = false;

#include "KTS_Button.h"
KTS_Button button1(7);
KTS_Button button2(8);


enum States {
  WELCOME = 0,
  TESTING,
  RESULTS,
};

States state = WELCOME;

  template<typename T>
  void LCDPrint(const T &printThis, int row = 0, bool clear = true) {
    if (clear) lcd.clear();
    lcd.setCursor(0,row);
    lcd.print(printThis);
  }
  

void setup() {
Serial.begin(9600);
lcd.begin(20, 4);

  for (int i = 0; i < NUM_PINS; i++) {
    pinMode(outputPins1[i], OUTPUT);
     pinMode(outputPins2[i], OUTPUT);
    pinMode(inputPins1[i], INPUT);
    pinMode(inputPins2[i], INPUT);
  }

  displayStartup();
  delay(2000);
  displayWelcome();
}

void displayStartup() {
  LCDPrint("Continuity");
  LCDPrint("Tester", 1, false);
  LCDPrint("help by: St3v3n92)", 2, false);
}

void displayWelcome() {
  LCDPrint("Left BNC Test");
  LCDPrint("Right USB Test", 1, false);
}

void resetResults() {
  for (int i = 0; i < NUM_PINS; i++) results[i] = '?';
}

void runTest() {
  LCDPrint("Testing...");

  for (count = 0; count < maxTestPins; count++) {
    digitalWrite(*outputPins + count, HIGH);
    delay(10);

    voltage = digitalRead(*inputPins + count);

    switch (voltage) {
      case HIGH:
        results[count] = 'P';
        break;

      case LOW:
        results[count] = 'F';
        break;

      default:
        results[count] = '?';
    }

    digitalWrite(*outputPins + count, LOW);
    delay(10);
  }
}

void displayResults() {
  if (maxTestPins == 2) {
    LCDPrint((String)"1:" + results[0] + " 2:" + results[1]);
  }
  else if (maxTestPins == 4) {
    LCDPrint ((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3]);
  }

  LCDPrint("Press To Restart", 1, false);
}

void loop() {
  switch (state) {
    case WELCOME:
      if (button1.read() == SINGLE_PRESS) {
        maxTestPins = 2;
        outputPins = outputPins1;
        inputPins = inputPins1;
        state = TESTING;
      }
      if (button2.read() == SINGLE_PRESS) {
        maxTestPins = 4;
        outputPins = outputPins2;
        inputPins = inputPins2;
        state = TESTING;
      }
      break;

    case TESTING:
      resetResults();
      testComplete = false;
      runTest();
      state = RESULTS;
      break;

    case RESULTS:
      if (!testComplete) { 
        displayResults();
        testComplete = true;
      }

      if (button1.read() == SINGLE_PRESS || button2.read() == SINGLE_PRESS) {
        displayWelcome();
        state = WELCOME;
      }
      break;

    default:
      break;
  }
}

Weird! I assigned the output pin different all, but share input pin 30, still error:
Test BNC (connected)= 1:P, 2:P
Test USB (no connect): 1:F 2:F 3:P 4:F
Am I missing anything?

int outputPins1[] = {25, 31}; // BNC-1 & BNC-2 OUTPUT
int inputPins1[] = {24, 30};  // BNC-1 & BNC-2 INPUT
int outputPins2[] = {22, 52, 38, 40}; //  USB-1, USB-4, USB-2, USB-3 OUTPUT
int inputPins2[] = {23, 30, 39, 41};  // USB-1, USB-4, USB-2, USB-3 INPUT

sorry. change #define to #undef

EDIT: Now, I think I've fixed the bug. Plus made it look way better :smiley:

I've also added some testing on the Wokwi page with toggle switches...
https://wokwi.com/arduino/projects/313193014357918274

If the switch is left it connects the output to the input, simulating a good wire connection. If you toggle the switch to the right it simulates a bad/broken connection.

Obviously, the set of switches on the left is the two-pin test and the right is the four-pin test.

So if you click the Wokwi link you can hit 'play' and then play around with the toggles while doing multiple tests.

@gcrj I think I understood what you meant before now. To answer, no this code won't tell you where the miswired/cross-connects are landing, but it will correctly notify you that the source did not reach the destination for that wire in the cable (indicating that an investigation might need to be made) and should correctly fail the cable.

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

#define NUM_PINS 4

// #define LED_DEBUG //Wokwi Testing Only (Delete otherwise)

// ODU PIN IN  ///////////// PIN OUT
//  22  = 1 (USB-1)         23
//  24  = 2 (BNC-1)         25
//  26  = 3                 27
//  28  = 4                 29
//  30  = 5 (BNC-2&USB-4)   31 & 52
//  32  = 6                 33
//  34  = 7                 35
//  36  = 8                 37
//  38  = 9 (USB-2)         39
//  40  = 10(USB-3)         41
//  42  = 11                43
//  44  = 12                45
//  46  = SHIELD            47

int outputPins1[] = {25, 31}; // BNC-1 & BNC-2 OUTPUT
int inputPins1[] = {24, 30};  // BNC-1 & BNC-2 INPUT
int outputPins2[] = {22, 52, 38, 40}; //  USB-1, USB-4, USB-2, USB-3 OUTPUT
int inputPins2[] = {23, 30, 39, 41};  // USB-1, USB-4, USB-2, USB-3 INPUT
int *outputPins;
int *inputPins;
int maxTestPins;
int count;
int voltage;
char results[NUM_PINS] = {'?', '?', '?', '?'};
bool testComplete = false;
bool cableApproved = true;

#include "KTS_Button.h"
KTS_Button button1(7);
KTS_Button button2(8);

enum States {
  WELCOME = 0,
  TESTING,
  RESULTS,
};

States state = WELCOME;

template<typename T>
void LCDPrint(const T &printThis, int row = 0, bool clear = true) {
  if (clear) lcd.clear();
  lcd.setCursor(0,row);
  lcd.print(printThis);
}
  

void setup() {
  Serial.begin(9600);
  lcd.begin(20, 4);

  for (int i = 0; i < 2; i++) {
    pinMode(outputPins1[i], OUTPUT);
    pinMode(inputPins1[i], INPUT);
  }
  for (int i = 0; i < 4; i++) {
    pinMode(outputPins2[i], OUTPUT);
    pinMode(inputPins2[i], INPUT);
  }

  displayStartup();
  delay(2000);
  displayWelcome();
}

void displayStartup() {
  LCDPrint("====================");
  LCDPrint("  Two / Four Wire   ", 1, false);
  LCDPrint(" Continuity Tester  ", 2, false);
  LCDPrint("====================", 3, false);
}

void displayWelcome() {
  LCDPrint("====================");
  LCDPrint("  Left:  BNC Test", 1, false);
  LCDPrint("  Right: USB Test", 2, false);
  LCDPrint("====================", 3, false);
}

void resetResults() {
  for (int i = 0; i < NUM_PINS; i++)
    results[i] = '?';
}

void runTest() {
  resetResults();
  testComplete = false;

  LCDPrint("====================");
  LCDPrint("      Testing       ", 1, false);
  LCDPrint("      Cable...      ", 2, false);
  LCDPrint("====================", 3, false);

  for (count = 0; count < maxTestPins; count++) {
    digitalWrite(*(outputPins + count), HIGH);
    delay(10);

    // Delay for Wokwi testing only (delete otherwise)
    #ifdef LED_DEBUG 
    delay(1000);
    #endif

    voltage = digitalRead(*(inputPins + count));

    switch (voltage) {
      case HIGH:
        results[count] = 'P';
        break;

      case LOW:
        results[count] = 'F';
        break;

      default:
        results[count] = '?';
    }

    digitalWrite(*(outputPins + count), LOW);
    delay(10);
  }
}

void displayResults() {
  LCDPrint("-  Test Complete   -");
  
  if (maxTestPins == 2)
    LCDPrint((String)"      1:" + results[0] + " 2:" + results[1], 1, false);

  else if (maxTestPins == 4)
    LCDPrint ((String)"  1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3], 1, false);

  cableApproved = true;
  
  for(int i = 0; i < maxTestPins; i++) {
    if (results[i] != 'P') 
      cableApproved = false;
  }
  
  if (cableApproved)
    LCDPrint("   Cable Passed!   ", 2, false);
  else 
    LCDPrint("    Cable Failed    ", 2, false);

  LCDPrint("- Press To Restart -", 3, false);

  testComplete = true;
}

void loop() {
  switch (state) {
    case WELCOME:
      if (button1.read() == SINGLE_PRESS) {
        maxTestPins = 2;
        outputPins = outputPins1;
        inputPins = inputPins1;
        state = TESTING;
      }
      if (button2.read() == SINGLE_PRESS) {
        maxTestPins = 4;
        outputPins = outputPins2;
        inputPins = inputPins2;
        state = TESTING;
      }
      break;

    case TESTING:
      runTest();
      state = RESULTS;
      break;

    case RESULTS:
      if (!testComplete) 
        displayResults();

      if (button1.read() == SINGLE_PRESS || button2.read() == SINGLE_PRESS) {
        displayWelcome();
        state = WELCOME;
      }
      break;

    default:
      break;
  }
}

Can you test this and let me know if it's working better for you?

Very clean code and it works!
Except my LCD will not work when I use this: (it never work, I don't know why)

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

But it always works with this, probably the driver issues:

//LCD
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
const uint8_t i2cAddr = 0x27;
const int rs=0, rw=1, en=2, db4=4, db5=5, db6=6, db7=7, bl=3;
typeof(POSITIVE) blpol=POSITIVE; // backlight polarity level
LiquidCrystal_I2C lcd(i2cAddr, en, rw, rs, db4, db5, db6, db7, bl, blpol);

I tried adding 3rd Test based on your code, it seems to work (haven't test with cable) but I am stuck at this, can't see all 9 pins at "Test Completed", showing only 1-5 running out space of display. I need space for new line :slight_smile:

Is there anyway I can remove "Test Complete" to saving a line? Because the Cable Passed, Failed already tells result, so I don't need "Test Complete" anymore.

Thanks

  if (maxTestPins == 9)
    LCDPrint ((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3] + " 5:" + results[4] + " 6:" + results[5] + " 7:" + results[6] + " 8:" + results[7] + " 9:" + results[8], 1, false);
    

Yeah just delete the line saying test complete and adjust the rows on the LCDPrint function. That template function is pretty simple, you just write what you want to print then a comma, the row you want to print it on (defaults to row 0) and a bool of it you want it to clear the lcd or not (defaults to true).

I wouldn't really say this is clean code, 90% of it seems like UI 'fluff' printing messages and handing presses making it nice but it's essentially just a digital write and a read like you had originally.

Gcjr's version is likely more useful than this and certainly less code :grin:

I also tried that, too. messing around with the LCD setting but the ================== line goes down instead of the test result 1,2,3,4,5,6,7,8,9:F/P
Your code almost perfect for me, this would be the last thing.
Btw, the perfect part that I am now can use all input/output same pins.

template<typename T>
void LCDPrint(const T &printThis, int row = 0, bool clear = true) {
  if (clear) lcd.clear();
  lcd.setCursor(0,row);
  lcd.print(printThis);
}

Okay post the full code you are currently using and I'll take a look

Thanks, please see photo.
It shows 5 pins instead of 9.
Thanks

//LCD
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
const uint8_t i2cAddr = 0x27;
const int rs=0, rw=1, en=2, db4=4, db5=5, db6=6, db7=7, bl=3;
typeof(POSITIVE) blpol=POSITIVE; // backlight polarity level
LiquidCrystal_I2C lcd(i2cAddr, en, rw, rs, db4, db5, db6, db7, bl, blpol);

#define NUM_PINS 9

int inputPins1[] = {24, 30};
int outputPins1[] = {25, 31};
int inputPins2[] = {22, 30, 38, 40, 46};
int outputPins2[] = {23, 31, 39, 41, 47};
int inputPins3[] = {22, 24, 30, 32, 34, 36, 38, 40, 46};
int outputPins3[] = {23, 25, 31, 35, 33, 37, 39, 41, 47};
int *outputPins;
int *inputPins;
int maxTestPins;
int count;
int voltage;
char results[NUM_PINS] = {'?', '?', '?', '?', '?', '?', '?', '?', '?'};
bool testComplete = false;
bool cableApproved = true;

#include "KTS_Button.h"
KTS_Button button1(5);
KTS_Button button2(6);
KTS_Button button3(7);

enum States {
  WELCOME = 0,
  TESTING,
  RESULTS,
};

States state = WELCOME;

template<typename T>
void LCDPrint(const T &printThis, int row = 0, bool clear = true) {
  if (clear) lcd.clear();
  lcd.setCursor(0,row);
  lcd.print(printThis);
}
  

void setup() {
  Serial.begin(9600);
  lcd.begin(20, 4);

  for (int i = 0; i < 2; i++) {
    pinMode(outputPins1[i], OUTPUT);
    pinMode(inputPins1[i], INPUT);
  }
  for (int i = 0; i < 5; i++) {
    pinMode(outputPins2[i], OUTPUT);
    pinMode(inputPins2[i], INPUT);
  }
  for (int i = 0; i < 9; i++) {
    pinMode(outputPins3[i], OUTPUT);
    pinMode(inputPins3[i], INPUT);
  }
  displayStartup();
  delay(4000);
  displayWelcome();
}

void displayStartup() {
  LCDPrint("=   Multi Cable   =");
  LCDPrint("       TESTER", 1, false);
  LCDPrint("   support by:	", 2, false);
  LCDPrint("  Arduino Forum", 3, false);
}

void displayWelcome() {
  LCDPrint("  Switch Selector:");
  LCDPrint("  1: BNC Test", 1, false);
  LCDPrint("  2: USB Test", 2, false);
  LCDPrint("  3: REMOTE Test", 3, false);
}

void resetResults() {
  for (int i = 0; i < NUM_PINS; i++)
    results[i] = '?';
}

void runTest() {
  resetResults();
  testComplete = false;

  LCDPrint("====================");
  LCDPrint(" Checking Cable", 1, false);
  LCDPrint(" Please wait...     ", 2, false);
  LCDPrint("====================", 3, false);

  for (count = 0; count < maxTestPins; count++) {
    digitalWrite(*(outputPins + count), HIGH);
    delay(200);


    voltage = digitalRead(*(inputPins + count));

    switch (voltage) {
      case HIGH:
        results[count] = 'P';
        break;

      case LOW:
        results[count] = 'F';
        break;

      default:
        results[count] = '?';
    }

    digitalWrite(*(outputPins + count), LOW);
    delay(10);
  }
}

void displayResults() {
  LCDPrint("-  Test Complete   -");
  
  if (maxTestPins == 2)
    LCDPrint((String)"      1:" + results[0] + " 2:" + results[1], 1, false);

  else if (maxTestPins == 5)
    LCDPrint ((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3] + " 5:" + results[4], 1, false);

  if (maxTestPins == 9)
    LCDPrint ((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3] + " 5:" + results[4] + " 6:" + results[5] + " 7:" + results[6] + " 8:" + results[7] + " 9:" + results[8], 1, false);
    
  cableApproved = true;
  
  for(int i = 0; i < maxTestPins; i++) {
    if (results[i] != 'P') 
      cableApproved = false;
  }
  
  if (cableApproved)
    LCDPrint("     GOOD CABLE   ", 2, false);
  else 
    LCDPrint("     BAD CABLE    ", 2, false);

  LCDPrint("- Press To Restart -", 3, false);

  testComplete = true;
}

void loop() {
  switch (state) {
    case WELCOME:
      if (button1.read() == SINGLE_PRESS) {
        maxTestPins = 2;
        outputPins = outputPins1;
        inputPins = inputPins1;
        state = TESTING;
      }
      if (button2.read() == SINGLE_PRESS) {
        maxTestPins = 5;
        outputPins = outputPins2;
        inputPins = inputPins2;
        state = TESTING;
      }
      if (button3.read() == SINGLE_PRESS) {
        maxTestPins = 9;
        outputPins = outputPins3;
        inputPins = inputPins3;
        state = TESTING;
      }
      break;

    case TESTING:
      runTest();
      state = RESULTS;
      break;

    case RESULTS:
      if (!testComplete) 
        displayResults();

    if (button1.read() == SINGLE_PRESS || button2.read() == SINGLE_PRESS || button3.read() == SINGLE_PRESS) {

        displayWelcome();
        state = WELCOME;
      }
      break;

    default:
      break;
  }

Okay, I've updated that for you:
(Note, I've also updated a few names of some of the variables to things that make more sense. They still do the same thing but have better-suited names now).

After some additional thought, I realised that cross-wire checking was essential. Lets say for example output pin 1 was correctly being received by input pin 1, if that wire also connected to input pin 2 my previous code would have been oblivious to this and passed the wire. This is a fatal flaw that could damage hardware and/or cause harm to a person... and one I've hopefully now fixed!

I've updated the testing process to show P/F/X for Pass/Fail/Cross-wired. And added some comments at the top as to how it's calculated. If you or anyone else see further flaws in this approach PLEASE LET ME KNOW!

Also, I've not been able to test the 9-wire setup, the 2 and 5-wires seem to be working okay but please test (and edge-case test!) these as well as the 9-wire setup before you go using this 'in the wild'.

// #include <LiquidCrystal_I2C.h>

// LiquidCrystal_I2C lcd(0x27, 20, 4);
 
/* 
OVERVIEW:
The LCD shows P (pass), F (fail), X (cross-wired) or ? (invalid) for each wire when checking 
the signal from source to destination (i.e from Output to Input on the Arduino).

In the code there are pin sets of inputs and outputs. A 'wire' is considered an external connection 
from an output pin of the arduino, to an input pin of the arduiino.

PROCESS:
The first output signal is set high. All input pins are monitored and the number of active inputs
are counted. Here are the criteria:

- If no inputs are active that wire is marked as an 'F' (fail)
- If more than one input is active, the wire is marked as 'X' (Cross-Wired)
- If only one input is active but it doesn't match the correct output that wire is marked as 'X' (Cross-wired)
- If only one input is active and it matches the correct output the wire is marked as 'P' (pass)

The first output is then set as low and the process starts over with the second output.

After all output pins have been checked anything other than *'straight P's'* is a bad cable, else the cable is a good cable.
*/

//LCD
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
const uint8_t i2cAddr = 0x27;
const int rs=0, rw=1, en=2, db4=4, db5=5, db6=6, db7=7, bl=3;
typeof(POSITIVE) blpol=POSITIVE; // backlight polarity level
LiquidCrystal_I2C lcd(i2cAddr, en, rw, rs, db4, db5, db6, db7, bl, blpol);

#define ARRAYSIZE(x) sizeof(x)/sizeof(x[0])

// MAX_TEST_WIRES should be the size of the biggest pin set
#define MAX_TEST_WIRES 9

// Be CERTAIN that all 'pin sets' have matching numbers of in vs out elements
int pinSetA_In[] =  {24, 30};
int pinSetA_Out[] = {25, 31};
int pinSetB_In[] =  {22, 30, 38, 40, 46};
int pinSetB_Out[] = {23, 31, 39, 41, 47};
int pinSetC_In[] =  {22, 24, 30, 32, 34, 36, 38, 40, 46};
int pinSetC_Out[] = {23, 25, 31, 35, 33, 37, 39, 41, 47};
int *outputPins;
int *inputPins;
char results[MAX_TEST_WIRES] = {'?', '?', '?', '?', '?', '?', '?', '?', '?'};
int numTestWires;
int count;
int voltage;
bool cableApproved = true;
bool testComplete = false;

#include "KTS_Button.h"
KTS_Button button1(5);
KTS_Button button2(6);
KTS_Button button3(7);

enum States {
  WELCOME = 0,
  TESTING,
  RESULTS,
};

States state = WELCOME;

template<typename T>
void LCDPrint(const T &printThis, int row = 0, bool clear = true) {
  if (clear) lcd.clear();
  lcd.setCursor(0,row);
  lcd.print(printThis);
}
  

void setup() {
  lcd.begin(20, 4);

  for (int i = 0; i < ARRAYSIZE(pinSetA_Out); i++) {
    pinMode(pinSetA_Out[i], OUTPUT);
    digitalWrite(pinSetA_Out[i], LOW);
    pinMode(pinSetA_In[i], INPUT);
  }
  for (int i = 0; i < ARRAYSIZE(pinSetB_Out); i++) {
    pinMode(pinSetB_Out[i], OUTPUT);
    digitalWrite(pinSetB_Out[i], LOW);
    pinMode(pinSetB_In[i], INPUT);
  }
  for (int i = 0; i < ARRAYSIZE(pinSetC_Out); i++) {
    pinMode(pinSetC_Out[i], OUTPUT);
    digitalWrite(pinSetC_Out[i], LOW);
    pinMode(pinSetC_In[i], INPUT);
  }

  displayStartup();
  delay(2000);
  displayWelcome();
}

void displayStartup() {
  LCDPrint("     Multi-Cable    ");
  LCDPrint("  Continuity Tester ", 1, false);
  LCDPrint("     Support by:    ", 2, false);
  LCDPrint("    Arduino Forum   ", 3, false);
}

void displayWelcome() {
  LCDPrint("  Switch Selector:");
  LCDPrint("  1: BNC Test", 1, false);
  LCDPrint("  2: USB Test", 2, false);
  LCDPrint("  3: REMOTE Test", 3, false);
}

void resetResults() {
  for (int i = 0; i < MAX_TEST_WIRES; i++)
    results[i] = '?';
}

void runTest() {
  resetResults();
  testComplete = false;

  LCDPrint("====================");
  LCDPrint("   Checking Cable   ", 1, false);
  LCDPrint("   Please wait...   ", 2, false);
  LCDPrint("====================", 3, false);

  for (count = 0; count < numTestWires; count++) {
    digitalWrite(*(outputPins + count), HIGH);
    delay(10);

    int activeInputs = 0;

    for (int i = 0; i < numTestWires; i++) {
      if (digitalRead(*(inputPins + i)))
        activeInputs++;
    }

      if (activeInputs == 0)
        results[count] = 'F'; 
      else if (activeInputs > 1)
        results[count] = 'X';
      else { // else activeInputs must equal one
        if (digitalRead(*(inputPins + count)))
          results[count] = 'P';
        else results[count] = 'X';
      } 

    digitalWrite(*(outputPins + count), LOW);
    delay(10);
  }
}

void displayResults() {
  if (numTestWires == 2)
    LCDPrint((String)"      1:" + results[0] + " 2:" + results[1]);

  else if (numTestWires == 5)
    LCDPrint((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3] + " 5:" + results[4]);

  if (numTestWires == 9) {
    LCDPrint((String)"1:" + results[0] + " 2:" + results[1] + " 3:" + results[2] + " 4:" + results[3] + " 5:" + results[4]);
    LCDPrint((String)"  6:" + results[5] + " 7:" + results[6] + " 8:" + results[7] + " 9:" + results[8], 1, false);
  }

  cableApproved = true;
  
  for(int i = 0; i < numTestWires; i++) {
    if (results[i] != 'P') 
      cableApproved = false;
  }
  
  if (cableApproved)
    LCDPrint("     GOOD CABLE   ", 2, false);
  else 
    LCDPrint("     BAD CABLE    ", 2, false);

  LCDPrint("- Press To Restart -", 3, false);

  testComplete = true;
}

void loop() {
  switch (state) {
    case WELCOME:
      if (button1.read() == SINGLE_PRESS) {
        numTestWires = 2;
        outputPins = pinSetA_Out;
        inputPins = pinSetA_In;
        state = TESTING;
      }
      if (button2.read() == SINGLE_PRESS) {
        numTestWires = 5;
        outputPins = pinSetB_Out;
        inputPins = pinSetB_In;
        state = TESTING;
      }
      if (button3.read() == SINGLE_PRESS) {
        numTestWires = 9;
        outputPins = pinSetC_Out;
        inputPins = pinSetC_In;
        state = TESTING;
      }
      break;

    case TESTING:
      runTest();
      state = RESULTS;
      break;

    case RESULTS:
      if (!testComplete) 
        displayResults();

    if (button1.read() == SINGLE_PRESS || button2.read() == SINGLE_PRESS || button3.read() == SINGLE_PRESS) {
        displayWelcome();
        state = WELCOME;
      }
      break;

    default:
      break;
  }
}

Now I've spent some time with this code I do think I would like to refactor it. For example, it's risky business and error-prone to assume the button code in various states is set up correctly throughout. If numTestWires ever got out of alignment with the appropriate pin set arrays then it's undefined behaviour.

Maybe a class or struct for the wire test setups would be useful to group these data together so they couldn't be accidentally swapped.

But maybe that's a future project for you :wink: For now, if you test this and you can't find any faults with it then it will do.