Best way to make a cable tester?

Hi

I'm trying to figure out what way to make a cable tester using an arduino Mega.

I have to test a lot of cable bundles to test after a field test at work, with about 31 cables totally going from 3 connectors to 4 connectors on the other side. I don't want to use LED or something like that to check continuity.On each connector on the input side all pins go in to the same input. I want to sweep fast all 31 pins on the "3 connectors" over and over again and make the arduino able to detect if :

  • a wire is broken
  • a wire goes to the wrong connector

For example: Pin 4 on connector B goes to connector E and F pin 4 and 2. I put output HIGH on that pin, and should have HIGH on the input pins for connector B and C. otherwise something is wrong.

Therefore I only need 4 inputs and 31 outputs . That way i can detect the most likely type of error (broken wire)

I was experimenting today, didn't get it to work, and was unable to find much on google.

1. Is it possible to connect an output directly to an input on the same arduino? Should I have a current limiter in series?
** 1a. or do I need 2 arduinos for this application?**
2. Or can I use transistors, if so. How?
3. Or do i need to use relays (slow)

drawing:

31 OUT 4 IN

A---------------------D
B------I--------------E
C------I--------------F
I-------------G

Thanks in advance

More people than You have asked about the same project, cable testing, in recent time. Have You been searching Forum for those topics?

Looks like about 1,600 threads here so take your pick - check several out and probably get a head start

https://www.google.com/search?ie=UTF-8&oe=UTF-8&q=cable+tester&domains=https%3A%2F%2Fforum.arduino.cc&sitesearch=https%3A%2F%2Fforum.arduino.cc

Yes you will need some resistors to keep thing from floating and giving you erratic results - the built in resistors might work

Thanks for the replies

I have been searching, yes.
Even though I am doing a cable tester, my question is more about how to connect an output to an input. with/without resistors, with/without pulldown resistors. That is what I had trouble finding. I will try harder

needlegate:
Even though I am doing a cable tester, my question is more about how to connect an output to an input.

I normally use a piece of wire for that.

If I understand correctly, the four-connector side of the cable is the "input" and for each of those four connectors you don't care if any of the (unspecified number of) input pins are shorted together?

johnwasser:
If I understand correctly, the four-connector side of the cable is the "input" and for each of those four connectors you don't care if any of the (unspecified number of) input pins are shorted together?

Correct, at the moment at least. My idea is that is I send a HIGH on pin 1 in connector A, and get a response on the correct connector on the input side, it is very likely that the cable is correct.

There are 42 cables on the input side and more 30 on the output. And I dont have 70+ pins on a mega.

My plans for future modifications is to use one mega as output and one mega as input. So it can be used not only for better checks on completed cables, but also used in the manufacturing to see if it was correctly made.

For the moment I know they are correctly made, because they have been used on diesel engines.

You don't need a Mega, any 328P board will do.
You just need some TPIC6C595 shift-out registers as outputs, and 74HC165 shift-in registers as inputs. Have pullup resistors on the '165 inputs.

You shift a pattern into the tpic6c595 with 1 low output, and read the 74hc165s. There should only be 1 low input (assuming the connections are made 1 to 1). All 1s indicate no connection, a 0 in the wrong place indicates a miswire, two 0s indicate a short, etc.

The '6c595s have open drain outputs, so if an output is shorted to Gnd there will be no issue, the output can only pull low anyway. The pullup resistor provides the high signal, so if a line shorted to Gnd, there is no issue.

Depending on how many inputs you had, you could use the tpic6c595 to provide the outputs to drive the cables, and perhaps the Mega with its internal pullups as the inputs instead of the hc165.

update!

I not have a working device that works perfectly and have already saved us lots of hours.
It uses 16 outputs and reads 16 inputs, only straight cables. For example out-pin 1 → in-pin 1 = ok
out-pin 1 → in-pin 2 = not ok.

I have adaptors for every type of cable we check. If the cable has more than 16 wires, I test it in steps with several adaptors.

I can chose the number of pins with a knob and the result gets displayed. and to reset a previous error i have a reset button.

For the future I’m thinking about a saving option, you plug in a cable you know is correct and save the result on the eeprom. that way special cables will be ok to check and you dont have to think so much when you make the adaptors.

The code is a bit messy, its work in progress every day more or less

