Monday, June 22, 2026

Repair Log: HP 3335A


This blogpost describes my efforts repairing three HP 3335A Synthesizer/Level Generators that have the following combined problems:

  • Blank display,
  • Intermittent Display Digit
  • Power Switch won't toggle ON/OFF
  • Keyboard key-bounce (in which a single keypress registers as several)
  • RF Output Amplitude Changing / Bad -15 VDC Power Supply Voltage
  • Output Frequency does not match the Displayed Frequency

But first, a thumbnail sketch of this generator's features:

The HP 3335A Synthesizer/Level Generator is a late 1970's-era low-distortion precision RF generator useful for testing in the 0 - 80 MHz region.  It has the following specifications:
  • Output Frequency Range:  200 Hz to 80.999 999 999 MHz in steps of 0.001 Hz
  • Output Amplitude Range:  +13.01 dBm to -86.98 dBm in steps of 0.01 dB (50 Ohm termination).
  • High-stability frequency reference that can be locked to an external reference, such as a GPS Disciplined Oscillator.
  • Remote Control via HP-IB parallel interface.
Its keyboard input of frequency and amplitude makes it easier to use, in my opinion, than HP's 8640B generator when tests require frequently changing frequency.

And its HP-IB interface makes it ideal for computer control.  I used a pair of 3335As for automated IMD Testing of my 500 Watt Solid State Power Amplifier, as shown below:



Simplified HP 3335A Theory of Operation for Frequency Generation:

Let's take a look at the following simplified Block Diagram (see:  "Operating and Service Manual, Model HP 3335A, Synthesizer/Level Generator," HP publication number 03335-90003) to get a better understanding of how the HP 3335A generates its RF signal.


A Quick Overview:

Internally, the 3335A's frequency-generation creates creates a signal that can span from 40 to 81 MHz.

To cover lower frequencies, this 40-81 MHz signal is divided by an appropriate power-of-two (2 or 4), giving an additional range of 10-40 MHz (similar to how the HP 8640B generates its lower frequencies).

Finally, for output frequencies spanning from 0 to 10 MHz, the 40-81 MHz Oscillator (set to a frequency between 40 and 50 MHz) is mixed with a 40 MHz reference frequency, creating lower and upper sideband mixing products.  Filtering removes the higher-frequency products, leaving only the LSB products in the 0-10 MHz range.

Generating the RF Signal:

Two phase-locked loops, the "N-Fractional Loop" (also known as the "N.F Loop" for brevity's sake) and the "N-Step Loop" (also known as the "N Loop") generate two VCO-controlled signals under the control of the microprocessor.  Their frequency ranges are:
  • N.F Loop:  Output is 1 - 1.999 999 999 MHz in 1 mHz steps.
  • N Loop:     Output is 39 - 79 MHz in 1 MHz steps.
The output of these two loops drive a third phase-locked loop, the "Summation Loop", to create the final output signal whose frequency is the sum of the N.F Loop's and the N Loop's frequencies.  This third loop's VCO Output spans from 40 to 80.99(...) MHz, per the figure, below:


If the final Output frequency is to be in the range of 10 - 80.99(...) MHz, the Summation Loop's output frequency (which is in the range of 40 to 80.99(...) MHz) is divided by an appropriate power-of-two to give a final output frequency of between 10 and 80.99(...) MHz:
  • For generator output frequencies between 10 and 19.99(...) MHz, divide the Summation Loop's output frequency by 4.
  • For output frequencies between 20 and 39.99)...) MHz, divide the Summation Loop's output frequency by 2.
  • And for output frequencies between 40 and 80.99(...), divide the Summation Loop's output frequency by 1.
For output frequencies between 0 to 10 MHz, the Summation Loop's frequency is set to be between 40 and 50 MHz, and this frequency is then mixed with a 40 MHz reference, generating mixing products at the sum and difference frequencies: (40 to 50 MHz) minus 40 MHz and (40 to 50 MHz) plus 40 MHz.  A low-pass filter filters out the high-frequency components, leaving only the 0 to 10 MHz mixing product.


Because one of the problems I was trying to fix involved wrong frequencies, I thought I should try to better understand how frequency generation works.

So I ran a couple of simple tests on a good HP 3335A using the conveniently located test connectors its Motherboard (one RF connector is the 1-2 MHz output of N.F Loop, and another is the 39-79 MHz output of the N Loop).

