DIY: Adjustable 30 kV High Voltage Power Supply

High voltage power supplies can open interesting doors to research topics such as laser, x-ray, spark gap transmitters. And many other specialized niches. Unfortunately, laboratory grade high voltage power supplies are rather costly. Luckily, there is a much less expensive way to put high voltage experiments into the hobbyists reach. This article shows how to build an inexpensive and adjustable 5 kV to 30 kV high voltage supply from a commercial laser supply.

UPDATE: There also is a German version of this article bd the corresponding YouTube video available on my German blog: Einstellbares 30 kV Hochspannungs-Netzeil im Eigenbau

Homebrew 5 kV to 30 kV high voltage power supply.

Homebrew 5 kV to 30 kV high voltage power supply.

Overview

The foundation of this project is a commercial laser power supply. It’s a 50 Watt CO2 laser supply made by the manufacturer VEVOR [1]. According to the manufacturer, it has a starting voltage of 20 kV and a maximum output current of 20 mA. In reality, the supply can start as low as 5 kV, produces voltages in excess of 30 kV and provides output currents of over 30 mA. These operating parameters seem perfect for laser and spark gap experiments.

Front view of the homebrew 5 kV to 30 kV high voltage power supply.

Front view of the homebrew 5 kV to 30 kV high voltage power supply.

The entire project is mounted inside a 19" case. There is a (pretty fancy) single-pole, single-throw switch and a small momentary switch to enable the high-voltage output. A 10-turn potentiometer allows for easy adjustment of the desired output voltage. Current and voltmeters provide insight into the current operating parameters. To avoid having to find a panel mount high voltage connector, the high voltage cable (rated for up to 50 kV) was simply fed through a rubber grommet to the outside world. An inexpensive high voltage connector is then used to establish connections to future projects [3].

Top-view of the high-voltage power supply and its internal wiring around the VEVOR laser power supply

Top-view of the high-voltage power supply and its internal wiring around the VEVOR laser power supply

Current and Voltmeter

One primary design requirement is to have a voltmeter and a current meter to monitor voltage and current simultaneously. The current measurement is accomplished through a 30 mA panel meter. To stay clear of the high voltage itself, the current meter is installed so that the measurement occurs between the load and ground. Low side current sensing so to speak.

Front facing top-view of the high-voltage power supply and its internal wiring

Front facing top-view of the high-voltage power supply and its internal wiring

A simple voltmeter would be quite easy to buy off the shelf for very little money, if it wasn’t necessary to measure up to 30 kV or possibly more. The simple, low-cost solution is to use a 50 µA current meter and a 1 Gigaohm resistor connected between the high voltage supply rail and ground. Following Ohm’s law (I = V/R), the current through a one Gigaohm resistor is conveniently 1 µA per kilovolt. So at 30 kV, the current meter schould indicate a current of 30 µA (Eq. 1).

A 1 Gigaohm resistor and a 0 - 50 µA Ammeter suitable for measuring voltages up to 50 kV

A 1 Gigaohm resistor and a 0 – 50 µA Ammeter suitable for measuring voltages up to 50 kV

High voltage measurement set-up using a 1 Gigaohm resistor and a 0 to 50 μA ammeter

High voltage measurement set-up using a 1 Gigaohm resistor and a 0 to 50 μA ammeter

(1)   \begin{equation*} I = \frac{30 \cdot 10^3 V}{1 \cdot 10^9 \Omega} = 30 \mu A \end{equation*}

(2)   \begin{equation*} I = \frac{30 \cdot 10^3 V}{(1 \cdot 10^9 + 125 \cdot 10^3) \Omega} = 29.996250...\mu A \end{equation*}

Careful readers might note that the current meter itself has an internal resistance and that, therefore, the real current is actually lower than expected. Thus the current meter’s indication should be lower than desired. While this is technically correct, with the meaurement resistor having a value of 1 Gigaohm, even a few hunded Kiloohms more make little to no difference. Equation 2 shows that even an extra 125 Kiloohms in series will still yield a result that is accurate to within two decimal places. Therefore, the meter’s internal resistance can be considered to be insignificant for this purpose. For the perfectionists out there, any resulting error can be trimmed out using the adjustment screw on the meter itself.

From left to right: High voltage output cable (red), 1 Gigaohms measurement Resistor, 50 µA current meter for voltage measurement through measurement resistor, ground connection and 30 mA current meter.

From left to right: High voltage output cable (red), 1 Gigaohms measurement Resistor, 50 µA current meter for voltage measurement through measurement resistor, ground connection and 30 mA current meter.

The solder junction between the high voltage output cable and the 1 Gigaohm measurement resistor poses a problem of its own; Usually, a bit of heat shrink tubing would be sufficient to prevent most exposed contacts from causing havoc. But not at a voltage of up to 30 kV. The solder joint is covered in multiple layers of MG Chemicals 4226A insulting varnish [2]. And while this varnish has an extremely high breakdown voltage of 3 kV per mil (= 0.0254mm), I am not stopping there. Several pieces of cloth are soaked in epoxy and carefully wrapped around the joint. This is quite literally a t-shirt cut up into little strips, soaked in epoxy. Somewhat peculiar but efficient.

Laser Supply Pinout & Control Wiring

Figuring out the pinout of the laser power supply took a bit of effort. While there was a manual included, it’s English and nomenclature was fairly questionable. With a bit of try and error (and an unintended laser discharge), I was able to figure out the proper pinout eventually.

Connections to the commercial laser power supply: Mains voltage input (left connector), output voltage adjustment (center connector) and enable / disable input (right connector)

Connections to the commercial laser power supply: Mains voltage input (left connector), output voltage adjustment (center connector) and enable / disable input (right connector)

To make life easier for anyone following along at home, here is the correct pinout table for the connectors on the laser power supply:

Mains Connector (left):

Pin 1 (left) Pin 2 Pin 3 Pin 4 (right)
Ground
(white)
Mains Ground
(green/yellow)
Mains Neutral
(blue)
Mains Phase
(black)

Control Voltage Input Connector (center):

Pin 1 (left) Pin 2 Pin 3 Pin 4 Pin 5 Pin 6 (right)
To Pin 2
(black)
To Pin 1
(black)
Not Connected Voltage adj. Ground
(black)
Voltage Control Input
(orange)
Voltage adj. 5 VDC
(red)

Enable / Disable Input Connector (right):

Pin 1 (left) Pin 2 Pin 3 Pin 4 (right)
Not Connected GND Out
(Orange)
5 V DC Out
(10K Resistor to Pin 4)
Low-active input
(orange)

With the correct pinout figured out, the rest of the control wiring is pretty straight-foward. Mains power is fed into the casing through a switchable, fused IEC320 IEC60320 connector. The mains voltage is connected directly to the laser power supply. It should be mentioned that signal ground, high voltage ground and earth ground are connected internally inside of the laser supply. Just to be sure that there’s a proper connection to the metal frame of the 19" case, some of the paint is removed and a ring terminal with a dedicated ground wire is attached to the case. Additionally, the paint is also stripped below the laser supply before bolting it in place to ensure a good ground connection between the case and the supply itself.

Close-up of the internal wiring: IEC320 mains voltage intput connector (left), VEVOR laser power supply connectors (top) , enable / disable switches and voltage adjustment potentiometer (right)

Close-up of the internal wiring: IEC320 mains voltage intput connector (left), VEVOR laser power supply connectors (top) , enable / disable switches and voltage adjustment potentiometer (right)

A 10-turn, 10 Kiloohms potentiometer is used to set the desired output voltage. The control voltage input of the laser power supply expects a control voltage between 0 to 5 Volts to adjust the output voltage from minimum to maximum. Conveniently, ground and 5 V DC terminals are provided directly next to the control voltage input. The latter is connected to the wiper of the potentiometer, ground and 5 Volts DC to the ends of the resistive strip. A single-pole, single-throw switch and a momentary switch for enabling the high voltage output are wired in parallel and connected between ground and the active-low enable input. Just to be on the safe side, I added a 10 Kiloohms pull-up resistor between the enable pin and 5 V DC.

Test Results

Let’s be honest, testing a high-voltage power supply is the most fun part of the entire build. But I wanted this moment to be special. Simply producing some arcs is kind of uninspired. So I quickly built a (sub-optimal) spark gap transmitter with an emission frequency of around 3 MHz. With the spark gap connected to the power supply, the mains voltage is finally connected to the high voltage power supply. Somewhat fearful of what might arc over, the momentary switch is pushed and after adjusting the output voltage to a sufficiently high level, the spark gap transmitter hapilly fired away.

Spark-gap transmitter used for testing the high voltage power supply

Spark-gap transmitter used for testing the high voltage power supply

Just as a teaser: The spark gap transmitter itself, including much better designs than the one shown here, will be the subject of an upcoming article. So stay tuned!

YouTube Video

Conclusion

My idea of combining commercial reliability and low-costs homebrewing is a complete success. The overall cost ist about 100 to 150 USD, depending on where exactly the components are sourced. This high voltage power supply will be the foundation of some interesting future content. I should add that there are commercial laser supplies that are capable of providing up to 50 kV output voltage with currents in excess of 30 mA. So if you need even higher voltages than the 30 KV shown in this article, that might be an avenue to explore. However, the higher voltage laser supplies are of course also more expensive. Still a lot less expensive than a commercial high voltage laboratory power supply.

