Monday, 15 December 2025

Updating a 25 Year old Test Rig!

I recently (about six months ago) had to update a high power test rig.  The original test rig had been in service for over 25 years and was showing its age.  It wasn't working properly due to interference from external sources which was causing the control of the test equipment to malfunction.

The rig was used to control a power converter product during temperature and vibration stress testing.  The power converter itself would receive electrical energy from an external source and then use this electricity to generate a very stable 28 V dc which was then used to power sub systems.  I cannot provide the specific function as it is proprietary.

I won't share a photo of the units under test as that is also proprietary.  I can however discuss how the test rig was originally implemented using some custom hardware and various pieces of off the shelf instrumentation to achieve the various test signals and routines required as this is fairly standard for any test rig.

The device under test is essentially a very high power switch mode buck boost converter which takes in a range of voltage inputs and provides a steady output at a range of power requirements as needed.  Various outputs are also monitored to ensure that the device under test does not change state whilst under test.

The test regime required several different test conditions to be satisfied but essentially relied on the control of two HP 6681A power supplies to provide the simulated electrical supply from the external source. The unit under test was powered by these supplies and combined with a switch box which would satisfy the input signals needed. A large external load provided the standard operating conditions the unit would be exposed to and the outputs present would be monitored by a data-logger.

The original test rig is below:

The image shows several pieces of test equipment - 5x lab power supplies which were used to power and control the test rig, the 2x high power power supplies used to provide the power to the devices under test and 2x high power resistive loads.  A Keysight data-logger is used to monitor the device under test outputs and the data is displayed on the fly on the computer monitor on the top shelf.

The critical part of the system was the device which provided the voltage profile to control the 2x large high power supplies which we shall call the profile generator.

A rough diagram of the test rig is below:

The profile generator is the key part of the system as it is that which controls the power supply to the device under test. The signal required was a slowly changing ramp signal which began at 24.5 V dc and reduced to 12 V dc in a second and then slowly increased over 18 seconds back up to 24.5 V dc simulating a specific start condition.  The unit under test had to maintain its 28 V dc output  under load during this ramp without any of the outputs being affected.  

The original profile generator was in a very sorry state.  It had been constructed on strip board and was showing its age.  The circuitry used was also very out-dated and contained 555 timers (one of my favourite devices), 741 Operational amplifiers and an TTL logic counters used to create the time period needed to produce the ramp.  The profile of the ramp itself was hard coded with a UV erasable EEPROM, the output of which was passed to a DAC08 digital to analogue converter.  I should state that I have no issue with this implementation as it had worked for many many years without issue.  It was only recently found to be affected by external interference due to the test rig being moved from one part of the building to another.  A photo of the original profile generator is below:

There was unfortunately not a great deal of documentation for the profile generator and it had been repaired on several occasions.  The operational amplifier circuitry required positive and negative supplies which had been mis-connected a few times which destroyed the linear regulators and often took out the 555 timer and the op-amps as well. 

For weeks I attempted to find out what was causing the issue with the test rig.  The profile generator output was a negative voltage signal between 0 and -5 V dc.  This signal was passed to the voltage control input of the HP 6681A which in turn controlled the output between 12 V dc and 24.5 V dc. Various probing of points within the system with an oscilloscope showed some spurious signals which no amount of filtering or cable screening could remove. A photo of an oscilloscope trace showing the spurious signal is below:


Once I realised that I couldn't fix the current rig I decided to record the output of the original profile generator and reproduce it somehow.  I disconnected the profile generator from the test rig and recorded the output with an oscilloscope and a data-logger which allowed me to obtain the profile in comma separated values.  The traces recorded by the oscilloscope are below, the yellow trace is the output from the power supply (12 V dc to 24.5 V dc), the blue trace is the voltage control signal from the profile generator (0 V dc to -5 V dc).


From this recording I tried to program an arbitrary function generator to produce the required waveform.  Unfortunately this was also affected by the same spurious interference signal which plagued the original profile generator.  

