Thursday 6 September 2018

Playing with Buck Converters

I wanted to learn about switching power regulators and while I get the general principles, I have no idea how to control one or set one up. I thought I'd start with a simple MC34063 and bought some from ebay.

Buck Maths - Simple

This analysis is not unique and with any luck it is actually right! I hope it is of use to someone and maybe even me in the future when I forget how to do these calculations! First things first - here is a simplified circuit for a buck converter.


I've omitted some important things like the controller and the feedback but in essence the way this works is:
  • The controller turns on the PMOS transistor which causes current to start flowing through L1 and the load R1 as well as charging up C1. The diode D1 is reverse biased so no current flows through there at the moment.
  • The current through the inductor ramps up linearly
  • At some point the transistor switches off and the back-EMF through the inductor keeps current flowing into R1 and C1. Now the diode D1 is forward biased and completes the circuit with the output. The current now linearly ramps down through L1.
  • The cycle repeats
The net result is the output voltage is lower than the input and while there is a transistor in the circuit, the transistor is only ever fully on or fully off. This means the resistive losses through the circuit are reduced compared with a linear regulator and most of the input power is transferred to the load.

So the transistor is switched at some period \(T\) and the time the transistor is on vs off is not the same. The proportion of the time the transistor is on is the duty cycle \(D\). The input voltage is \(V_{in}\) and the desired output is \(V_o\). The output voltage will vary but we assume that the average output will be the target \(V_o\).

Hysteretic Control

The way the MC34063 works is quite simple but quite limited. There is an internal oscillator that generates a ramp up and then ramp down at a frequency determined by an external capacitor. There is a comparator that triggers when the sampled output voltage (sampled via a resistor divider network) matches an internal reference.

During the ramp up time, if the sampled output drops below the reference the IC turns on the current to the inductor. The current remains on until the end of that cycle where it turns off. Usually the voltage won't have dropped far enough until after the start of the up-ramp so the longer it takes to fall the later the IC turns on and the shorter the on period. This serves to regulate the output voltage.

If the load is light however the IC may not turn on during the whole cycle. In fact if the output is unloaded it can take a long time between cycles.

As the output does not turn-off until the cycle is finished, there is nothing to stop it over-shooting by a lot before it turns off.

The IC has one additional trick up its sleeve and that is to fold-back the voltage under excessive load. The IC sense the current at the input and once this exceeds a threshold, the IC will hasten the up-ramp so the cycle finishes earlier. In the extreme case of a gross over-load the cycle will finish very quickly and minimize the output voltage. You can configure the max current by choosing the value of the sense resistor.

Duty Cycle - Simple

The the voltage over an inductor follows the equation
\[V = L\frac{di}{dt}\]
We know the voltage over the inductor when it turns on will be \(V_{in} - V_o\) so we know that the slope of the current increase through the inductor will be \(\frac{V_{in}-V_o}{L}\) and the amount the current increases will be \(\frac{V_{in}-V_o}{L}DT\).

When the switch turns off the inductor back-EMF will keep current flowing but it will decrease. The voltage across the inductor this time will just be \(V_o\) (neglecting the voltage drop of the diode) and so the downward slop will be \(\frac{V_o}{L}\). The down-slope occurs for a time period of \((1-D)T\) seconds so the total decrease in current will be \(\frac{V_o}{L}(1-D)T\)

Because we are in a steady-state, the increase in current during the on period must equal the decrease in current during the off period and hence we can write
\[\frac{V_{in}-V_o}{L}DT = \frac{V_o}{L}(1-D)T\]
We can simplify this a bit by cancelling the L and the T and we can expand the brackets to get
\[V_{in}D-V_oD = V_o-V_oD\]
Now we cancel the \(V_oD\) as this appears on both sides and get
\[V_{in}D= V_o\]
Then re-arrange to get
\[D= \frac{V_o}{V_{in}} \tag{1}\]

That's pretty damn cool! The buck converter drops the input voltage in proportion with the duty cycle.

Duty Cycle - Better

Lets try this again but this time we want to include the diode and transistor drop.

