Sunday, December 16, 2018

Low Noise Measurement Preamp


Recently I needed a low noise Preamp to measure voltage noise density of some low frequency amplifier circuits with my custom built FFT Analyzer [1]. This is surprisingly easy to do now with just a few IC’s from Linear Technology.

The basic specifications of what I needed are,
  • DC Coupled
  • Noise at 1 Hz   <=  10 nV/rt-Hz total in the measurement system.
  • Noise at 1 kHz <= 2.5 nV/rt-Hz total in the measurement system.
  • Frequency Range DC-100 kHz.
  • 1k Ohm input resistance.
  • Adjustable gain so that a wide variety of conditions can be measured.
  • Power from +/- 5 Volts.
  • Output Voltage at least +/- 2.5 Volts to drive FFT Analyzer Input
Some back of the envelope calculations suggested that I needed an overall gain of about 5000 for the Preamp to overcome about 90% of the FFT Analyzers input noise. With this in mind and to keep things simple, I picked a 2 stage preamp design consisting of a low noise OPAMP followed by a programmable gain amplifier.

The lowest voltage noise OPAMP for some decades now has been the LT1028 [1]. The low 0.9 nV/rt-Hz midband noise combined with the very low noise 1/f corner frequency was perfect for my needs. To expand the dynamic range of the preamplifier I added a post amplifier using the LTC6910-1 Programmable Gain Amplifier. The LTC6910-1 provides programmable gains of 1,2,5,10,20,50 and 100.

Setting the LT1028's gain to 52.1 V/V combined with the LTC6910-1's maximum gain of 100 combines for a maximum preamp gain of 5210 V/V [3].

Figure 1 – Using a low gain of 52 V/V on the LT1028 sufficiently overcomes the downstream noise and still allows for wide dynamic measurement range on even the highest gain settings. The overall gain can be set from 52.1 to 5210 V/V by programming the LTC6910. 

When measuring the noise floor of anything, the preamp noise is only part of the problem. It is equally important to have extremely well filtered power supplies and control lines to prevent,

#1 Spurious signals coupled in from the power supplies and showing up in the noise floor. As any switching noise that makes it way to the preamp will show up as a spurious peak in the measurement.

#2 Excellent damping and low impedance to prevent power supply feedback coupling and oscillation due to the large gains involved in the preamp. This is also important from one preamp channel to another as this design was ultimately a 2 channel design.

These two requirements are met with the application of the classic, simple and lowest of the low noise regulators, the: “Beta Multiplier” circuit. The circuit in Figure 2 is mounted close to the preamps and is in addition to the per-channel linear regulators on the main board. The combination of the two, then serves to help rid the noise floor of all but the most stubborn spurious signals.


Figure 2 – In any noise floor measuring system the preamp power supply is just as important as the preamplifier design. This adaptation of the classic and very low noise “Beta Multiplier” provides > 40 dB of isolation and very low noise at 100 Hz. The addition of the inductor provides continued rolloff well beyond the 100 kHz measurement bandwidth. High quality Tantalum’s must be used for the 220 uF capacitors.

The one downside of the Beta Multiplier is that it adds about 0.6 Volts of voltage drop. Hence the raw +6 and -5.5 Volt inputs end up being around +5.4 and -4.9 volts at the preamps voltage terminals in this application.

Since the ultimate usage of the preamp was in a dual channel design. To prevent coupling from one preamp channel to another, the circuit of Figure 2 was duplicated for each input channel.

To further prevent noise from coupling into the preamps noise floor, the LTC6910-1 control lines were heavily filtered and isolated from the microprocessors control bus. Control bus isolation was provided by using a MAX7317 I/O Expander in between the analyzer control bus and the preamp channels. This combined with the heavy filtering on the control lines at each LTC6910-1 provided the required isolation.


The preamp was attached to the FFT analyzer and the combined system noise floor was measured by shorting the input of the preamp.