At this point I had a bit of an epiphany and decided to use the recording of the signal to program a microcontroller with a built in digital analogue converter (DAC).  As I had one available, I used an Arduino R4.  This development board is normally used by hobbyists and students but is a perfectly functional microcontroller and is very well supported and fairly easy to program.  

The specifications of the arduino R4 are here: Arduino R4 Datasheet

The Arduino R4 had a 10 bit DAC and an op-amp which I could use to buffer the signal if needed.  It was helpfully a 5 V dc device as well which meant I could interface it with the HP Power supply without any extra circuitry or voltage manipulation required.

The first thing I did was write some code to create the voltage profile required. I had to convert the recorded 5 V dc CSV data to 1023 bit values to be able to produce the profile required but this was easily achieved with a spreadsheet formula. The microcontroller firmware worked like this:

1. Check if a trigger signal has been received.

2. If trigger is present output the voltage ramp over 18 seconds creating the ramp from hard coded bit values calculated from comma separated values recorded.

3. Light an LED to show that the profile generator is active to provide visual feedback to an operator.

4. Loop back to number 1.

I then tested the system and found it worked perfectly.  I then re-read all of the test requirements and specifications to ensure I had missed something critically required.  Luckily there didn't appear to be anything insurmountable and I proceeded to write the code:

Click here to view the Arduino Code

    
//Profile Generator Mk2
//Alex Lang

// constants won't change. They're used here to set pin numbers:

const int outputPin = A0; // DAC output pin on R4 (Analog pin A0)
const int dataSize = 51;
const unsigned long totalRampTime = 48000;
const int buttonPin = 3;  // the number of the pushbutton pin
const int ledPin = 13;    // the number of the LED pin

int buttonState = 0;  // variable for reading the pushbutton status

//Voltage data (scaled to 10 bits: 0-1023)
uint16_t voltageData[dataSize] = {
  352,773,749,722,696,667,640,614,587,561,534,507,481,452,426,399,
  372,346,319,293,293,293,293,293,293,293,293,293,293,293,293,293,
  293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,352
};

void setup() {
  analogWriteResolution(10); // Set analogWrite resolution to 10 bits  
  pinMode(ledPin, OUTPUT); // initialize the LED pin as an output
  pinMode(buttonPin, INPUT); // initialize the pushbutton pin as an input
}

void loop() {
analogWrite(outputPin, 352); // Output 10-bit value directly: equates to -1.71 V dc
read_Trigger();


}

void read_Trigger(){
  
  buttonState = digitalRead(buttonPin); // read the state of the pushbutton value
  
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    Profile_start();
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
}

void Profile_start(){
  
  unsigned long startTime = millis();
  unsigned long currentTime = startTime;
  unsigned long elapsedTime = 0;
  unsigned long delayTime = totalRampTime / dataSize;

  for (int i = 0; i < dataSize; i++) {
    analogWrite(outputPin, voltageData[i]); // Output 10-bit value directly
    elapsedTime = millis() - startTime;
    while(elapsedTime < (i+1) * delayTime){
      elapsedTime = millis() - startTime;
    }
  }
  delay(100);
}
  

  

The code worked well enough! The next stage involved checking all the product test requirements one more time with the design authority for the product as we needed to be certain that this new implementation of the profile generator wouldn't cause any issues for the reporting of the test results from the devices being tested - no issues were found.

I ended up modifying the code somewhat as it transpired that two profiles were required for the testing with two separate triggers:

Click here to view the full Arduino Code
    
//Test code for analogue voltage output via pin A0
// Author: Alexander Lang
// Date 14/05/2025
// Updated after changing PSU 1 as there appeared to be an issue.

// Variables

const int outputPin = A0; // DAC output pin on R4 (Analog pin A0).
const int apuTrigger = 5; // Trigger input from APU signal
const int pp3Trigger = 6; // Trigger input from PP3 Signal
const int dataSize = 40;  // Number of steps in APU Ramp.
const int ledPin = 13;    // Using built in LED to show when an APU trigger has been received. 
const unsigned long totalRampTime = 19000; // Time period for ramp in milli-seconds

