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
For now, if you test this and you can't find any faults with it then it will do.