Build two short, disconnected 8P8C specimens. A meter will be able to find pin 1 at pin 1, pin 2 at pin 2, and so on in both. Only one specimen keeps the intended conductors together in each twist. The experiment makes that difference visible and gives you a repeatable way to record both observations.
Evidence scope. The pin maps and example output are calculated from the proposed wiring. The Python program was exercised on synthetic files. Build and measure your own specimens to collect readings. Keep both specimens isolated from all network equipment, Power over Ethernet (PoE), phone wiring and wall outlets.
An 8P8C connector has eight positions and eight contacts. It is commonly called RJ45 in Ethernet hardware. A DC resistance reading between two contacts asks whether there is a low-resistance path. A twisted pair is two insulated conductors physically wound around each other. The pair may be hidden inside the jacket even when you can identify both ends of each conductor.
The T568A and T568B arrangements assign colors to the same four intended pin groups: 1–2, 3–6, 4–5 and 7–8. In a split pair, a logical pin group contains conductors from two different physical twists. Fluke Networks illustrates exactly this failure, including a case with correct end-to-end continuity. Closely twisting the two conductors of a differential signal helps them couple similarly to surrounding fields. Splitting the group changes that geometry and can increase crosstalk. This experiment records the wire map and construction. A pair-aware cable instrument measures separate electrical properties.

With each adapter loose and unplugged, confirm which terminal reaches each plug contact. DFRobot’s specification lists terminal sequence 3, 4, 5, 2, 1, 6, 7, 8. The product image shows wire numbers in a different order. Verify the mapping on each unit with the meter and fine probes without bridging adjacent contacts. Label the terminals by the connector contacts they actually reach. All numbers in the figures, table and CSV refer to those verified contact identities. Check that the loose terminals have no unintended low-resistance connections. Stop if you cannot identify all eight contacts reliably.
Label both ends A and B. Follow Leviton’s jacket removal, 110 punchdown and dust cap directions. Keep pair twisting to within ½ in (about 13 mm) of the contact where the routing permits, and keep the jacket against the rear as shown in the instructions. Trace each stripe while the twist is visible. When a stripe or mate is uncertain, record it as unknown. The intentionally faulty specimen is a teaching prop. Mark it SPLIT — DO NOT USE on both ends.
The table applies at both ends of each specimen. The 5G108’s IDC slots are physically staggered. Find the printed pin number for each row before seating a conductor. The split specimen exchanges the white/green and white/blue conductors on pins 3 and 5, at both ends. The solid blue and solid green wires stay on pins 4 and 6.
| Pin | Control at A and B | Split at A and B |
|---|---|---|
| 1 | WO (white/orange) | WO |
| 2 | O (orange) | O |
| 3 | WG (white/green) | WBL (white/blue) |
| 4 | BL (blue) | BL |
| 5 | WBL (white/blue) | WG (white/green) |
| 6 | G (green) | G |
| 7 | WBR (white/brown) | WBR |
| 8 | BR (brown) | BR |