float originalVoltageData[dataSize] = {
-2.75,-2.75,-2.7,-2.65,-2.60,-2.55,-2.50,-2.45,-2.40,-2.35,
-2.30,-2.25,-2.20,-2.15,-2.10,-2.05,-2.00,-1.95,-1.90,-1.85,
-1.80,-1.75,-1.70,-1.65,-1.60,-1.55,-1.50,-1.45,-1.40,-1.35,
-1.30,-1.25,-1.20,-1.15,-1.10,-1.10,-1.10,-1.10,-1.10,-1.10,
};

//Scaled 10-bit voltage data (0-1023)
uint16_t scaledVoltageData[dataSize];

// Setup function to set pin states

void setup() {
    Serial.begin(9600); // Set serial Monitor Running at 9600 baud
    //analogWriteResolution(12); // Set analogWrite resolution to 12 bits
    pinMode(apuTrigger, INPUT);  // Configure pin as an input
    pinMode(pp3Trigger, INPUT);  // Configure pin as an input
    pinMode(ledPin, OUTPUT);     // Configure pin as an output

    analogWriteResolution(10);   // Set analogWrite resolution to 10 bits

  //Scale the original voltage data to the 10-bit range (0-1023)
  float minValue = 0; // Find the minimum voltage
  float maxValue = -4.75; // Find the maximum voltage

  for (int i = 0; i < dataSize; i++) {
     //Use the map function to linearly scale the voltage to the 0-1023 range
    scaledVoltageData[i] = map(originalVoltageData[i] * 100, minValue * 100, maxValue * 100, 0, 1023);
     //We multiply by 100 to work with integers in the map function for better precision
  }
}

void loop() {

analogWrite(outputPin, 336); //Set output 336 to default to -1.564 V to ensure a 20.5 Volt output at the agilent PSU - CR16514
delay(100);                  //Delay to ensure no issues

readAPUTriggerState(); //Read the APU trigger state.  If a trigger has been received output the profile.
readPP3TriggerState(); //Read the APU trigger state.  If a trigger has been received output the profile.
}

void readAPUTriggerState(){
byte apuTriggerState = digitalRead(apuTrigger);

if (apuTriggerState == HIGH) {
      Serial.println("APU Trigger Received");
      digitalWrite(ledPin, HIGH);
      APU_start();
  }
  else {
      Serial.println("APU Trigger not received");
      digitalWrite(ledPin, LOW);
  }
  delay(100);
}

void readPP3TriggerState(){
byte pp3TriggerState = digitalRead(pp3Trigger);

if (pp3TriggerState == HIGH) {
      Serial.println("PP3 Trigger Received");
      digitalWrite(ledPin, HIGH);
      PP3_start();
  }
  else {
      Serial.println("PP3 Trigger not received");
      digitalWrite(ledPin, LOW);
  }
  delay(100);
}

void PP3_start(){
 unsigned long startTime = millis();
  unsigned long elapsedTime = 0;
  unsigned long delayTime = totalRampTime / dataSize;

  for (int i = 0; i < dataSize; i++) {
    Serial.print("PP3 in operation");
    Serial.println();
    analogWrite(outputPin, 200);  //Set profile generator to provide 0.93 V dc which equates to a 24.5 V dc output at the agilent PSU CR
    delay(300);
    elapsedTime = millis() - startTime;
    while (elapsedTime < (i + 1) * delayTime) {
      elapsedTime = millis() - startTime;
    }
  }
  delay(10); // Small delay at the end
}