Links and Sources:
[1] VEVOR 50W CO2 Laser Power Supply, Amazon: https://amazon.com/
[2] MG Chemicals 4226A, Dr. Dietrich Müller GmbH: https://www.muellerbestellung.de/
[3] MCWlaser High Voltage connectors, Amazon: https://amazon.com/

 

Diplexer with integrated Bias-T (Triplexer) for QO-100 and X-band microwave reception using LNBs

This article shows how to build a simple Triplexer (Diplexer plus integrated DC Bias-T) for use with commercial TV LNBs for QO-100 or X-band microwave experiments.

Introduction

When using modified, commercial LNBs for reception of the QO-100 amateur radio satellite or X-band microwave experiments, it is necessary to pass a clock-reference signal, a DC supply voltage and the receive IF signal through the same coax. It is, therefore, necessary to separate these signals at the other end of the coax. For that purpose a Diplexer for IF / clock-reference separation plus an additional Bias-T is needed. Additionally, the LNBs are designed for a typical systems impedance of 75 Ohms instead of the 50 Ohms commonly used in RF communications equipment. An ideal Diplexer with integrated bias-T, which I will call a Triplexer from now on, also takes care of the impedance matching.

Different PCB prototype versions of the Diplexer with integrated bias-T

Different PCB prototype versions of the Diplexer with integrated bias-T

Circuit Design

For the Intermediate Frequency (IF) and clock-reference separation, the circuit makes use of two T-type LC-networks. Their corner frequencies are calculated in a way that even reception on the 2m amateur radio band would be possible on the IF-side of the setup. The additional benefit of the low-pass characteristic of the T-network on the clock-reference side is that a reference square wave will effectively be turned into a sine-wave. Therefore, square wave shaped clock signal sources can be used.

Schematic of the LNB Triplexer (Diplexer with integrated Bias-T) for use in QO-100 reception and X-band microwave receive setups.

Schematic of the LNB Triplexer (Diplexer with integrated Bias-T) for use in QO-100 reception and X-band microwave receive setups.

The IF and reference-clock nodes are then combined and sent to the primary side of a MiniCircuits ADT1.5-17+ transformer with an impedance transformation ratio of 1:1.5 [1]. The secondary side of the transformer (now 75 Ohm impedance) is isolated from the DC bias-T by a simple blocking capacitor. The bias-T itself, consisting out of C5 and L4, is a simple LC-low-pass filter. The combined signal-path from the secondary side of T1 and the supply voltage from the bias-T are combined and connected to an F-type output connector.

For C1, C2 and C3 no capacitors with class 2 dielectric are recommended. C0G or NP0 type capacitors are recommended to provider more stability of the passband characteristics of the T-filters.

PCB Design

Except for the RF-connectors and the DC input terminal, all components are surface mount devices. By using mostly 1206 footprint passive components, this is still extremely easy to assemble at home. The PCB layout is intended for standard 1.6mm thick FR4 material and a . The general design-considerations regarding impedance matching of PCB traces, or rather to what extend it is even necessary, from my article “Critical length of a PCB trace and when to treat it as a transmission line” [2 have been applied in this design. For that reason, the IF portion is situated a lot closer to the primary side of the transformer than the reference-clock input.

PCB design with part markings, without copper pur (for better visibility) for the Triplexer.

PCB design with part markings, without copper pur (for better visibility) for the Triplexer.

The PCB features two edge-mount SMA connectors for the reference-clock input and the IF output. The DC supply voltage can be applied using 2,54 mm screw terminals. Care has been taken to orient all inductors in a way that coupling of their magnetic fields is reduced to a minimum.

Triplexer PCB with all components except the connectors assembled.

Triplexer PCB with all components except the connectors assembled.

Backside of the Triplexer PCB with F-type connector for the LNB-syde, edge mount SMA connectors and screw terminal for the DC supply voltage

Backside of the Triplexer PCB with F-type connector for the LNB-syde, edge mount SMA connectors and screw terminal for the DC supply voltage

Test Results

For a subjective, general function test, modified Goobay 67269 LNB [3] was used for initial testing. The LNB was connected to the F-connector using a few metres of 75 Ohm coax. As a test signal source with a frequency of 10.488 GHZ, the 23rd harmonic of a 456 MHz signal (Po = 500 mW) from a handheld radio was used. The LO frequency was set to 10 GHz by injecting a reference-clock frequency 25.641025 MHz.

Output from the IF port viewed on a SDRPlay RSPdx, reference input frequency 10.488 GHz, reference clock input =  25.641025 MHz

Output from the IF port viewed on a SDRPlay RSPdx, reference input frequency 10.488 GHz, reference clock input = 25.641025 MHz

It should be noted that for this prototype test, I deviated from the calculated component values. 270 nH inductors where used in Place of the 220 nH inductors (L2 and L3)and some deviation was also on the IF-side, but I can’t really remember what capacitor values were actually used. I will update the figures once I have the updated prototype revision with the correct component values assembled. Nonetheless, port characteristics were measured with a NanoVNA.

Nano VNA used to verify the port characteristics of the IF port. The LNB port and the reference clock port are properly terminated with a 75 Ohm (LNB) and 50 Ohm load (reference clock).

Nano VNA used to verify the port characteristics of the IF port. The LNB port and the reference clock port are properly terminated with a 75 Ohm (LNB) and 50 Ohm load (reference clock).

To measure the input VSWR of the IF port, the LNB connector was properly terminated with a 75 Ohm load. The reference clock input was terminated with a 50 Ohm load. The resulting VSWR-plot is okay, but I’d like to see better results than that.

S11 VSWR of the IF port with all other ports properly terminated.

S11 VSWR of the IF port with all other ports properly terminated.

The test was repeated on the reference-clock port by connecting the NanoVNA to the reference-clock input port and terminating the IF port with a 50 Ohm load. The result is acceptable but should be re-verified with the next revision.

Reference clock input port VSWR measurement with all other ports properly terminated.

Reference clock input port VSWR measurement with all other ports properly terminated.

Conclusions

This article shows a simple design approach on how to implement a functional triplexer design for QO-100 reception and X-band microwave experiments using with a modified LNB. Some improvements will be implemented in the next revision, such as a larger power inductor being able to handle higher supply currents. When the next revision becomes available, I will update this article to provide measurements and the design-files (Gerber and drill files).

Links and Sources:

[1] ADT1.5-17+ Datasheet, MiniCircuits: https://www.minicircuits.com

[2] Westerhold, S. (2023), “Critical length of a PCB trace and when to treat it as a transmission line”. Baltic Lab High Frequency Projects Blog. ISSN (Online): 2751-8140.: https://baltic-lab.com

[3] Westerhold, S. (2023), “LNB Modification for 10 GHz QO-100 Satellite Reception”. Baltic Lab High Frequency Projects Blog. ISSN (Online): 2751-8140.: https://baltic-lab.com

 

Tremolo DSP Effect for Arduino

This article continues my newly acquired interest in implementing digital signal processing algorithms on the Arduino GIGA R1 by showing how to implement a tremolo effect algorithm in software.

After showing how to implement an Audio Loopback Device and a DSP Diode Clipping Algorithm for Overdrive and Distortion Effects on the Arduino GIGA R1 WiFi, this article will show how to implement a tremolo effect in software.

The Tremolo Effect

The tremolo effect has 2 basic parameters: Depth and Frequency. The depth determines how much the incoming audio signal is being altered by the effect and inversely how much of the original signal is passed-through unaltered. The frequency determines the frequency of a low-frequency oscillator. Another common effect parameter is the waveform itself. Sinusoidal, triangle and rectangle LFO waveforms are common.

Block Diagram of a Tremolo Effect

Block Diagram of a Tremolo Effect

The LFO produces a waveform at the pre-selected frequency. A portion of the incoming audio signal (or all) corresponding to the set depth-amount is then multiplied by the LFO signal, shaping it’s waveform envelope. The resulting signal is then added back together with the desired portion (or none) of the unaltered, original signal. And that’s all there is to the tremolo effect.

Software Implementation

The main loop of the program continiously acquires samples from the ADC0 input at a fixed sample-rate with the help of the AdvancedAnalog-library. Whenever the sample buffer is full, the samples get passed to an effect stack-function. The function first applies a DSP distortion algorithm and then passes the sample on to the tremolo function itself.

Tremolo effect implemented in an Arduino sketch

Tremolo effect implemented in an Arduino sketch

A global variable keeps track where the acquisition currently is located in time, relative to the sample-rate. MY example code only implements a sinusoidal waveform. Since the DSP alorithm operates in discrete-time and not continuous time, a variable holding the amount of radians per sample has been pre-calculated. The input sample is then multiplied by the sine value of the given frequency at the given sampling time. The resulting value is further multiplied by the fractional depth value. The result is then added to a fration of the original signal with the inverse amount of depth.

And this is what the end result sounds like (99 % modulation depth, LFO frequency = 5 Hz):

Conclusions

The tremolo effect is extremely simple to implement in software. As expected, the Arduino GIGA R1 is perfectly up to the task and even more than capable of stacking multiple effects for well-sounding results.

Arduino Sketch

The following sketch was tested on an Arduino GIGA R1 with various sample rates. Please note that the ADC is only able to capture positive voltages and may even be destroyed when applying a negative signal. Therefore, the input audio signal has to be shifted up before connecting it to the ADC0 input pin. A simple 10K / 10K voltage divider at the ADC input between the 3.3 V supply rail and ground will suffice for basic experiments.

/*
 * Arduino Giga R1 WiFi - DSP Tremolo Effect Example
 *
 * Copyright (C) 2022 Westerhold, S. (AI5GW) 
 * Web (EN): https://baltic-lab.com
 * ORCID: https://orcid.org/0000-0001-7965-3140
 *
 * Tested sample-rates: 192000, 96000, 48000, 44100
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */

#include <Arduino_AdvancedAnalog.h>

// Instantiate ADC 0 (Pin A0), DAC 0 (Pin A12) and DAC 1 (Pin A13)
AdvancedADC Chan1(A0);
AdvancedDAC Out1(A12);
AdvancedDAC Out2(A13);

// Define ADC Midpoint
#define ADC_MIDPOINT 2038
#define SAMPLE_RATE 96000
static float RADIAN_PER_SAMPLE = (float)(2.0 * PI) / SAMPLE_RATE;

long SAMP_POS = 0;

void setup() {

  Serial.begin(115200);

  // Set-up ADC0, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!Chan1.begin(AN_RESOLUTION_12, SAMPLE_RATE, 128, 128)) {
    Serial.println("ADC fail...");
    while (1)
      ;
  }

  // Set-up DAC0, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!Out1.begin(AN_RESOLUTION_12, SAMPLE_RATE, 128, 128)) {
    Serial.println("Failed to initialize DAC 1");
    while (1)
      ;
  }

  // Set-up DAC1, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!Out2.begin(AN_RESOLUTION_12, SAMPLE_RATE, 128, 128)) {
    Serial.println("Failed to initialize DAC 1");
    while (1)
      ;
  }
}