Figure 3 – The overall system noise performance of a LT1028 and OPA140 version of the preamp with shorted inputs. The FFT Analyzers ADC and ADC Driver amplifier also add noise to the overall result.

The LT1028 input is suitable for measuring a large class of circuits since the useful measurement nodes tend to be low Impedance (i.e. regulator or amplifier outputs). However there are instances where the impedance is higher than the optimum source impedance of the LT1028 (which is quite low at around 160 Ohms @ 1 Hz). In these cases a higher impedance preamp is desirable. By simply substituting a JFET OPA140 for the LT1028, circuits up to the Megohm range can be measured. For comparison, the noise performance of both the LT1028 and OPA140 versions of the preamp are plotted together in figure 3.


The base Analyzer that this preamp was designed for has a mezinnine connector for the Analog input and utput circuits, this allows the overall instrument configuration to change with very little work. Just whip up a new Analog Input Board, add jst a few lines of embedded C code to the instrument application to 'teach' it how to run the new hardware, plug in the board. QED!


Figure 4 - The completed Low Noise PreAmp as implemented. The input used BNC connectors and both channels can clearly be seen. Plenty of room left on the board for future expansion.


Bonus Figure: Since Linear Technology does not publish low frequency curves of the LTC6910 Programmable Gain Amplifier. I have measured a typical device and present it here for a Gain of 100.


[1] Hageman, Steven C., “A Modern DSP Based Lock-In Amplifier”, 2018

[2] Linear Technology has a redesigned LT1028, the LT6018 but it doesn’t have significantly lower noise and unlike the LT1028 the noise isn’t 100% tested on every device.

[3] Clever readers will note that the LTC6910-1 does not have a minimum guaranteed Gain-Bandwidth product (GBW) that meets the required 100 kHz bandwidth at a gain of 100. I was only building a few of these preamps and the ones I had do meet the typical specification specification of 11 MHZ GBW, so I went with the typical specifications which met my requirements.

Article By: Steve Hageman

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.

Note: This Blog does not use cookies (other than the edible ones).

Friday, November 23, 2018

PIC32MZ/EF Pin Slew Rate Control

If you look very carefully at the PIC32MZ/EF processor data sheet you will find a few references to the ability to set individual pins Slew Rate. This functionality essentially changes the driver output current in several discrete levels. This then changes the achievable Slew Rate of the pin, or: “How fast the pin transitions from one logic level to another”. This is useful in controlling ringing on traces and meeting EMI emissions requirements.

While FPGA’s have Slew Rate control on nearly all their output pins, the PIC32MZ/EF only has this available on selected pins.

Two registers attached to the port registers control the Slew Rate of the selected pin and each pin can be set independently of the others.

The Slew Rate control registers are,

    SRCON0x, SRCON1x

Where ‘x’ is the port letter designation (A, B, C … K)

Figure 1: Section 12:2 of the PIC32MZ/EF data sheet gives a brief description of the Slew Rate functionality. Also note that the table lists: Slowest, Slow, Medium and Fastest – yet the enumerations in Harmony list these as: Slowest, Slow, Fast and Fastest. Showing just how hard it is to keep ‘comments’ and ‘code’ synchronized, using the same terms!

To find the ports/pins that allow this control, search the data sheet for: ‘SRCON0A’, B, C, etc… This should take you to the tables in section 12.5 of the data sheet titled: “I/O Ports Control Registers” (Be careful that you are looking at the proper table for the exact package of the device you are using). The SRCONx bits are currently listed at the bottom of each port register table.

The port pins that allow Slew Rate control on a PIC32MZxxxxEFx064, a 64 pin device can thus be found as follows,

    Port B: RB14, RB10, RB9, RB8 RB5 and RB3
    Port C: No pins
    Port D: No Pins
    Port E: RE3, RE2, RE1, RE0
    Port F: RF1, RF0
    Port G: RG9, RG6