The photo, below, shows the location of the 1-2 MHz N.F Loop Test Connector:



And here is the 39-79 MHz N Loop Test Connector (with my test cable attached):


First, I measured the output of the N Loop (that changes in 1 MHz increments) as I stepped the generator's Output frequency in 1 MHz steps from 1 to 80 MHz.  Below are the results:


Next, I stepped the Output frequency from 19.0 to 20.0 MHz in 0.1 MHz steps, measuring the frequencies of both the N.F Loop and N-Step Loop (i.e. N Loop) at each step:


From the table above, you can see that the generator's output frequency in the 19 MHz range is:

     Fout = (N.F_Loop_Frequency + N_Loop_Frequency) / 4

So, for example, for an output frequency of 19.3 MHz, Fout = (1.2 +76.0) / 4 = 19.3 MHz.

Note that at 20 MHz the division Factor, D, changes from 4 to 2.  In other words, for 20 MHz Fout = (N.F_Loop_Frequency + N_Loop_Frequency)/2 = (1.0 + 39.0)/2 MHz.

I hope that adequately summarize frequency generation.  For additional information on the generator's functional blocks, please refer to the next two images.  They are a more detailed Functional Block Diagram from HP's Ops & Service Manual (pub. number 03335-90003):




HP 3335A Repair,  S/N 1640A02777

Problems:
  • Display goes blank at power up.
A blank display implied that there was an issue with the boards in the front-panel assembly.  The most likely suspect was Controller Board.

I first tried swapping the Controller board with a known good one, but there was no change in the failure.

I decided to try swapping the entire front-panel assembly with a known good one, but while unplugging the cables connecting it to the 3335's chassis, I discovered that the display started working after I unplugged the cable to the HP-IB circuit board from the front-panel assembly.

I removed the 3335's central module assembly to get better access to the HP-IB PCB (see Service Group O (in Section 8) of the manual:  "Operating and Service Manual, Model HP 3335A, Synthesizer/Level Generator," HP publication number 03335-90003, for this procedure).  

A visual inspection of the HP-IB board revealed that a heatsink on the board was tilted over and touching the PCB.  Perhaps it was creating a short-circuit?  I pushed it back up, plugged in the HP-IB interconnect cable to the front panel, and powered-up the generator.  The display came up!

So it seems that the heatsink might have been shorting something out.

Summary of Repairs:
  • Push heatsink on the HP-IB board up to prevent it from shorting to the PCB.

HP 3335A Repair,  S/N 1640A02812

Problems:
  • Intermittent Seven-segment Digit (DSM7) on the front-panel's numerical display.
  • Power Switch won't toggle ON/OFF
Intermittent digit:

If I pressed on the front panel with my finger, I could get the digit (DSM7 in the manual's schematic) to turn on or off.


The display consists of multiplexed seven-segment LED digits, the seven LED segments of each digit having common-cathode connections.

The fact that all seven segments of the DSM7 digit would turn on or off with finger-pressure implied that the problem was with the signal driving this digit's common-cathode (/D4, and, prior to inversion, D4, on the schematic).

Tracing /D4 back from the display digit, it becomes D4 (i.e. prior to its inversion to /D4) and comes from pin 28 of the XA12A header that connects the Keyboard's male header to the Display board's female header.

Examining the male header on the Keyboard side, it appeared that pin 28 had a bad solder connection.  I touched it up and it fixed the problem.

(Note:  when I received this generator (an eBay purchase) the front panel had been pushed in, probably in shipping, and this deformation might have broken the solder joint).


Power Switch won't toggle ON/OFF:

I needed to replace the power ON/OFF switch, but I could not find a replacement with the same form-factor.  But I did find a work-around.  See this blogpost for more details on the replacement switch I used and how I installed it.

Summary of Repairs:
  • Resolder pin 28 of the XA12A header on the Keyboard
  • Replace the power switch

HP 3335A Repair,  S/N 1640A01119

Problems:
  • Keyboard Switch Bounce
  • RF Output Amplitude Changing / Bad -15 VDC Power Supply Voltage
  • Output frequency does not match the Displayed frequency

Keyboard Switch Bounce:

If you press and release a digit button once, but the digit shows up multiple times on the display (not just once), this is keyboard switch bounce.  It is very annoying!

Because of the age of the units, I thought perhaps the pushbutton contacts were dirty or oxidized, so I decided to spray the switches with DeOxit.

Unfortunately, it can be difficult to get to the contacts of these pushbutton switches.

So I sprayed the white post of each switch, hoping that the DeOxit would run down the post and into the switch and down to its contacts.  This might have been easier if I had first removed the key caps from every pushbutton.  However, the keycaps are difficult to remove, and I was concerned that I might break a switch if I pulled too hard.  So I left the keycaps in place and sprayed the white switch posts between the caps and the bodies, as shown, below:


After spraying all of the buttons this way, I pushed each one up and down a number of times to exercise them, and then reassembled the front-panel assembly and tested the buttons.  No more keybounce!


Output RF Amplitude Changing / Bad -15 VDC Power Supply Voltage

I had noticed that there had been some weirdness on the output RF signal when viewed on my HP 8568B Spectrum Analyzer -- its amplitude seemed to move up and down at a slow rate.  Probing signals led me to discover a problem with the -15V DC power supply voltage -- it was not DC, but instead it had a 60 Hz pulse train on it, as seen on the 'scope capture, below:


These are short pulses and roughly 1 volt high, appearing at a 60 Hz rate on the -15VDC line.  What was causing them?  (Note that if debugging with a DVM this problem might have been missed, because the DC voltage measured -14.75 volts instead of -15.0 volts -- in other words, it could seem acceptable when it actually wasn't.)

The 60 Hz rate was a puzzle, because the DC supplies use full-wave rectification which results in a 120 Hz waveform (prior to filtering).

However, both the +15 and the -15 volt supplies utilize "voltage-doublers" to increase the voltage at the base terminals of the U1 and U2 Darlington-pair pass transistors.  Could the problem be there?

I took a look at board A15, which has the pass transistors and the voltage-doublers.  I immediately noticed that one of the caps (C1) had expanded, pushing out the plug at the '+' lead, as you can see in the photo below:


Not good.  So, before continuing, I decided to replace all four 10uF, 50V electrolytic caps (C1, C2, C3, and C4) used for the two voltage-doublers on this board.

The original HP caps are axial-leaded, but I only had radial-leaded caps in my parts bins (and I did not want to wait for an order to arrive from DigiKey).  So I used three Nichicon 10uF, 100V, 105 degree C caps plus one Kemet 10uF, 50V, 105 degree C cap.  I used 105 degree C caps in lieu of 85 degree C caps due to the parts being mounted very close to heatsinks.

Remove the board to replace the caps.  There are five screws holding it:


With the board out of the chassis, I removed the original four electrolytic caps.  However, I noticed that there were some exposed traces that would run under the new radial-leaded caps, so to prevent shorts between these traces and the capacitor leads, I covered the exposed traces with Kapton tape:


And here is the board with the four new capacitors installed:


Checking -15 VDC with a DVM, it now measured -14.99V, not the 14.75V that it had originally measured.  On a scope it was DC with no pulses, and on the spectrum analyzer the amplitude of the generator's output spectrum no longer varied with time.

By the way, as a final note -- the voltage doubler circuits create the voltages for biasing the base of U1 (the +15V Darlington pass transistor) to roughly +55V and the base of U3 (the -15V Darlington pass transistor) to roughly -55V.

The image below shows the voltages across C1 and C2 when generating the +55 VDC voltage.  If analyzing the circuit, note that the +20V DC voltage acts as a "stiff" rail for C1 when it charges during the negative cycle of the 40 Vpp AC waveform through diode CR1, and for C2 when C1 dumps its charge into C2, via diode CR2, during the positive cycle of the 40 Vpp AC waveform.



Output Frequency does not match Displayed Frequency:

During checkout of the unit I discovered that the frequency of the output signal often did not match the displayed frequency.

For example, if the displayed frequency was 19 MHz, the output might be somewhere around 16.5 MHz.

Where to begin troubleshooting?

Fortunately, the Operation/Service manual (HP publication number 03335-90003) has a very handy troubleshooting flowchart (see pages 8-O-5/8-O-6), which I've reproduced, below:


Following the flowchart, the 1-2 MHz test signal from the Fractional-N Loop was good (measured at1 MHz).  But when the generator's output frequency was set to 19 MHz (per the flowchart), the signal at the 39-79 MHz test output measured 75 MHz, not the 40 MHz shown in the flowchart!  Given this result, the flow chart recommended that I debug the N-Step Loop.

By the way, here's a photo of the 1-2 MHz test output, given a generator output of 1.0 MHz. Note the picket fence of harmonics spaced 1 MHz apart, given the fundamental of 1.0 MHz.


And here's a photo of the 39-79 MHz test output with the generator output at 19.0 MHz.  Note the nice signal at 75 MHz:


But wait a sec...was my measured 75 MHz actually wrong?

From the measurements I had made on a good 3335A (see my simplified Theory of Ops, above), the N-Step Loop's frequency for a generator output of 19 MHz should be 75 MHz, not 40 MHz.

So the N-Step Loop module appeared to be good, rather than faulty as indicated by the Troubleshooting flowchart, which clearly needed a correction:


So if the frequencies of the Fractional-N and N-Step Loop were OK, this implied that the problem was further downstream at the "Summation Loop," which contains the final system VCO, spanning from 40 to 80 MHz.

Measurement of the generator's output as I stepped it in 1 MHz increments from 40 MHz to 80 MHz implied that, indeed, this third VCO could go no higher than 65.5 MHz, rather than going all the way up to 80 MHz.

The Ops and Service Manual has a good Troubleshooting procedure for the Summation Loop (Service Group K, board A8).  However, this requires that A8 be on an Extender Board.  Fortunately I was able to find a pair of non-HP boards on eBay.  The images below shows A8 mounted on the Extender:


Be sure to support the Extender Board so that its traces don't short on the chassis!


With A8 outside of the chassis, I could access its test points.  A quick visual inspection of the board (with its EMI shields first removed) revealed that R54 appeared to have heat damage (body looked burnt) per the image, below:


This resistor's value should be 332 ohms, but, when removed from the circuit, it measured 742 ohms.  I replaced it with a new 332 ohm resistor and went back to testing, but not long after this repair the VCO took a turn for the worst -- I couldn't get the frequency to go beyond about 55 MHz.

I set the VCO back to 40 MHz and attached a DVM to TP3 to monitor the VCO's control voltage.  To my surprise, without me doing anything else, the voltage at TP3 started out high (above 7 volts -- consistent for a 40 MHz VCO frequency), but then slowly drifted down in value, not stopping -- exactly what one might expect if there was no source driving the VCO's Integrating Capacitor (C45), and the capacitor was instead slowly discharging through the DVM's high impedance attached between TP3 and Ground.

Well that was weird. 

I made a few more scope measurements and noticed that TP9 at the Rate Detector's output was at an ECL HIGH level (-0.8 volts).

If the Rate Detector's ECL output is HIGH, it signifies that the Summation Loop's VCO frequency is less than the N-Step Loop's frequency (the N-Step Loop VCO steps between 39 and 79 MHz in 1 MHz steps).

By design, the Summation Loop's VCO frequency should always be higher than the N-Step Loop's frequency.  If it isn't (as it wasn't in this case), the Rate Detector forces the Summation Loop's VCO frequency to increase by setting its output HIGH (as measured at TP9).


The Summation Loop's VCO frequency is controlled by the voltage across C45, the "Integrating Capacitor" (see next image), which in turn is controlled by one or the other of two current sources.  One current source "sources" current into C45, raising C45's voltage and thus decreasing the VCO's frequency.  The other current source "sinks" current out of C45, lowering its voltage and thus increasing  the VCO's frequency.

Setting the Rate Detector's Output HIGH forces the "sourcing" current source OFF (i.e. its output into a high-impedance state) and forces ON the "sinking" current source, thus driving the VCO frequency UP.  See image, below:


But the VCO frequency was not being "driven" up -- it was instead floating up, as though nothing were driving it except leakage current via my DVM.

Clearly the "sinking" current source wasn't turning ON, even though the signal at TP9 (Rate Detector Output) was HIGH.

TP1 and TP2 were also at their correct levels for the "current-source" to be OFF and the "current-sink" to be ON.

So there must be an issue with the current-sink circuitry.  I measured the current-sink's node voltages while TP9 was sitting HIGH -- they are shown below:


Q6 was sourcing way too much current (it should have been OFF) -- clearly a problem.  I removed it and checked its junctions with a DVM -- it looked like there was a Base - Collector short.

This probably explains R54's burned body, as the bad Q6 transistor meant it was dissipating more power than it was rated for.

Q6 needed replacing.  Its HP P/N is 1853-0018 -- a PNP spec'd at a power dissipation of 200 mW and an FT of 1 GHz. 

Unfortunately, I did not have any 1853-0018 transistors in my parts bins, nor did I have a 2N4260, Google AI's recommended replacement.

However, searching through my parts bins, I did find a single, used, 2N4959 transistor (PNP, FT 1 GHz).  I replaced Q6 with it, and...it worked!  The maximum frequency at A8's output now goes to 80 MHz when I enter it in on the 3335A's front panel.

A final adjustment of the Summation Loop's L15, L16, and R76 (per section 5-20 in the manual) completed the repair.

Summary of Repairs:
  • Spray all pushbutton switches with DeOxit.
  • Replace capacitors C1, C2, C3, and C4 on the A15 PCB.
  • Replace bad resistor R54 and bad transistor Q6 on the A8 PCB (using a 2N4959 as a replacement).

Final Thoughts:

1.  For reference...in STANDBY mode (power switch OFF), my last HP 3335A that I worked on drew roughly 14 watts (as measured on my General Radio Variac metered to read AC Volts and Watts).  When ON, power draw jumped to 120 Watts.

2.  Check out the HP 3335A repair videos on YouTube.  Some are more useful than others.

3.  There are also some posts on EEVblog site.  A good place to start would be here.

4.  I have one more HP 3335A that needs repair.  This one will need to wait, though, for a future blogpost...



Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Saturday, May 23, 2026

Replacement Power Switch for an HP Agilent 3101-2124 DPDT Push-Button Power Switch

I hadn't used one of my HP 3335A generators for a while, and when I turned it on a few weeks ago, the power-switch wouldn't stay latched ON.

In other words, it didn't act like a push-button power switch that toggles between OFF and ON states when pressed.  Instead, it acted like a momentary-contact push-button, and the generator would only remain ON if I kept my finger pressing on the button.  Not good!

I thought I'd try to pull off the key cap and squirt some DeOxit into the switch (if that were possible) to hopefully lubricate it.  Unfortunately, I accidentally pulled the switch apart while doing this, and it would not go back together again.  Below is a photo showing its parts (less the internal spring that I  lost).

Here's the switch shown on the HP 3335A's Keyboard Schematic Diagram:

This switch's HP part number is 3101-2124.  I searched the internet for an identical replacement but could not find one.  However, I did find a different HP / Agilent push-button power switch on eBay.  Its HP / Agilent part number is 3101-3226.

It has the appropriate number of pins (6), and, although the pin locations and spacing did not look identical to that of the original switch, I thought I'd order one and see if I could adapt it to my purposes.

Here are a couple of photos showing the differences between the original switch and the replacement switch:


As you can see, the pins of the original switch are offset from the vertical center-line of the switch, while the pins of the new switch are symmetrically placed about its center-line (see second image).

Also, the new switch is significantly shorter than the original switch.

But I thought I could make the new switch work.  Because the replacement switch is shorter than the original power switch, I spanned the gap between it and the PCB with stiff pins I cut from a standard header connector (e.g. the ones that have pins spaced 0.1 inches apart).  

These pins, in turn, I installed at a slight angle to align the new switch's pins with the off-center PCB pads.  And, being header pins, they are fairly stiff and less likely to bend when I press the button.

The image below shows the new switch mounted on the HP 3335A's front-panel PCB. 



The results:  It seems to work fine!  The "throw" of the switch (the difference in height between when the switch is ON versus when it is OFF) is a less than that of the original push-button switch, but that is an insignificant issue, in my opinion.

Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Friday, January 2, 2026

Tektronix DC 509: Simple Mod for Adding an External Reference Clock

 


I recently needed a portable counter for some measurement work.  Looking at my shelf of test gear, I found a Tektronix DC 509 Counter Module that I could plug into one of my TM 503 Mainframe for transportation.

However, when I went to test it, I discovered, when measuring a 10 MHz signal from my HP 8640B (that is locked to my GPS frequency standard), that the counter was off by about 20 Hz, and that this error would change as the counter warmed up.

Very annoying.  If only I could synchronize the counter to my GPS frequency standard...


TM 500 Series Mainframe Requirements

Per the DC 509 manual, the counter does support an External Reference Clock via its rear connector pins, and this clock can be either 10 MHz, 5 MHz, or 1 MHz.

To provide, for example, an External Reference Clock to the counter, the TM500 series of Mainframes has an option (Option 2) to add BNC connector(s) to their rear panels, as shown below (image from eBay):


I have five TM 503 mainframes, but none of them have these BNCs.  Instead, their rear panels all look like this:


Rather than purchase a TM 503 from eBay with the appropriate BNCs, could I instead somehow make a simple modification to let me add a connector to the DC 509 for an External Reference Clock?


DC 509 External Reference Clock Circuitry:

The answer to the previous question is "yes," and it's actually a pretty simple modification.

First, let's look at the DC 509's clock circuitry:


I've annotated the schematic to show how to set the on-board jumpers to (1) select External or Internal Reference Clock, and to (2) select the frequency of the Reference Clock.  Note that the external clock's amplitude should be roughly about 4 VPP (into an open load), at a minimum, from my own measurements.


Adding an External Clock Connector to the DC 509:

The External Clock comes into the DC 509 via the following pins on the Rear Connector P1625:

     P1625 pin 14A:  External Clock Input

     P1625 pin 15A:  Ground

There are two side-by-side vias for these signals, next to the connector, as shown in the image, below:



These two vias are slightly more than 0.1 inches apart.  Never the less, a 2-pin header with 0.1 inch spacing can be inserted into them (after removing the solder in the vias) and soldered without too much difficulty:


A matching two-socket ribbon cable can now be attached to this header for the External Reference Clock connection to the DC 509.  In my case, I made a cable that adapts a short 2-pin socket cable to an SMA connector cable (all parts from my junk box).  See below:


Note that, assuming a 10 MHz clock signal, the length of the 2-pin ribbon cable is not too unimportant, given that a 10 MHz signal's wavelength is 30 meters long (in the ribbon cable this wavelength will be shortened somewhat from 30 meters due to the the cable's velocity factor).