void loop() {

  if (Chan1.available()) {
    // Get handle for the input buffer
    SampleBuffer inBuf = Chan1.read();

    // Get handle for the output buffer
    SampleBuffer outBuf1 = Out1.dequeue();
    SampleBuffer outBuf2 = Out2.dequeue();

    for (int i = 0; i < inBuf.size(); i++) {
      // Store buffer value
      int INVal = inBuf[i];

      // Write copy to DAC0 output buffer
      outBuf1.data()[i] = INVal;

      // Send value to the effect stack and write result to DAC1 buffer
      outBuf2.data()[i] = EffectStack(INVal);
    }

    // Write contents of the output buffer to the DACs
    Out1.write(outBuf1);
    Out2.write(outBuf2);

    // Release the input buffer
    inBuf.release();
  }
}

int EffectStack(int INPUT) {
  float IN;
  int OUT = 0;

  if (SAMP_POS >= SAMPLE_RATE) { SAMP_POS = 0; }

  // Normalize to Zero around ADC midpoint
  IN = (float)INPUT - ADC_MIDPOINT;

  //Apply Effects
  OUT = DiodeClippingStep(IN, 300);

  // Tremolo
  OUT = Tremolo(OUT, 99, 5);

  // Denormalize
  OUT = OUT + ADC_MIDPOINT;

  // Update Sampling Position
  SAMP_POS++;

  // return result
  return round(OUT);
}


int Tremolo(float INPUT, float DEPTH, float FREQ) {
  float OUT = 0;
  DEPTH = (float)(DEPTH / 2.0) / 100.0;

  OUT = (float)INPUT * sin(RADIAN_PER_SAMPLE * (float)SAMP_POS * FREQ) * DEPTH;
  OUT = OUT + (INPUT * (1.0 - DEPTH));

  return round(OUT);
}


int DiodeClippingStep(int INPUT, int THRESHOLD) {
  float IN, OUT;
  int BUF = INPUT;  // Store for sign revovery

  // Normalize input to threshold level = 1.0
  IN = (float)abs(INPUT) / THRESHOLD;

  if (IN <= (1.0 / 3.0)) {
    OUT = 2 * IN;
  } else if (IN <= (2.0 / 3.0)) {
    OUT = (-3.0 * (float)pow(IN, 2)) + (4.0 * IN) - (1.0 / 3.0);
  } else {
    OUT = 1;
  }

  // Undo Normalization
  OUT = OUT * THRESHOLD;
  // recover sign
  if (BUF <= 0) { OUT = -1.0 * OUT; }

  return round(OUT);
}

Links and Sources:
[1] Westerhold, S. (2023), "Arduino GIGA R1 WiFi | Audio Loopback Example". Baltic Lab High Frequency Projects Blog. ISSN (Online): 2751-8140.: https://baltic-lab.com/

[2] Westerhold, S. (2023), "DSP Diode Clipping Algorithm for Overdrive and Distortion Effects". Baltic Lab High Frequency Projects Blog. ISSN (Online): 2751-8140.: https://baltic-lab.com/

 

DSP Diode Clipping Algorithm for Overdrive and Distortion Effects

This article shows how to approximate the behaviour of a regular diode in a mathematical equation and how to subsequently implement the behaviour in software. The DSP algorithm can be modified to implement different topologies, such as single diode clipping, dual diode symmetrical soft clipping or asymmetrical clipping.

The easiest way to implement distortion through a DSP algorithm would be hard clipping. With this method any value above a certain threshold will be fixed to that threshold level. While this is absolutely possible, hard clipping sounds very harsh. This might be desirable for some metal fans but it doesn’t mimic the behaviour of tube or diode distortion circuits in which the clipping process is a lot more gradual.

Update (08/21/2023): A YouTube video titled “Overdrive and Distortion Effect Digital Signal Processing (DSP) Algorithms on the Arduino GIGA R1” is now available.

Modelling Clipging Mathematically

The Shockley ideal diode equation is a good starting point to model the behaviour of semiconductor diodes. It descibes the current through a diode as a function of the applied voltage. In order to develop a suitable DSP algorithm, however, an equation describing the output voltage as a function of input voltage is needed. There are many different equations approximating diode clipping circulating around the web and in professional literature [1], albeit not always without errors.

Single diode clipping step-function with output voltage as a function of input voltage shown (blue)

Single diode clipping step-function with output voltage as a function of input voltage shown (blue)

A simple approximation for diode clipping through a step function is shown in equation 1 (positive clipping) and 2 (negative clipping). The equation consists out of a linear part, a quadratic part and a hard-clipping part. Which one of the terms is shaping the output signal is determined by the input voltage.

(1)   \begin{equation*} f(x) =  \begin{cases} 2x & for \:\:  x \le \frac{1}{3}\\ -3x^2+4x-\frac{1}{3} & for \:\: \frac{1}{3} < x \le \frac{2}{3} \\ 1 & for \:\: x >  \frac{2}{3} \\ \end{cases} \end{equation*}

(2)   \begin{equation*} f(x) = \begin{cases} 2x & for \:\: x \ge -\frac{1}{3}\\ 3x^2-4x+\frac{1}{3} & for \:\: -\frac{1}{3} > x \ge -\frac{2}{3} \\ -1 & for \:\: x <  -\frac{2}{3} \\ \end{cases} \end{equation*}

Both equations were combined and plotted in Python to simulate dual diode clipping as it is often found in guitar distortion pedals:

Dual, symmetrical diode clipping step-function with output voltage as a function of input voltage shown (blue)

Dual, symmetrical diode clipping step-function with output voltage as a function of input voltage shown (blue)

Admittedly the easiest model that can be implemented in software is using only the hyperbolic tangent function (Eq. 3). Use of this function results in an even softer clipping at the top-end of the input voltage range.

(3)   \begin{equation*} f(x) = tanh(x) \end{equation*}

Output voltages for the different clipping equations as a function of input voltage. Step-function (Blue), exponential function (orange) and hyperbolic tangens (green)

Output voltages for the different clipping equations as a function of input voltage. Step-function (Blue), exponential function (orange) and hyperbolic tangens (green)

The Schockley ideal diode equation is a natural exponential function. Therefore, it would make sense that a mathematical approximation would also be an exponential function with Euler’s number being raised to some variable. There is one particular function found in [1] that circulates around the web. The original equation contains a significant sign-error. Only the corrected version of the equation (Eq. 4) is shown here.

(4)   \begin{equation*} f(x) = \frac{x}{|x|} (1-e^{\frac{-x^2}{|x|}}) \end{equation*}

(5)   \begin{equation*} D = \{x \in \mathbb{R}\: |\: x \neq 0\} \end{equation*}

But even in the corrected form shown above (Eq. 4), the equation is still not suitable for direct implementation into a DSP algorithm just yet. The problem is the way the original author implements the signum function, which returns only the sign (+ or -) of a value. The \frac{x}{|x|} and \frac{-x^2}{|x|} terms are supposed to switch the signs of operands depending on whether the input is positive or negative. This works very well until an input value is 0, because the function’s domain is limited to all non-zero values (Eq. 5). We can do better than that and transform the exponential equation from the book (Eq. 4) into another step-function (Eq. 6). Doing this actually also improves the computational resources required.