void APU_start(){
  unsigned long startTime = millis();
  unsigned long elapsedTime = 0;
  unsigned long delayTime = totalRampTime / dataSize;

  for (int i = 0; i < dataSize; i++) {
    Serial.print(scaledVoltageData[i]);
    Serial.println();
    analogWrite(outputPin, scaledVoltageData[i]);
    delay(300);
    elapsedTime = millis() - startTime;
    while (elapsedTime < (i + 1) * delayTime) {
      elapsedTime = millis() - startTime;
    }
  }
  delay(10); // Small delay at the end
} 

I then switched to designing an enclosure for the new profile generator.  As time was of the essence and I didn't have access to machining services I couldn't use an off the shelf enclosure.  I designed something bespoke which could be 3D printed.  There are distinct benefits to doing this.  Everything fits first time without needing any machining or post processing and all the internal components should fit perfectly.

I used Freecad to design the enclosure as I didn't have access to a commercial cad package although I could have used Solidworks if more time had been available.  In previous projects I have created a parametric box design where I can set the required internal dimensions and a program then creates an enclosure and lid for me.  All that is then left to do is to create some internal support for the arduino R4 development board and holes for the various 4 mm banana connectors and LEDS present.


The 3D printer was then pressed into service and a case was created in less than a day.  Construction took less than 30 minutes and for once no further iterations were required...I will admit I often need more than one attempt at mechanical design...but that is the beauty of rapid prototyping, further iterations are cheap and easy to achieve assuming one has the time available.

The final result looks like this:

It has been in use ever since and I not heard of any issues or anything other than positive feedback from the production test department.

Because my profile generator used an off the shelf USB C power supply it was possible to remove 4x of the external lab power supplies from the test rig as these were being used to satisfy the positive and negative power requirements from the original profile generator.  These power supplies are being used in other areas within the test department.

I have been informed that the HP power supplies used originally in the test rig are to be replaced as they are 'long in the tooth'.  The new power supplies have been selected to work with the profile generator as it works exactly as intended - quite the endorsement!

That's all for now - Langster!

Wednesday, 19 November 2025

More work on the Robot Arm - EEZYBot Mk 2

 In March 2017 I 3D printed a Robot arm.  The original post is here:

https://langster1980.blogspot.com/2017/03/another-robot-arm.html

I saw the arm in amongst a pile of boxes covered in dust and looking rather sad.  In a moment of pure nostalgia...and possibly guilt I decided the robot arm needed a new lease of life and some purpose.  To be fair this is also true for me.  I rarely make time for personal projects and blog posts these days...this will hopefully change.

I also managed to find the boards I had made by Elecrow and I must have intended something as It was populated and working!  

There were various broken 3D printed parts and linkages on the Robot arm that I have 3D printed and replaced.  I also upgraded the base servo motor and the gripper.

Here is the new and improved robot arm😆


EEZYBot Mk2 - my implementation - design credits to Daguismo the original designer

The sense of satisfaction at getting this working reminded me of why I chose engineering as a profession and I really must make more time for this.

To that end I wrote up some new arduino code which I then decided to have Google Gemini assist me with.  It actually did an excellent job and provided some significant improvements.

The arduino code is here: Robot Arm Arduino Code

The code essential works as follows:

1. Prompt the user via the serial terminal as to whether they want Local potentiometer control or Serial Control

2. Handle the inputs from the serial terminal (and the Python front end)

3. Handle the inputs from the potentiometers

4. Drive the servo motors appropriately

The table below provides further information:

SectionPurposeKey Mechanism
State & ModeDefines the two control modes (M0 Serial, M1 Potentiometer).The global variable currentMode dictates which handler runs in the loop().
handleSerialControl()Reads all incoming commands (M0, S5, U90, ; comment) from Python.Uses Serial.readStringUntil('\n') to read entire commands and a switch statement to process them. It ignores lines starting with ;.
handlePotControl()Reads the analog values from the potentiometers.readSmoothAnalog() averages multiple samples to prevent noisy/jittery movement.
Target SettingUpdates the target angle (targetBase, targetUpper, etc.).setServoTarget() takes the desired angle (from serial or a pot) and updates the target variable, but does not move the servo yet.
handleRamping()Manages the speed and movement of the servos.Runs every 20ms (RAMPING\_INTERVAL\_MS). It moves the servo's current position (posBase) only a small step (maxSpeed) closer to its final target position (targetBase). This creates the smooth, speed-controlled motion.
reportCurrentPosition()Sends the arm's actual position back to the Python GUI.Sends a dedicated string (e.g., P:B85,U90,...) every 100ms to synchronize the GUI sliders with the physical arm.

