Triggering Instruments for Equidistant Time Measurements

Background

I bought a Keysight 34420A Nanovoltmeter for noise measurements between 01.Hz and 10Hz (related to my precision oscillator phase nois research). The instrument can make multiple measurements, but it is not possible to use it as a digitizer where the time between measurements is fixed at a given rate. We can employ external triggering, and that works.

More details about the Keysight 34420A and some measurement issues can be seen here:

Measuring Nanovolts

A Simple Trigger Source

The requirements for this trigger generator are fairly modest; it should have the following features:

  • TTL square wave as needed by (I think all) Keysight trigger input ports
  • USB powered
  • SCPI controllable
  • 2 Channels, BNC outputs. Mine have 220Ohms of output impedance to protect them from short circuits.
  • Pulse width from 1ms to 30 seconds with low jitter. Resolution is 1ms.
  • Either free running or a presettable number of pulses triggered from USB
  • Ability to change pulse width once after a given number of pulses have been created (slow/fast switching).
  • Status LEDs for the channels

Low jitter here means something below some microseconds. The external trigger response time of a 34420A is in the range of milliseconds, so stellar precision is not needed.

A trigger generator like this can be easily implemented in an Arduino Micro with a shield to provide the connections to the LEDs and the BNC sockets. It all fits into a small Hammond box, as can be seen here:

The details of the trigger generator can be seen here:

Controlling the Trigger Generator using SCPI

The trigger generator is controlled by SCPI commands. The following commands are available (use *SYNTAX? or *STDSYNTAX? to see more):

  • :CHANNEL:PULSEWIDTH:SET? channelNo, pulseWidth
  • :CHANNEL:PULSEWIDTH? channelNo
  • :CHANNEL:STATUS:SET? channelNo, ON | OFF
  • :CHANNEL:STATUS?
  • :CHANNEL:PULSELIMIT:SET channelNo, pulseLimit
  • :CHANNEL:PULSELIMIT? channelNo
  • :CHANNEL:PULSELIMIT:RESET channelNo
  • :CHANNEL:SWITCHLIMIT:SET channelNo, switchLimit, newPulseWidth
  • :CHANNEL:SWITCHLIMIT:RESET channelNo
  • :CHANNEL:SWITCHLIMIT? channelNo
  • :STORE
  • :LOAD
  • :PRINTALL

The channelNo is either 1 or 2, all times are in milliseconds. Changing a channels parameters also resets the pulses so no runt pulses are formed at the start of the new pulse chain. If something is changed while output is running the last pulse may be truncated. Resetting the pulse count limit also re-enables the output status. STORE and LOAD retrieves the pulse parameters from EEPROM so they are available at the next cold start. The unit supports *SYNTAX? and *STDSYNTAX? commands to help you with further commands. PULSELIMIT sets the total number of pulses that will come out a channel before it turns itself off. SWITCHLIMIT waits for a given number of pulses, and then changes the pulse width to a new value. This is necessary for, e.g., instruments that needs slow triggerering during a settling phase and fast pulses afterwards. The total number of pulses is not affected. Example:

:CHANNEL:PULSEWIDTH:SET 1,1000
:CHANNEL:PULSELIMIT:SET 1,1024
:CHANNEL:SWITCHLIMIT:SET 1,24,50
:CHANNEL:STATUS:SET 1,ON

will create a train of 24 pulses a second wide, then 1000 pulses with 50ms width, and then stop. until the next status setting to ON.

Results

I build a unit and connected it to my DSOS604A scope for jitter measurements. What came out was quite OK for the intended use; the 34420A (and also similar other instruments) have milliseconds of trigger delay, so we dont have an issue there. A sample screen shot with 2Hz squarewave can be seen here:

Jitter is below 6us peak-peak and less than 0.6us RMS. To be sure everything is OK the test was performed with all 2 channels on, plus a periodic host update every second using the PRINTALL? and *AUTOPRINT:SET ON commands. The same thing was tried with pulse count limits on on both channels so the interrupt routines has some more work, but results were the same.

The trick for low-jitter timing on an Arduino is to output the value to the ports immediately at the beginning of the interrupt routine and to do all conditioning, counting, resetting, … afterwards to prepare the next output state that will again be transferred to the outputs at the next call of the interrupt routine.