(6)   \begin{equation*} f(x) =  \begin{cases} -1+e^{x} & for \:\:  x < 0\\ 0 & for \:\: x=0 \\ 1-e^{-x} & for \:\: x > 0 \\ \end{cases} \end{equation*}

The following graph simulates the resulting output voltage waveform for a sinusoidal 2 Vpp signal applied to the input of each of the algorithms shown here.

Time-domain simulation of output voltages for the different clipping equations as a function of time with a 2 Vpp sinusoidal signal applied. Step-function (Blue), exponential function (orange) and hyperbolic tangens (green)

Time-domain simulation of output voltages for the different clipping equations as a function of time with a 2 Vpp sinusoidal signal applied. Step-function (Blue), exponential function (orange) and hyperbolic tangens (green)

Test and Results

With the math out of the way, the rest is fairly easy. For this experiment, the new Arduino GIGA R1 WiFi [2] has been used as it has two inbuilt DACs that come in handy for trying out the developed algorithms. The framework used here is derived from my Arduino GIGA R1 WiFi | Audio Loopback Example. The entire sketch can be found in the section at the end of the article.

For my first experiment, I implemented the step-functions (Eq. 1 and 2) for a dual diode, symetrical type of distortion. The results are quite satisfying.

Output (yellow) and input (purple) voltages of the step-function clipping algorithm implementet with an Arduino

Output (yellow) and input (purple) voltages of the step-function clipping algorithm implementet with an Arduino

Next, I made use of the two DACs of the Arduino GIGA R1 WiFi by applying different overdrive / distortion algorithms to the output of each DAC. The first channel utilizes the step-function (Eq. 1 and 2), the second the re-packaged natural exponent step function (Eq. 6). The results for various input voltage levels are shown in the following images.

Input voltage (yellow), dual-diode step-function output from DAC0 (purple) and exponential function output from DAC1 (green) just before clipping.

Input voltage (yellow), dual-diode step-function output from DAC0 (purple) and exponential function output from DAC1 (green) just before clipping.

Input voltage (yellow), dual-diode step-function output from DAC0 (purple) and exponential function output from DAC1 (green) with clipping activity becoming visible.

Input voltage (yellow), dual-diode step-function output from DAC0 (purple) and exponential function output from DAC1 (green) with clipping activity becoming visible.

Input voltage (yellow), dual-diode step-function output from DAC0 (purple) and exponential function output from DAC1 (green) with strongly visible clipping.

Input voltage (yellow), dual-diode step-function output from DAC0 (purple) and exponential function output from DAC1 (green) with strongly visible clipping.

Caution: Aliasing

Due to the nature of distortion, higher order harmonics of the input signal’s frequency will be present in the signal after applying distortion algorithms. All hormonics that exceed the Nyquist-limit (half the sample-rate) will inadvertently cause aliasing. Therefore, in a practical high-quality digital signal processing application, the sampled input signal would be upsampled first, the algorithm would be applied, followed by an anti-aliasing filter before downsampling back to the original sampling rate (or any other desired rate for the DAC). For this very simple example I omitted this step. Given the relatively high sample rate of 96 kS/s, the Nyquist limit is 48 kHz and thus relatively far away from the high-spectral density part of the usual guitar harmonics. However, this issue should be something to be aware of when implementing the alogrithm shown here in own designs.

Conclusions

It is absolutely possible to model different diode clipping behaviours and easily package the resulting equations into a DSP algorithm. Given the relatively low computational power needed, even a lower-end Arduino is perfectly capable of performing this task, allowing for software adjustable parameterization of the exact overdrive and distortion characteristics.

Arduino Sketch

/*
 * Arduino Giga R1 WiFi - DSP Diode Clipping Example
 *
 * Copyright (C) 2023 Westerhold, S. (AI5GW) 
* Web (EN): https://baltic-lab.com
 * ORCID: https://orcid.org/0000-0001-7965-3140
 *
 * Tested sample-rates: 192000, 96000, 48000, 44100
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */

#include <Arduino_AdvancedAnalog.h>

// Instantiate ADC 0 (Pin A0), DAC 0 (Pin A12) and DAC 1 (Pin A13)
AdvancedADC Chan1(A0);
AdvancedDAC Out1(A12);
AdvancedDAC Out2(A13);

// Define ADC Midpoint
#define ADC_MIDPOINT 2047

void setup() {

  // Set-up ADC0, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!Chan1.begin(AN_RESOLUTION_12, 96000, 32, 32)) {
    Serial.println("ADC fail...");
    while (1)
      ;
  }

  // Set-up DAC0, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!Out1.begin(AN_RESOLUTION_12, 96000, 32, 32)) {
    Serial.println("Failed to initialize DAC 1");
    while (1)
      ;
  }

  // Set-up DAC1, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!Out2.begin(AN_RESOLUTION_12, 96000, 32, 32)) {
    Serial.println("Failed to initialize DAC 1");
    while (1)
      ;
  }
}

void loop() {

  if (Chan1.available()) {
    // Get handle for the input buffer
    SampleBuffer inBuf = Chan1.read();

    // Get handle for the output buffer
    SampleBuffer outBuf1 = Out1.dequeue();
    SampleBuffer outBuf2 = Out2.dequeue();

    for (int i = 0; i < inBuf.size(); i++) {
      // Dual diode, symmetrical clipping step-function on DAC0
      outBuf1.data()[i] = DiodeClippingStep(inBuf[i] - ADC_MIDPOINT, 800) + ADC_MIDPOINT;

      // Dual diode, symmetrical clipping exponential-function on DAC1
      outBuf2.data()[i] = DiodeClippingExponential(inBuf[i] - ADC_MIDPOINT, 800) + ADC_MIDPOINT;
    }

    // Write contents of the output buffer to the DACs
    Out1.write(outBuf1);
    Out2.write(outBuf2);

    // Release the input buffer
    inBuf.release();
  }
}

int DiodeClippingStep(int INPUT, int THRESHOLD) {
  float IN, OUT;
  int BUF = INPUT; // Store for sign revovery

  // Normalize input to threshold level = 1.0
  IN = (float)abs(INPUT) / THRESHOLD;

  if (IN <= (1.0 / 3.0)) {
    OUT = 2 * IN;
  } else if (IN <= (2.0 / 3.0)) {
    OUT = (-3.0 * (float)pow(IN, 2)) + (4.0 * IN) - (1.0 / 3.0);
  } else {
    OUT = 1;
  }

  // Undo Normalization
  OUT = OUT * THRESHOLD;
  // recover sign
  if (BUF <= 0) { OUT = -1.0 * OUT; }

  return round(OUT);
}

int DiodeClippingExponential(int INPUT, int THRESHOLD) {
  float IN, OUT;

  // Normalize input to threshold level = 1.0
  IN = (float)INPUT / THRESHOLD;

  if (IN < 0) {
    OUT = -1.0 + exp(IN);
  } else if (IN > 0) {
    OUT = 1.0 - exp(-IN);
  } else {
    OUT = 0;
  }

  // Undo Normalization
  OUT = OUT * THRESHOLD;
  return round(OUT);
}

Links and Sources:

[1] Zölzer, Udo. (2011). DAFX: Digital Audio Effects: Second Edition. 10.1002/9781119991298. : https://www.researchgate.net/

[2] Arduino Giga R1 WiFi, Elektorstore: https://www.elektor.com/arduino-giga-r1-wifi

[3] Westerhold, S. (2023), "Arduino GIGA R1 WiFi | Audio Loopback Example". Baltic Lab High Frequency Projects Blog. ISSN (Online): 2751-8140.: https://baltic-lab.com/

[4] Yeh, David & Smith, Julius. (2008). Simulating guitar distortion circuits using wave digital and nonlinear state-Space formulations. Proceedings - 11th International Conference on Digital Audio Effects, DAFx 2008: https://www.researchgate.net/

 

Critical length of a PCB trace and when to treat it as a transmission line

Ideally, the impedance of PCB traces should be matched to the load and source impedances. This becomes especially important in high-frequency and high-speed digital PCB designs. Various rules of thumb are available to determine the critical length at which a PCB trace should be treated as a transmission line. Below this critical length, an impedance mismatch can safely be ignored. Or can it?

SAW filter PCB with SMA connectors for 1090 MHz (ADS-B). Mismatched input and output traces (Z=100 Ohms, l=3,5mm) have been deemed acceptable.

SAW filter PCB with SMA connectors for 1090 MHz (ADS-B). Mismatched input and output traces (Z=100 Ohms, l=3,5mm) have been deemed acceptable.

Rule of Thumb

Rules of thumb are made to simplify our everday engineering life. For the critical length of a PCB trace, there are various different rules of thumb available. One of those rules is the 1/10 rule (Eq. 1). It basically states that the critical length for a PCB trace is 1/10th of the wavelength. It suggests that for length smaller than 1/10 of a wavelength, any impedance (mis)match and transmission line effects can safely be ignored.

(1)   \begin{equation*}  l_{crit} = \frac{\lambda}{10 \sqrt(\varepsilon_r)} \end{equation*}

The \varepsilon _r term in the equation corrects for the difference between physical length and electrical length. \varepsilon _r is equal to the relative permittivity, also oftentimes called the dielectric constant (Dk), of the PCB material used. For FR4 this varies between about 4.3 and 4.5. \lambda is of course the wavelength as defined by the speed of light divided by the frequency.