This time lets assume the switch has a voltage drop of \(V_{sw}\) and the diode has a forward voltage drop of \(V_d\).  When the switch is on we can ignore the diode as before but now if we apply KVL to the loop from the input voltage to the output we get:
\[V_{in}-V_{sw}-L\frac{di}{dt}-V_o=0\]
Where \(\frac{di}{dt}\) is the slope of the inductor current during the on-period. Re-arranging we get
\[\frac{di}{dt}=\frac{V_{in}-V_{sw}-V_o}{L}\]
If we define \(t_{on}\) to be the amount of time the switch is on and \(t_{off}\) the time the switch is off (so \(D=\frac{t_{on}}{t_{off}}\)) then the rise in inductor current (\(I_p\) is:
\[I_p=\frac{V_{in}-V_{sw}-V_o}{L}t_{on}\]
Similarly for the period the switch is off
\[V_d+L\frac{di}{dt}+V_o=0\]
\[\frac{di}{dt}=\frac{V_o+V_d}{L}\]
During the off period the current starts at \(I_p\) and reduces for the time \(t_{off}\) so:
\[I_p=\frac{V_o+V_d}{L}t_{off}\]
Equating the two equations for \(I_p\) we get
\[\frac{V_{in}-V_{sw}-V_o}{L}t_{on} = \frac{V_o+V_d}{L}t_{off}\]
And therefore:
\[\frac{t_{on}}{t_{off}}=\frac{V_o+V_d}{V_{in}-V_{sw}-V_o} \tag{2} \]

Peak Current


So what is the value of  \(I_p\)? Well it has to be the average of the current over the whole cycle. So if we integrate the current during \(t_{on}\) and during \(t_{off}\) and divide by \(T\) then this should be the average. As the current increases linearly to \(I_p\) and then decreases linearly to the starting point again we know that the average current \(I_{avg}\) can be calculated as:
\[I_{avg} = \frac{I_p \frac{t_{on}}{2} +I_p \frac{t_{off}}{2}}{T}\]
\[I_{avg} = \frac{I_p t_{on} +I_p t_{off}}{2T}\]
\[I_{avg} = \frac{I_p ( t_{on} + t_{off})}{2T}\]
As \(T = t_{on}+t_{off}\) then:
\[I_{avg} =\frac{ I_pT}{2T}\]
\[I_{avg} = \frac{I_p}{2} \tag{3} \]
So that's pretty useful - the peak current is twice the average output current.

Inductor

So if we choose a frequency of operation \(F\) and we realize that \[F = \frac{1}{t_{on}+t_{off}}\] then we can work out \(t_{on}\) and \(t_{off}\) based on the ratio we calculated in equation 2.

Then re-arranging the formula for \(I_p\)
\[I_p = \frac{V_{in}-V_{sw}-V_o}{L}t_{on}\]
We can work out the minimum inductor value as follows:
\[L = \frac{V_{in}-V_{sw}-V_o}{I_p}t_{on}\tag{4}\]

Or alternatively if we know have an inductor on hand of size L we can work out \(t_{on}\) then work out \(t_{off}\) from the ratio and therefore \(F\).

Capacitor

Ok this gets harder - so the current through a capacitor is \(i=C\frac{dv}{dt}\). The output is drawing \(I_{avg}\) but the inductor current ramps from below this to above it. The difference in current flows either into our out of the output capacitor.

The inductor current ramps linearly to \(I_p\) so the current at any point from the start of the ramp is \(i_1 = \frac{\frac{1}{2}I_pt}{\frac{t_{on}}{2}}\). Similarly the current during the ramp down can be calculated as \(i_2 = \frac{\frac{1}{2}t}{\frac{t_{off}}{2}}\). The voltage change can be calculated from the integral of the curent. The peek-to-peek ripple voltage includes the positive and negative ripple so this is calculated from
\[V_{ripple} = \frac{1}{c}\int_0^{t_1} i_1 dt + \frac{1}{c}\int_{t_1}^{t_2} i_2 dt \]
and \(t_1 = \frac{t_on}{2}\), \(t_2-t_1 = \frac{t_off}{2}\) So the integral becomes

\[V_{ripple} = \frac{1}{c}\left|\frac{I_p}{t_{on}}\frac{t^2}{2}\right|_0^{t_1} + \frac{1}{c}\left|\frac{Ip}{t_{off}}\frac{t^2}{2}\right|_{t_1}^{t_2}\]

If we substitute \(t_1\) and \(t_2-t_1\) we get:
\[V_{ripple} = \frac{1}{c}\left(\frac{I_p t_{on}^2}{8t_{on}} + \frac{I_p t_{off}^2}{8t_{off}}\right)\]

\[V_{ripple} = \frac{I_p(t_{on}+t_{off})}{8c}\]

And  \(t_{on} + t_{off}\) is basically the period. This is equal to \(\frac{1}{f}\) so then  we can write this as:
\[V_{ripple} = \frac{I_p}{8Cf}\tag{5}\]

I won't try and calculate the input capacitor here. I think it is a matter of choosing a capacitor value and ESR such that the input ripple is below some desired maximum. I suspect you need to subtract the ripple from the minimum input voltage and use that as the minimum input for the buck design. For now I am just choosing something I think will be big enough.

Test Circuit

To try this out I am using a MC34063 which is a hysteretic (i.e. bang-bang) converter. It's a pretty basic part but will do to for building a basic circuit.

The plan is to build a converter that takes 12V in (minimum) and outputs 5V. at a maximum of 300mA (this is the close to the limit of the chip but also the limit of my inductor). Also we want to get 10mV of ripple or less.

I am using a EGP20D fast diode which has a forward drop of around 0.5V. The chip datasheet spec has the switch drop as 0.8V. Using (2) we calculate:

\[\frac{t_{on}}{t_{off}}=\frac{5 + 0.5}{12 - 0.8 - 5.0}\]
\[\frac{t_{on}}{t_{off}}=0.89\]

We have a 100uH inductor so we want to adjust the frequency to suit this. We re-arrange (4) as follows:
\[t_{on} = \frac{I_p}{V_{in}-V_{sw}-V_o}L\]
And calculate this as
\[t_{on} = \frac{600e-3}{12.0-0.8-5.0}100e-6\]
\[t_{on} = 9.7\mu s\]
\[t_{off} = \frac{9.7e-6}{0.89} = 10.8\mu s\]
\[f = \frac{1}{t_{on} + t_{off}} = 48kHz\]
We check that \(\frac{t_{on}}{t_{on}+t_{off}} < 0.857\) and in our case it is 0.47

Then to calculate the output capacitor we use (5) and calculate:
\[c = \frac{600e-3}{8 \times 10e-3 \times 43e3}\]
\[c = 174\mu F\]
But we choose \(c = 200\mu F\)

The MC34063 also requires a current sense resistor and can fold-back the voltage if the current is exceeded. You choose a resistor so that the voltage over the sense resistor is 0.33 at max current. We choose \(\frac{0.33}{0.6} = 0.5\Omega\)


There are more calculations to work out the sense resistor and the resistor divider for measuring the output voltage but these are pretty easy so I won't go through them all here. The only thing was I didn't have the resistors I needed so used 1.1K and 3.9K which give out output voltage of about 5.3V


Here is the test circuit

I tried proto-typing this on breadboard but while it worked the noise was horrendous. I tried again by dead-bugging the circuit on a piece of copper but again the leads were too long and the noise was bad. I decided to home-brew a single-sided PCB like this:



Results

This image shows the timing capacitor waveform. You can see the ramp-up is \(9.2\mu s\) which is close to the 9.7 designed. The bump in the ramp up is caused by the output turning on. The overall frequency is much higher than the 48kHz design however and this makes sense from the timing waveform. The ramp down is alway 1/6 of the ramp up period which here is 1.5uS. Consequently the total period is around 94kHz. I think I have confused \(t_{on}\) with max \(t_{on}\). This will need some more thinking if I ever build one of these again.


In this trace the module is providing 300mA to dummy load. The green waveform is the output and the yellow is once again the timing capacitor. The cursors show that the output ripple is around 50mV - much higher than the 10mV predicted. Part of the reason for this difference is the ESR of the output capacitor which is \(0.1\Omega\). This results in a 30mV ripple just as a result of the ESR. This combined with the predicted ESR is pretty close to the design.

The on time however seems far to low compared with what was calculated. The on/off ratio is around 50% compared with the calculated 90%. Amusingly it is quite close to the crude approximation of 5.3/12. Also the on time is quite low at 5.2uS compared with the 9.7 calculated for 300mA. Not really sure why that is.


You can see the effect of the hysteretic control on the load regulation in the image below. In this image the output is unloaded so the system will very occasionally fire a single pulse to re-charge the output. Without any load the voltage rises far above the design and then takes many cycles to come back down to a level where another pulse is fired.


In this trace the output voltage is shown in yellow and the current flowing in the electronic load is show in green. The electronic load is set to draw power in pulses from the supply. When the load turns on it takes quite a few cycles before the voltage drops to a level where the power supply starts pulsing the inductor. 


Conclusion

So it's been an interesting foray in DC-DC converters and while it was a good start I think I am missing the interesting bits. The much harder problem looks to be the control loop that usually regulates the output (rather than the bang-bang controller implemented by this chip).

Thursday 7 December 2017

Anritsu PSN50 Power Sensor

As I got further with the Rohde and Schwarz sweep generator I realized I really had no accurate way of measuring the power output. My spectrum analyzer was pretty good but also not overly precise and not calibrated.

Power meters are pretty expensive and usually the power sensor is sold separately. Power sensors often are as much or more than the meter and for USB power sensors this is even more the case.

I found this Anritsu PSN50 power sensor very cheaply on eBay. I found there is some software for it that seems to support Windows but decided this was Ok and bought it.

Then I realized I couldn't download the software. After talking with Anritsu support it appears the sensor is only intended for use with Anritsu base-station test systems (portable spectrum analyzers) and the stand-alone software is intended only for calibrating the sensor and retails for $3K AUD!!

Anritsu support were not unhelpful but didn't help. I was essentially asking them to expose an internal interface. They basically told me they have no information on the interface. I asked again in a different way but the result was unless it is information they have already published they can't give me any more.

Before I put it back on eBay - can I hack it?

Talking to the Sensor

I found an Ada fruit guide on how to talk to unknown USB devices. It explained configuration, endpoints etc. The first step is using lsusb on linux to see what the device reports. In the case of the PSN50 I got this:

Bus 004 Device 002: ID 0b5b:ffc8  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            2 Communications
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x0b5b 
  idProduct          0xffc8 
  bcdDevice            0.00
  iManufacturer           1 Anritsu Company
  iProduct                2 PSN50 Power Sensor
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           67
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Status:     0x0001
  Self Powered

So that abstract modem looked pretty promising. It appears to be a USB serial device. This makes sense as the device has a serial port in addition to the USB. So how to talk to it?

Well it turned out Linux just quietly loaded a serial device for me. I found there was a /dev/serial/by-id/usb-Anritsu_Company_PSN50_Power_Sensor-if00 device. For some reason I couldn't get screen or mincom etc to talk to it properly. The device would just keep sending back 'NO TERM'. If I cat the device from one terminal while echoing a command from another terminal it would respond with a BAD CMD. That's pretty promising though - I can talk to it!

Commands

Anritsu make a number of other USB power sensors that you ARE supposed to talk to with a computer (like this one). For these they publish commands so I tried a few of those. Not many of the commands worked but I found a couple that did. For example I figured out that IDN? would respond with the ID of the device:

ANRITSU,PSN50,0748037,0748037,1.00

TEMP? Returned the current temperature of the device. 

AVG? Returns 0 and I figured out if I say AVG 1 it said 'OK'. So that means if I send a command with a question it queries (makes sense) and without it sets some state. If the state change is good it says 'OK'

STATUS? Returns a byte which contains the status of the device. I haven't figured this out yet.

ZERO Makes the device sit there for a long time and eventually say 'OK'. From reading the user guide it appears it is supposed to reset the zero power setting (i.e. you do this with nothing connected).

But nothing I tried gave me the power level. So what to do? Well I decided to try brute force. I used some code like that below to search for all 3 letter commands (assuming no numbers). Only looking for commands that return values too (like the power level!). I found the device would lock up if I sent the commands to quickly so I had to add a small delay between commands.
import serial
import time

commands = []

port = serial.Serial(timeout=5.0, port="/dev/serial/by-id/usb-Anritsu_Company_PSN50_Power_Sensor-if00")


def test_commands(prefix, seq_len, test_func):
    for charOrd in range(ord('A'),ord('Z')+1):
        if len(prefix) < 3:
            print("Starting "+prefix+chr(charOrd)+"...")

        test_func(prefix+chr(charOrd))

        if len(prefix) < seq_len-1:
            test_commands(prefix+chr(charOrd), seq_len, test_func)


def check_command(command):
    # print ("Trying "+command)
    port.write(command+"?\n")
    response = port.readline()
    if "BAD CMD" not in response:
        print("** Got One!! " + command+"?")
        print(response)
        commands.append(command)
    time.sleep(0.05);


test_commands("", 3, check_command)

port.close()

print commands

This took quite some time to run and it only gave me two more but it gave me an important one!

POW? Returns the power level in dbM (as a floating point)
VER? Returns the version of the firmware (1.0)

I tried running a four letter scan and it took a full two days and yielded nothing extra.

Anritsu publish an application note on using the device with their other equipment. This tallied with the commands I was seeing such as averaging mode, temperature etc. The application note also talked about setting the centre frequency of the device and that it had calibration constants for each 500MHz slab of bandwidth.

I modified my script a bit to search for commands with up to a three letter prefix before FREQ? so AAAFREQ? through to ZZZFREQ? and I found CFFREQ? returned a number. After a bit of fiddling it appears the number is from 0.05 through to 6.0 and is the frequency in GHz (0.05 is the lowest frequency and is 50MHz).

The application note also talked about a limit (min/max) mode but I haven't found commands for this. it could be they are doing it in software. Similarly they talk about setting an offset for doing relative power measurements but again this could be done in software. There is also a max hold mode in the manual and I would have thought this would have to be done in firmware but again I haven't found a command.

Power Measurements

By creating a couple of small python tools I can take power readings and switch the centre frequency. I took some readings from my signal generator and compared the readings my spectrum analyzer reported.

I found for signals over 1GHz the measurements were quite close and made me feel like the power sensor was working. But for frequencies below 1GHz they were miles out (20dB or more). Interestingly at 990MHz this was already quite wrong and got worse as you go down. The CFFREQ command didn't seem to make a whole lot of difference too which is odd. The numbers were consistent from run to run however so I could (if I had a source I could trust) make up adjustment factors. The size of the error though will limit the dynamic range significantly.

Hardware

The unit has four screws on the bottom and you can remove the bottom plate. Initially I thought this is as far as I could get in without undoing the power input connector (which would surely stuff up the calibration). Later I realized the screws at the end come undone so now I can fully access the board.

Here is the bottom side. Nothing much to see apart from some passives for the different power supplies etc. There is a light-pipe near the USB port. I figured out (accidentally) the LED is red/green as I tried to ZERO the device while I had a signal applied. The LED went red and it stopped talking to me for a while.


Here is the top side. The highlights are:
  • Main micro is a PIC18F455 running at 20MHz
  • LTC2444 high speed, 24bit 16 channel DAC. This seems like way overkill for this. Not really sure why...
  • AD8629 Low offset, low drift, low noise op amps that look like they read the actual power off the detectors. The CalXpert software guide explains the internals of the sensor and how it has a high and a low power path. See section 1.2 here
  • MAX32221 RS-232 Line driver
  • LTC1258 4.1V LDO



I can't believe they machined the case. Wow.



Friday 24 November 2017

Automation Experiments

Lots of my electronics lab equipment has some sort of automation interface that allows it to be remotely controlled. I used the Ethernet interface on one of my bench multi meters to automatically calibrate my home-brew power supply. I wanted to explore what else can be done with automation.

National Instruments VISA Drivers

VISA or the Virtual Instrument Software Architecture is a set of APIs for communicating with lab equipment. The VISA interface provides an API you can use to communicate with instruments regardless of whether the instrument is connected with Ethernet, USB or GPIB. VISA provides abstractions for device addresses and allows an application send commands and receive events generated by instruments.

VISA provides primarily a C interface however there is the pyVISA library that allows you to use VISA though Python.

National Instruments provides the VISA runtime for free on a large number of platforms including Windows, Mac and Linux. Using this with Python means I can run my scripts on all three platforms.

Keysight MSO-X-2024

My oscilloscope supports automation via Ethernet. Ethernet however is an expensive ($400) option as it also provide a VGA interface to allow the instrument to display the screen on a monitor. Luckily someone figured out that all the Ethernet capability was on the motherboard so all that is required is a couple of inductors and  MagJack.

Someone on the EEVBlog forum was selling surplus homebrew Ethernet boards (unpopulated) and so I bought one. It was pretty easy to assemble and the design also included STL files that can be 3D printed into a case to support the board when it is plugged into the oscilloscope.

The scope takes longer to boot and displays an error about the VGA functionality but otherwise the Ethernet works fine. The details about the board can be found here. There is also this github with KiCAD schematics etc but I think they are the same.

Here it is assembled


Siglent SDG1020 Signal Generator

This signal generator has served me quite well over the last couple of years. The unit has a USB interface that you can use to control it including uploading of custom waveforms.

Siglent provides Windows drivers and an application you can use to control the device. Initially I assumed I would have to use the Siglent driver to interface with the device and so I would have to use Windows. Siglent provide some tools to enable the signal generator to be used with NI Virtual Bench and to begin with I thought this is what I needed to talk to it via VISA.

I figured out that NI VISA can directly interface with USB devices without a driver.  I found a short step-by-step guide here for doing this. The trick is the instrument must implement the USB TMC protocol which the Siglent device does.

I followed the steps but it didn't initially work. I turns out you have to tell the signal generator to support USB TMC mode. You use the utility button and then select Interface, USB Setup and select USB TMC (instead of the default with is 'RAW'). Reboot the signal generator and then you can send commands to it via NI VISA. I opened the VISA interactive control tool (provided with NI VISA), selected the Siglent instrument and used the Input/Output option to send an *IDN? command which came back with the device ID!

There is a programmers guide for the signal generator here. The device includes commands to control pretty much everything you can do from the user interface.

GPIB

I have a few instruments that provide GPIB based control interfaces. In particular this would be useful for my old HP3478A multimeter as then I could do precision voltage/current measurements between that and the Keysight 34461A. In addition my 53131A and my Rohde & Schwarz signal generator provide GPIB.

I find everything about GPIB is expensive. The cables, the interface cards and even instruments that support GPIB tend to be more expensive. But then GPIB is also quite ancient (it was originally HPIB until IEEE published it as IEEE 488.2). Amusingly the Commodore 64 spent many hours hacking on when I was growing up had a GPIB interface. GPIB is not a terribly quick protocol and for most applications you don't even need as much speed as it provides.

GPIB allows instruments to be daisy-chained together on the bus. The cable connectors have a plug on one side and a socket on the other to allow them to be chained. Each instrument has an address which is usually adjustable via the instrument interface. For the most part the computer directs everything on the bus however it is possible for an instrument to generate a service request or to raise a trigger. 

The main ways people connect to GPIB seem to be these Agilent USB to GPIB modules. Recently these have become quite cheap on eBay ($100 instead of $400).  The major downside of these is that they only come with Windows drivers. It is possible to make them work on Linux but it is relatively painful as you have to upload firmware onto the USB device when it connects.

Another popular option is the ProLogix GPIB modules but these are quite pricey and don't support NI VISA.

By luck I found an older ICS-8065 Ethernet to GPIB gateway going quite cheaply on ebay. What interested me about this device is it uses the VXI-11 protocol over Ethernet. This protocol is a pre-cursor to LXI and is based on RPC. This means that in the future if I can't get software for this device I can always write something using RPC. NI VISA already supports VXI-11 so there is no need for that. An added plus is that as it requires no additional software (apart from NI VISA) I can run my scripts on my Mac with pyVISA.

The downside though was my unit was a bit old so it didn't have a web interface for configuration. I had to dowload some Windows software from the ICS Electronics website to configure it. I tried to update the firmware but after a couple of emails with support it turned out my device required a major (i.e. too big to do) hardware upgrade to run the newer firmware.

There is a slight trick to configuring the gateway in NI VISA. You select the hostname of the gateway but then you somehow have to select which instrument the alias is for. In the ICS 8065 configuration you can choose a device name but the default is gpib0. The way you select what instrument connected to the bus you want to talk to is by adding the GPIB address to the LAN device name. So the instrument with GPIB address 3 has a LAN Device name of gpib0,3. See below.


Using this I was able to get my HP3478A and my HP53131A to work. The HP3478A isn't SCPI so the commands are a bit different but it is relatively simple. Even though the 53131A is SCPI I actually found it hard to use. For some reason I couldn't get the R&S signal generator to work at all. Really not sure why but it may be a fault in the unit. I will look at that another time.

Bode Plotter

So I wanted to try using this for something. Frankly the possibilities with automatic measurements are quite large but recently I've been reading about active filter design so I thought it might be fun to make a bode plot.

The basic plan is to:
  • Use the USB interface to the Siglent signal generator to sweep across a frequency range.
  • For each frequency, use the oscilloscope to measure the amplitude of the output and to work measure the phase between the input and output.
You can measure the amplitude easily enough with the scope using a command like

MEAS:VPP? CHAN3

Phase is pretty easy too

MEAS:PHAS? CHAN3, CHAN1

Amusingly when you do this the Peak to Peak measurement and phase get displayed in the oscilloscope screen.

The problem is to measure the amplitude and phase you need to have at least one complete cycle on the screen. We know the frequency as we are controlling the signal generator so we can set the time base of the oscilloscope. We can set the seconds per division to whatever value using something like this:

TIME:RANG 1.1e-3

To set the signal amplitude we can use this command sent to the signal generator:

C1: BSWV, FRQ, 10e3,AMP, 0.25

This sets channel 1 to a basic wave (sine wave) of frequency 10kHz and amplitude 0.25V peek to peek.

So now I started to think about how I sweep the frequency across a range logarithmically but while maintaining an even number of points per decade. While looking up maths code for Python I found this numpy library which actually has a function for it!

for freq in numpy.logspace(numpy.log10(100),numpy.log10(1e5),num=100):

This for loop iterates over a set of 100 frequencies spread evenly (in logarithmic fashion) between 100Hz and 100kHz. Neat!

Now for frequency I 
  • Change the signal generator frequency, 
  • Move the scope time base to match the frequency, 
  • Measure the peak to peak voltage of the input and the output
  • Measure the phase difference between the input and the output.
Then to calculate the gain I just use:

gain = 20 * numpy.log10(output/input)

For each frequency I add the frequency, gain and phase to an array. But now what can I do with the data? I found this Python library called Matplotlib. This has loads of capability include log plots.

I use Matplotlib to graph the gain (in dbM on a linear scale) vs frequency (on a log scale).

When I tried this a bunch of things didn't work:
  • I found that if I sent commands to the signal generator too quickly it would just ignore them! I had to add sleep commands to slow things down enough for this not to happen.
  • At very low frequencies the scope automatically goes into 'roll' mode and is not able to make phase measurements.
  • The output impedance of the signal generator would cause the signal at the input to drop at some frequencies. If the input impedance of the circuit under test is low at some frequencies the input amplitude drops and throws out the gain measurements. Instead I used the second signal generator channel to generate an identical input waveform and measured between this and the output.
  • numpy.log() is the *natural* logarithm. I accidentally used this instead of log10() initially which threw all my gain calculations out (facepalm).
  • I am manually setting the scope vertical adjustments but at regions of very low or very large gain I can't get phase or amplitude readings. I didn't fix this but ideally the script would adjust the scope's vertical range to correct for this.

Bode Plotting Things...

What can I plot? What about a bilinear active filter - like this:


So to understand what is going on imagine C1 and R1 are combined into an impedance (Z1) and C2 and R2 are combined into Z2. Then it is a simple inverting amplifier and the gain is just Z2/Z1,

At DC the capacitors are open circuits so the gain is 1 (0dBm) but at the peak the gain will be C2/C1 = 10 or 20dBm.

So because the gain is Z1/Z2 then we get a zero due to Z1 and a pole due to Z2. The corner frequency of the zero is 1/2 * pi * r1 * c1 which is 234Hz. Then the pole is calculated similarly and is at 2.3K Hz.

Here is the LTSpice Bode plot. There is an extra pole and zero created by the input capacitance of the of the op amp (I think). The actual amp I am using is a LM14588N so this will be different.


Here is the output of the bode-plotter:


It's not a totally silly approximation.  Unfortunate that the phase wraps but no matter. Still much study to do...






Thursday 10 August 2017

Rohde & Schwarz SWP.339.0010.02 Synchronizer PLL unlocked

Last time I fixed a problem in the sweep generator where the 600MHz IF was being disabled when it shouldn't. After that all the self-tests passed and the unit was working overall except that when using the Synchroniser with frequencies above about 980MHz it would lose lock.

Lock Loss

The loss of PLL lock would occur around 980MHz but is wasn't reliable. Sometimes the output would be stable up to 1GHz but then after the unit warmed up a bit it would revert back to the usual behaviour.

This is what the output look like on the spectrum analyzer when the PLL is locked and the frequency relatively is stable (in fact this snapshot isn't all that great - it got better later).


Then if you shift the frequency ever so slightly the output would loose it all together.

The Synchronizer PLLs

The synchronizer has two PLL loops used to lock the output frequency to the 10MHz reference.

In the block diagram below the 'fast' PLL is shown in green and the 'slow' PLL is red. The slow PLL locks a 87-122MHz VCO to the 10MHz reference. The fast PLL divides down the output using a set of frequency dividers


The way it all works is that there are a few paths depending on the frequency range.
  • Below 20MHz the output is generated by mixing the VCO output with the 100MHz reference signal generator off the converter board. In this case the output is not fed back through the PLLs.
  • Above 20MHz but below 70MHz the output frequency is band-pass filtered and fed to the PLLs
  • Above 70Mhz and below 700MHz the output signal is divided by 10 and then fed to the fast PLL and the 700Mhz fed to the fast PLL
  • Above 700MHz the output is mixed with a 1200MHz signal derived from the 600MHz IF generated on the IF board to down covert the frequency to 0..700Mhz. This is then divided by 10 to get 0..70MHz which is fed to the fast PLLs. The 700Mhz is again fed to the slow PLL
  • Above 1200MHz the output is mixed with an 1800MHz signal generated from the 600MHz IF and the 0..700Mhz fed to the PLLs as above.
When the output is below 20MHz the slow PLL locks the VCO to the 10MHz signal.  There is a phase comparator that compares the VCO output with a 10kHz and a 1kHz signal generated from  the 10MHz reference. Because the 100MHz this is later mixed with is also locked to the 10MHz reference then this is all that is required.

When the output is above 20MHz the slow PLL takes the 0..70MHz signal derived from one of the paths listed above is divided by a factor K and compared with the 1kHz and 10kHz reference derived signals and used to control the VCO.  The VCO is then divided by 64 to generate a signal between 1.5Mhz and 1.9Mhz that is fed to another phase comparator and then used to control the output frequency.

The fast PLL does its own division of the 0..70Mhz signal (divides by M and then by N) to generate a frequency around 1.5MHz to 1.9MHz which gets fed to the phase comparator described above. The fast PLL has extra logic for sweeping so it can lock just at the beginning of a sweep and can handle fast frequency transitions that the slow PLL can't.

Debugging PLLs

So I was dreading this problem because of the  PLL loops. The problem is that if the loop is out of lock then all of the loop is out of lock and it's hard to tell where in the loop the fault lies. In this case it is even  worse because there are two PLL loops.

Initially I mistakenly thought I could check the slow PLL on its own. I thought it was totally derived from the reference and so should remain in lock regardless. That isn't the case as it does depend on the output. Therefore if the output is unlocked so is the slow PLL and the VCO.

With a brief warm up I could get the unit so it would be in lock and then if I shifted the frequency just a bit it would lose lock. This made debugging easier as I could compare the 'working' with the 'unlocked' states quite easily.

So I started with the slow PLL and began with the VCO. I found that when the loop is locked the VCO frequency was stable but when it lost lock the frequency would jitter. Also I found that the frequency would go to 132MHz which is outside the specified range. Stepping back through the VCO inputs I found that the control voltage was hitting the limits (going to zero) when it lost lock. I walked back further and found the two phase comparison signals (PHKOM11 and PHKOM12) coming from the digital board were hitting the rail (15V) when the PLL lost lock.

Digital Section

Debugging the digital section wasn't much fun. It has two SMB connectors through to the motherboard and I didn't have any SMB patch leads - I have SMC and SMA (both of which are used in this instrument) but not SMB. This meant I can't run the board on risers as the signals on the coaxial connectors are required to debug the PLL loop. I found I could connect to the test points with a wire and then stuff the board back in the unit.

First I looked at the test-points around the dividers (see below). To be honest I don't really understand this circuit. It's a messy mix of ECL and TTL with lots of TTL to ECL conversion going on. There are ECL D type flip-flops feeding ECL counters that adjust to either count by 10 or 11(??).


The core of this is this two chip set that implements a pre-scale and phase comparator. This is the HEF4751VD and HEF4750VD. The pre-scaler has more capability than what is used here but the circuit seems to be controlling these two 4 bit registers that are used to subtract from the count (to adjust the divide ratio). There is a feedback path that clocks out signals that then adjust the counters feeding into the pre-scaler.

Ok so I got a bit lost here but I could see the 10kHz and 1kHz signals at P9 and P10. When the loop lost lock the frequency of these would drop just a little. The phase comparator output would alter also and that matched what I was seeing on the analog board.

So the question is why is this happening? I thought about maybe the counters are not being setup correctly so the division ration is wrong, I traced signals in to check that they aren't being lost (and they weren't). It seemed to be working apart from the fact that it lost lock.

It was about here that I realized that the input is a 700Mhz signal and not the VCO. I also realized that if either PLL was wrong they would both lose lock.

I start looking at the fast PLL - I looked at the frequency of the P11 signal. This signal has already been divided by 10 on the analog board and is divided by another 1,2 or 4 depending on how many of the D flip-flops are enabled by the multiplexer (D140).

You can figure out the division easily from the table provided in the service manual below. You take the output frequency, work out the down converted freqency by subtracting it from either 1200 or 1800 (or don't subtract if it is less than 700Mhz) and you look up this frequency in table. Then you divide the frequency by M and that should be the frequency at P11.


Again I found this matched exactly - or at least it did when the PLL was locked. When it fell out of lock the frequency would wander off (lower).

New Piece of Test Gear

Up to this point my only way of checking the output frequency above 300MHz was with my spectrum analyzer and I wasn't confident this was correct. A while ago I ordered a pre-scaler for my frequency counter from this polish eBay seller and it finally turned up. The quality of the board and the wiring etc was excellent. I installed this in my 53131A and did some tests. It happily counts -30dBm signals up at 2.5GHz.

Tuning the YIG

One thought I had was that because the YIG output was very out of tune that this could effect the synchronizer PLL's ability to lock. Up to this point I could adjust it as I couldn't measure the output with any accuracy. I followed the procedure to adjust the low end (10MHz) and then the high end (2.5GHz) using my new pre-scaler.

Then I tried the synchronizer again - and it locked at 2.5GHz!

The problem was simply the YIG being too far out.

That was too easy. Well at least I learned a few things.

Final Cleanup

So here it is in my bench (gee it's getting crowded!).



I even took the time to polish up the BNCs with a bit of aluminium polish and a Dremel tool. They look good!



Thursday 3 August 2017

Rohde & Schwarz SWP.339.0010.02 - No Output

This is the third part of the project to refurbish an old Rohde and Schwarz sweep generator.

So I have had this one problem on and off since I got the unit. The output will be stuck at around 38MHz or sometimes 13MHz and if I run the self-test I get an error 22 1C 00 which translates to "the 600MHz IF is missing"

In the first part but the conclusion I reached was that it wasn't the IF generation at fault but something is turning it off.

Well this fault is back and now it is around more than it is not around. This makes working on anything else impossible so its time to kill it once and for all!

Where Does the control Signal Come From? 

In part 1 I found that the 600MHz IF was being blanked by this HF SW TTL signal from elsewhere. The line is labelled HF SW but actually there is a HF SW1 and HF SW2. So if you look at the schematic for the motheboard that carries the RF components, you can see that pin 15 of the converter board connector  is connected to pin 9 of the connector that bridges the RF motheboard to the main motherboard. This is labeled HFSW 1 on the left hand side connector (the bridge).



So this means HF SW 1 is actually controlling the converter and disabling the IF. I got a multimeter out and rang out this line and sure enough that connection is good.

So following this onto the main motherboard you can see HF SW 1 connects to the digital section of the synchroniser (pin 8A labelled HFSW1) . It's not that simple though as there is a jumper (X91) that if in place will bridge this onto a line labelled HFSW. Ok this is a worry - so should the jumper be in place or not?

So I looked at the logic controlling this HFSW 1 line on the digital part of the synchroniser (below). 


What you can see here is the HFSW 1 and HFSW 2 signals being generated from the HF SW1 coming in. The symbols are confusing but D96 is just an OR gates and D75 an inverter. Remember that HFSW 1 is active low - that is a low output turns the 600MHz IF on. 

I pulled the Synchorniser digital board out, unscrewed all the covers and put it on risers. The HFSW 1 was indeed high and the reason was that the signal labelled Y (in a circle) was high which was then inverted by D75 and no matter what HFSW did the HFSW1 signal would be high (as it is a NAND gate).

So then I went searching for this signal labelled Y and it turned out it is controlled via a register interfaced to the bus. So if this register output is high then HF SW 1 will be high and we get the error.




At one point the unit mysteriously worked and I could check my theory and sure enough when the value of Y was low the output worked.

I setup my logic probes to watch the input to that line from the bus (pin 18 of D118), the Y signal (pin 19) and triggered on the clock line (pin 11). I never got a trigger! It was never written to so the register output was at the default.

Debugging the Address Decoding Logic

First of all I hooked up my logic probes to the two inputs to D95 and the clock line feeding D118 to see why the clock pulse never happened. One of the inputs to the OR gate (D95) is from the decoder and this stays high until the address corresponding to this register is present and then it goes low. The other signal is from the EXTWR-N signal off the bus to signal a write is occurring.

I could see a longish (1uS) low pulse on the write signal but the decode line would go low for a brief bit and then high again before the write pulse went low. They needed to both be low for some time period to generate a low on the output of the OR gate and then when write goes high it will generate the positive going edge that triggers D118 to latch the data off the bus.

So why is it only going low briefly? I thought perhaps this was a write to some other address and that the low was just a transitory state while the bus settled. There are too many lines to decode the address bus, the clock line and the data port all at once (my scope has 8 logic probes and 4 analog channels). I decided to break it down bit by bit.

First I hooked probes up to all the inputs and outputs of D77 (the 8 input NAND gate that decodes the upper bits of the address bus). This was functioning correctly in that when the outputs were all high the output went low). The OR gate seems fine so what else? It can't be the decoder as it does go low for a bit. Can it?

I continued with my process and hooked up the 3 select lines plus G1. G2A and G2B of the decoder plus Y2 which triggers the latch. Again the output matched what I saw before - the decode signal stayed low for a bit but went up again. I thought perhaps the logic analyser was simplifying a slow rising waveform or a glitch so I connected an analog channel to Y2 also but sure enough it was staying low for a very short time.


In this scope trace the bottom three signal lines are the select lines (which I combined into a bus). You can see these have a value of 2 to select Y2. The next three lines are the G1, G2A and G2B signal lines which are high, low and low respectively - again this is good and should result in the decoder decoding. The next line is the decoder output and this is echoed by the yellow trace at the top which is the same signal connected to an analog line. You can see it goes low for a very short time.

The top digital line (D7) is the write pulse and you can see the decoder output has gone high again before this has been pulled low. This is why the latch is never triggered as they both need to go low together.

In fact on one occasion while I had this hooked up it worked and in that case the decoder output stayed low *just* long enough to overlap the write pulse.

It can't be a broken trace as the decode signal output is clean (not a slow ramp etc). But can a decoder fail in this way? This doesn't make sense. I bought a replacement decoder chip (as they are cheap), desoldered the one from the board and replaced it. It worked! The decode output then stayed low for as long as the select lines did which was long enough to overlap the write pulse and now the HF consistently (had to take the snapshot from my phone as the scope doesn't like the USB for some reason and  I couldn't hold the analog probe in place).


So what Now?

This is pretty good as now the unit is pretty functional. It sweeps, the power output looks correct and the synchroniser is now looking pretty good. Up to 300MHz (limit of my counter) the frequency has lots of zeros in the values. All the self-tests pass now too.

I thought there was a problem with modulation (as when you hit AM or FM button it doesn't affect the signal) but it turned out to be me being stupid. The unit doesn't generate an internal modulation signal but you have to provide one via a BNC on the front panel. When I did this it worked fine.

The final problem is that for some reason there is a lot of phase noise at higher frequencies when using the synchroniser. I figured out there is a spot around 970MHz where the signal would suddenly degrade. The frequency also gets less and less accurate above this point so by the time I get to 2GHz it is many MHz off.

But that's a problem for next time...