Similar lists can be quickly made for the other package types.

It can be seen that this is not every pin in the PIC32MZ/EF-064 device. So what is the logic here?

#1 – There are a few high speed, 50 MHz SPI ports available on this device and they have specific requirements of what pins must be used for high speed operation.

    • 50 MHz Max on SPI2: Pins RB3 &RB5
    • 50 MHz Max on SPI3: Pins RB10, RB9 & RF0

    These Fast SPI pins are all Slew Rate controllable

#2 – The REFCLKOx pins can be mapped to Slew Rate controllable pins.

#3 – In PIC32 devices that include a DDR SDRAM interface, the drive strength of that interface is also controllable as a whole. See the Harmony enumeration: “DDR_PHY_DRIVE_STRENGTH”.

Controlling the Pin Slew Rate

There are several Harmony 2.x functions available to control the Slew Rate of the pins.

Note: See Harmony Help for exact details on using these functions.

* See if the Slew Rate functionality even exists for your PIC32 device,

* Get the current Slew Rate setting of a port pin,

* Set the Slew Rate for a pin or a group of pins on a port (i.e. Channel),

The Slew Rate is specified as one of the following enumerations,

The ‘channelMask’ is a UINT16 that has a ‘1’ in the pins bit position for the pin you want to change, otherwise the pins strength remains the same and is not changed.

For example, to set just RB3 to the ‘Slow’ Slew Rate,

To Set pins B3 and B5 to the ‘Fast’ Slew Rate,

The various PLIB functions above must be called manually in your PIC32 Project as there are currently no Harmony Configuration Settings for the pins Slew Rates.

This is easy enough to do with a ‘Standard’ Harmony Application in the App_Initilize() function as shown in Snippet 1 below.

Snippet 1 – An example showing how to set an individual pin to a selected Slew Rate in the Harmony App_Initialize() function, this function is located in the file App.c.

What Does Each Setting Do?

The PIC32MZ/EF data sheet is a little vague on the exact nature of the various Slew Rate setting, so I made some measurements on one of my proto boards.

First thing is to compare a normal pin with a Slew Rate controllable pin. Note that the default Pin Slew Rate is set to Fastest for the Slew Rate controllable pins (See the note on the bottom of figure 1).

Using a standard CMOS loading test circuit [1], I measured a normal pin and a Slew Rate controllable pin, a plot is shown in figure 2 and 3. The various Slew Rate settings of a fast pin are shown in figure 4. Table 1 summarizes all the results.

Figure 2 – Rise time comparison of a normal pin and a Slew Rate controllable pin at their fastest settings.


Figure 3 – Fall time comparison of a normal pin and a Slew Rate controllable pin at their default settings.

Figure 4 – Effects of the various Slew Rate Settings applied to a test pin.


Table 1 – Tabulated Slew Rates of the various Pin types and Slew rate settings.

Wrapping It Up

The Overshoot seen in the figures at the fastest pin Slew Rate setting is undoubtedly a result of my test fixture being less than optimal. Normally the Oscilloscope probe would be located very close to the devices driving pin to minimize the parasitic inductance of the trace. In my ‘Quick-N-Dirty’ test jig, I used a MINI32MZ PIC-On-A-Stick module, this interfaced to one of my own breakout boards. The length of the trace from the PIC32 pin to my Oscilloscope probe is approaching 1 inch and even worse for a fast pules is the 0.1” header strip that the pulse has to traverse from the PIC32MZ to my breakout board and test load. These header strips add quite a lot of inductance to the overall path.

This, through leads to a great demonstration of why Slew Rate control adjustments are so useful in digital applications. My less than perfect test fixture is a ‘real’ PCB and I have seen much worse designs than what I had, still look at the amplitude of that ring I was able to make in just an inch!