I also...with Google Gemini's assistance wrote a Python front end which provides a graphical user interface to the serial terminal - very cool.  I am not a great python coder...with the AI assistance a lot was achieved.

The Python Code is here: Robot Arm Python GUI

Here is a screen shot of the GUI


Here is how the code roughly works:

FunctionPurposeConnection to Arduino
connect_serial()Establishes the connection and starts the arm.Creates the serial.Serial object. It includes a 2-second time.sleep(2) to wait for the Arduino to reboot.
initialize_arm_position()Runs the initial setup (M0, S2, B85...) to guarantee a safe, stable starting state after connection.Sends commands line-by-line using self.ser.write().
serial_reader()Runs in a separate thread to constantly listen for incoming data from the Arduino.Uses self.ser.readline() in a loop. It looks for lines starting with P:.
update_gui_position()Synchronizes the interface sliders with the physical arm position.Crucially, it ignores position updates if the GUI is set to Serial Mode (M0) to prevent the Arduino's periodic report from overriding a position you just selected on a slider.
run_sequence()Manages script execution.Runs in its own thread to prevent the GUI from freezing. It sends commands separated by the configurable Delay. It checks the self.stop_requested flag to allow immediate interruption.
record_all_positions()Creates movement script lines.Reads the current angle values from the synchronized sliders and formats them into the line-by-line command structure (e.g., U90\nL150\n).

Finally here is a video of the arm performing a pre-determined function <massive grin>


I intend doing a lot more with this Robot arm now that I have it working reasonably consistently.  I have always wanted to couple a robot arm with an AI assisted camera to perform sorting operations...so that's next.  I expect I will need to create a leader arm to assist with creating the AI learning model.

Take care as always - Langster!











Sunday, 14 September 2025

Create Wiring Harnesses using WireViz 0.41

I often need to create diagrams showing how to make wiring harnesses for test cables in work.  I have tried previous versions of WireViz and found it to be useful but needed a little more work.  I am not a coder by any stretch of the imagination and YAML (Yet Another Markup Language) syntax is new to me.

Here is the Hackaday article on WireViz:

https://hackaday.com/2020/06/23/an-open-source-tool-to-document-your-wiring/

Installing WireViz is fairly simple assuming one has Python installed properly and the system variables in the path.  Instructions for installing Python correctly here:

https://docs.python.org/3/using/windows.html#

Ensure you add the python path to the system variables...if this doesn't happen WireViz does not work.

Next grab the latest version of Wireviz....

Open a command prompt and type:

pip install wireviz

Once installed check things are working by typing:

wireviz --version

If things are working correctly the result should read:

WireViz 0.4.1

If that doesn't happen please check your python installation and system variables etc.

For reference here is the git repository for the WireViz Project - it contains useful information and example files:

https://github.com/wireviz/WireViz

If WireViz has correctly installed we can start to create a simple wiring harness diagram. Lets create a simple test cable - a BNC to screw terminals connector on one end and a red 4 mm banana connector and a black 4 mm banana connector at the other end with two red and black wires which are 24 AWG.  Lets make the cable 400 mm in length.

To describe this in YAML we create a text file.  I like to use notepad++ but one can use any text editor they wish providing it can save the file with a yml extension.  We can call it whatever we like but it is good practice to use a sensible filename.  I called mine BNC2Banana.yml.  Ensure you save it in a folder you can locate.

While we are at it lets create a folder called IMG within the same folder we are using to store the text file.  We will need this later...

