LTC5582 and LT5537 Power Detectors
Features: LTC5582
Broadband performance: ± 0.5 dB over the range 0.1 to 4 GHz.
Linear dynamic range of 50 dB over the range 0.1 to 4 GHz.
Usable to over 6 GHz with reduced dynamic range.
On board EEPROM for calibration parameters.
Optional access to detector output voltage.
Features: LT5537
Broadband performance: ± 0.5 dB over the range 5 to 600 MHz.
Linear dynamic range of 55 dB over the range 5 to 600 MHz.
Usable to 1 GHz with reduced dynamic range.
On board EEPROM for calibration parameters.
Optional access to detector output voltage.
LTC5582 Typical Performance Characteristics
Dynamic Range and Accuracy
The actual range of the linear response will vary from one detector to another. The calibration process described later in this document deals with determining limits for the linear response of a given detector.
Figure 1 shows the calibrated response of a typical LTC5582 detector. By inspection of the plotted response it can be seen that region of linear response for this detector is from approximately 0 down to -50 dBm. The region is not constant across all input signal frequencies. At lower frequencies (up to approximately 3 GHz) the linear response region is actually -5 down to -55 dBm. At frequencies above 4 GHz it is expected that the linear response region will be reduced. This is in line with the response data presented in the LTC5582 data sheet.
Detector level measurement uncertainty
After calibration, the maximum measurement uncertainty when the detector is operated in it's region of linear response will be ± 1 dB. Typically, the uncertainty should be ± 0.5 dB.
Error in the detector input power level measurements will be from the following sources:
Uncertainty in the measurement of the detector output voltage. This uncertainty comes from the detector board
attiny45
MCU ADC which is 10 bits with an absolute uncertainty of 2 LSB. Since the internal 2.56V reference is used, this equates to an uncertainty of 5 mV in the detector voltage reading.-
Uncertainty in the detector calibration process and the derived calibration parameters. This is made up of two parts:
Uncertainty in the input signal power levels as produced by the signal generator used for the detector calibration.
Uncertainty in the derivation of the calibration parameters.
The determination of the uncertainties in the calibration is deal with in more detail in the Calibration Procedure section of this document.
Input Return Loss
The detector input return loss is dependent of the input matching network. The detector board design currently uses the matching network as given in LTC5582 data sheet: Figure 2, p10, Test Schematic Optimized for 40MHz to 5500MHz in Single-Ended Input Configuration.
The effects of the detector board input return loss on the power level measurements are corrected by the detector calibration process. Further details are provided in the Calibration Procedure section of this document.
LT5537 Typical Performance Characteristics
As with the LTC5582, the actual range of the linear response will vary from one detector to another. The calibration process described later in this document deals with determining limits for the linear response of a given detector.
Figure 3 shows the calibrated response of a typical LT5537 detector. By inspection of the plotted response it can be seen that region of linear response for this detector is from approximately -5 down to -65 dBm. The region is not constant across all input signal frequencies. At lower frequencies (up to approximately 200 MHz) the linear response region is actually 0 down to -65 dBm. At frequencies above 200 MHz it is expected that the linear response region will be reduced. This is in line with the response data presented in the LT5537 data sheet.
Applications Information
In general the most convenient method for taking detector input power
measurements is by using the detector board serial peripheral interface
(SPI). Figure 4 illustrates the SPI setup of a detector board with the
atmega USB controller which is running the ECApp embedded control firmware.
In this configuration, the atmega
board becomes the SPI master with the
detector board being the slave. When connected to a host computer, the
USB port of the atmega
board also powers the detector board.
The rfblocks Python package provides the LogDetector class which can be used for software control of the detector board. The code snippet below shows a minimal example of how the detector board is initialized and a power measurement taken. In this example the detector is the LTC5582 and the input signal is set to 1500 MHz with a power of approximately -6 dBm.
>>> from rfblocks import LogDetector, create_serial, write_cmd >>> ser_device = '/dev/tty.usbmodem14101' >>> ser = create_serial(ser_device) >>> det = LogDetector('D0') >>> write_cmd(ser, det.pin_config()) b'.' >>> det.initialize(ser) >>> det.frequency_range (100.0, 6000.0) >>> det.detector_type 0 >>> LogDetector.LTC5582 0 >>> det.read_raw(ser) 948 >>> det.vout(ser) 2317.5 >>> det.power(ser, 1500.0) -6.275880776959141
The code does the following:
Import the
rfblocks
LogDetector
class and some support functions.Open the USB/RS-232 serial device which connects the host computer to the
ECApp
control firmware running on theatmega
microcontroller board.Create an instance,
det
, of theLogDetector
class. The detector board's chip select (CS
) pin is connected to the controllerPD0
pin and this is specified when creatingdet
.Set the required controller pin states. The
LogDetector.pin_config()
method generates the requiredECApp
commands for this and thewrite_cmd
support function sends the commands to the controller board.Initialize the
det
instance. This loads detector board calibration parameters from the detector on-board EEPROM.Check the frequency range of the detector and type of the detector.
Measure the detector input signal power.
More detail
The LogDetector.power()
method will return the measured input signal
power corrected using the calibration parameters stored in the
detector's on-board EEPROM. The power()
method defines the
following parameters:
ser
-
the serial device to write commands to. In general this will be an instance of the pySerial
Serial
class but can be any instance of a Python file object. freq
-
the frequency of the detector input signal in MHz.
avg
-
an optional argument specifying the number of measurements to average over. The default value is 1.
The power()
method does the following:
Calls the
LogDetector.vout()
method to read the detector output voltage.vout()
calculates this voltage by first calling theLogDetector.read_raw()
method which reads a raw 10-bit value from the detector board. The raw value is converted to a voltage (in millivolts) by multiplying byLogDetector.RAW_TO_MILLIVOLTS
.Corrects the raw detector voltage using the detector calibration parameters and the input signal frequency as specified by
freq
. Further details of the correction procedure and detector calibration is provided in the Calibration Procedure section below.
Calibration and correction. Using PwrDetectorController.
In general, power detectors will be connected to the device under test via some intermediate set of cabling and other devices. For example, if the expected signal power to be measured is outside the linear range of the detector then either attenuation or amplification must be included. Similarly, cable losses must be corrected. What is required is for the calibration plane of the detector to be moved from the detector's connector to the connector which is mated with the device under test.
>>> from rfblocks import LogDetector, PwrDetectorController, create_serial, write_cmd >>> ser_device = '/dev/tty.usbmodem14101' >>> ser = create_serial(ser_device) >>> det = LogDetector('D0') >>> det_ctl = PwrDetectorController('det1', det) >>> det_ctl.initialize(ser) >>> cal_file = 'referencedesigns/PowerMeter/app/cal-files/12dB-atten-5640-128-100-6000MHz.json' >>> det_ctl.load_caldata(cal_file) >>> det_ctl.apply_correction = True >>> det_ctl.avg = 1 >>> det_ctl.freq = 1000 >>> det_ctl.measure(ser) >>> det_ctl.pwr -10.184789915966384 >>> det_ctl.avg = 8 >>> det_ctl.measure(ser) >>> det_ctl.pwr -10.10819677871148
Detector linearity
When measuring the input signal power it is vital to know whether the
detector is operating within it's region of linear response. The
LogDetector.linear_range()
method returns a tuple containing the
minimum and maximum input signal powers (in dBm) for which the
detector provides a linear response.
Continuing with the minimal code snippet above, suppose the input signal power is -40 dBm (at 1000 MHz):
>>> det.power(ser, 1000, avg=8) -40.387142857142855 >>> det.linear_range(1000) (-57.41793316505692, -1.2007444914343335)
It can be seen that the detector's region of linear response is between -57.4 and -1.2 dBm. With the input signal power set to -40 dBm the measured power is seen to be within the quoted typical range of uncertainty for the detector.
Now the input signal power is set to -60 dBm and then to -65 dBm (at 1000 MHz) with measurements taken at each setting:
In these cases the detector is operating outside of it's linear response region and the measurements show an increasing departure from the actual input signal power.
Similar behaviour occurs at the other end of the linear response region. Setting the input signal power to 2 dBm and then to 5 dBm (at 1000 MHz) and making measurements at each setting:
Low level SPI commands
CS
on the power detector board is active low (that is, pulling CS
low will enable detector SPI).
Note that the SPI clock rate should be 500 kHz or less. The S3
ECApp embedded control command can be used to set this.
An ADC conversion of the input RF power must be explicitly commanded
using the 0x40
command byte. This will result in the raw ADC value
being stored in register 1 (low byte) and register 2 (high byte).
Figure 10 shows the timing of an ADC read operation. The following Python code is taken from the LogDetector.read_raw method.
# SPI clock speed for the attiny45 should be <500 kHz cmd = 'L{}:S3:'.format(self.cs) write_cmd(ser, cmd) # Start an ADC conversion cmd = 'W40:' write_cmd(ser, cmd) # Max. ADC conversion time on the attiny is approx 0.2 millisecs # (125kHz ADC clock) time.sleep(0.00025) # Read the ADC low byte from register 1 cmd = 'W01:' write_cmd(ser, cmd) cmd = 'R:' resp = query_cmd(ser, cmd) low_byte = int(b''.join(resp).decode('utf-8')[:-1], 16) if len(resp) > 1 else 0 # Read the ADC high byte from register 2 cmd = 'W02:' write_cmd(ser, cmd) cmd = 'R:' resp = query_cmd(ser, cmd) high_byte = int(b''.join(resp).decode('utf-8')[:-1], 16) if len(resp) > 1 else 0 # SPI clock speed is returned to 4 MHz cmd = 'H{}:S1:'.format(self.cs) write_cmd(ser, cmd) return low_byte + (high_byte * 256)
The following C code is taken from Zephyr ECApp code. Since the C code is
in general much faster than the equivalent Python code it is necessary to
insert k_sleep
calls in order to satisfy the timing requirements.
uint8_t spi_rate[] = "3"; struct cmd_values spi_cmd = { .data[0] = 0x40, .count = 1 }; // SPI clock speed for the attiny45 should be <500kHz (void)set_spi_clock_rate(spi_rate); // Enable attiny SPI (void)set_pin_low(cs_pin); k_sleep(K_TICKS(1)); // Start an ADC conversion write_spi_bytes(&spi_cmd); // Pause for 0.25 millisecs. k_sleep(K_TICKS(10)); // Read ADC low byte spi_cmd.data[0] = 0x01; write_spi_bytes(&spi_cmd); k_sleep(K_TICKS(1)); uint8_t low_byte = read_spi_byte(); k_sleep(K_TICKS(1)); // Read ADC high byte spi_cmd.data[0] = 0x02; write_spi_bytes(&spi_cmd); k_sleep(K_TICKS(1)); uint8_t high_byte = read_spi_byte(); // Disable attiny SPI (void)set_pin_high(cs_pin); // SPI clock speed is returned to default spi_rate[0] = '1'; (void)set_spi_clock_rate(spi_rate); uint16_t level = ((uint16_t)high_byte) << 8; level += low_byte; return level;
Board connector configuration
Board Pin |
Type |
Description |
---|---|---|
|
Input |
Serial interface data input |
|
Output |
Serial interface data output |
|
Input |
Serial interface clock |
|
Input |
Serial interface board select |
|
Input |
Module microcontroller reset |
|
Output |
Optional power detector voltage output |
|
Input |
Female SMA connector for RF input signal |
|
Power Input |
5V DC module power |
|
Power Input |
Module ground |
Reference Designs
Calibration Procedure
The steps taken to calibrate a given power detector board are as follows:
-
Capture calibration measurements and produce linear fits to the data using
measure-cal-data.py
. Here's an example command line:python measure-cal-data.py -O ltc5582-unit2-cal-data.json
See Figure 9 for an example of a calibration measurement setup. See Capturing calibration measurements for more details of the
measure-cal-data.py
script. -
Generate overall fits for the slopes and intercepts of the detector linear regions. Here's an example command line:
python plot-cal-data-fits.py -I ltc5582-unit2-cal-data.json \ -E -O ltc5582-unit2-extrapolated-cal-data.json -P \ ltc5582-unit2-cal-fits.svg
Figure 7 shows example plots of the overall fits for the detector slopes and intercepts as generated by
measure-cal-data.py
. -
Calculate detector linearity errors and linearity limits. An example command line:
python plot-cal-data-linearity.py \ -I ltc5582-unit2-cal-data.json \ -L ltc5582-unit2-linlimits.json
-
Format detector slope/intercept fits for EEPROM. An example command line:
python cal-data-eeprom.py \ -I ltc5582-unit2-extrapolated-cal-data.json -L ltc5582-unit2-linlimits.json
Build EEPROM image and write it to the detector board.
Calibration Details
The following sections describe the calibration procedure in more detail.
-
A set of detector measurements are taken using a known accurate RF signal source. The power range -75 to 10 dBm is covered at frequencies from 250 to 4250 MHz. Note that we use the Rohde & Schwarz SMHU58 signal generator as our reference. This has an upper frequency limit of approximately 4300 MHz. The power detector being calibrated is connected directly to the SMHU58 via an N-type to male SMA adapter. See Capturing calibration measurements for more details.
Some example measurements are shown here:
$ python scripts/measure-cal-data.py -O ltc5582-unit4-cal-data.json -75.0: 605.47 604.06 603.59 606.25 604.22 606.72 598.75 598.44 600.78 601.09 599.22 599.53 598.28 597.50 595.16 596.88 595.16 -70.0: 629.22 626.56 624.84 623.12 620.94 617.03 612.66 614.38 608.75 610.31 609.38 606.56 606.72 608.75 613.91 607.19 607.19 -65.0: 675.16 669.84 670.00 665.47 662.81 658.44 653.75 639.06 639.38 636.41 633.75 628.91 629.06 623.75 630.00 617.19 613.28 ... 0.0: 2433.91 2424.84 2416.88 2410.62 2406.72 2397.97 2383.59 2357.03 2362.19 2360.00 2350.78 2335.94 2327.19 2323.44 2315.94 2296.56 2278.75 5.0: 2502.97 2504.69 2496.09 2489.69 2486.41 2479.06 2472.66 2452.19 2454.84 2447.97 2440.16 2430.78 2424.53 2412.19 2402.50 2389.53 2384.22 10.0: 2553.59 2551.72 2549.84 2545.47 2506.56 2501.88 2495.00 2486.56 2477.81 2471.88 2460.62 2454.06 2443.91 2434.22 2423.44 2410.47 2397.50
-
A set of lines are now fitted to the linear portion of the detector response curve at each of the measurement frequencies. An example of the line fits is shown in Figure 6.
The measured detector response together with the slope and intercept of the line fits for each measured frequency are saved to a file for later use. See Capturing calibration measurements for more details.
-
The LTC5582 datasheet shows plots of linear response slopes and intercepts across the frequency range 450 to 5800 MHz (p7 of the datasheet, 'Slope vs Frequency' and 'Logarithmic Intercept vs Frequency'). We produce similar plots using the slopes and intercepts produced in step (2). The slope and intercept data are extrapolated linearly up to 6000 MHz and down to 0 MHz. The detector slope and intercept data from the datasheet plots are used to guide the extrapolation (the plot data for a case temperature of \(25^\circ\) C is used).
Table 2 shows an example set of slope/intercept values derived from the line fits of the measured detector response.
Table 2: Example Calibration Data Frequency (MHz)
Slope (mV/dB)
Log Intercept (dBm)
0
30.66
-82.38
250
30.66
-82.38
500
30.67
-82.12
750
30.62
-81.95
1000
30.56
-81.88
1250
30.60
-81.72
1500
30.59
-81.43
1750
30.57
-80.73
2000
30.76
-79.85
2250
30.90
-79.52
2500
30.92
-79.12
2750
30.57
-79.43
3000
30.74
-78.72
3250
30.88
-78.09
3500
31.01
-77.42
3750
31.22
-76.55
6000
31.96
-69.44
Example plots are shown in Figure 7. The slope and intercept data from the LTC5582 datasheet are shown as red, green, and yellow dashed plots (for case temperatures of \(25^\circ\), \(-40^\circ\) and \(85^\circ\) C respectively). The measured slope and intercept values are shown as a solid blue line with the extrapolated values shown as blue dotted lines. Note that the last two measured values (at signal frequencies 4000 and 4250 MHz) are ignored for the purposes of the extrapolation. The accuracy of the signal generator power output levels for these cases is doubtful.
-
In order to effectively use the detector the range of the linear response region as a function of input power and frequency must be known. This range is determined using the following procedure:
Calculate the linearity error for each measured input signal power and frequency. This will be the difference between the measured input power and the input power as calculated from the linear fit at that input signal frequency.
-
Perform polynomial fits for the calculated linearity errors. These fits are then used to determine the upper and lower input signal power linearity limits. The limits are taken to be the input signal powers which produce an (absolute) linearity error of \(\ge 0.5\) dB.
The upper two panels of Figure 8 show example plots of the measured linearity errors and the associated polynomial fit. The horizontal dashed lines indicate the ± 0.5 dB linearity error limits.
Calibration data is stored in the attiny45
EEPROM. Measured raw ADC
values for eighteen input RF power levels are stored as 16-bit
integers in the attiny45
EEPROM. These values can be retrieved via
the SPI by reading registers 100 through to 135. The values are
stored low byte first followed by the high byte.
Writing Calibration Data to EEPROM
The calibration data produced by the plot-cal-data-fits
script is
formatted for inclusion as EEPROM data using the code below. In
essence, the calibration data is converted to a set of positive 16
bit integers which can then be stored as an array in the attiny45
EEPROM.
# # Example command line: # # python cal-data-eeprom.py \ # -I measuredData/ltc5582/ltc5582-unit2-extrapolated-cal-data.json # -L measuredData/ltc5582/ltc5582-unit2-linlimits.json # import json import struct from argparse import ArgumentParser if __name__ == '__main__': parser = ArgumentParser(description= '''Generate EEPROM formatted cal. data.''') parser.add_argument("-I", "--inputfile", required=True, help="The JSON formatted input cal. data file.") parser.add_argument("-L", "--linearity", required=True, help="JSON file containing linearity limit data.") args = parser.parse_args() with open(args.inputfile) as fd: cal_data = json.load(fd) with open(args.linearity) as fd: linlimits = json.load(fd) print('cal_data_type cal_data __attribute__((section(".eeprom"))) = {') print('{', '{},'.format(len(cal_data)), ', '.join(['{}, {}, {}'.format(int(float(f)), int(float(v[0])*100), abs(int(float(v[1])*100))) for f, v in cal_data.items()]), '}') print('};') ba = struct.pack('f', linlimits['min_limit_coeffs'][0]) ba += struct.pack('f', linlimits['min_limit_coeffs'][1]) ba += struct.pack('f', linlimits['min_limit_coeffs'][2]) ba += struct.pack('f', linlimits['min_limit_coeffs'][3]) ba += struct.pack('f', linlimits['max_limit_coeffs'][0]) ba += struct.pack('f', linlimits['max_limit_coeffs'][1]) ba += struct.pack('f', linlimits['max_limit_coeffs'][2]) ba += struct.pack('f', linlimits['max_limit_coeffs'][3]) print('lin_limits_type lin_limits_data __attribute__((section(".eeprom"))) = {') print('{', ', '.join([ "0x%02x" % b for b in ba ]), '}') print('};')
Output from this script can then be placed in the spiadc.cpp
source file as shown in the following example code snippet:
namespace app { namespace registers { const std::uint8_t reg_file_size = 16U; const std::uint16_t cal_data_size = 52U; typedef std::array<std::uint8_t, reg_file_size> reg_file_type; typedef std::array<std::uint16_t, cal_data_size> cal_data_type; reg_file_type register_file; lin_limits_type lin_limits_data __attribute__((section(".eeprom"))) = { { 0x87, 0x76, 0xe9, 0xad, 0xcd, 0x47, 0x63, 0xb3, 0xab, 0x10, 0xf5, 0x3a, 0x2a, 0xa9, 0x71, 0xc0, 0x2c, 0x48, 0xd7, 0xae, 0x5d, 0x6b, 0xbb, 0x35, 0x38, 0xe9, 0x30, 0xbb, 0x18, 0x26, 0x5e, 0xc2 } }; cal_data_type cal_data __attribute__((section(".eeprom"))) = { { 17, 0, 2977, 8657, 250, 2977, 8657, 500, 2972, 8640, 750, 2953, 8651, 1000, 2952, 8634, 1250, 2953, 8609, 1500, 2946, 8573, 1750, 2932, 8526, 2000, 2942, 8433, 2250, 2958, 8443, 2500, 2956, 8429, 2750, 2942, 8409, 3000, 2952, 8344, 3250, 2980, 8257, 3500, 2985, 8197, 3750, 2993, 8106, 6000, 3067, 7394 } }; void write(const uint8_t reg, const uint8_t val); uint8_t read(const uint8_t reg); } }
The ordering of the lin_limits_data
and cal_data
must be as indicated
in the above code snippet. The compiler/linker then places cal_data
first in EEPROM followed by the lin_limits_data
:
.eeprom 0x0000000000810000 0x88 tmp/obj/spiadc.o 0x0000000000810000 app::registers::cal_data 0x0000000000810068 app::registers::lin_limits_data 0x0000000000810088 __eeprom_end = .
After updating the cal_data
in spiadc.cpp
the firmware is
rebuilt and the EEPROM data uploaded to the attiny45
using the
procedures documented in Building the firmware.
Firmware
The firmware which runs on the attiny45
is a variant of the ECApp framework and
acts as an SPI slave providing access to a collection of registers. Source for the
firmware is available here: ECApp for the attiny45.
The contents of a register is read by performing an SPI write of the 8-bit address of the register and then an SPI read of the returned 8-bit value. For example, reading the contents of register 1 using ECApp commands:
After initialization, the firmware is entirely interrupt driven. Figure 9 shows a summary of the operation.
The pin change interrupt (
vector_2
) monitors pinB3
which is theCS
line. WhenCS
goes low the SPI system is enabled. WhenCS
goes high the SPI system is disabled.The USI overflow interrupt (
vector_14
) monitors serial traffic on thePB0
(MOSI
) andPB2
(SCK
) pins and receives SPI commands from the SPI master. Commands are interpreted and, if required, responses are loaded into theUSIDR
for transmission to the SPI master (viaPB1
,MISO
).The ADC conversion complete interrupt (
vector_8
) writes the low byte of the ADC conversion result to register 1 and the high byte to register 2.
Register |
Description |
---|---|
0x0 |
Reserved |
0x1 |
ADC low byte |
0x2 |
ADC high byte |
0x14 |
Detector type |
0x40 |
Start ADC conversion |
0x64 |
Calibration data |
Writing the register value 0x40
starts an ADC conversion. Registers 1
and 2 will receive the 10 bit ADC output value after a conversion.
Register 1 will contain the lower 8 bits and register 2 the upper 8 bits.
The LogDetector.read_raw method illustrates doing an ADC conversion and
reading the result.
- t_1
-
Time required to enable the SPI system after the CS signal goes low. This is approximately 10uS.
- t_2
-
Time required for the ADC to carry out one complete conversion. This is approximately 0.2mS.
- t_3, t_5
-
Time required to setup a specific register for a read operation. This is approximately 35uS (with an SPI clock rate of 250kHz).
- t_4, t_6
-
Time required to read the contents of a register. This is approximately 35uS (with an SPI clock rate of 250kHz).
Registers from (decimal) 100 upward are read only and access the contents
of the attiny45
EEPROM. The detector calibration data is stored here
and the LogDetector.read_cal_data method illustrates how the calibration
data is retrieved fro use.
Building the firmware
Ensure that the correct branch of the source code is checked out:
If not, check out the correct branch before proceeding:
$ git checkout spiadc/attiny45 Switched to branch 'spiadc/attiny45' Your branch is up to date with 'origin/spiadc/attiny45'.
The make file is target/app/make/app_make_linux.gmk
. The essential
build commands are:
$ cd $ECAPP $ rm -rf ./tmp $ make -f target/app/make/app_make_linux.gmk $ make -f target/app/make/app_make_linux.gmk avrdude
Alternatively, the program firmware may be uploaded using the following
avrdude
command:
Building and uploading just the EEPROM data is done using the following commands:
Updating the firmware
Prior to updating the firmware a copy of the EEPROM contents must be made. This is because a chip erase will be done before uploading the new firmware.
The new firmware is uploaded either using the procedure described in
the previous section or using the following command to upload the
hex
file directly:
cd $ECAPP $ avrdude -p attiny45 -P /dev/tty.usbserial-A600e0V2 -c buspirate -U flash:w:bin/spiadc.hex
Now the previously read copy of the EEPROM contents is uploaded:
Design Notes: LTC5582
The detector uses the LTC5582 coupled with an attiny45
MCU.
IC3
, the attiny45
, is used essentially as an SPI enabled ADC. The
voltage output from the LTC5582 is connected via R1
to channel 2 of
the attiny45
ADC. Optionally, output from the LTC5582 can be
accessed directly via J3
by populating R3
(and removing R1
).
The attiny45
ADC is configured to make use of the internal 2.56V voltage
reference. This matches quite well with the possible voltage swing of
the LTC5582.
The input network for the LTC5582 is as specified for the test circuit shown in Figure 2 of the LTC5582 data sheet. Accordingly, the network is optimized for the frequency range 40 to 5500 MHz.
Design Notes: LT5537
To achieve the best sensitivity, the input termination impedance should be increased and the input pins should be differentially driven. The input network therefore uses a transformer to step up the impedance and perform the balun function. The 240 ohm resistor (R2) sets the impedance at the input of the chip to 200 ohm. A 1:4 transformer is used to match the 50 ohm signal source impedance to the circuit input impedance. C8 and C9 are DC blocking capacitors. According to the LT5537 data sheet this arrangement has a (3dB error) sensitivity of -82.4 dBm at 200MHz.
Scripts
This section presents the source code of the scripts referenced in
this document. In order to more effectively maintain these scripts we
use org-mode
as a literate programming environment.
measure-cal-data.py
plot-cal-data-fits.py
plot-cal-data-linearity.py
measure-accuracy.py
Capturing calibration measurements
This script measures the raw response of the detector under test. The output voltage of the detector board is recorded for a set of known input signal power levels at each of a set of input signal frequencies. The test setup is shown in Figure 11. Linear fits are then made for each set of measured detector voltages at each of the input signal frequencies. Finally, the measured voltages and linear fits are saved in a file.
usage: measure-cal-data.py [-h] [-d DEVICE] [-C CSPIN] [-G {DSG815,SMHU58}] [-O OUTFILE] Calibrate LTC5582 power detector module. optional arguments: -h, --help show this help message and exit -d DEVICE, --device DEVICE The serial device (default: /dev/tty.usbmodem14101) -C CSPIN, --cspin CSPIN Chip select controller pin (default: D0) -G {DSG815,SMHU58}, --gen {DSG815,SMHU58} The signal generator in use for the calibration. Default: SMHU58 -O OUTFILE, --outfile OUTFILE Output file for measured calibration data. Default: ltc5582-cal-data.json
An example command line:
python scripts/measure-cal-data.py -O ltc5582-unit2-cal-data_2.json
A full description and code for the script is given here: measure-cal-data.py.
Figure 6 shows a set of example plots of measured detector voltage
together with linear fits for each. (These plots were produced by
running the plot-cal-data.py
script - further details of this
script are given in the next section.)
Plotting calibration data fits
This script reads the calibration measurements and associated linear
fit parameters acquired using the measure-cal-data.py
script. The
script produces plots of the linear fit slope and intercept
parameters together with similar plots taken from the LTC5582 data
sheet.
Optionally, the script may be used to extrapolate the measured fits up to 6 GHz using the data sheet curves as a guide.
usage: plot-cal-data-fits.py [-h] [-E] [-I INFILES [INFILES ...]] [-O OUTFILE] [-P PLOTFILE] Plot LTC5582 detector calibration data fits. optional arguments: -h, --help show this help message and exit -E, --extrapolate Extrapolate cal. data fits linearly to 6 GHz. -I INFILES [INFILES ...], --infiles INFILES [INFILES ...] Input file(s) containing calibration data. Default: ['ltc5582-unit1-cal-data.json'] -O OUTFILE, --outfile OUTFILE Output file for extrapolated cal. data. Default: ltc5582-unit1-extrapolated-cal-data.json -P PLOTFILE, --plotfile PLOTFILE Output file for slope/intercept plots. Default: static/tmp-ltc5582-unit1-cal-fits.svg
An example command line:
python scripts/plot-cal-data-fits.py -I ltc5582-unit4-cal-data.json \ -E -O ltc5582-unit4-extrapolated-cal-data.json -P \ ltc5582-unit4-cal-fits.svg
More than one JSON input file can be specified as follows:
python scripts/plot-cal-data-fits.py \ -I measuredData/ltc5582/ltc5582-unit2-cal-data.json \ measuredData/ltc5582/ltc5582-unit2-cal-data_2.json \ measuredData/ltc5582/ltc5582-unit2-cal-data_3.json \ measuredData/ltc5582/ltc5582-unit2-cal-data_4.json \ measuredData/ltc5582/ltc5582-unit2-cal-data_5.json \ -P static/tmp-ltc5582-unit2-cal-fits.svg -E \ -O measuredData/ltc5582/ltc5582-unit2-extrapolated-cal-data.json
Note that if multiple data sets are specified the slopes and intercepts will be averaged.
A full description and code for the script is given here: plot-cal-data-fits.py.
Plotting calibration data linearity
This script calculates detector linearity errors and linearity limits
from data captured using the measure-cal-data
script. Additionally
it produces plots of the detector linearity and the linearity limits
as a function of input signal frequency.
usage: plot-cal-data-linearity.py [-h] [-I INFILE] [-O OUTFILE] [-P PLOTFILE] [-L LINLIMITSFILE] [-E LINERRFILE] Plot LTC5582 detector calibration data linearity. optional arguments: -h, --help show this help message and exit -I INFILE, --infile INFILE Input file containing calibration data. Default: ltc5582-cal-data.json -O OUTFILE, --outfile OUTFILE Output file for plot. Default: ltc5582-cal-data.svg -P PLOTFILE, --plotfile PLOTFILE Output file for slope/intercept plots. Default: ltc5582-lin-fits.svg -L LINLIMITSFILE, --linlimitsfile LINLIMITSFILE Output file for linearity limits. Default: ltc5582-linlimits.json -E LINERRFILE, --linerrfile LINERRFILE Output file for linearity error plots. Default: ltc5582-linerr.svg
An example command line:
python scripts/plot-cal-data-linearity.py \ -I measuredData/ltc5582/ltc5582-unit4-cal-data.json \ -L measuredData/ltc5582/ltc5582-unit4-linlimits.json
A full description and code for the script is given here: plot-cal-data-linearity.py.
Format calibration data for EEPROM
The calibration data produced by the plot-cal-data-fits
script is
formatted for inclusion as EEPROM data using the code below. The
calibration data is converted to a set of positive 16 bit integers
which can then be stored as an array in the attiny45
EEPROM.
usage: cal-data-eeprom.py [-h] -I INPUTFILE -L LINEARITY Generate EEPROM formatted cal. data. optional arguments: -h, --help show this help message and exit -I INPUTFILE, --inputfile INPUTFILE The JSON formatted input cal. data file. -L LINEARITY, --linearity LINEARITY JSON file containing linearity limit data.
An example command line:
python cal-data-eeprom.py \ -I measuredData/ltc5582/ltc5582-unit2-extrapolated-cal-data.json -L measuredData/ltc5582/ltc5582-unit2-linlimits.json
Measure calibration accuracy
This script will measure the calibration accuracy of a given
detector. The test setup is shown in Figure 11. Currently, the
script recognises either the R&S SMHU58 or the Rigol DSG815 signal
generators. In order to eliminate cable losses, the detector input
should be connected directly to the signal generator output via an
N-type to SMA adapter. The script assumes the use of the rfblocks
Python package together with the ECApp
embedded control software.
usage: measure-accuracy.py [-h] [-d DEVICE] [-C CSPIN] [-G {DSG815,SMHU58}] [-O OUTFILE] Measure LTC5582 power detector module accuracy. optional arguments: -h, --help show this help message and exit -d DEVICE, --device DEVICE The serial device (default: /dev/tty.usbmodem14101) -C CSPIN, --cspin CSPIN Chip select controller pin (default: D0) -G {DSG815,SMHU58}, --gen {DSG815,SMHU58} The signal generator in use for the calibration. Default: SMHU58 -O OUTFILE, --outfile OUTFILE Output file for plot. Default: ltc5582-accuracy.svg
A full description and code for the script is given here: measure-accuracy.py.