In the fastest setting shown in figure 4 that little, high frequency ‘ring’ can cause all sorts of EMI emissions issues. In the worst case the ringing can be so bad as show up on the leading edge of the pulse, or be so high in amplitude to possibly cause double clocking.  This is why the PIC32 devices that have an external DDR SDRAM interface have Slew Rate controls on all the pins associated with those ports. It is much easier to set the output pin Slew Rate to control EMI and ringing than to add, then adjust, a bunch of series resistors in each output line on a PCB to control the rise time and overshoot problems.

[1] The standard CMOS loading circuit is 15pF in parallel with 1 Megaohm to ground. The measured rise time of the Oscilloscope used was 1.2 nSec. The Oscilloscope rise time was not corrected for in the rise time plots. It is corrected as noted in the tabular results.

Article By: Steve Hageman

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.

Note: This Blog does not use cookies (other than the edible ones).

Wednesday, September 12, 2018

How I spent my Summer Vacation

I remember in the 5th Grade, at the beginning of the school year we were tasked with writing 500 or some such words on that very subject. I didn't like the assignment, perhaps because I didn't really do anything that I thought was noteworthy. I do remember listening to many faraway lands on Knight Kit and Magnavox Shortwave radios, plus looking at the Stars and Planets with my trusty Tasco Telescope.

But this year was way more fun than that!

I built this small footprint Data Acquisition System.

  • 32 Bit MCU @ 250 MHz with Floating Point Unit
  • 5 x 16 Bit ADC's
  • 3 x 16 Bit DAC's
  • 3 x DDS Chips
  • +/- 1 Amp Precision Current Source 
  • 6 Analog IO Pins
  • 8 Digital IO Pins
  • Thermometer + Barometer
  • Real Time Clock
  • Onboard EEPROM
  • MicroSD Card for Data Logging
  • 6-30 VDC Input Power @ 1 Watt
  • Reduced 2 x 4 Inch Footprint

Article By: Steve Hageman

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.

Note: This Blog does not use cookies (other than the edible ones).

Sunday, June 10, 2018

Improving Code Quality with Microchips MPALB-X IDE and XC32 Compiler

Authors Michael Barr [1], Les Hatton [2], Robert Martin [3] and a host of others basically plead with programmers to use more formal code analysis techniques, such as: “Static Analysis” during the design phase of all embedded projects.

Addition of these steps is not time consuming or even expensive in most cases, the payback is usually justified by preventing even a single problem in shipped code.

Recently I have moved all my Microchip PIC development to their MPLAB-X and XC32 compiler. This saved a nominal sum per year in compiler updates, because this Microchip tool chain is free and it makes my clients also happy to be able to get the development tool chain for really the cost of a very simple programmer / debugger.

The XC32 compiler is a version of the venerable GNU GCC compiler geared especially for the MIPS based PIC32 product line. This tool chain also includes their rather all encompassing ‘Harmony’ software framework that handles all the driver and peripheral initialization and provides a consistent Hardware Abstraction Layer when programming any of the PIC32 devices.

Note: This article applies to MPALB-X version 4.15 and greater and XC32 Version 2.05 and later, the current versions as of June 2018.

Improved Static Analysis for Free:

The first step to better code is to turn all the GCC warnings, this is accomplished by supplying the ‘-Wall’ switch to the compiler options window [4], as shown below.

   Add All Warnings to the XC32 compiler options

‘Wall’ or ‘Warnings All’ will enable all the possible compiler warnings, but it doesn’t go out of its way to mark every library function as a problem. I find that it only adds three or four warnings from a previously cleanly compiled project. The errors it finds are mostly relevant and easy to deal with. You will find unused variables, bad definitions and improperly initialized variables.

I’m not sure what level of warnings are enabled as default in XC32, but you should definitely not compile without ‘all warnings’ turned on. It’s absolutely free, so use it.

GCC supplies a push/pop mechanism to disable specific warnings at various places in the code.

For example the function,

void foo(void)
    int32_t unused = 0;

will produce a warning: “warning: unused variable 'unused' [-Wunused-variable]”