#include <LiquidCrystal.h>
const int input[16] = {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
const int output[16] = {15, 14, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17 };
const int green = 24;
const int yellow = 25;
const int red = 26;
const int reset = 27;
bool reset_state;
const int num_pin = 16;
bool readings[16][16];
bool init_readings[16];
int encoder0PinA = 28;
int encoder0PinB = 29;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
LiquidCrystal lcd(30, 31, 32, 33, 34, 35);
void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);
  Serial.println("online");
  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(reset, INPUT);
  for (int i = 0; i < num_pin; i++) {
    pinMode(input[i], INPUT);
    pinMode(output[i], OUTPUT);
  }

}

void loop() {
  unsigned long cT = millis();
  // startup(cT);
  bool start_complete = true;
  unsigned long last_motion;
  int display_enc_value = 0;
  bool error_detected = false;
  bool last_display_state;
  while (start_complete)
  {
    cT = millis();
    read_inputs();

    if (reset_state == HIGH) {
      save_readings();
      error_detected = false;
    }

    if (motion_detection(cT, last_motion )) { // changes enc_val
      last_motion = cT;
      lcd.clear();
    }

    bool lds = last_display_state;
    if (cT - last_motion < 1000) {  //what to display
      lcd_display(true);
      last_display_state = true;
    } else {
      lcd_display(false);
      last_display_state = false;
    }

    if (lds != last_display_state) {  // change of state
      lcd.clear();
    }

    bool alright =  evaluate_readings(encoder0Pos, false);
    if (alright == false) {
      error_detected = true;
    }

    lights(alright, error_detected);



  }

}


void lcd_display(bool display_encoder) {
  if (display_encoder == true) {
    lcd.setCursor(0, 0);
    lcd.print("Antal pins: ");
    lcd.print(encoder0Pos);
  } else if (display_encoder == false) {
    lcd.setCursor(0, 0);
    for (int i = 0; i < num_pin; i++) {
      if (i < encoder0Pos) {
        lcd.setCursor(i, 0);
        lcd.print("1");
      } else {
        lcd.setCursor(i, 0);
        lcd.print("0");
      }
      lcd.setCursor(i, 1);
      lcd.print(readings[i][i]);
    }
  }
}




void save_readings() {

  for (int in = 0; in < num_pin; in++) {
    init_readings[in] = digitalRead(input[in]);
  }

}

bool encoder_read() {   //changes encoder0Pos and returns true if motion detected
  bool motion_detect = false;
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {

    if (digitalRead(encoder0PinB) == LOW) {
      motion_detect = true;
      encoder0Pos--;
    } else {
      encoder0Pos++;
      motion_detect = true;
    }

  }
  if (encoder0Pos > 16)
    encoder0Pos = 16;

  if (encoder0Pos < 1)
    encoder0Pos = 1;

  encoder0PinALast = n;

  return motion_detect;
}





void startup(unsigned long sT) {
  unsigned long cT = millis();
  bool tick_on = false;
  unsigned long last_tick;
  byte blinkOn = 0;
  while (cT - sT < 2000)
  {
    cT = millis();
    if (cT - last_tick > 250) {
      last_tick = cT;
      tick_on = true;
    }
    unsigned long tick = millis();
    lcd.setCursor(0, 0);
    lcd.print("    martins");
    lcd.setCursor(0, 1);
    lcd.print("  kabeltestare");

    if (tick_on) {
      blinkOn = (blinkOn + 1) % 3;
      tick_on = false;
    }
    digitalWrite(red, LOW);
    digitalWrite(green, LOW);
    digitalWrite(yellow, LOW);
    digitalWrite(24 + blinkOn, HIGH);


  }
  lcd.clear();
  digitalWrite(green, LOW);
  digitalWrite(yellow, LOW);
  digitalWrite(red, LOW);
}
void lights(bool readings_ok, bool error_detected ) {
  if (readings_ok && !error_detected) { // no error, and nothing detected
    digitalWrite(green, HIGH);
    digitalWrite(yellow, LOW);
    digitalWrite(red, LOW);
  } else if (readings_ok && error_detected) {
    digitalWrite(green, LOW);
    digitalWrite(yellow, HIGH);
    digitalWrite(red, LOW);
  } else if (!readings_ok && error_detected) {
    digitalWrite(green, LOW);
    digitalWrite(yellow, LOW);
    digitalWrite(red, HIGH);
  }
}