Lets look at the example code provided for some context:

connectors:
  X1:
    type: D-Sub
    subtype: female
    pinlabels: [DCD, RX, TX, DTR, GND, DSR, RTS, CTS, RI]
  X2:
    type: Molex KK 254
    subtype: female
    pinlabels: [GND, RX, TX]

cables:
  W1:
    gauge: 0.25 mm2
    length: 0.2
    color_code: DIN
    wirecount: 3
    shield: true

connections:
  - - X1: [5, 2, 3]
    - W1: [1, 2, 3]
    - X2: [1, 3, 2]
  - - X1: 5
    - W1: s

Ok so the code is fairly easy to read...lets break things down:

The code creates a wiring harness with two connector types (X1 and X2) - a 9 pin D-type connector and a three pin molex kk connector with 2.54 mm pitch.  An RS232 serial cable has the following signals present: DCD, RX, TX, DTR, GND, DSR, RTS, CTS and RI.  The code makes connections to GND, RX and TX which will be present at the Molex Connector.  The wire type is set in the cables: section - the wire gauge used will be 0.25 mm squared cable and will use the DIN colour code and the cable itself will be 200 mm in length or 0.2 metres.

If we run this code the output looks like this:


We are going to edit this code for our own purposes to create our test cable:

Instead of calling the connectors X1 and X2 lets use variable names that make sense:  Lets call them what they actually are:

4mm_Red_Banana:
4mm_Black_Banana:
BNC_SCREW_Terminal:

Let us also update the type and pinlables variables to something more appropriate:

type:

Therefore our code should look like this:

connectors:
 
  4mm_Red_Banana: 4mm_Banana_Red # Red 4mm Banana
    type: 4 mm Red Banana Connector
    pinlabels: [+VE]
    
  4mm_Black_Banana: 4mm_Banana_Black # Black 4mm Banana
    type: 4 mm Black Banana Connector
    pinlabels: [GND]

  BNC_SCREW_Terminal: # Female BNC to Screw Terminals
    type: BNC Connector female - Screw Terminal
    pinlabels: [+VE, GND]

The next section of the code relates to the cable itself (cables: Section).  We want to use something sensible but we only need two wires and I would like to specify the insulation jacket colour and the length as well as the gauge.  To achieve that we can update the code as follows:

cables:
 
  C:
    colors: [RD, BK] # number of wires implicit in color list
    gauge: 0.25 mm2 # also accepts AWG as unit
    show_equiv: true # auto-calculate AWG equivalent from metric gauge
    length: 0.4 # length in m
    shield: false

I have chosen to call the cable C as opposed to W1. It makes more sense to me. Feel free to use your own variable names...

Finally we need to write the code which describes how the connectors and cables are connected which is denoted in the connectors: section...I like how simple this actually is to read...

The BNC connector pin 1 needs to connect to the cable C1 which will have a red insulation jacket and then on to the red 4 mm banana connector.  The BNC connector pin 2 needs to connect to Cable C2 which will have a black insulation jacket which in turn connects to the black 4 mm banana connector.

The code looks like this:

connections:
  -
    - BNC_SCREW_Terminal: [1]
    - C.C1: [1]
    - 4mm_Red_Banana: [1]
  -
    - BNC_SCREW_Terminal: [2]
    - C.C1: [2]
    - 4mm_Black_Banana: [1]

The entire code for reference looks like this:

connectors:
 
  4mm_Red_Banana: # Red 4mm Banana
    type: 4 mm Red Banana Connector
    pinlabels: [+VE]
    
  4mm_Black_Banana: # Black 4mm Banana
    type: 4 mm Black Banana Connector
    pinlabels: [GND]

  BNC_SCREW_Terminal: # Female BNC to Screw Terminals
    type: BNC Connector female - Screw Terminal
    pinlabels: [+VE, GND]
    