When working with digital singals, the critical length is expressed as a function of the rise or fall time(Eq. 2).

(2)   \begin{equation*}  l_{crit} = \frac{0.25 t c_0}{\sqrt(\varepsilon_r)} \end{equation*}

Where t denotes the rise- or fall-time (whichever is smaller) and c_0 the speed of light.

Now that we have commonly accepted rules of thumb and can easily calculate the length of a PCB trace below which we can safely ignore pesky things such as impedance matching and the relative permittivity of the PCB material used, I could wrap up this article and just leave it at that, right? Unfortunately, no…

What exact fraction of a wavelength to consider to be the threshold for the critical PCB-trace length varies by literature and people’s personal preferences. There’s also the 1/4, 1/8, 1/16 and 1/20 rule and many more. So which one of these is correct and which one should you use?

Transmission Line Math

To the question of when a PCB trace should be regarded as a transmission line, the short answer is: Always! To answer the question of when it really matters, we will have to dive a little bit into the science involved. Equation 2 shows the complex input impedance (Z_{IN}) of any stripline of length l in metres. Z_0 is the characteristic impedance of the transmission line itself, in this case the PCB trace. \beta is the propagation constant with the peculiar unit of radians per metre (Eq. 4). Z_L denotes the load impedance present at the end of the transmission line.

(3)   \begin{equation*}  Z_{IN} = Z_0 \frac{Z_L + j Z_0 tan(\beta l)}{Z_0 + j Z_L tan(\beta l)} \end{equation*}

(4)   \begin{equation*}  \beta = \frac{2 \pi}{\lambda} = \frac{2 \pi f}{c_0} \end{equation*}

The abomination of an equation can be simplified very slightly if the length l is given as a factor relative to the wavelength, for instance 0.25 or 1/4 for a quarter wavelength (Eq. 5).

(5)   \begin{equation*}  Z_{IN} = Z_0 \frac{Z_L + j Z_0 tan(2 \pi l)}{Z_0 + j Z_L tan(2 \pi l)} \end{equation*}

From this equation it is apparent that there is only a single case where the length of the PCB trace doesn’t matter. And that is when Z_0 = Z_0. Or in other words when the trace impedance perfectly matches the load impedance, for instance 50 Ohms. Under any other condition, except at length 0 (and multiples of 1/2 wavelength), the trace impedance will have some influence on the impedance seen at the beginning of the trace. But by how much and how much is acceptable?

A picture is worth a thousand words as they say. Let’s assume a load impedance of 50 Ohms and arbitrarily pick mismatched trace impedances of 60, 70, 80 and 90 Ohms. Using equation 4, the impedance seen at the beginning of the trace can be plottet as a function of electrical length.

Input impedance as a function of electrical length and trace-impedance.

Input impedance as a function of electrical length and trace-impedance.

Just for fun, I also plottet the same function with trace impedances of 20, 35, 65 and 80 Ohms. However, a smaller characteristic impedance of a PCB trace means that it is too wide. In that instance, honestly, just make it thinner and match it to 50 Ohms. Because the usual case of why we even might want to ignore impedance matched traces is because of their width. Especially in home made projects or when using one’s favorite chinese PCB manufaturer, the default PCB material is 1.6mm thick FR4. Assuming a dielectric constant of roughly 4.3, a microstripline with a characteristic impedance of 50 Ohms would have a thickness of around 3.1 mm. Using just 1mm thick FR4 with the same dielectric constant would reduce this to a more acceptable 2mm. Additionally, FR4 has the tendency to not have a very well controlled dielectric constant.

Input impedance as a function of electrical length and trace-impedance.

Input impedance as a function of electrical length and trace-impedance.

The previous graphs confirm what the math already showed: Any length (except 0) of a mismatched PCB trace has an influence on the input impedance of the trace. To decide what is acceptable and what not, we have to define what we will accept in our designs. Two possible figures of merit vould be the VSWR or the mismatch loss. The mismatch loss indicates how much of the input power is lost due to the impedance mismatch. I included two horizontal lines enclosing a VSWR of < 1:1.1, which corresponds to a mismatch loss of 0.01 dB. Another pair of horizontal lines marks the area in which the mismatch loss is below 0.1 dB, corresponding to a VSWR 1:1.356. At a VSWR of 1:1.356, 97.72 % of the transmitted power reaches the load, 2.28 % get reflected back to the load. At a VSWR of 1:1.1, these values improve to 99.77 % forward power and 0.23 % reflected power.

Input impedance plottet as a function of trace impedance for trace lengths of 1/10, 1/16 and 1/20 of a wavelength.

Input impedance plottet as a function of trace impedance for trace lengths of 1/10, 1/16 and 1/20 of a wavelength.

What you deem acceptable for your design is entirely up to you. Personally, in my hobby designs I yield for a mismatch loss of less than 0.1 dB. As shown in the graph, using the 1/10 rule of thumb will quickly put the design outside of those limits. The 1/16 rule (Eq. 6), however, is a really good and useful approximation. At least for PCB traces with a characteristic impedance of less than 110 Ohms. By simply keeping all relevant traces wider than 0.75 mm (max. Z ~100 Ohms, FR4, Dk=4.3, PCB thickness=1.6mm) I effectively eradicate the need to double check the trace impedance in addition to the critical length.

(6)   \begin{equation*}  l_{crit} = \frac{\lambda}{16 \sqrt(\varepsilon_r)} \end{equation*}

The periodicity of the input impedance at 1/2 wavelength intervals is also an interesting phenomenon. Half a wavelength corresponds to 180 degrees of phase shift. For a reflected signal the total round trip delay would thus be 360 degrees. Assuming a periodic signal, the reflected signal would thus be in phase with the “new” signal at the input. Therefore, one could theoretically intentionally design a mismatched transmission line with a total length less than the critical length plus any integer multiple of 1/2 \lambda.

Periodicity of the input impedance of a mismatched transmission line as a function of electrical length

Periodicity of the input impedance of a mismatched transmission line as a function of electrical length

Conclusions

Within certain constraints, rules of thumb can be an effective guide to estimate the critical length of a PCB trace. However, it is important to be aware of one’s own design requirements and not be tempted to completely ignore any transmission line effects regardless of length.

 

Etching PCBs using hydrochloric acid and hydrogen peroxide

Choosing the right etchant for home made PCBs could be a science on its own. Some people prefer ferric chloride, some advocate for sodium persulfate and I personally prefer hydrochloric acid and hydrogen peroxide. This article shows how to use a mixture of hydrochloric acid and hydrogen peroxide in a safe and controllable manner.

UPDATE: There also is a German version of this article available on my German blog: Leiterplatten mit Salzsäure und Wasserstoffperoxid ätzen

Introduction

Using a combination of hydrochloric acid (HCl) and hydrogen peroxide H2O2 in itself is nothing new. When I recently rediscovered this method (because I was out of sodium persulfate), I was amazed by the quality and sharpness of the resulting traces and pads. I shared my amazement on Twitter [1]. To my surprise, the responses were extremely divided. Many people confirmed that they have been using the same etchant for a long time and had great success with it. Others proclaimed it was a terrible etchant, extremely dangerous and poor controllability. As always, the devil is in the details. The group confirming the high reliability of hydrochloric acid and hydrogen peroxide as an etchant use – just like me – highly diluted solutions. Just like the common saying “it is the dose that makes the poison” goes, for use as an etchant it is absolutely essential to use proper concentration levels.

Etchant Preparation

For 1 litre of etchant the following ingredients are used:

  • 700 ml distilled water
  • 200 ml 30-35 % hydrochloric acid (HCl)
  • 100 ml 12 % Hydrogen Peroxide (H2O2)

All ingredients are added together in a beaker. Water is added first, then the hydrochloric acid, lastly the hydrogen peroxide.

Two GL45 bottles containing 8 % hydrochloric acid (left) and 12 % hydrogen peroxide (right)

Two GL45 bottles containing 8 % hydrochloric acid (left) and 12 % hydrogen peroxide (right)

Concentrated hydrochloric acid, also called muriatic acid, does fume a lot and the fumes are quite unpleasant to breathe in. The fumes are also highly corrosive to anything near it. So in order to mitigate the possible hazards, and to simplify the preparation of the etching solution, I prepared an 8 % hydrochloric acid solution in a well ventilated area. Additionally, I prepared a 12 % hydrogen peroxide solution. Both are safe for storage and use in a regular indoor lab. The concentrations were chosen to further simplify the preparation of the etchant: 9 parts of the 8 % HCl and 1 part of the 12 % H2O2 solution are added together to yield 10 parts of ready to use etchant solution. For example, adding 90 ml of the 8 % HCl and 10 ml of the 12 % H2O2 solution yield 100 ml of etching solution.

Another option, especially in countries where 12 % hydrogen peroxide is hard to come by, would be to use 3 % H2O2 and premade 14 % hydrochloric acid. In that case, the mixture ratio is further simplified to 1:1. For instance, 500 ml of 14 % HCl and 500 ml of 3 % hydrochloric acid would yield 1 litre of etchant.

It should be noted that hydrogen peroxide likes to decompose when exposed to light. Therefore, the H2O2 stock solution should be kept in an amber glass bottle, or at least be kept away from (natural) light sources.