The DC 509 can now be inserted into a TM 500 series mainframe and the External Reference Clock cable brought out the front of the mainframe (as long as the mainframe has at least one slot that can be left empty, to route the clock cable out the front of the mainframe), 


Setting the Jumpers:

On the DC 509 PCB, the 3-pin Header, J1621, selects whether the Reference Clock source will be Internal or External:

    Jumper J1621 pin 1 to pin 2 for Internal Clock (this is the default factory setting).

    Jumper J1621 pin 2 to pin 3 for External Clock

The 5-pin Header, J1511, should be set to match the Reference Clock frequency:

    Jumper J1511 pin 1 to pin 2 if the Reference Clock is 10 MHz (this is the default factory setting).

    Jumper J1511 pin 2 to pin 3 OR pin 3 to pin 4 if the Reference Clock is 5 MHz.

    Jumper J1511 pin 4 to pin 5 if the Reference Clock is 1 MHz.

The image below shows the 3-pin Header, J1621, set for External Clock:


Operation:

As a quick test I hooked up my "External Clock Header-to-SMA" cable to the DC 509, and then attached this cable to an HP 3335A signal generator set to 10.000000 MHz (itself locked to my GPS frequency standard).  The HP 3335A's amplitude was set to +10 dBm (i.e. 2 Vpp into a 50 ohm load, or 4 Vpp into an open load).