cables:
 
  C:
    colors: [RD, BK] # number of wires implicit in color list
    gauge: 0.25 mm2 # also accepts AWG as unit
    show_equiv: true # auto-calculate AWG equivalent from metric gauge
    length: 0.4 # length in m
    shield: false
 
connections:
  -
    - BNC_SCREW_Terminal: [1]
    - C.C1: [1]
    - 4mm_Red_Banana: [1]
  -
    - BNC_SCREW_Terminal: [2]
    - C.C1: [2]
    - 4mm_Black_Banana: [1]

Save the code - always a good idea!

Jump into a command prompt and navigate to the directory where you have saved your YAML code:


Type the following command:

WireViz BNC2BananaSimple.yml

If everything has gone according to plan you should see the following response:


A number of files should have been created in the folder:
  • An SVG file
  • An HTML file
  • A TSV file
  • A PNG file
If we look at the PNG file we can see our cable harness diagram:


The other files are copies of the above diagram except the TSV file which is a tab separated value file making up the bill of materials.

The above diagram should be more than enough information for a wiring person to create a wiring loom but due to the improvements in WireViz we can now add more code which in turn creates more information.

As 4 mm banana connectors are essentially all the same part apart from the number we can use some programming tricks to make the code slightly more easy to understand and we can add more information to make our diagram more comprehensive and the bill of materials more explicit:

connectors:
 
  4mm_Red_Banana: &4mm_Banana_t # https://uk.rs-online.com/web/p/banana-connectors/2080252
    pinlabels: [+VE]
    type: 4 mm Red Banana Connector
    manufacturer: RS Components
    mpn: 2080252
    supplier: uk.rs-online.com
    spn: 2080252
    subtype: male
    color: RD
    image:
      src: IMG/4mm.Red.Banana.png
 
  4mm_Black_Banana: # https://uk.rs-online.com/web/p/banana-connectors/2080251
    <<: *4mm_Banana_t
    pinlabels: [GND]
    type: 4 mm Black Banana Connector
    mpn: 2080251
    spn: 2080251
    color: BK
    image:
      src: IMG/4mm.Black.Banana.png
 
  BNC_SCREW_Terminal: # https://uk.rs-online.com/web/p/coaxial-adapters/1242521
    pinlabels: [+VE, GND]
    type: BNC Connector Male - Screw Terminal
    manufacturer: RS Components
    mpn: 1242521
    supplier: RS Components
    spn: 1242521
    subtype: female
    color: BK
    image:
      src: IMG/BNC-SCREW-TERM-MALE.png

The change in the connectors section is the line containing this:

&4mm_Banana_t

Essentially what this line of code does is create a template for the 4 mm banana connector type.   

It means that connectors of the same type but with slightly different attributes can be used without quite so much typing needed.  If we look at the next connector section it references the template with this line of code:

<<: *4mm_Banana_t

The rest of the code should be self explanatory.

We now need to obtain some images of our connectors.  I downloaded some stock images with white backgrounds:

The BNC to Screw Terminal Connector

The Red 4 mm Banana Connector

The Black 4 mm Banana Connector

Save these pictures (or find your own) into the IMG folder we created earlier.  Be sure to rename them to the same names used in the code:
  • 4mm.Red.Banana.png
  • 4mm.Black.Banana.png
  • BNC-SCREW-TERM-MALE.png
The rest of the code remains unchanged but for completeness here it is in case it is needed:
   
connectors:
 
  4mm_Red_Banana: &4mm_Banana_t # https://uk.rs-online.com/web/p/banana-connectors/2080252
    pinlabels: [+VE]
    type: 4 mm Red Banana Connector
    manufacturer: RS Components
    mpn: 2080252
    supplier: uk.rs-online.com
    spn: 2080252
    subtype: male
    color: RD
    image:
      src: IMG/4mm.Red.Banana.png
 
  4mm_Black_Banana: # https://uk.rs-online.com/web/p/banana-connectors/2080251
    <<: *4mm_Banana_t
    pinlabels: [GND]
    type: 4 mm Black Banana Connector
    mpn: 2080251
    spn: 2080251
    color: BK
    image:
      src: IMG/4mm.Black.Banana.png
 
  BNC_SCREW_Terminal: # https://uk.rs-online.com/web/p/coaxial-adapters/1242521
    pinlabels: [+VE, GND]
    type: BNC Connector Male - Screw Terminal
    manufacturer: RS Components
    mpn: 1242521
    supplier: RS Components
    spn: 1242521
    subtype: female
    color: BK
    image:
      src: IMG/BNC-SCREW-TERM-MALE.png
 