For an unspliced specimen, a conductor gives one connection from its A contact to its B contact. In the control, white/green connects 3 to 3. In the split specimen, white/blue takes its place at both ends, so 3 still connects to 3. The same reasoning holds for pin 5. In the control, green occupies 3–6 and blue 4–5. In the split specimen, blue occupies 3–4 and green 5–6. Each intended group now draws one wire from each physical pair.
remote_pins cell for each A row. Record 3 for one match, 3|5 for more than one, or - when none of the eight contacts gives continuity. Leave unfinished entries blank until measured. The color columns describe the physical conductor on the same numbered contact at each end, regardless of which remote pin matches. Use ? for an uncertain color.The cable overview gives examples of how conductor construction varies by application. The short RS-485 lesson gives a separate example of using a physical twist for a differential signal. Cable overview · Differential RS-485 bench link
Use Python 3.9 or later. The archive contains the program, both synthetic specimens, the blank worksheet, both original diagrams and executable host tests. Run the shipped examples first, then give your own complete worksheet a different filename. The provenance switch records your choice in the JSON.
python3 wire_map.py --kind synthetic synthetic-control.csv
python3 wire_map.py --kind synthetic synthetic-split.csv
python3 wire_map.py --kind observed control-readings.csv
The two synthetic examples produce continuity: straight with identical remote_pins. The control gives pair_evidence: paired and T568B at both ends. The deliberate swap gives pair_evidence: split and lists both affected groups at each end. A bijective map other than identity is one_to_one_nonstraight. Zero or several matches in a row, or reusing a remote pin, gives open_or_multilink. The program accepts a detected wiring fault as an observation and reserves exit status 2 for bad input.
A known split remains visible when another group is unknown. With no known split, unknown groups make the pair result incomplete. For a one-to-one map the tool checks color identity along each link where both colors are known. If A3 measures through to B3 but they have different colors, recheck both adapter labels and observations before interpreting the pair report. A single uninterrupted conductor should keep its identity. The reported colors come from your visual observations.
#!/usr/bin/env python3
"""Compare cross-end continuity and visible twist membership in an 8P8C fixture."""
import argparse
import csv
import json
from pathlib import Path
PINS = tuple(range(1, 9))
GROUPS = ((1, 2), (3, 6), (4, 5), (7, 8))
COLORS = ('WO', 'O', 'WG', 'G', 'WBL', 'BL', 'WBR', 'BR')
PAIR = dict(zip(COLORS, ('orange', 'orange', 'green', 'green', 'blue', 'blue', 'brown', 'brown')))
T568A = ('WG', 'G', 'WO', 'BL', 'WBL', 'O', 'WBR', 'BR')
T568B = ('WO', 'O', 'WG', 'BL', 'WBL', 'G', 'WBR', 'BR')
HEADER = ['pin', 'remote_pins', 'a_color', 'b_color']
PIN_TEXT = tuple(map(str, PINS))
def read_matrix(path):
"""Read complete thresholded observations. A blank is an unfinished reading."""
remotes, a_colors, b_colors = {}, {}, {}
with path.open(encoding='utf-8-sig', newline='') as stream:
rows = csv.reader(stream, strict=True)
if next(rows, None) != HEADER:
raise ValueError('expected header: ' + ','.join(HEADER))
for row in rows:
if len(row) != len(HEADER):
raise ValueError('every data row must have four fields')
pin_text, remote_text, a_color, b_color = (value.strip() for value in row)
if pin_text not in PIN_TEXT:
raise ValueError(f'pin must be 1 through 8 at line {rows.line_num}')
pin = int(pin_text)
if pin in remotes:
raise ValueError(f'duplicate pin {pin}')
items = [] if remote_text == '-' else remote_text.split('|')
if any(item not in PIN_TEXT for item in items):
raise ValueError(f'pin {pin}: remote pins must be 1–8 separated by |, or - for none')
if len(items) != len(set(items)):
raise ValueError(f'pin {pin}: repeated remote pin')
if any(color not in (*COLORS, '?') for color in (a_color, b_color)):
raise ValueError(f'pin {pin}: color must be one of {", ".join(COLORS)} or ?')
remotes[pin] = sorted(map(int, items))
a_colors[pin] = a_color
b_colors[pin] = b_color
if len(remotes) != len(PINS):
raise ValueError('the matrix must contain all eight pins')
for label, colors in (('A', a_colors), ('B', b_colors)):
known = [color for color in colors.values() if color != '?']
if len(known) != len(set(known)):
raise ValueError(f'end {label}: repeated known color')
return remotes, a_colors, b_colors
def end_wiring(colors):
sequence = tuple(colors[pin] for pin in PINS)
if '?' in sequence:
return 'unknown'
if sequence == T568A:
return 'T568A'
if sequence == T568B:
return 'T568B'
return 'other'
def inspect_pairs(colors):
result = []
for pair in GROUPS:
a, b = (colors[pin] for pin in pair)
if '?' in (a, b):
status = 'unknown'
else:
status = 'paired' if PAIR[a] == PAIR[b] else 'split'
result.append({'pins': list(pair), 'colors': [a, b], 'status': status})
return result
def analyze(remotes, a_colors, b_colors, kind):
destinations = [dst for pin in PINS for dst in remotes[pin]]
one_to_one = (all(len(remotes[pin]) == 1 for pin in PINS)
and sorted(destinations) == list(PINS))
if not one_to_one:
continuity = 'open_or_multilink'
elif destinations == list(PINS):
continuity = 'straight'
else:
continuity = 'one_to_one_nonstraight'
pairs = {'A': inspect_pairs(a_colors), 'B': inspect_pairs(b_colors)}
statuses = {row['status'] for end in pairs.values() for row in end}
pair_evidence = 'split' if 'split' in statuses else (
'incomplete' if 'unknown' in statuses else 'paired')
compared = 0
mismatches = []
for a_pin, b_pin in zip(PINS, destinations) if one_to_one else ():
a_color, b_color = a_colors[a_pin], b_colors[b_pin]
if '?' in (a_color, b_color):
continue
compared += 1
if a_color != b_color:
mismatches.append({'a_pin': a_pin, 'b_pin': b_pin, 'a_color': a_color, 'b_color': b_color})
if not one_to_one:
color_trace = 'not_evaluated'
elif mismatches:
color_trace = 'inconsistent'
else:
color_trace = 'consistent' if compared == len(PINS) else 'incomplete'
return {
'kind': kind,
'continuity': continuity,
'remote_pins': {str(pin): remotes[pin] for pin in PINS},
'end_wiring': {'A': end_wiring(a_colors), 'B': end_wiring(b_colors)},
'pair_status': pairs,
'pair_evidence': pair_evidence,
'color_trace': color_trace,
'colors_compared_across_ends': compared,
'color_mismatches': mismatches,
'scope': 'One disconnected, unspliced specimen. No link performance or certification claim.',
}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--kind', choices=('synthetic', 'observed'), required=True,
help='operator-supplied provenance for the CSV')
parser.add_argument('csv', type=Path, help='complete wire-map worksheet')
args = parser.parse_args()
try:
result = analyze(*read_matrix(args.csv), args.kind)
except (OSError, UnicodeError, csv.Error, ValueError) as exc:
parser.error(str(exc))
print(json.dumps(result, indent=2))
if __name__ == '__main__':
main()
Blank worksheet · Synthetic control · Synthetic split pair · Complete experiment and tests ZIP
Suppose you exchange the white/green and white/blue conductors at end B only. Which A rows change? Which end has the split pair?
A3 now reaches B5 on white/green and A5 reaches B3 on white/blue. All other links stay in place. The map remains one-to-one but becomes nonstraight. A is still paired. At B, intended groups 3–6 and 4–5 mix the blue and green twists.