I connected the DC 509 to the output of my HP 8640B generator (the latter with its frequency display expanded to show resolution of  1 Hz), and compared the frequency displayed on the generator with the frequency displayed on the counter.  They matched (as shown, below)!


Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Friday, October 17, 2025

GPS Clocks: Automatic Daylight Savings Time and Baudrate Configuration

Third K6JCA GPS Clock

Third GPS Clock:

For my third GPS clock (the second one to use the PCB I designed and had fab'd in China), I chose to build it into a small metal box I purchased on Amazon:

In fact, I designed the PCB to fit within this case, as you can see from the photo, below:


GPS Receiver Baudrate:

The previous two clocks (see here and here) used GPS receivers that I had configured to power-up with a serial-port baudrate of 38,400 baud.  Configuration was done using U-BLOX's "u-center" app, and I used this same app to store the new baudrate within the receivers so that they would power-up at the new baudrate.

But when I tried to configure a third GPS receiver for this new GPS clock, it would not store the new baudrate, but instead it would default back to 9600 baud at power-up.

Hmmm -- well, if I cannot store the new baudrate, why not have the Arduino Nano, at power up, always reprogram the receiver to the new baudrate?  Then it doesn't matter if I can or cannot store it.


Adding Automatic Baudrate Detection and Configuration:

I did some quick Googling and found the list of UBX commands used by the two types of GPS receiver's I had at hand.  Rather than write the code myself, I asked ChatGPT to do it.  Below is the code, shown in a simplified GPS Clock sketch.

// ChatGPT-generated code to detect and set a GPS receiver's
// baud rate using a U-BLOX UBX port-configuration command.

#include <SoftwareSerial.h>

#define GPS_RX 6   // Nano receives GPS data on pin 6
#define GPS_TX 11  // Nano transmits GPS data on pin 11

SoftwareSerial gpsSerial(GPS_RX, GPS_TX);

// Possible GPS baud rates (try these for detection)
const long supportedBauds[] = {4800, 9600, 19200, 38400};
const int numBauds = sizeof(supportedBauds) / sizeof(supportedBauds[0]);

// User-chosen Nano/GPS baud
const long desiredBaud = 38400;   // <-- change to what you want

// -----------------------------------------------------------------
// Build and send UBX-CFG-PRT message to set GPS baud dynamically
// -----------------------------------------------------------------
void sendUBXsetBaud(long baud) {
  uint8_t msg[] = {
    0xB5, 0x62,             // sync
    0x06, 0x00,             // CFG-PRT
    0x14, 0x00,             // payload length = 20

    // payload (20 bytes)
    0x01, 0x00, 0x00, 0x00, // portID=1, reserved, txReady=0
    0xD0, 0x08, 0x00, 0x00, // mode = 0x08D0 (8N1), little endian
    0x00, 0x00, 0x00, 0x00, // baud placeholder
    0x07, 0x00,             // inProtoMask: UBX+NMEA
    0x03, 0x00,             // outProtoMask: UBX+NMEA
    0x00, 0x00,             // flags
    0x00, 0x00              // reserved
  };

  // Fill baud (little-endian) at payload[8..11]
  msg[14] = (uint8_t)(baud & 0xFF);
  msg[15] = (uint8_t)((baud >> 8) & 0xFF);
  msg[16] = (uint8_t)((baud >> 16) & 0xFF);
  msg[17] = (uint8_t)((baud >> 24) & 0xFF);

  // Fletcher checksum
  uint8_t ckA = 0, ckB = 0;
  for (int i = 2; i < sizeof(msg); i++) {
    ckA += msg[i];
    ckB += ckA;
  }

  // Send message
  for (int i = 0; i < sizeof(msg); i++) gpsSerial.write(msg[i]);
  gpsSerial.write(ckA);
  gpsSerial.write(ckB);
}

// -----------------------------------------------------------------
// Try a baud rate, return true if NMEA sentences detected
// -----------------------------------------------------------------
bool detectBaud(long baud) {
  gpsSerial.begin(baud);
  unsigned long start = millis();
  String sentence = "";
  while (millis() - start < 1000) { // 1 second timeout
    while (gpsSerial.available()) {
      char c = gpsSerial.read();
      if (c == '\n') {
        if (sentence.startsWith("$GP") || sentence.startsWith("$GN")) {
          return true; // NMEA detected
        }
        sentence = "";
      } else {
        sentence += c;
      }
    }
  }
  return false;
}

// -----------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println(F("GPS Baud Auto-Detect & Configure"));

  long currentBaud = -1;

  // Detect current GPS baud
  for (int i = 0; i < numBauds; i++) {
    if (detectBaud(supportedBauds[i])) {
      currentBaud = supportedBauds[i];
      Serial.print(F("Detected GPS baud: "));
      Serial.println(currentBaud);
      break;
    }
  }

  if (currentBaud == -1) {
    Serial.println(F("No GPS detected at supported bauds!"));
    return;
  }

  // If GPS baud not what we want → change it
  if (currentBaud != desiredBaud) {
    Serial.print(F("Attempting to change GPS baud to "));
    Serial.println(desiredBaud);

    bool success = false;
    for (int attempt = 1; attempt <= 3; attempt++) {
      Serial.print(F("  Attempt "));
      Serial.println(attempt);

      gpsSerial.begin(currentBaud); // talk at old baud
      sendUBXsetBaud(desiredBaud);

      delay(500); // let GPS switch
      gpsSerial.begin(desiredBaud);

      if (detectBaud(desiredBaud)) {
        Serial.println(F("  ✔ Baud change verified OK!"));
        success = true;
        break;
      } else {
        Serial.println(F("  ✘ Verification failed"));
      }
    }

    if (!success) {
      Serial.println(F("❌ Could not change GPS baud after 3 tries."));
    }
  } else {
    Serial.println(F("GPS already at desired baud."));
  }
}

