Based on a PSoC5LP SoC
Lock-in amplifiers are sophisticated, somewhat specialized pieces of scientific instrumentation. The Infineon PSoC5LP System-on-a-Chip (SoC) contains most of the necessary circuit functions to implement a basic lock-in amplifier, and is supported by an excellent toolchain called PSoC Creator 4.4.
I encountered many different scientific measuring devices while working in the Chemistry Department of Dalhousie University. One such instrument was a lock-in amplifier. I didn’t encounter them too often, but it was an interesting device. The two companies that made them at the time were Princeton Applied Research and Stanford Research Systems. The units from those two firms were sophisticated instruments and were quite expensive.
Lock-in amplifiers are primarily designed to measure low-level signals in the presence of noise/interference that is generally much higher in amplitude than the signals themselves. At their best, lock-in amplifiers can measure signals that are many orders of magnitude lower in level than the electrical noise that is present. This measurement dilemma occurs frequently in scientific studies, but is also common in communications links over large distances or in hostile environments.
As with life in general, the expression “you don’t get something for nothing” applies here as well. If the signal you are trying to measure has some amount of randomness and is not correlated with the noise signal present (which is often random too), then it is difficult or impossible to pick out the desired signal and eliminate the noise. Of course, the higher the magnitude and randomness of the noise, in relation to the signal, the more difficult this task becomes.
The key to the lock-in amplifier’s effectiveness lies in the nature of the signal being measured itself. If that signal is an AC signal, and there exists a reference signal which has the same frequency and a fixed phase relationship to that signal, then the lock-in amplifier can pull that signal “out of the noise” quite effectively. But, where does that reference signal come from? That depends upon the application. In the communications field, providing a reference signal is often difficult and may depend upon there being some repetitive feature in the signal itself that can be extracted. I don’t have experience in that field, so I’ll instead explain some ways in which lock-in amplifiers are used in scientific measurements.
Let’s consider the case of spectroscopy, where there may be especially low levels of light that need to be measured. For such an application, a device such as a photomultiplier tube (PMT) may be employed—these detectors are complex and expensive, but can detect low levels of light. However, there are often sources of stray light that leak into the apparatus, and all PMTs exhibit the “dark current” effect whereby they produce a random, virtually DC signal in the complete absence of any light impinging upon their detector surface.
Let’s assume that we can place a “chopper wheel” between the PMT device and the source of light that we’re interested in measuring. A chopper wheel is a metal disk, with slots cut into it, that is rotated at a fixed speed by a motor. As the chopper wheel rotates, it will either let the light that we are measuring pass through (when the slot is positioned properly), or completely block it. Therefore, 50% of the time the PMT is seeing the light signal we are interested in, and the other 50% of the time that light will be completely blocked. However, the PMT will send out the same dark current regardless of the position of the chopper wheel, and we can assume that any stray light getting into the apparatus will be impinging upon the PMT constantly.
The chopper wheel provides a square wave output signal which is high when the disk’s slot allows light to pass through and low when the light is blocked. This is our reference signal, and it’s equal in frequency to the light signal that the PMT sees (at least in terms of when the light is present, versus when it is absent). This reference signal is also locked in phase with the light signal that the PMT sees.
In the lock-in amplifier, we use the reference signal from the chopper wheel for two purposes:
1. We incorporate a “tracking” band-pass filter. That is, it will only allow signals from the PMT to pass that are very close in frequency to that of the chopper’s reference signal. The reference signal is used to adjust the center frequency of the band-pass filter—in other words, to allow it to track the PMT’s signal frequency. We can then amplify the PMT’s signal, after having passed through this tracking filter, by a large amount (if necessary) without overloading/saturating the amplifier with the noise and interference that were rejected by the filter.
2. The amplified signal can then be sent to a synchronous detector that has, as its switching signal, the chopper’s reference signal. This detected signal now represents the amplitude of the light that we’re trying to measure using the PMT. It is no longer an AC signal at the chopper wheel rate. Fluctuations in this signal can easily be low-pass filtered to achieve a more stable measurement.
Another example is measuring small forces using a strain gauge. Strain gauges are generally configured in a Wheatstone bridge and bonded to a metal carrier—then referred to as a “load cell.” They have to be powered by what’s called an excitation power source, and the two outputs of the Wheatstone bridge must be fed into a differential amplifier. This differential signal may be only microvolts in amplitude and will ride on a common-mode voltage equal to half the excitation voltage. The wires conducting this differential signal to the measuring device may have to be long, depending on the application. They may be exposed to lots of electrical noise along the way. While they are a differential signal, which by nature tends to allow the induced noise to be canceled out even if the wiring is shielded, the remaining noise may still overwhelm the microvolt-level strain gauge signals.
Now, instead of using a common 10V DC excitation supply for the strain gauge, let’s use a 10V AC signal for excitation. Let’s further assume that we set the frequency of this excitation source as 1kHz. Figure 1 represents the output of a typical amplifier versus frequency. At DC and low frequencies, all op-amps generate what is known as “1/f” noise (or Johnson noise after its discoverer), which is inversely proportional to the frequency. Since the strain gauge is measuring a mechanical strain, it is likely low in frequency (vibrations would be an exception). Therefore, if we power the strain gauge (load cell) with a DC excitation voltage, we will be attempting to measure voltages close to DC or low in frequency. That can easily be swamped out by 1/f noise. As we go up in frequency, we’ll likely encounter high amplitude interference signals from the 60Hz (or 50Hz in EU) power that could be used to power the motors associated with the machinery to which the load cell is attached. However, if we use a 1kHz excitation power source, we are well clear of the power line interference, and this higher frequency will also drastically decrease the contribution of the 1/f noise to the measurement.
The lock-in amplifiers made by Princeton Applied Research and Stanford Research Systems are sophisticated devices that can be used in cutting-edge research. In this article, I’m interested in describing a lower-cost version of a lock-in amplifier that’s useful for less demanding applications or teaching purposes. While it has the same basic functionality as the instruments mentioned above, it consists of only two analog ICs and an Infineon PSoC5LP System-on-a-Chip (SoC). It can be built for less than $100 if you don’t get too fancy with the case.
BASIC IMPLEMENTATION USING A PSOC5LP
How is a lock-in amplifier implemented using Infineon’s PSoC5LP SoC? Figure 2 shows the PSoC5LP mounted on Infineon’s CY8CKIt-059 development module. The break-away section at the left is the programmer/debugger module. Please refer to Figure 3 for a block diagram of my design. All of the circuit elements presented in pale blue are contained within the PSoC5LP. As explained earlier, a differential input is often needed for measuring sensors that are assembled in a Wheatstone bridge configuration. Real-world signals will often contain noise which may consist of spikes of a relatively high voltage. For differential signals, like those obtained from a Wheatstone bridge, noise and spikes and so forth are generally common-mode signals—that is, they’re identical or at least highly similar on both of the differential inputs. Therefore, they cancel themselves out, to a large extent, at the output of a differential amplifier. But, that amplifier must be able to handle the common-mode voltage.
I chose a Texas Instruments INA121 Instrumentation Amplifier for the “front end” of my lock-in amplifier. This device has a high input impedance of 1012Ω and a high common-mode rejection ratio of 106dB. Among instrumentation amplifiers, it also stands out for its low input noise figure of 20nV per √Hz, which is important in a lock-in amplifier since it is dealing with AC signals. I supply it with ±12V to allow it to handle higher common-mode signals, and the INA121 has internal input protection up to ±40V.
I chose a Maxim (now Analog Devices) LTC1059 Switched Capacitor Universal Filter block. With this device, it’s easy to implement a tracking band-pass filter by supplying it with a clock signal that is 100x the band-pass center frequency. The sine wave excitation signal is provided by the PSoC5LP’s WaveDAC8 component, which is configured with a 200-sample waveform array. Therefore, it’s clocked at 200x the desired excitation frequency. This clock signal is then divided by two to provide the 100x clock needed by the LTC1059. The LTC1059 is powered by ±6.8V power supplies, regulated down from the ±12V power rails using Zener diodes. This is close to the LTC1059’s maximum supply rating of ±8V, and provides for the largest possible signal-handling capability—especially for larger out-of-bandwidth signals present at its input. The LTC1059 feeds the PSoC5LP’s Delta-Sigma ADC through a capacitor that shifts its ground-based, bipolar output signal to one that is referenced to the 2.048V virtual ground used by the various PSoC5LP components in the design. The LTC1059 provides a second-order band-pass filter, but the similar LTC1060 could be used to provide a fourth-order band-pass filter. The small protoboard that I used didn’t have enough room left to mount the larger 20-pin package of the LTC1060.
The band-pass filtered signal then goes to the PSoC5LP’s Delta-Sigma ADC. The PSoC5LP’s Delta-Sigma ADC contains a feature that I haven’t seen in any ADC found in other microcontrollers (MCUs): a modulator input. This input will either measure the incoming signal directly, or invert it—depending on the logic level applied to the modulator input. I would personally call this a de-modulator input, because I use it to synchronously detect the ADC’s incoming AC signal, which is the heart of the lock-in amplifier circuit. In this design, the excitation signal is generated by the WaveDAC8 component. The WaveDAC8 is configured to have a sample table that is 200 samples long. At the end of the waveform, its wc1 output signal goes high. The combination of Counter1, Counter2, the excitation frequency clock, and the wc1 synchronizing signal provide a 50% duty cycle signal at the same frequency as the excitation output signal. This signal feeds the Delta-Sigma ADC’s Modulator input and results in synchronous detection. Since there may be a phase shift between the excitation signal and the output signal from the sensor being measured, the user can adjust the compare count of the Counter1 component to vary the phase of the modulator signal. Counter2 has a fixed setting of 100 (half of the 200-sample array used by WaveDAC8), so it always produces a square wave signal to the modulator input.
The ADC output signal is a full-wave rectified version of the incoming AC signal, so it varies between zero and the peak value of the incoming AC signal. I operate the Delta-Sigma ADC in the 16-bit mode at a fixed sample rate of 15,000 samples/second. I allow for the generation of excitation signals in the 50-2,000Hz range. Therefore, at the highest excitation frequency of 2,000 Hz, the ADC would only collect 7.5 samples per cycle. Thus, in software I average 20 cycles’ worth of readings, for higher resolution.
The ADC output, averaged over an integral number of excitation frequency cycles, is then fed to a software-based IIR low-pass filter. See Circuit Cellar’s article materials page for a link to Infineon’s application note which describes this routine . Since this is a digital filter operating on a sampled signal, its time constant will vary in proportion to the sampling frequency (which, in this case, is proportional to the excitation frequency). There is a rotary encoder that allows the user to set the low-pass filter time constant from basically zero up to x seconds (where x is dependent upon the excitation frequency).
I have mentioned that the AC excitation signal is generated by the WaveDAC8 component within the PSoC5LP. I use the “Buffered” configuration of this component which adds a buffer to the DAC output, giving it more drive capability. The WaveDAC8 component is also configured to reference its sine wave output to a virtual ground, which in this case is 2.048V. The DAC output signal is 4V peak-peak and is fed to a 10k potentiometer, giving an excitation signal range from 0V to 4V peak-to-peak. This variable amplitude signal is fed to the PSoC5LP’s Op-amp2, configured as a voltage follower. The PSoC5LP’s op-amps, when configured in the High-Power mode, can source/sink up to 25mA, but this amount of current would be somewhat less, if you wanted to use the full 4V output swing, due to the fact that the PSoC5LP is powered by a 5V supply.
For a more detailed look at the circuitry, let’s first look at Figure 4, which contains most of the circuitry external to the PSoC5LP itself. 5V power for the project is provided by a Recom RAC05-05SK/C14 (Figure 5). This is a rather unique little power source contained within an industry-standard IEC320-C14 power socket. For many projects requiring small amounts of power, I generally use a wall-socket adapter. However, for shielding purposes in this project, it’s useful to be able to house the project in a metal enclosure that’s connected to the ground pin of the AC mains socket. The Recom power module provides this capability and is easier to mount than a normal PCB-based power supply.
The RAC05’s 5V output has a 1A current rating which is more than adequate. It feeds the CY8CKIT-059 development module containing the PSoC5LP via the VDD and GND pins. The PSoC5LP chip runs on 5V, which is unusual for an Arm MCU. Therefore, there is no LDO regulator on the CY8CKIT-059 module. All of the PSoC5LP’s digital ports operate at voltage levels set by the voltage level present at the VDDIO pin, which is tied to VDD on the CY8CKIT-059 module itself.
To provide the ±12V for the INA121, I used a tiny PEM1-S5-D12-S DC-DC converter module. These rails were dropped down to ±6.8V for the LTC1059 using 470Ω resistors and 6.8V Zener diodes.
The INA121’s gain is set by the value of R6, as follows:
For this project, I set the INA121’s gain at 1 by omitting R6.
If the +,- inputs of the INA121 are at equal DC levels, the INA121 output would be at ground level. Therefore, the INA121 could be DC-coupled to the LTC1059 Switched Capacitor Universal Filter block, which uses a bipolar power supply. However, if there was any significant difference in the DC input levels, it is better to capacitively couple these two circuits, which I did with C3,C4. I used two 2.2µF capacitors in parallel as they were the largest values I had in stock in quantity, and were physically quite small.
If you look closely, you will note that I have labeled the project’s input terminals opposite from the way that they are labeled on the INA121 itself. The reason for this is that the LTC1059 produces an inverted output, so connecting the INA121’s inputs in this manner will compensate for the LTC1059’s 180-degree inversion.
The LTC1059 provides band-pass, low-pass, high-pass, or notch filters depending upon how it is wired up. I used the band-pass configuration. The gain is set by the ratio of R4/R5 and the Q is set by the ratio of R4/R3. I picked a gain of 1 and a Q factor of 6.9 using resistor values I had on hand. For “real-life” applications, higher gains might be necessary if the sensor being measured had low output levels (a strain gauge for example). However, the PSoC5LP’s ADC has full-scale configurations down to 64mV and incorporates an input buffer amplifier with gains from 1 to 8. Here, the main purpose of the LTC1059 is its band-pass filtering, not its inherent gain.
The LTC1059’s band-pass output is capacitively coupled to the PSoC5LP’s Delta-Sigma ADC. This is necessary to level-shift the LTC1059’s ground-referenced bipolar output signal to the 2.048V virtual ground used by the PSoC5LP’s ADC and other analog components. Not shown here are two diodes used to limit the signal to the 0-5V level needed by the PSoC5LP’s ADC input. These diodes can be found in Figure 6.
Figure 6 is the “topDesign.cysh” tab in the PSoC Creator 4.4 development software. It shows how I configured the PSoC5LP. The editor which produces this representation of the PSoC5LP’s internal configuration is also capable of drawing a limited variety of off-chip components, so I placed a few of the external components in this figure for purposes of clarity.
The excitation signal generator, made up of a WaveDAC8 and Opamp_2 buffer, is shown at the upper right. The WaveDAC8 is capable of producing two distinct waveforms which can be dynamically switched using the “ws” input terminal. In this case, I am only using one waveform, so the ws input must be set to “0.”
The WaveDAC8 is clocked by Clock_2, which is a generic PSoC5LP clock component that uses one of several “system” clocks, followed by a programmable divider. While I set it to 200kHz (providing an excitation frequency of 1,000Hz), its value is modified in the software when an excitation frequency switch is pressed. Whenever a frequency change is requested, Clock_3 also has its divider ratio changed in order to provide a clock to the LTC1059 which is 100x the excitation frequency. This allows the band-pass filter to track the excitation frequency.
The WaveDAC8’s sine wave output passes through R2, a 10k 10-turn amplitude potentiometer, before being routed back into the PSoC5LP where it is buffered by Opamp_2. Since this is a variable amplitude sine wave referenced to 2.048V, it is passed through C2 to return it to a ground-referenced signal.
Both the sensor being measured and the capacitively-coupled INA121 instrumentation amplifier/LTC1059 band-pass filter will introduce some phase shift between the excitation signal and the signal being measured. This phase shift must be accounted for if the measured signal amplitude is to be correct. A corresponding phase shift can be introduced between the excitation signal generator and the synchronous detector function performed by the delta-sigma ADC using its modulation input “mi.” This phase shifting is performed by Counter1, Counter2 and an SR flip-flop component in the PSoC5LP.
Clock_2, which clocks the WaveDAC8, is also fed into the “count” input of Counter_1. Due to the design of Counter_1, this count input must be synchronized to an internal system clock, so I have connected Counter_1’s clock input to a 12MHz internal clock. At the end of a WaveDAC8 cycle, its “wc1” output goes high for two clock cycles. This synchronizes the start of Counter_1’s counting to the beginning of the next WaveDAC8 sine wave signal. Counter_1 has a compare function; the value that is set for this compare value depends upon the position of the phase rotary encoder. Counter_1’s compare output will go high after some user-selected counts, triggered by the start of the WaveDAC8’s sine wave. This will set the SR flip-flop and send a high logic value to the ADC’s modulation input (“mi”). It will also reset Counter_2, which is similarly being clocked by the same clock as the WaveDAC8 and Counter_1. Counter_2 has a fixed compare value of 99 (which equals 100 counts as it is zero-based). This is exactly half the number of clocks needed by WaveDAC8 to generate a full sine wave, since its wave table consists of 200 samples.
Therefore, 100 clock cycles after the SR flip-flop was set, it will be reset by Counter_2’s compare output. The result of all of this is that the ADC’s modulator input will receive a 50% duty cycle signal which is synchronized to the excitation signal, but lags in phase by some user-selected amount. In practice, one would turn the phase encoder slowly while watching the signal output voltage reading on the LCD display until it reaches a maximum value. The phase values that can be dialed in this way have an increment of 360 degrees/200 counts, or 1.8 degrees.
I didn’t try it, but I think one could provide a smaller phase increment by:
- providing another clock (Clock_3) that is higher in frequency than Clock_2;
- changing Counter_1 and Counter_2 to 16-bit counters;
- increasing the compare values used by both counters by a factor (to match 1).
While this should work in theory, all of these counters use the 24MHz system clock followed by an integer divider. All the excitation frequencies that I allow for in this project—50Hz, 60Hz, 100Hz, 200Hz, 500Hz, 1,000Hz, 1,500Hz, and 2,000Hz—can have Clock_1 and Clock_2 configured to provide exact frequencies. However, Clock_3, at some multiple of Clock_2, might not be able to be configured with the exact frequency needed at the higher excitation frequency settings.
There are a few components at the lower right of Figure 6 which need an explanation. I have made provisions for substituting the source of the ADC’s “mi” signal from the default WaveDAC8 (phase-adjusted) sync signal, to an external source. This would be used if the signal being measured by the lock-in amplifier was not derived from an excitation signal provided by this project. In this case, another sync signal would need to be provided from an external source. As mentioned earlier, when measuring low light level signals in a scientific apparatus, a chopper wheel may be used to modulate the light before it hits the photodetector. This chopper wheel will provide a square wave signal which is synchronized to the slots in the chopper wheel. Assuming it is a 5V logic level signal, this could be provided to the PSoC5LP’s P15_3 pin, the “Ext. Sync In” pin. Such external synchronization would require Control_Reg_1 to be set to “1” to switch the multiplexer (above it on the diagram) to the correct input.
The analog circuits in the PSoC5LP operate with a virtual ground of 2.048V. This is provided by the internal 1.024V reference amplified by two using Opamp_0. Both of the ADC’s differential inputs are referenced to this virtual ground using 1MΩ resistors R_4 and R_5. (Note that these are not the same parts as R4,R5 in Figure 4.)
The phase and filter time constant rotary encoders are handled by the QuadDec_1 and QuadDec_2 PsoC components. These are bidirectional counters which interface directly with the quadrature signals provided by the encoders. To read an encoder, you simply have to call the QuadDec_1_GetCounter() API routine. You can also set the counter to a desired value using the SetCounter() API. Unlike the rotary encoder routines on most other MCUs, these APIs don’t use interrupts and don’t affect the timing of your program code in any way. The QuadDec_x component provides debouncing of the encoder switches, and can provide one, two, or four counts per detent position.
The five user switches are polled using the Status_Register component. All five input pins are configured with internal resistive pull-ups.
Figure 7 shows the LCD readout of the lock-in amplifier in operation. The fourth line is a bar-graph representation of the measured voltage—normalized to the 2.048V full-scale value shown on line 2.
MODIFICATIONS TO THE CY8CKIT-059 BOARD
The CY8CKIT-059 prototyping board contains a number of 1.0µF capacitors which are connected to specific GPIO pins. These are used as reference bypass capacitors for both the Delta-Sigma ADC and the two SAR ADCs. Likely because of internal routing matrix limitations, some of these capacitors are connected to the same pins that are used for the four op-amps contained in the PSoC5LP. Table 1 is a list of the four capacitors used for the ADCs, along with the op-amp pins to which they are also connected.
The C9,C12 capacitors are used for the two SAR ADCs—one for each. However, in the case of C7,C13, when you configure the only Delta-Sigma ADC, there are three options for reference bypassing: no reference bypassing, C7 on P3_2, or C13 on P0_3.
If you need to make use of several of the four internal op-amps, you can see from the above chart that op-amps 0,2 and 3 share input pins with these four capacitors. Therefore, unless you’re able to tolerate a 1.0µF capacitor from that op-amp’s input to ground, you will either have to remove the capacitor, or pick a combination of op-amps that don’t contain capacitors. As mentioned above, if you are only using the Delta-Sigma ADC, you can pick which of C7 (P3_2) or C13 (P0_3) you configure the ADC to use, and remove the other one. I don’t use the SAR ADCs at all in this design. I removed C9 and C12, freeing up pins P0_4 and P0_2 for use by op-amp0 and op-amp2. I configured the Delta-Sigma ADC to use C7 on P3_2 for reference bypassing, so I also removed C13 on P0_3.
These are all 0603 surface mount capacitors, well-marked on the board, but close to the PSoC5LP. I just heated both ends alternately with a small soldering tip until the solder melted and the capacitor basically clung to the soldering tip for removal.
Apart from the above notes, there are a few other tricks that I’ve learned the hard way using the PSoC5LP’s op-amps. If you’re expecting to need high current capability on any of these op-amps, it’s important that the output of the op-amp is connected directly to its dedicated IO pin rather than being routed through the PSoC5LP’s internal analog multiplexer arrays. These multiplexers and their signal paths have too high a resistance to be able to supply anywhere near 25mA. You must also configure the op-amp for high-power in the PsoC Creator’s configuration menu.
If you plan on using an op-amp as a unity gain voltage-follower, it’s tempting to configure the op-amp in the follower mode, using PSoC Creator’s configuration menu for that component. That means you don’t have to place a physical wire between the op-amp’s output pin and its inverting input pin. You thereby free up an IO pin.
But, if you need any significant amount of output drive capacity, this doesn’t work. In reality, the op-amps are not directly connected to these dedicated pins, but rather through an electronic switch. This switch gets activated only when you have enabled the op-amp using the Opamp_x_start() command (where x indicates the specific op-amp). The switch has some resistance. The voltage follower doesn’t work properly because the effective op-amp configuration looks like Figure 8. Any voltage drop due to the output switch resistance is not sent back as negative feedback to the inverting input pin, so the output voltage drops in proportion to the current draw. In earlier projects, I had given up on using these op-amps in places where I needed more than a few mA, as the output voltage dropped significantly as the current draw increased. Once I switched to using the op-amp in the amplifier mode and ran an external wire between the output and inverting input pin, everything worked fine. Note that the op-amp’s output enable switch resistance is still present, so you wouldn’t be able to get rail-to-rail output under higher loads (that is, 10mA or more).
On the CY8CKIT-059, VDDIO is connected to VDD via a 0Ω resistor R11. Since the only digital peripheral I am using is a 40×4 character LCD, which itself runs on 5V, it was not necessary to remove R11 and supply the VDDIO pin with a regulated 3.3V. However, I have done so on other PSoC5LP projects which contained peripherals running on 3.3V logic.
CHANGES TO THE STANDARD BUILD SETTINGS
Since I do most of my projects using various Arm MCUs which are supported by the Arduino IDE, I am not particularly knowledgeable when it comes to setting up a makefile or playing around with a lot of compiler/linker settings. Most of this is done for you and hidden in the Arduino IDE.
In a similar fashion, most of these details taken care of for you in the PSoC Creator IDE—once you choose which PsoC device you wish to use, Creator looks after most of the compiler/linker parameters. However, I’ve come across one exception to this: the use of the standard C sprintf function. This function accepts variables of different numeric types, converts them to the String format, and optionally concatenates them with some “label” string (such as “value =”). It’s needed for displaying numbers on the LCD screen or sending them out via UART or USBUART. With all other compilers that I have used, floating point variables are handled properly with sprintf. With PSoC Creator 4.4 software, only integer numbers are handled by default—floats are ignored and no compiler error is raised. This has been a feature (or bug) of Creator software for as long as I’ve used it. It’s not obvious what you must do to make sprintf work with floats, so here is the solution.
Referring to the Build Settings page shown in Figure 9, change “Use newlib-nano Float Formatting” from “False” to “True.” In “Additional Libraries” make sure there is an “m” shown. In the Build Settings page shown in Figure 10, place “-u _printf_float” in the command line section. Even doing this still won’t work until you click on the “System” icon in the Workspace Explorer window and increase the Heap Size from its default (0x80) to 0x1000. Obviously, the sprintf function requires a lot more heap space than the Creator software allocates by default, when you start a new project.
These changes would have to be made for all PSoC5LP projects you develop, assuming you need floating-point numbers printed out as strings to LCD or UART.
I find it quite a pleasure writing software for the PsoC5LP MCU using the PSoC Creator 4.4 software. Apart from the exception mentioned in the prior section, the Creator software takes care of all of the compiler/linker options when you select which Infineon PSoC device you have chosen. It provides a tab in the work area titled project_name.cydwr that shows the pin layout of the PsoC device, which is color-coded according to the type of pin (power, analog, digital, and so on), and which will contain descriptive pin names that you define as you allocate pins. This view also contains a matrix display on the right which allows you to dynamically change which physical pins are connected to the internal components and IO pins. This matrix also lets you know which pins have components that are more or less “hardwired” to that specific pin.
Once you choose a PsoC5LP component for your project and drag it to the work area (topDesign.cysch tab), you click on it to bring up a comprehensive configuration “wizard” which contains all of the parameters that are available to be set. In the early design stages, you can virtually drag the needed components to the work area, configure them in a default mode, and then “build” the project. The build process will then generate all of the necessary .c and .h files for the API for each component you’ve added to the work area. No need to add a list of #include statements at the top of your main.c file. Actually, for preliminary testing, the only program code you may have to write to test out your chosen components is to add statements like ADC_DelSig_1_start() to the main.c code. Most, but not all, components need to be initiated in this way. After adding these lines and re-building, you go to the Debug menu item and choose Program. Unlike other MCUs where you may have some difficulty in connecting to your target board or attached programmer, the KitProg programmer, which is attached to the CY8CKit-059 module, gets recognized by Windows when it is first plugged in. When you first program your target, you’ll see a screen pop-up (Figure 11) showing the KitProg programming module as well as the PsoC5LP (CY8C5888LT*-LP097) MCU on the CY8CKIT-059 module. Click Program and the process completes quickly.
The KitProg module also contains real-time debugging capability. You can set breakpoints and do all of the fancy debugging that is available on Arm MCUs using a CMSIS-DAP debugger. Ironically, I’ve done many complicated projects using Arm Teensy MCUs or ESP32/8266 MCUs where I could have used such debugging capabilities (which are not available in the Arduino IDE). However, I’ve never found it necessary to use the advanced debugging capability with the PsoC5LP—partially because the PSoC Creator-generated APIs are straightforward and well-documented, and my own code has not had to be too complex.
When a project is finished, there is an item in the File tab labeled “Create Workspace Bundle.” This produces a zip file with everything needed to recreate the project on another computer (except the PSoC Creator application itself). This bundle is provided on Circuit Cellar’s article materials webpage for this column. Figure 12 is a photo of the finished project.
 AN2099 Infineon Application note describing IIR filter implementation:
CY8CKit-059 PSoC5LP development board:
Analog Devices LTC1059 Universal Filter Block:
T.I. INA121 Instrumentation Amplifier:
Recom RAC05-05SK/C14 Power module in IEC320 case: https://www.digikey.ca/en/products/detail/recom-power/RAC05-05SK-C14/9695301?s=N4IgTCBcDaIEoEEDCAGArAWnQZQNIHokBGAFhAF0BfIA
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • MAY 2023 #394 – Get a PDF of the issueSponsor this Article