I don't have a switch in the sketches but i can add if i am able to run between input pin are 2,3,4,5 (e.g.)
As of now, i am running this script loop. (No switch)
so there's no way for the code to know which routine to run?
Not needed
why?
are you trying to suggest that the 4 conductor test is always performed and if the results match the 2 conductor configuration it recognizes that that must be the cable plugged in?
the 3rd and 4th conductors are open and there are no cross connects to those pins
Had a little mess around... So as you'll see in the Wokwi below there are two buttons left/right. The left conducts a 2-Pin test the right conducts a 4-Pin test, then you press either button to go back to the selection screen.
https://wokwi.com/arduino/projects/313193014357918274
#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define NUM_PINS 4
int outputPins[] = {2, 3, 4, 5}; // For testing in Wokwi I've wired pins 2 to 22 and 5 to 25
int inputPins[] = {22, 23, 24, 25};
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 < NUM_PINS; i++) {
pinMode(outputPins[i], OUTPUT);
pinMode(inputPins[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;
state = TESTING;
}
if (button2.read() == SINGLE_PRESS) {
maxTestPins = 4;
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;
}
}
Comments/criticism welcomed! - I'm always trying to learn more and improve.
Hi Steve,
Very interesting both posts, it looks like code i want. Let me try over weekend and let you know. Appreciate your time.
G.night
Yeah, give the one in post #27 just above a go (much better ideas I think) and let me know if it works or not.
This is my setup, very simple and straightforward. I have the tester running without switch. Basically, it's running in real time hot pluggable. When you connect both ends it tells me the result without extra step or switches. But this only work with 1 sketch. My 2nd sketch similar to 1st one for 2 pins instead of 4. I want to add a switch between 2pin or 4pin just like @anon46966594 described.

Hi Steve,
you're genius! it does work! but you had it swap. The right button 4-pin Test results = 2 Pin
and left button 2-pin test results = 4 pin
![]()
I will switch them back... and do more test... but, Can I assign 4/4 to different pin than 2/4?
Example:
int outputPins[] = 2, 3 ////// 2 pin cable
int inputPins[] = 22, 23 ////// 2 pin cable
int outputPins[] = 44, 45, 46, 47 ////////// 4 pin cable
int inputPins[] = 34, 35, 36, 37 ////////// 4 pin cable
Thanks
Code seems fine in the example and Wokwi, maybe you've wired them backwards?
Sure you could do this:
https://wokwi.com/arduino/projects/313193014357918274
#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 < 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 (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;
}
}
now that st3v3n92 has pointed out that the one test is a subset of the other and that there is an external switch for selecting the test, i was wonder how the results are indicated
for a Bad cable, wouldn't you want to indicate which connections are open or mis-wired
consider this approach for testing which repeated indicates the open and crossed connections. a test can be repeated by pressing reset
#define MyHW
#ifdef MyHW
# include "sim.h"
#else
#endif
LiquidCrystal_I2C lcd(0,0, 0);
byte endA [] = { 22,24,26,28 };
byte endB [] = { 23,25,27,29 };
#define N_Apins sizeof(endA)
#define N_Bpins sizeof(endB)
int connects [N_Apins][N_Bpins] = {};
enum { Off = LOW, On = HIGH };
char s0 [20];
char s1 [20];
// -----------------------------------------------------------------------------
void lcdDisp (
char *s0,
char *s2 )
{
#if 0
Serial.print (s0);
Serial.print (" ");
Serial.println (s1);
#endif
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print (s0);
if (NULL != s1) {
lcd.setCursor (0, 1);
lcd.print (s1);
}
}
// -----------------------------------------------------------------------------
#define DispDelay 1000
void analyze ()
{
int bad = 0;
for (unsigned out = 0; out < N_Bpins; out++) {
for (unsigned inp = 0; inp < N_Apins; inp++) {
if (inp == out && ! connects [inp][out]) {
bad ++;
sprintf (s0, "pin %d open", inp);
lcdDisp (s0, NULL);
delay (DispDelay);
}
if (inp != out && connects [inp][out]) {
bad ++;
sprintf (s0, "pins %d %d crossed", inp, out);
lcdDisp (s0, NULL);
delay (DispDelay);
}
}
}
if (! bad) {
sprintf (s0, "GOOD CABLE");
lcdDisp (s0, NULL);
delay (DispDelay);
}
}
// -----------------------------------------------------------------------------
void
loop () {
analyze ();
}
// -----------------------------------------------------------------------------
void test ()
{
for (unsigned out = 0; out < N_Bpins; out++) {
digitalWrite (endA [out], On);
for (unsigned inp = 0; inp < N_Apins; inp++)
connects [inp][out] = digitalRead (endB [inp]);
digitalWrite (endA [out], Off);
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
lcd.begin(20, 4);
if (N_Apins != N_Bpins) {
lcdDisp ((char *)"unequal in/out pins", NULL);
}
else {
for (unsigned i = 0; i < N_Apins; i++) {
digitalWrite (endA[i], Off);
pinMode (endA[i], OUTPUT);
pinMode (endB[i], INPUT_PULLUP);
}
test ();
}
}
Yeah in my interpretation it displays a series of either pass (p) or fail (f) for each pin depending on if the pin was read as high or low.
So on the LCD 1:P 2:F 3:P 4:P indicates that 3/4 wires received the high signal and that wire 2 failed.
what about mis-wired cross connects?
The code sets all pins low... Then each pin high, checks the receiving side then sets its low again.
So unless I've misunderstood, if pin 1 was crosswired to pin 3 and back, then the receiver of pin 1 will still report the error, as will pin 3.
guess the test doesn't tests for shorts between pins ?!
Surely if all pins are low except one at a time, there will be no accidental high signals getting to the receiving end of the pin being checked? That pin is either getting the correct HIGH or it isn't, no?
Pardon my naivety but am I misunderstanding this?
You got me! Sorry i had my switch block upside-down. I see you have assigned different pins for i/o #1 and i/o #2. Just like @gcjr mentioned if i can see miswires or short? My original code would show X...
Let me play more with the new code again and let you guys know the outcome.
Btw, i changed to LCD 20x4 for more line "Welcome"
Thanks
Good idea! Passed Pin would show Fail.
Can you please describe this in full detail so I can understand better? Which pins are passing/failing/which ones are crossed... Which ones are high/low