void loop() {
  // Pass GPS data to USB Serial for monitoring
  while (gpsSerial.available()) {
    Serial.write(gpsSerial.read());
  }
}

This worked great, and I incorporated it into the code for all my clocks.

But I still had a few more bare-PCB boards from the fab.  What to do with them?


My Fourth GPS Clock (with Auto-Daylight Savings Time): 

For this clock I used an Adafruit 4-digit seven-segment display.  Besides being noticeably larger, the difference between this display and the TM1637 displays I had used previously is that this display uses an I2C interface.


Unfortunately, I hadn't thought to add an I2C interface to my PCB design.  But the modifications are simple -- two cuts, two jumpers, as I show on the schematic, below:


I also decided I wanted to minimize the number of round-holes-drilled and rectangular-holes-cut in whatever case I used.  

To this end, I found a box on Amazon with a clear top.  Great!  No rectangular holes required!


And here's the clock:


Auto-Daylight Savings Time (Auto-DST):

Unlike my earlier GPS clocks, there is no toggle-switch on this clock to select between Daylight-Savings-Time (DST), Standard Time, or GMT.  I decided to forego GMT time and also to program the Nano to automatically adjust between DST and Standard-Time, depending upon the date and time it received from the GPS receiver.  So no switch needed.

Auto-DST mode is selected by shorting both the nGMT and the nDST signals to ground.  Note that if the DST/Standard-Time/GMT toggle switch is installed, these two signals are never grounded simultaneously, so the same revision of Nano code can be used for either version: DST/Standard-Time/GMT toggle switch installed or no switch but with auto-DST.