This warning (or other warnings) can be disabled at the ‘function scope’ like this,

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
void foo(void)
    int32_t unused = 0;
#pragma GCC diagnostic pop

The above works to disable this specific warning at the ‘function level’

Trying to disable this warning inside a function will not always work and may be ignored.

void foo(void)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-variable"

    int32_t unused = 0;

    #pragma GCC diagnostic pop

The above does NOT work to disable this specific warning inside a function.

If you think about the above example, this makes sense. How could the compiler know that the variable is unused until it hits the final closing brace ‘}’ ? So by extension this example does work,

void foo(void)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-variable"

    int32_t unused = 0;
#pragma GCC diagnostic pop

The above does work to disable a specific warning inside a function, but not for a single variable. This will disable the ‘unused variable’ warnings for all variables between the ‘ignored’ and the ‘pop’.

For more information in the GCC diagnostic pragmas see Reference 5. Also note that Microchip makes no mention of this functionality in their documentation so it should be considered: ‘Undocumented’.

Improved Static Analysis for very little cost:

The next level of static analysis is to use a ‘Lint’ program [6]. First developed for UNIX in the mid 1970’s, but not widely used with regularity much of anywhere else because of the lack of suitable executables.

In the mid 1980’s when I first started writing C code, there was a program advertised called PC-Lint [7] and it sold for probably $300 then. That was a lot of money. Today the same program, but updated for 30+ years sells for $400. That’s not so much money when you consider the cost of giving one bug to your customers. In fact now, it’s downright cheap and will pay for itself if it finds a single problem! There are a few open source version of something like Lint, but nothing that compares to a reasonably priced, finished commercial product like PC-Lint.

MPLAB-X contains an optional plug-in to enable PC-Lint functionality inside the MPLAB-X environment. It is fairly easy to get going, but it took me probably 3 hours to get it working inside MPLAB-X the first time. I might be able to save you some time with the following instructions.

Installing the MPALB-X Plug-In:

Start MPLAB-X and install the PC-Lint Plug-In
    Tools - > Plugins - > Available Plugins
    Select: “PC-Lint Plugin”, and finally select: “Install”.

Installing PC-Lint:

With the advent of User Account Controls (UAC) in Windows 7 and later it is much harder to get software to play properly, because many programs need elevated privileges to have access to certain directories, etc.

The default install location for PC-Lint is in “C:\Program Files(x86)\PC-Lint”, this is a problematic directory when running with UAC enabled, and I wasted an hour trying to get configuration files properly written until I gave up and re-installed PC-Lint off the root directory here: “C:\PL-Lint\”, then no problems at all. Just do this and save yourself time!

Even with the very latest PC-Lint version you won’t get the latest XC32 compiler initialization files or ‘.Int’ files. You will need to go to the Gimple website ( ) and get this file,


Save the file in this directory,


Don’t run the PC-Lint supplied configuration file builder (CONFIG.exe) it won’t know about the latest co-xc32.Int file anyway and it will just need to be manually modified anyway.

Instead just make a file named: ‘XC32-std.Int’ in the directory: “C:\PC-Lint\”

Place these lines in the file,

//  Microchip MPLAB XC32 C, -si4 -sp4,
//  Custom lint options file for XC2 V2.x


C:\PC-Lint\options.lnt  -si4 -sp4
-i"C:\Program Files (x86)\Microchip\xc32\v2.05\pic32mx\include\lega-c"

You may need to modify the exact path and name depending on your circumstances. Here you can see that I am using Harmony Version 2.05 and I use the ‘Lega-c” library and include files.

If you are in doubt as to the exact path to use, just open up your projects ‘stdio.h’ or some other well known system header file and see what the path is by hovering on the file name tab in the GUI, then use that.

Make sure that there is a file called: “Options.Int” in this directory also: “C:\PC-Lint\”. Right now this file can just have a single empty line in it.