bool evaluate_readings(int pins, bool special) { //returns true if ..etc (for straight connections (1-1,2-2..)
  bool correct = true;
  if (!special) {
    for (int out = 0; out < num_pin; out++) {
      for (int in = 0; in < num_pin; in++) {
        if (out < encoder0Pos) {//cares only about pins that are selected
          if (out == in) {
            if (readings[out][in] != 1) {
              correct = false;
            }
          }
          if (out != in) {
            if (readings[out][in] == 1) {
              correct = false;
            }
          }
        } else {

        }
      }
    }
  } else if (special) {
    for (int i = 0; i < num_pin; i++) {
      if (readings[i][i] != init_readings[i]) {
        correct = false;
      }
    }
  }
  return correct;
}

void read_inputs() {  // reads all inputs always
  reset_state = digitalRead(reset);
  for (int out = 0; out < num_pin; out++) {
    digitalWrite(output[out], HIGH);
    for (int in = 0; in < num_pin; in++) {
      readings[out][in] = digitalRead(input[in]);
    }
    digitalWrite(output[out], LOW);
  }
}
bool motion_detection(unsigned long cT, unsigned long last_motion) {
  bool motion_detect = encoder_read();
  if (motion_detect) {
    last_motion = cT;
  }
  return motion_detect;
}

I recommend that you make your testing more robust by setting all 32 pins to INPUT_PULLUP and then making each pin in turn OUTPUT and LOW. That way you can make sure that every input and every output is only connected to the corresponding pin at the other end. This sketch tests 1 to 16 pins in turn and reports how far it got before it discovered a problem. If you cable has 7 pins and it finds the first problem at 8 pins then your cable is OK. :slight_smile:

const byte NumPins = 16;