For more on the Automatic Daylight Savings Time code, see my previous post...


Adding Auto-DST to Clocks that Already have SP3T Front Panel Switches:

My first three clocks have a front panel single-pole three-throw toggle switch for selecting between Daylight-Savings Time (UP position), Standard Time (Mid position) and GMT (Down position).

I wanted to add Auto-DST to these clocks, but also retain some way to select between Auto-DST and GMT, as well as allow Standard Time, too, if for some reason our government decided, in the future, to get rid of the DST time change.

The addition of a diode, connected between the signals "nDST" (diode cathode) and "nGMT" (diode anode)  as shown, below, changes the switch's UP position from "Daylight Savings Time" to "Automatic Daylight Savings Time".  Now, with the switch in the UP position, the clock will automatically "spring forward" or "fall back" as appropriate for the time changes in Spring and Fall.

Mid-position is still Standard Time (no longer necessary, with the new Auto-DST code), and the Down-position displays time as GMT.


Note that when the SP3T switch is in the "UP" position, nDST, and thus the diode cathode, is grounded.  nGMT (the diode's anode) will about 0.6 V higher than ground, and thus also a logic "low".


My Fifth GPS Clock: 

The displays of my previous clocks were all limited to four seven-segment digits.  Why not make a multi-line clock and display the GPS-received date, along with the derived weekday, too?  (Date and day modified to account for local time offset from GMT time).

Here is the clock, using a 4-line by 20 character display:

I had purchased the display a few years ago when I was designing my 500 Watt HF Amplifier project.

The bottom line of the display's four lines is used to display various parameters and menus for setting up the receiver (selected using the two push-buttons on top of the case).  The image above shows this 4th line displaying GMT time.  And the image below shows it displaying the number of satellites being used by the receiver:


The display itself has a parallel interface, but I converted it to I2C with an I2C adapter (purchased from Amazon) that solders onto the display's PCB:

Note that the 4-pin connector's GND and VCC pins are swapped compared to their assignment for the Adafruit I2C interface.  I handle this difference by swapping the VCC and GND wires in the cable connecting the PCB to the LCD Display Adapter.

Also, if the Adapter uses the 'A' version of the PCF7584 IC, its I2C address is typically 0x3F.  Otherwise, if it is the non-A version, the I2C address is typically 0x27.


LCD Brightness:

The LCD backlight can only be turned on or off -- it's brightness cannot be varied.  So I use the "ambient-light" photoresistor to turn off the backlight at night, when the room has turned dark (this feature can be disabled via a menu selection).


Arduino NANO Code:

Code for all versions of my GPS clock can be found here:

https://github.com/k6jca/Arduino_GPS_Clock


That's it!  I have one more Clock PCB left.  (It will become a 2-line LCD clock)


Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.