Hazard of Chlorine gas production

A common warning is, that this method produces extremely dangerous and toxic chlorine gas. While chlorine is always produced (Eq. 1 and 2), it’s release as chlorine gas does depend strongly on the concentration of the HCl and H2O2 used [2]. If the concentrations are kept below a certain threshold, the chlorine is staying in solution and is eventually consumed in another reaction mechanism (Eq. 3).

(1)   \begin{equation*}  H_2O_2 + HCl -> H_2O + HOCl \end{equation*}

(2)   \begin{equation*}  HOCl + HCl -> H_2O + Cl_2 \end{equation*}

(3)   \begin{equation*}  H_2O_2 + Cl_2 -> 2HCl + O_2 \end{equation*}

So how much is too much? To quote directly from a research paper titled “Oxidation of hydrogen chloride with hydrogen peroxide in aqueous solution”:

The oxidation of hydrogen chloride with hydrogen peroxide at common temperature with the evolution of chlorine into the gas phase occurs at a hydrogen chloride concentration in a solution exceeding the threshold value (5.2 M).

A 5.2 M concentration of HCl corresponds roughly to 16.1 %. The concentration used in the etchant recommended in this article is about 2.27 M, less than half of the critical threshold level!

Etching Process

When ready to etch a PCB, I prepare the necessary amount of etchant as describeb before. A glass beaker is used as the container for the etching process. The PCB is completely submersed in the etchant. For a copper thickness of 35 µm (1 oz) the etching time is about 17 minutes at room temperature. After the etching has completed, remove the PCB from the etchant and rinse the PCB with water.

FR4 PCB after 17 minutes in the HCl and H2O2 etchant.

FR4 PCB after 17 minutes in the HCl and H2O2 etchant.

Conclusions

The results are quite satisfactorily. The quality of the traces in regards of sharpness, lack of overetching is outstanding. While standard precautions should be in place when working with chemicals, I can involuntarily state that even a few drops of the etchant won’t eat your flesh anytime soon. Which is no surprise at these high levels of dilution.

Prototype of a Triplexer etched using a hydrochloric acid and hydrogen peroxide etching solution

Prototype of a Triplexer etched using a hydrochloric acid and hydrogen peroxide etching solution

In the beginning of the etching process, the copper is attacked and copper chloride is formed. After a while, the etching process will follow the same chemical principles of using Copper(II) chloride directly [3]. Having a bit of cupric chloride in the etching solution to begin with might help the etching process. In any case, due to it’s regenerative nature, the etching solution should last for a long time. That said, I have never attempted to store used etchant and always prepare a fresh solution when I need it.

YouTube Video

Links and Sources:

[1] Twitter Post, Baltic Lab: https://twitter.com/BalticLabEE/status/1687521760386670592

[2] Oxidation of hydrogen chloride with hydrogen peroxide in aqueous solution, Skudaev, V. and Solomonov, A. and Morozovskii, A. and Isakov, N.: https://link.springer.com/article/10.1134/S1070427208010035

[3] Etching with Air Regenerated Acid Cupric Chloride, By Adam Seychell: http://techref.massmind.org/Techref/pcb/etch/cucl2.htm

 

Universal Clock Translator using Renesas VersaClock 6E Devices

Due to the popularity of the QO-100 geostationary amateur radio communication satellite, precision GPS reference frequency sources (GPSDO) are becoming more and more common in home labs. The desire to derive different, fixed frequency signals from a GPSDO has similarly been increasing as different devices requiere different reference clocks with different frequencies. Therefore, this article is taking a closer look at the VersaClock 6E devices from Renesas.

General Overview

The most common reference signal frequency in professional labs is 10 MHz. Many GPS disciplined frequency standards, therefore, provide 10 MHz signals and most professonal laboratory equipment has 10 MHz reference input connectors. When it comes to a QO-100 satellite station, one might need a 25 MHz reference signal for the LNB, a 40 MHz reference signal for the ADALM Pluto and the transmit transverter usually requieres yet another, different reference frequency. While some GPSDOs, such as the common Leo Bodnar devices, have the ability to change the output clock frequency, it still doesn’t solve the problem of generating multiple clock reference signals with different frequencies. The ICS501 / ICS502 devices might appear like a good (but obsolete) part for frequency translation. However, their phase noise performance is subpar. While researching, I came across the VersaClock 6E devices from Renesas.

The devices I tried are the 5P49V6965 and 5P49V6975. Both devices are capable of providing 4 independent outputs with frequencies ranging from 1 kHz to 350 MHz with a low phase noise PLL of typically les sthan 0.5ps RMS phase jitter. Two different reference clock inputs provide additional flexibility. The first input is designed to support an external crystal as frequency selective device with a crystal frequency range from 8 to 40 MHz. A second, external clock input accepts reference signals from 1 to 200 MHz in single-ended mode [1,2].

Programming Kit for VersaClock 6E devices, such as the 5P49V6965 and 5P49V6975

Programming Kit for VersaClock 6E devices, such as the 5P49V6965 and 5P49V6975

Using the Programming Kit for VersaClock 6E [3] and the software IDT Timing Commander, a 5P49V6965 was programmed to generate 3 different output signals with frequencies of 25 MHz, 40 MHz and 100 MHz from an external 10 MHz reference signal.

IDT Timing Commander used for testing and programming the 5P49V6965 and 5P49V6975

IDT Timing Commander used for testing and programming the 5P49V6965 and 5P49V6975

After writing the desired values to the 5P49V6965, an external 10 MHz reference signal was connected to the board and the output was ovserved using an oscilloscope. It should be mentioned that absolutely no care was taken to implement proper impedance matching.

Example output of a 25 MHz signal from a 10 MHz reference signal by a Renesas 5P49V6965

Example output of a 25 MHz signal from a 10 MHz reference signal by a Renesas 5P49V6965

Test Results

The first thing that was observed, was that the 5P49V6965 has absolutely no problem accepting external, sinusoidal reference signal with negative amplitude components. When the reference generator’s output amplitude was set to 1 Vpp with no offset, thus sending the negative half-wave down to -500 mV, the device locked onto the reference signal perfectly. When a square wave is used, the necessary minimum signal amplitude for a proper lock was even lower.

25 MHz clock signal generated from an external 10 MHz reference signal by a 5P49V6965

25 MHz clock signal generated from an external 10 MHz reference signal by a 5P49V6965

40 MHz clock signal generated from an external 10 MHz reference signal by a 5P49V6965

40 MHz clock signal generated from an external 10 MHz reference signal by a 5P49V6965

100 MHz clock signal generated from an external 10 MHz reference signal by a 5P49V6965

100 MHz clock signal generated from an external 10 MHz reference signal by a 5P49V6965

Unsurprisingly, the outputs generated signals of 25, 40 and 100 MHz according to their programming.

Conclusions

The 5P49V6965 and 5P49V6975 devices appear to be perfect candidates for a univeral clock translator board that can be programmed to provide 4 different reference frequencies from a single, standard reference clock source. The next step is to design a prototype PCB that properly takes care of input- and output termination to a systems impedance of 50 Ohms. The two different clock inputs of the device and the clock select pin open up an easy implementation of an on-board TCXO with automatic switchover when an external reference is applied to the PCB. Since 4 different, hardware selectable configurations can be burned into the device, the most commonly needed reference frequency can be programmed into the device and be selected by jumpers.

Links and Sources:

[1] 5P49V6975 Datasheet, Renesas: https://www.renesas.com/us/en/document/dst/5p49v6965-datasheet?language=undefined

[2] 5P49V6965 Datasheet, Renesas: https://www.renesas.com/us/en/document/dst/5p49v6975-datasheet

[3] Programming Kit for VersaClock 6E, Renesas: https://www.renesas.com/us/en/products/clocks-timing/clock-generation/programmable-clocks/5p49v6965-prog-programming-kit-versaclock-6e

 

Arduino GIGA R1 WiFi | Audio Loopback Example

This article shows a basic sketch outline to use the Arduino GIGA R1 WiFi for audio DSP experiments. The sketch presented makes use of the Advanced Analog Library to implement a simple audio loopback device.

UPDATE: There also is a German version of this article available on my German blog: Arduino GIGA R1 WiFi | Audio Loopback Beispiel-Code

General Overview

The new Arduino GIGA R1 WiFi offers great potential as an inexpensive platform for DSP audio experiments. Elektor kindly sent me a review sample of the Giga R1 [1]. With 12 ADCs, features two 12-bit buffered DACs and plenty of memory and horsepower, it was only logical to see how well the Giga performs in the world of DSP. The obvious starting point is to implement an audio-loopback-device. Since I was unable to locate any working code examples, I quickly cooked up a sketch from scratch using the Advanced Analog Library.

Arduino GIGA R1 WiFi being evaluated as an audio DSP platform

Arduino GIGA R1 WiFi being evaluated as an audio DSP platform

Arduino Code

/*
 * Arduino Giga R1 WiFi - Audio Loopback Example
 *
 * Copyright (C) 2022 Westerhold, S. (AI5GW) 
 * ORCID: https://orcid.org/0000-0001-7965-3140
 * Web (EN): https://baltic-lab.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */

#include <Arduino_AdvancedAnalog.h>