cables:
 
  C:
    colors: [RD, BK] # number of wires implicit in color list
    gauge: 0.25 mm2 # also accepts AWG as unit
    show_equiv: true # auto-calculate AWG equivalent from metric gauge
    length: 0.4 # length in m
    shield: false
    mpn: UL1007-24AWG
 
connections:
  -
    - BNC_SCREW_Terminal: [1]
    - C.C1: [1]
    - 4mm_Red_Banana: [1]
  -
    - BNC_SCREW_Terminal: [2]
    - C.C1: [2]
    - 4mm_Black_Banana: [1]

With that done we can now re-run the WireViz command and we get a different and in my opinion, a much improved diagram:


In my opinion that is a more than satisfactory diagram for a test cable harness.  There are ways to set the page size adding a header section to ensure that the code is more readable.  I would like to be able to add a template with a title block but at the moment this feature isn't working.

Here is the full code in case it might provide further insight:

metadata:
 
  title: BNC <-> 4 mm Banana
  pn: BNC2Banana01
 
  authors:
    Created: 2025-09-14
    name: Lang 
    date: 2025-09-14
    Approved:
      name: Lang 
      date: 2025-09-14
 
  revisions:
    A:
      name: Lang 
      date: 2025-09-14
      changelog: Initial commit
 
  template:
    name: din-6771
    sheetsize: A3
 
connectors:
 
  4mm_Red_Banana: &4mm_Banana_t # https://uk.rs-online.com/web/p/banana-connectors/2080252
    pinlabels: [+VE]
    type: 4 mm Red Banana Connector
    manufacturer: RS Components
    mpn: 2080252
    supplier: uk.rs-online.com
    spn: 2080252
    subtype: male
    color: RD
    image:
      src: IMG/4mm.Red.Banana.png
 
  4mm_Black_Banana: # https://uk.rs-online.com/web/p/banana-connectors/2080251
    <<: *4mm_Banana_t
    pinlabels: [GND]
    type: 4 mm Black Banana Connector
    mpn: 2080251
    spn: 2080251
    color: BK
    image:
      src: IMG/4mm.Black.Banana.png
 
  BNC_SCREW_Terminal: # https://uk.rs-online.com/web/p/coaxial-adapters/1242521
    pinlabels: [+VE, GND]
    type: BNC Connector Male - Screw Terminal
    manufacturer: RS Components
    mpn: 1242521
    supplier: RS Components
    spn: 1242521
    subtype: female
    color: BK
    image:
      src: IMG/BNC-SCREW-TERM-MALE.png
 
cables:
 
  C:
    colors: [RD, BK] # number of wires implicit in color list
    gauge: 0.25 mm2 # also accepts AWG as unit
    show_equiv: true # auto-calculate AWG equivalent from metric gauge
    length: 0.4 # length in m
    shield: false
    mpn: UL1007-24AWG
 
connections:
  -
    - BNC_SCREW_Terminal: [1]
    - C.C1: [1]
    - 4mm_Red_Banana: [1]
  -
    - BNC_SCREW_Terminal: [2]
    - C.C1: [2]
    - 4mm_Black_Banana: [1]

It is possible to use WireViz using Linux but I haven't had the time to try it.  I am confident it works just as well.

I used this blog post as reference material for this post but I changed it slightly.  If blog readers need more examples on how to use WireViz please leave a comment below.

I think that's all for now - take care always - Langster!