Now setup the PC-Lint interface in MPLAB-X. Select: Tools - > Options → Embedded and then select the PCLint tab at the right hand side as shown below. Then click: OK.

Set these options as above on the PC-Lint configuration screen.

Right click on your main projects name, then select: “Generate PCLint Dependency Files” You should see this in the PC-Lint output window.

If the directory is not writable these files will not be written correctly and you will waste another hour trying to figure out why. To be safe, re-generate these files every time you switch and start working on another XC32 project. Just think of it as “Getting Latest” from your source control.

Let’s go Linting:

This step will seem daunting and you will wonder why you did all this in the first place. Why? Because your first ‘Lint’ will produce about 20 pages of warnings.

Let’s try it – Select a small ‘c’ file from your project, like “App.c” for example, right click on its name and select: “Lint this file”.

Have no fear – 99% of those warnings will be the same complaint about some name probem or some header file, etc. These warnings that can be easily suppressed.

Just open the file: “C:\PC-Lint\options.Int” file and start adding errors to suppress the spurious warnings. In 30 minutes, by checking half a dozen of my code modules, I was easily able to get rid of all the ‘chaff’ and get down to those few simple things that should be checked or fixed.

Here is the “Options.Int” file that I ended up with,

// Please note -- this is a representative set of error suppression
//                options.  Please adjust to suit your own policies
//                See  manual (chapter LIVING WITH LINT)
//                for further details.

-w3     // Overall warning level (3=default) Settings 2 and 3 are OK.

-e586   // function 'printf' is deprecated.
-e793   // suppress message about extern identifiers being more than 31 chars long
-e9045  // non-hidden definition of type 'struct
-e9058  // unused outside of typedefs
-e970   // Use of modifier or type '_Bool' outside of a typedef
-e9071  // defined macro '_APP_H' is reserved to the compiler
-e537   // repeated include
-e950   // Note 950: Non-ANSI reserved word or construct: like: '_nop()'

-passes(2) // Make 2 passes on the code

Now that wasn’t so bad after-all – Now I can just Lint my files one by one and see the warnings / errors that really show up. I had a number of iffy initialized variables, some missing ‘defaults’ in Switch statements and a few of the dreaded,


instead of,



Most importantly I found a few real problems (like copy and paste errors) that would have prevented proper program operation and would have cost me debugging time to fix.

Gimpel offers this sage advice for first time “Linters”,

“If you've never linted your code before, you may want to modify the warning level initially.  Try running with -w1 to report only errors.  After you've fixed the resulting errors (or suppressed those that you don't want reported), run with -w2, and so forth. “

Further Reading:
Hopefully this tutorial will get you at least 80% of the way to where you want to be, in a very short period of time. For more information, the Gimpel website has a FAQ list that provides helpful hints and the PC-Lint manual is full of further in depth information.

You may also want to consider "Breadboarding" your C code on your PC before placing it on your target Embedded System, these two posts show how I accomplish this,

* Breadboarding Embedded Code
* Breadboarding Embedded Code - Part II


[1] Micheal Barr The Barr group. Prolific writer about best ‘C’ practices,

[2] Les Hatton, Author of: “Safer C”, McGraw-Hill, 1994

[3] Robert Martin is a frequent speaker at programming conferences. Many of his talks can be viewed on Youtube.

[4] There are a number of other compiler options available, I find that this one is the best for catching stupid mistakes without marking every single library function as non-compliant. For other possible options see the XC32 Compiler Users Guide – Yes there is actually a manual and as near as I can tell Microchip keeps it up to date.

[5] GCC Diagnostic Pragmas manual page,

[6] LINT

[7] Gimple Software PC-Lint, Version 9.00L is the current version.

PC-Lint has been called the longest continuously available software product in the history of mankind, since it has been available from the 1980’s until now.

Article By: Steve Hageman

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.

Note: This Blog does not use cookies (other than the edible ones).