// Instantiate ADC 0 (Pin A0) and DAC 0 (Pin A12)
AdvancedADC ADC0(A0);
AdvancedDAC DAC0(A12);

void setup() {
  Serial.begin(9600);

  // Set-up ADC0, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!ADC0.begin(AN_RESOLUTION_12, 44100, 128, 128)) {
    Serial.println("ADC fail...");
    while (1);
  }

  // Set-up DAC0, stop program on failure
  // Resolution, sample rate, number of samples per channel, queue depth.
  if (!DAC0.begin(AN_RESOLUTION_12, 44100, 128, 128)) {
    Serial.println("Failed to initialize DAC 1");
    while (1);
  }
}

void loop() {

  if (ADC0.available()) {
    // Get handle for the input buffer
    SampleBuffer inBuf = ADC0.read();
    // Get handle for the output buffer
    SampleBuffer outBuf = DAC0.dequeue();

    for (int i = 0; i < inBuf.size(); i++) {
      // Copy contents of input buffer to the output buffer
      outBuf.data()[i] = inBuf[i];
    }

    // Write contents of the output buffer to the DAC
    DAC0.write(outBuf);

    // Release the input buffer 
    inBuf.release();
  }
}

Test Results

After compiling the code and flashing the Arduino GIGA R1 WiFi, a signal generator was connected to the A0 input pin. The DAC0 output pin was monitored using an oscilloscope. The first test was performed by applying a 800 Hz sine wave signal with an amplitude of 1 Vpp and an offset-voltage of 500 mV. The offset voltage is necessary because the DACs of the Arduino Giga R1 WiFi are not capable of generating negative voltages.

800 Hz sine-wave (bottom trace) fed into the Arduino Giga R1 WiFi (bottom), Output on pin DAC0 from the arduino (top trace)

800 Hz sine-wave (bottom trace) fed into the Arduino Giga R1 WiFi (bottom), Output on pin DAC0 from the Arduino (top trace)

A more close-up view reveals the typical stair-steps of the DAC. For actual audio applications, the output signal would obviously have to be filtered. Note that absolutely no care was taken to adjust the conversion frequency of the DAC in any way. The examples were implemented using the default configurations.

Closeup of the same 800 Hz sine wave shown in the previous picture

Closeup of the same 800 Hz sine wave shown in the previous picture

Next, the waveform was changed to a 1 kHz square wave. The amplitude settings were left unchanged.

1 kHz square wave test. Bottom trace; Input, Top Trace: Output from DAC0

1 kHz square wave test. Bottom trace; Input, Top Trace: Output from DAC0

Lastly, a ramp signal with a frequency of 1 kHz and an amplitude of 1 Vpp and an offset-voltage of 500 mV was applied to the A0 input.

1 kHz ramp signal test. Bottom trace; Input, Top Trace: Output from DAC0

1 kHz ramp signal test. Bottom trace; Input, Top Trace: Output from DAC0

Conclusion

The sketch provided above provides a great starting point for audio DSP experiments. Instead of simply copying the input buffer straight to the output buffer, it would be quite easy to manipulate the input buffer to achieve certain DSP-functions.

Links and Sources:

[1] Arduino Giga R1 WiFi, Elektorstore: https://www.elektor.com/arduino-giga-r1-wifi

 

LNB Modification for 10 GHz QO-100 Satellite Reception

This article shows how to modify an inexpensive LNB to accept an external LO-reference signal in order to be used as a K-band downconverter for QO-100 (Qatar Es’hail 2) amateur radio sattelite reception, radio astronomy or similar K-band experiments.

This article is a shortened version of a scientific paper that I wrote as the lead author. For a more in-depth, scientific version , feel free to download the research paper. [1]. There also is a German version of this article available: LNB Modifikation für X-Band und QO-100 Empfang

Introduction

The commercial LNB chosen here is a Goobay 67269 LNB. According to the manufacturer, the LNB is suitable for reception from 10.7 to 11.7 GHz (low-band) and from 11.7 to 12.75 GHz (high-band) [3]. The IF frequency range is 950 MHz to 1950 MHz (low-band) and 1100 to 2150 MHz (high-band). This corresponds to a local-oscillator (LO) frequency of 9.75 GHz (low-band) and 10.6 GHz (high-band).

Unmodified Goobay 67269 LNB

Unmodified Goobay 67269 LNB

The LO signal of the LNB is referenced to a 25 MHz crystal. In low-band operation, the 25 MHz is multiplied by a factor of 390, in high-band operation the multiplication factor is 424. While a standard 25 MHz crystal reference is stable enough for broadband satellite TV reception, it is insufficient for the reception of narrow-band signals commonly found on radiocommunication satellites such as the popular, geostationary QO-100 (Qatar Es’hail 2). Therefore, the desire arises to lock the LO to an externally provided reference.

This also opens up the possibility to change the LO-frequency so that the IF-frequency range can be moved to a more convenient range. For instance, the narrow-band transponder of QO-100 has a downlink frequency range of 10489.5 to 10490 MHz. The standard LO-frequency of 9750 MHz results in an intermediate frequency (IF) frequency range of 739.5 to 740 MHz. If the reference frequency is changed to 25.780 – corresponding to a LO-frequency of 10054.20 MHz -, the resulting IF frequency range would move to 435.30 MHz – 435.80 MHz, right in the center of the 70 cm amateur radio band.

Modification

The modification itself is quite simple. In essence, the 25 MHz crystal is removed and replaced by a 25 MHz LC-series resonant circuit with bandpass characteristic connected to the F-connector of the LNB. Standard component values of 18 pF and 2,2 µH were chosen for the series LC circuit.

(1)   \begin{equation*}  Z_{LC} = |2 \pi f L - \frac{1}{2 \pi f C}|  \end{equation*}

This in an impedance of 8.1 Ω at a frequency of 25 MHz. At 26 MHz the resulting impedance is 19.32 Ω, at 27 MHz this value further increases to 45.74 Ω (Eq. 1).

After removing the plastic cover using a flat screwdriver, the metal cover for the PCB housing can be removed after loosening two screws. The required screwdriver is of type Torx T8. After removal of the metal cover, the top-side of the LNB’s PCB is accessible.

Plastic cover of the LNB removed

Plastic cover of the LNB removed

Removal of the PCB housing screws

Removal of the PCB housing screws

The main function blocks of the LNB’s PCB can easily be identified. The circuit design is centered around a fully integrated PLL/LO/Downconverter-chip marked “3566E”. Even after a thorough search, very little information on this chip can be found. However, knowing the general working principle of such a chip, the relevant parts of the circuit can be reverse engineered without specific device information at hand.

The DC supply-voltage from the F-connector is passed to a 7806-type voltage regulator through a printed circuit board inductor (yellow rectangle), supplying the 3566E with stable 6 V DC. The PINS marked XTAL1 and XTAL2 connect to a 25 MHz crystal located on the backside of the PCB.

Closeup of the PCB with markings for the PLL, crystal pins and the printed circuit board inductor choke in front of the voltage regulator (yellow rectangle)

Closeup of the PCB with markings for the PLL, crystal pins and the printed circuit board inductor choke in front of the voltage regulator (yellow rectangle)

In order to identify the proper input pin for injection of an external LO-reference-signal, the waveforms on pin 1 and pin 2 where examined using an oscilloscope. Pin 2 of the 3566E (XTAL2) was consequently identified to be the most suitable pin for injection of an external reference signal.

After removal of a single solder pin right above the F-connector, the PCB can be removed from the casing. It was found to be best to apply a slight upward pressure to the PCB while heating the solder joint.

Applying slight upward pressure right next to the solder-joint

Applying slight upward pressure right next to the solder-joint

Two of the LNB PCBs before the modification (top) and after the removal of the 25 MHz crystal (bottom)

Two of the LNB PCBs before the modification (top) and after the removal of the 25 MHz crystal (bottom)

The 25 MHz, through-hole crystal on the back of the PCB was removed using a soldering iron and solder wick. A 2.2 µH inductor was then installed instead of the previously removed crystal. In order to protect the leads of the inductor from unintended contact with the grounded enclosure, it was covered with a small piece of Kapton tape. The PCB was then re-installed inside the metal enclosure and soldered back in place.

2.2 µH inductor installed in lieu of the removed 25 MHz crystal

2.2 µH inductor installed in lieu of the removed 25 MHz crystal

The now unnecessary and hindering PCB trace connecting the crystal socket pin previously described as “XTAL 1” and the 3566E PLL was cut using a sharp object. Lastly, the 18 pF capacitor has been soldered between the input connection pin (from the F-connector) and XTAL 1.

The PCB-trace connected to pin XTAL 1 has been cut using a sharp tool

The PCB-trace connected to pin XTAL 1 has been cut using a sharp tool

A 18 pF capacitor has been installed between the F-connector input pin and the XTAL 1 pin, connecting directly to the 2.2 µH inductor

A 18 pF capacitor has been installed between the F-connector input pin and the XTAL 1 pin, connecting directly to the 2.2 µH inductor

Test and Results

In order to test the functionality of the performed modification, the LNB was connected to a makeshift diplexer with integrated bias tee. Absolutely no care was taken to match the LNB’s input impedance of 75 Ω to the 50 Ω impedance of the equipment used in this test.