const int InputPins[NumPins] = {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
const int OutputPins[NumPins] = {15, 14, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17 };


void setup()
{
  for (int i = 0; i < NumPins; i++)
  {
    pinMode(InputPins[i], INPUT_PULLUP);
    pinMode(OutputPins[i], INPUT_PULLUP);
  }


  // Test until a failure is found or until all possibler lines are tested.
  for (int i = 1; i < NumPins; i++)
  {
    if (TestCable(i))
    {
      Serial.print("Failed at pin ");
      Serial.println(i + 1);
      Serial.println("Press reset to test another cable.");
      break;
    }
  }
}


void loop() {}


boolean TestCable(int pinCount)
{
  boolean failure = false;


  // Probe the input side
  for (int i = 0; i < pinCount; i++)
  {
    // Temporarily set the mode to OUTPUT
    pinMode(InputPins[i], OUTPUT);
    digitalWrite(InputPins[i], LOW);  // Pull the pin, and anything it is connected to, LOW
    
    // Check for connections to the input side pins
    for (int i2 = 0; i2 < pinCount; i2++)
    {
      if (i2 == i)
        continue;  // Skip the input pin itself


      if (digitalRead(InputPins[i2]) == LOW)
      {
        Serial.print("Input Pin ");
        Serial.print(i + 1);
        Serial.print(" is shorted to Input Pin ");
        Serial.print(i2 + 1);
        failure = true;
      }
    }


    // Check for connections to the output side pins
    for (int o2 = 0; o2 < pinCount; o2++)
    {
      if (o2 == i)
      {
        // This wire is SUPPOSED to be here
        if (digitalRead(OutputPins[o2] != LOW))
        {
          Serial.print("Open wire on pin ");
          Serial.print(i + 1);
          Serial.println(" Input to Output");
          failure = true;
        }
      }
      else if (digitalRead(OutputPins[o2]) == LOW)
      {
        Serial.print("Input Pin ");
        Serial.print(i + 1);
        Serial.print(" is shorted to Output Pin ");
        Serial.print(o2 + 1);
        failure = true;
      }
    }


    pinMode(InputPins[i], INPUT_PULLUP);  // Set the mode back
  }




  // Probe the output side
  for (int o = 0; o < pinCount; o++)
  {
    // Temporarily set the mode to OUTPUT
    pinMode(OutputPins[o], OUTPUT);
    digitalWrite(OutputPins[o], LOW);  // Pull the pin, and anything it is connected to, LOW


    // Check for connections to the input side pins
    for (int i2 = 0; i2 < pinCount; i2++)
    {
      if (i2 == o)
      {
        // This wire is SUPPOSED to be here
        if (digitalRead(InputPins[i2] != LOW))
        {
          Serial.print("Open wire on pin ");
          Serial.print(o + 1);
          Serial.println(" Output to Input");
          failure = true;
        }
      }
      else if (digitalRead(InputPins[i2]) == LOW)
      {
        Serial.print("Output Pin ");
        Serial.print(o + 1);
        Serial.print(" is shorted to Input Pin ");
        Serial.print(i2 + 1);
        failure = true;
      }
    }


    // Check for connections to the output side pins
    for (int o2 = 0; o2 < pinCount; o2++)
    {
      if (o2 == o)
        continue;   // Skip the output pin itself


      if (digitalRead(OutputPins[o2]) == LOW)
      {
        Serial.print("Output Pin ");
        Serial.print(o + 1);
        Serial.print(" is shorted to Output Pin ");
        Serial.print(o2 + 1);
        failure = true;
      }


    }
    pinMode(OutputPins[o], INPUT_PULLUP);  // Set the mode back
  }
  return failure;
}

johnwasser:
I recommend that you make your testing more robust by setting all 32 pins to INPUT_PULLUP and then making each pin in turn OUTPUT and LOW. That way you can make sure that every input and every output is only connected to the corresponding pin at the other end. This sketch tests 1 to 16 pins in turn and reports how far it got before it discovered a problem. If you cable has 7 pins and it finds the first problem at 8 pins then your cable is OK. :slight_smile:

[

Could you explain that a little deeper for a slow thinking creature? :slight_smile:

What is the weakness with my solution, and what is the strength with yours?

I set first output high, read all inputs and stores that in a 2D-array. Then set the output low and move to next output. What could go wrong there?
if "" is true and [any other number] is false would return true, else false.
I cant see how anything else but a 5v feed from somewhere else in the exact same milli second would give a false result. And that is nearly impossible.
I should also add that i have never used input_pullup and have only read about it just now.

I know this is an old thread.
In a short while, I’m going to design my tester so for now, I can test the cables on my CRAPPY 3D printer. LOL :o

I like the ideas here, but I think I’m going to add some extra testing.

I’m thinking of adding a test, that if the wire passes continuity, then each line’s resistance will be tested as well.
Then, compare all the resistances to find is any one wire has a higher or lower resistance than the others (by a certain factor).

I’m also considering adding a PWM signal to measure reaction to a pulsed signal.
That might be able to detect a kink in a wire, I think.

Anyway, it’s a fun project, but important when you run into issues with 3D pritners.

OK, my circuit for this is in another post, it may take a while to find it.

The trick is that you are talking about very low resistance (milliohms), so you need to be able to pass substantial currents through the wires, of the order of one Amp, which is well beyond the capability of the Arduino itself.

It also means that if you use semiconductors such as FETs (well, it would have to be FETs) to perform the switching rather than relays (which are unduly cumbersome), you have to compensate for the "resistance" of the FETs.

How many wires at once?

TDR is not going to be practical on cables shorter than several feet. How long are yours?

Way out of the box...
If you set the pin as an output drive it high.
Set it as an input and watch the voltage you can test capacitance

Wire ampacity
Based on wire diameter
With a power supply
And a load.
Wire will het warn at the right combination
Voltage will drop between wire and load depending on conditions.

dave-in-nj:
If you set the pin as an output drive it high.
Set it as an input and watch the voltage you can test capacitance

Not what was asked, however if you do want to test capacitance, you need a reference resistor to actually discharge the capacitance. For large capacitances, this could be the internal pullup, otherwise it will be in the Megohm range.

Paul__B:
Not what was asked,

PWHT (poster who hijacked thread) said he wanted to add features.
Basic cable testing is for continuity.
What properties does a cable have?
Ampacity
Resistance
Capatance
Induction
What are the major problems with cables?
Bad connections
Shorted
Open
If the request is for more testing functions such as was asked of how to test for a kinked cable... then Some additional circuits aare Needed
The phone company can tell how long a wire is ffrom Only one end and an open circuit.

dave-in-nj:
The phone company can tell how long a wire is ffrom Only one end and an open circuit.

Yes, using a TDR as per #12.

As has been discussed before, not really an Arduino project.