The high-pass path of the diplexer (fc = 100 MHz) was connected to a RTL2832 SDR through a 10 dB attenuator. The low-pass path of the diplexer (fc = 30 MHz) was connected to a signal generator. The signal generator was then set to a frequency of 25.78 MHz, resulting in a LO-frequency of 10054.2 MHz if locked on correctly. 14 VDC were then supplied to the LNB through the bias tee of the diplexer. It was observed that the LNB draws a current of 60 mA when unlocked. This value jumps to approx. 90 mA when the PLL has properly locked onto the external reference signal. Lock was observed at a signal amplitude of 3 Vpp into the diplexer. At 75 Ohms, this corresponds to a drive level of around 12 dBm.

Two signals of 3496 MHz and $3496.333 MHz were generated using an ADF4351 evaluation board from Analog Devices. The third harmonics of said signals should produce suitable test signals with frequencies of 10.488 GHz and 10.489 GHz. The ADF4351 evaluation board was set to hop between both frequencies at a rate of 500 ms.

LNB ignal output viewed in SDRSharp

LNB signal output viewed in SDRSharp

The resulting output spectrum was viewed in AirSpy SDR# Studio. The two test signals were clearly visible and the alternating 500 ms hops confirmed their identity. It was noted that due to the high gain of the LNB, it was very easy to overdrive the LNB. Despite using the third harmonic of signals with an amplitude of -4 dBm, the LNB had to be pointed away from the signal source in order not to cause distortion. Further, the 10 dB attenuator in front of the RTL2832 SDR was absolutely necessary in order not to exceed the full-scale dynamic range of the receiver.

It was further observed that varying the frequency of the reference signal between 24 MHz and 27 MHz does indeed change the LO-frequency without a visible change in IF output power or spurious frequency components.

Conclusions

This article shows that it is possible to successfully modify an inexpensive Goobay 67269 LNB to accept an external reference signal. Furthermore, the experiments shown demonstrate that the LNB is capable of down-converting K-band signals outside of the manufacturer’s specified frequency range.

Links and Sources:
[1] Westerhold, S. and Matlinski, C., “Modification of a Goobay 67269 LNB for use in 10 GHz communication satellite reception”, Jul. 2023, doi: 10.5281/zenodo.8102235.

[2] Armin Duft. “Goobay 67269 LNB Modification”. In: (2019). url: https://dh1da.darc.de/projekte/Amateurfunk/QO-100_LNB/Goobay_67269_LNB_Mod-DH1DA.pdf (visited on 07/01/2023).

[3] Wentronic GmbH. Universal Single LNB | Wentronic. url: https://www.wentronic.com/de/universal-single-lnb-67269 (visited on 07/01/2023).

 

Program uBlox GPS-module timepulse frequency (dynamically) with an Arduino

The uBlox GPS-modules are capable of providing various reference clock signals through the TIMEPULSE pin. By default, this pin outputs a 1 pulse-per-second (PPS) signal. For an upcoming project, a GPS disciplined oscillator (GPSDO), this output had to be adjusted to 100 kHz. Instead of using the manufactuer’s software, u-center, this task is supposed to be accomplished using an Arduino. This article shows how to (dynamically) adjust the TIMEPULSE reference signal using an Arduino.

General Overview

For my experiments, I used uBlox NEO M6, M7 and M8 modules. The modules were connected to a Laptop using a FT232RL-based UART to USB converter. Using the uBlox u-center software, the Timepulse 5 settings were adjusted to generate 10 kHz and 100 kHz signals with a duty cycle of 50 %. The generated commands were observed using the binary console view of the u-center software.

Setting the Timepulse 5 settings using the uBlox u-center software. Commands sent to the NEO-6 GPS module can be observed in the binary console view.

Setting the Timepulse 5 settings using the uBlox u-center software. Commands sent to the NEO-6 GPS module can be observed in the binary console view.

Those binary commands were then translated to C++ compatible arrays. These commands can now be sent to the GPS-modules using an Arduino quite easily. For instance, the command array to set Timepulse 5 to generate a 10 kHz reference signal with 50 % duty cycle, synchronized to UTC time if the receiver has a valid position fix is as follows:


// UBX CFG-TP5: Set 10 kHz, 50 uS Pulses (50 % duty-cycle), Synch UTC-Time, no output if GPS unlocked
byte TP5_10K_LOCK[]{0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x73, 0xF3};

Sending this command to the GPS-module using the inbuilt UART can be accomplished as follows:

Serial.write(TP5_10K_LOCK, sizeof(TP5_10K_LOCK));

uBlox NEO-6 GPS module connected to an Arduino Uno for dynamic Timepulse 5 setting.

uBlox NEO-6 GPS module connected to an Arduino Uno for dynamic Timepulse 5 setting.

Another useful setting for GPS-locked frequency references is the CFG-NAV5 setting. It can be used to set the navigation mode to stationary.

// CFG-NAV5: Set navigation mode to stationary
byte CFG_NAV5_STATIONARY[] = { 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x60 };

Note that all settings, including Timepulse 5 and CFG-NAV5, are volatile. That means the settings are lost upon power-cycling the module. This can be avoided by permanently storing the adjusted settings using the CFG-CFG-command.

// UBX CFG-CFG: Save all. BBR + FLASH:
byte CFG[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1D, 0xAB };

After sending the CFG-CFG-command, all settings will be permanently stored and retrieved upon power-up. Therefore, a microcontroller is not necessary for operating a uBlox GPS-module as frequency reference. The settings can be adjusted dynamically during operation in order to generate different reference frequencies as needed.

Test Results

A simple and straight-forward Arduino sketch was written to test the commands on various uBlox modules. The code sets the Timepulse 5 output frequency to 10 kHz, the navigation mode to stationary and stores the settings permanently. It then goes on to change between 10 kHz and 100 kHz every 10 seconds. The Timepulse output was connected to an oscilloscope and the resulting waveforms were observed. As shown in the images below, the module successfully accepted the commands and alternatingly put out 10 kHz and 100 kHz signals when locked to a valid GPS-source.

100 kHz, 50 % duty-cycle output from a uBlox NEO-6M GPS module

100 kHz, 50 % duty-cycle output from a uBlox NEO-6M GPS module

10 kHz, 50 % duty-cycle output from a uBlox NEO-6M GPS module

10 kHz, 50 % duty-cycle output from a uBlox NEO-6M GPS module

Commands

Here is a list of useful commands in array-form for the Arduino IDE:

// UBX CFG-CFG: Save all. BBR + FLASH:
byte CFG[] = { 0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1D, 0xAB };

// CFG-NAV5: Set navigation mode to stationary
byte CFG_NAV5_STATIONARY[] = { 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x60 };

// UBX CFG-TP5 Timepulse 5: 10 kHz, 50 uS (50 % duty cycle), synch to UTC Time, No Putput when unlocked
byte TP5_10K_LOCK[]{ 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x73, 0xF3 };

// Timepulse 5: 100 kHz, 5 uS (50 % duty cycle), synch to UTC Time, No Putput when unlocked
byte TP5_100K_LOCK[]{ 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x36, 0x36 };

// UBX CFG-TP5 Timepulse 5: 10 kHz, 50 uS (50 % duty cycle), synch to UTC Time, free running 10 kHz if unlocked
byte TP5_10K[] = { 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xDB, 0xFC };

// UBX CFG-TP5 Timepulse 5: 100 kHz, 5 uS (50 % duty cycle), synch to UTC Time, free running 100 kHz if unlocked
byte TP5_100K[] = { 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x61, 0x8E };

Arduino Code

/*
 * uBlox u-blox NEO-6M / NEO-7M 
 *
 * Copyright (C) 2022 Westerhold, S. (AI5GW) 
 * ORCID: https://orcid.org/0000-0001-7965-3140
 * Web (EN): https://baltic-lab.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */


// CFG-NAV5: Set navigation mode to stationary
byte CFG_NAV5_STATIONARY[] = { 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x60 };

// UBX CFG-CFG: BBR + FLASH:
byte CFG[] = { 0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1D, 0xAB };

// UBX CFG-TP5 Timepulse 5: 10 kHz, 50 uS (50 % duty cycle), synch to UTC Time, No Putput when unlocked
byte TP5_10K_LOCK[]{ 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x73, 0xF3 };

// Timepulse 5: 100 kHz, 5 uS (50 % duty cycle), synch to UTC Time, No Putput when unlocked
byte TP5_100K_LOCK[]{ 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x36, 0x36 };

void setup() {
  Serial.begin(9600);
  // Set Timepulse output to 100 kHz, 50 % duty-cycle
  Serial.write(TP5_10K_LOCK, sizeof(TP5_10K_LOCK));
  // Set navigation mode to stationary
  Serial.write(CFG_NAV5_STATIONARY, sizeof(CFG_NAV5_STATIONARY));
  // Store settings permanently
  Serial.write(CFG, sizeof(CFG));
}

// loop switches between 10 kHz and 100 kHz every 10 seconds
void loop() {
  Serial.write(TP5_10K_LOCK, sizeof(TP5_10K_LOCK));
  delay(10000);
  Serial.write(TP5_100K_LOCK, sizeof(TP5_100K_LOCK));
  delay(10000);
}