Jan Cumps, jc2048 and peteroakes are building an electronic load with what they call a Booster Pack control board to front end. I've found it really interesting to look at what is being done and decided I wanted to have a go at something similar without just replicating what they have done. I also wanted to have a go at playing with a DAC and ADC so it seemed like a good tie-in. More specifically, these are the questions I'm asking myself:
- Could this be a generic control board for any instrument? Jan's and Peter's has been designed alongside a Load/Power Supply but it's pretty generic and it strikes me that it ought to be possible to provide a software library for a board such that an application could be built on top of it, specifically for the purpose required. Jan has layered his software in a similar manner. A downstream instrument would be required of course, and that may have to reflect back to chosen components on the control board, but could the fundamental design be such that significant change would not be required? Making it modular should facilitate that.
- Could I create such a software library that could be used by applications built on top?
- Make it SCPI programmable - I've been intrigued by Jan's approach to testing automation and it seems worthwhile understanding this protocol.
- I want to make it independent of a PC for running - so wholly self-contained. Jan's and Peter's are connected to a PC for automation and for power when full isolation from the power components is required. If it will need connecting to a PC, I want to be able to do say without making board adjustments.
- Like Jan and Peter I also want to protect the attached MCU. I've previously burnt a £76 pound Arduino building my PSU because I slipped when probing and sent 15V into some mV analog inputs! Whilst it is still somewhat functional I've learned that lesson and don't want a repeat.
- How accurate can I make it? Rather than just having software compensation, can more be done in hardware (Jan has/is already investigating this as well.)
I had intended to just write a one-piece post showing what I'd built rather than a multi-post description but Jan has expressed an interest in collaborating, a chance I jumped at, so I'm starting now. The fact we're building different solutions for the same purpose should give us different insights, I hope.
So far, I've been working on a design and I'm ready to create a PCB for prototyping. I'm sure that I don't have a final design yet but I have been trying things out on a breadboard as I go along and realised, somewhat belatedly, that it's now cheaper to get prototype PCB boards made up than buy DIL adapters for the ICs; depending on size, it's even cheaper than buying prototyping board!
It is a long read so...
This is the start of a project for creating a modular instrument control board using DACs and ADCs. I'm trying to make it modular enough to be expandable, for example I'm considering adding a EEPROM module to hold calibration/compensation data. It's as much about the fun for me of investigating DACs and ADCs (and Op Amps as it happens) as a 'solution' to a 'problem' I have. In this post, I'm describing the approach to prototyping and component selection for the design I've created, and I am presenting my 'stake in the ground' design, broken down into its modules:
- Reference supply module
- Compensation module
- Real Time Clock module
- Fan module
- Board I/O module
- Off-Board Control module
At least in my imagination, I can see this as the front-end for a number of headless instruments, but that's much further down the road. In a separate post I describe my choice of DAC, ADC and Op Amp.
Here's what I've come up with after a number of trials with breadboards; iterations whilst choosing components; and finding, and resolving, problems. At this stage, it's just a reasonably well developed 'stake in the ground' and is likely to undergo changes following prototyping which I cover off later.
Kicad files can be downloaded from Github.
There is a larger image in the attached PDF.
The schematic is grouped by module. I used global labels as they are a bit clearer to see than net labels but serve the same purpose. Interactions between modules are via these global labels so I'm hoping that it's easy enough to follow. This block diagram should help:
This post became rather too long so I decide to offload this section to its own post Instrument Control Board - Component Selection. I describe the choices I made when deciding on the DAC, ADC and Op Amp to use.
In order to drive all components I need the following rails:
- +12V for the fan module and the DC/DC Isolator to power the Isolated side. This is provided by a high-efficiency 12V DC/DC regulator. In turn, this provides a base voltage for creating the other rails. I've provided a bypass diode for it.
- +5V for the majority of ICs on the board. I've actually chosen here a SMD version of a stalwart LM7805 as it has a low noise output; I do have a high-efficiency 5V DC/DC regulator (same model range as the 12V one) but it has up to 75mV ripple on the output. Again, I've provided a bypass diode for protection.
- -5V for the Op Amps to alleviate any issues with signals close to 0V. This is charge pump that inverts the +5V rail.
I also chose to insert a schottky diode to block any reverse voltage that may arise if things go catastrophically wrong with any attached instrument (I would expect that to have its own additional protection.) I can't place this on the 5V rail because of the voltage drop so those elements would valiantly lay down their lives! The DC/DC Isolator allows me to provide power across the isolation barrier from a single power source and mitigates the need for two power cables into any case, or for an attached MCU to be powered from an external source. The capacitors on the output have been chosen based on some measurements I made when it was on a breadboard so may change when I test on a PCB. In fact, any output noise doesn't seem to impact the operation of components on the isolated side.
The whole board is supplied from a +15V (minimum) supply - typically, a wall-wart or similar. The red dotted line indicates the isolation barrier which the DC/DC Isolator straddles.
The dotted red line is the isolation barrier and I term the left side, Side A, and the right side, Side B. I have two isolators to cover what I need and the I2C isolator is self-explanatory. The digital isolator uses a modulated RF carrier rather than light like an Opto Coupler. The channels are fixed direction but I only need one input direct from Side B of the board - an alarm signal from the RTCC. On Side A, the global labels connect direct to the Off-Board Control Module (essentially, direct to the MCU); Side B global labels connect direct to the relevant IC or module:
- LDAC_A|B: This is a control signal for the DAC that synchronises the output of channels (Load DAC). By pulling high, the Input Register for channels can be updated with a new output value without actually changing the the DAC Register value, which drives the output value; when it is pulled low the new values are transferred to the DAC Register and output simultaneously.
- LDAC_CMP_A|B: LDAC control signal for the DAC used in the Compensation Module.
- RESET_A|B: A reset signal for the DAC (not the Compensating DAC) that sets all the outputs to the power up value - zero in the case of this board.
- PWRSIG_A|B: A passthrough to the Board I/O Module of the current state of the power button - High is Power On; Low is Power Off.
- FAN_A|B: A signal to the Fan Module to turn the fan on (High) or off (Low).
- RTCC_MFP_A|B: A signal from the RTCC module indicating that an alarm has triggered - this is passed to the MCU.
At startup, the digital isolator will default to output LOW on both sides:
- LDACs: any DAC output change in this state will change immediately.
- RESET: the DAC will not power up correctly (it will require a positive action on behalf of the Software Library to resolve this.)
- PWRSIG: power is off.
- FAN: Fan is off
- RTCC_MFP: No alarm is triggered.
So, apart from RESET, this is fine. There's no way around this start up behaviour if I want the ability to control the device RESET as the LOW output from the digital isolator will override any pull up resistor.
Reference Supply Module
This module will provide a reference to any other IC that needs it. On the control board this is:
- The MCP4728 DAC used in the compensation module. This has its own internal 2.048V reference and each channel can either use that or Vdd (in this case, 4.096V) individually.
- The AD5696R DAC used for output (pre-compensation). This runs on its own internal 2.5V reference which has better specifications than the REF5040 so I will be using that internal reference. However, looking at the graphs in the datasheet, this DAC performs better with an input voltage around 4V than it does at 5V. As long as VDD has a minimum voltage of Vref + 1.5 (4V) then the internal reference can be gained up by x2.
The additional components are used for noise reduction and to trim the output and are as specified in the datasheet. The 1uF capacitor works with internal resistors to create a low-pass filter with a cut off frequency of 10Hz. The 10uF output capacitor, C33, is required and needs an ESR of <= 1.5Ohms, but preferably 1Ohm <= C33 <= 1.5Ohms. The datasheet is quiet on specific values but gives a range of 1uF to 50uF and an example of 22uF. That seems to work for Jan and Peter too.
I'm using a 16-bit, 4 Channel DAC which is driven over an I2C interface. DAC outputs A, B and C go to the compensation module and DAC output D goes straight to the Board I/O module. The Vref pin is an output of the internal 2.5V Vref; this DAC can take an external Voltage Reference but its internal reference specification is very good - better than a REF50XX for example. This output also goes to the compensation module as there is no way to trim or otherwise adjust its value. The GAIN pin drives the actual Vref value and thus the output value range; as configured with the connection to Vdd, it will provide a gain of x2 with an output range for the DAC channels of 0V to 5V. I may decided during prototyping to reconfigure this to a gain of x1 (0V to 2.5V.)
The RESET pin works in conjunction with the RSTSEL pin. RSTSEL drives the power-on reset function and, as configured, all channels will start up to zero scale - the other option is midscale; when pulled LOW, RESET will actually reset the DAC outputs to the level determined by RSTSEL. When the board powers up, RESET will be held LOW automatically by the output from the Digital Isolator - as mentioned earlier, this will prevent the DAC from powering up properly - so before actually using the DAC, this pin must be pulled high and a delay incurred for the IC to correctly power up to its zero scale level.
Internally, the DAC has two registers for each channel. Values to output on the channel are written into the Input Register. This register is then copied to the DAC register and the output generated. When that copy occurs is controlled by the LDAC pin (Load DAC): only when it is pulled LOW will the copy occur and the output adjust to its new level. If constantly held low, all output is 'instantaneous', i.e. a write into the Input Register is copied to the DAC register immediately. When LDAC is high, that copy does not occur. This will allow each channel to be updated (serially, through an I2C command) and then all channel outputs changed simultaneously by pulling LDAC low. This allows for synchronisation of output. The channels impacted by LDAC can be masked so it's possible to use this pin over a subset of channels.
I'm using the 4.096Vref to drive this DAC, rather than the +5V rail, as the graphs in the datasheet indicate it is a lot more accurate at around 4V input. This is not being used to drive any Voltage Reference for the DAC to work as noted above.
The ADC I've chosen is a 16-bit, 4 channel IC from Microchip and the incoming ADC connections are straight from the Board I/O module. It uses its own internal Voltage Reference limiting inputs to +-0V to +-2.048V and each channel can be used in a differential mode. I haven't designed this to do that, yet, but I think I'm likely to do so; for example, measuring across a current sense will be more accurate if the kelvin feed is passed into the differential inputs of a channel.
I have chosen to buffer each of the incoming connections and provide for a Low Pass Filter between the OpAmp and the ADC input, as recommended in the datasheet. I'm struggling to calculate an appropriate value for the LPF because there doesn't appear to me to be enough information given in the datasheet (see my notes in the post on Component Selection) so the resistor and capacitor shown here are placeholders and I'll use the prototype to see if I can improve things. I've also provided input protection to the ADC in the form of fast switching, low current leak diodes that will route any high +ve or -ve voltage away from the OpAmp. All of this I will be testing and validating in the prototype and it may well be that this whole input stage is removed!
This is the most 'contentious' module and the one most likely to disappear I suspect. The concept I have for this it to take the DAC outputs, which will suffer from internal errors (zero scale, offset, gain) and trim these through a differential amplifier via a compensating signal from a second DAC. So, from the DAC module, I'm passing DAC channels A, B and C straight into this module. The compensated output is passed straight to the Board I/O module but also into an ADC which will convert the value for feedback into the compensating routine. The idea is that the compensating routine, in the software library, will adjust the compensating DAC output to 'trim' the output signal. I'm not thinking that this occurs automatically all the time, but when the compensating routine is run, e.g. when the output is powered off or under instruction of the application that runs on top of the library.
I'm also passing in the DAC Vref signal (as a voltage follower) to see if I can trim the DAC outputs taking into account the actual value of the Vref used. This does mean that one of the DAC outputs, DAC D, is not being compensated.
Do I think this will work? Well, I have my doubts. The ADC that is reading the values suffers from its own internal errors so that's going to impact any result, ditto the compensating DAC. Offset and Gain errors can be trimmed in the software and that may well turn out to be good enough. Also, it may be that it works well enough that having a manual calibration approach rather than automated approach is a better solution. Whatever, it feels like an interesting challenge to investigate in the Prototype before I make any final decisions.
The DAC shown in this module are 12-bit ICs and not ideal for trimming 16-bit outputs. If the prototype shows this approach works then I'll change it.
Real Time Clock Module
I thought it would be useful to provide some clock functionality, perhaps for timing of measurements. It would seem that keeping track at a resolution better than 1 second is quite expensive and given that the time has to be retrieved over I2C not sure that's worth it. So, this module will be accurate to 1 second - any further resolution would need to be finagled on the MCU (e.g. by taking a microseconds timestamp before/after the I2C read) and taken as 'reasonably accurate'; it would seem a reasonable trade-off. This module has a dual alarm function as well, accessed from the MFP, which is routed back through the Digital Isolator to the MCU. The MFP can be alternatively configured to output a square wave so I'm also routing the output to the Board I/O module in case it is useful.
I'm providing the means for a battery backup so that any configured date/time/calibration data can be stored - this will allow for relative measurements over a number of days for example or even just to keep a date/time on display on the MCU.
I can easily envisage many instruments requiring mechanical cooling based on feedback of temperature through one of the ADC channels. It's going to be up to the application to determine when to turn on / off a fan but the software library will actually do it.
FAN_B is directly connected to Pin 11 (B5) of the digital isolator.
How it works
There are many designs on the internet for controlling a fan. I've made some assumptions here:
- 12V supply required
- up to 0.5A current drawn
- two wire
- Activation driven by the MCU
There are 388 (as of writing) on the UK.Farnell website with no delivery surcharges and a wide range of operating current that meet these assumptions so they seem reasonable.
The 12V supply is fed out to the connecter and the diode (an SMD 1N4001 equivalent) is there to deal with any back-emf. The MJD122 (a SMD version of TIP122) is used to actually control the turning on/off of the fan as follows. The MCU can turn the fan on by pulling a digital output high which is reflected across the Digital Isolator, Pin 11 (B5), pulling the base of the MJD122 high, turning the transistor on into its saturation region allowing 12V to flow over the fan to ground. When the MCU pulls the digital pin low, voltage at the base falls to 0, turning the transistor off causing an open-circuit for the fan turning it off.
The Digital Isolator, SI8661 can source 4.8mA typical/7.2mA max from a pin so I need to ensure that the limit isn't exceeded. Calculations based on a range of current required by a fan of 100mA to 500mA
Ib = base current; Ic = collector current; Vbe = voltage base-emitter; Rb = base resistor; hFe = DC current gain aka beta
From the datasheet: with an Ic of 0.5A, hFE is 2000; with an Ic of 0.5A, Vbe = 1.4V
Ib = Ic / hFE = 0.5/2000 = 250uA
The base resistor needs calculating;
Rb = (Vin - Vbe) / Ib = (5.0 - 1.4) / 250 * 10^-6 = 14,400 Ohms
From the datasheet: with an Ic of 0.1A, hFe is 500; with an Ic of 0.1A, Vbe = 1.25V
Ib = Ic / hFE = 0.5 / 500 = 200uA
Rb = (Vin - Vbe) / Ib = (5.0 - 1.25) / 200 * 10^-6 = 18000 Ohms
Also, calculate the minimum resistor size for the current limit, 4.8mA:
Rb = (5.0 - 1.4) / 4.8 * 10^-3 = 750 Ohms
Rb = (5.0 - 1.25) / 4.8 * 10^-3 = 782 Ohms
A resistor between 750 Ohms and 18000 Ohms is needed: I've chosen 2K2 Ohms to provide a safety overhead but not overly limit the current in case the fan requires more at startup. Also I have that value on-hand.
Board I/O Module
Not really a module, just a set of headers that would be used to connect to any instrument. It's worth mentioning that if I change the ADC inputs to allow for one or more differential inputs, then J5 would change to provide more incoming connections.
Off-Board Control Module
Off-board controls are all on 'Side A' of the isolation, with power provided by the DC/DC isolator. I want to be able to drive this from a suitable MCU so I'm not providing header connectors for any specific device. I will use my 4Duino because I have it to hand and I'm more familiar with Arduino coding - I've covered the 4Duino elsewhere - here and here - so I won't go into much detail but the advantages I see here are:
- Built in touch-capable LCD so no separate powering or control circuitry required
- Built in ESP8266 for Wi-Fi access so no need to connect to a PC for remote control.
- Built in SD card for data storage (e.g. logging profile data for off-board processing)
I have also made provision for a momentary power button to toggle the board output on/off - using a momentary button means I won't need to have any complicated syncing routing between any touch button on a screen and the button state which would be needed if it was a latching type. A rotary encoder will provide an alternate input mechanism for selecting options or entering control values. These are manual controls to supplement a touch interface.
There is a 14-pin header on the board for connecting power to the external MCU along with the control lines to/from Digital/Analog/GPIO pins. The design schematic shows how I intend to connect the 4Duino to the board; the global labels on connections 14 - 7 go straight to the isolators.
I've described above the stake-in-the-ground design but I want to explore some of these modules and concepts a bit more. I've realised that it's actually cheaper to get some PCBs made up than it is to buy DIL adapters for the parts so I will be doing that. It also gives me some time to get up to speed with creating tests and using Labview - Jan's approach to testing really appeals. I have breadboarded quite a bit of this already (not compensation) so I do know that fundamentally, or at least electrically, the design will work.
So for the prototype I'm going to concentrate on the DAC, ADC and Compensation modules. I also want to do this in the context of the power supply and isolation components to see how (if) they impact control and accuracy. Specifically, I want to cover the following with the prototype:
- Characterise different ADCs with different performance and functionality specs. I've picked the Microchip MCP3428, Texas Instruments ADS1115 and Analog Designs LTC2487. These are all 16-bit, Sigma-Delta converters. I will use jumpers to route signals where I want them, e.g. individual ADCs, or all ADCs.
- Test the OPA4192, so for each ADC: 1 channel buffered with Low Pass Filter (LPF) using the ADC to apply gain; 1 channel gained-up by x2, with LPF; 1 channel buffered with no LPF, ADC providing gain; 1 channel unbuffered with the ADC providing gain.
- Test various compensation approaches with an Analog Devices AD5696R DAC and Microchip MCP3428 ADC. Here, I will use one DAC channel to provide an offset amount to another DAC channel; one DAC channel compensated with the approach documented by Jan here, from the AD white paper, figure 6; and one DAC channel uncompensated that I could use to pass its output straight through to the ADC circuit (or just measure it.)
I'll describe the DAC compensation and ADC modules but the others are pretty much the same as described above.
DAC Compensation Module
Here, you can see that I will ask the AD5696R to output a signal through one or more of its channels:
- VoutA goes to a terminal block which I can either link directly into the ADC module inputs or run a load, say a resistor, and measure the voltage drop across that through the ADC module. Although each channel is characteristically different, this will give me a baseline behaviour to measure against as well as additional flexibility in the prototype.
- VoutB is fed into a compensation configuration as described in the AD paper linked above. The values I've chosen generate an offset of 5mV according to the calculation and I assume that can be adjusted with the potentiometer.
- VoutC is used to generate an offset compensation signal that is subtracted from VoutD's signal to adjust for that error. In theory, I can read the 'actual' output through the ADC and dynamically adjust in software to get the signal I want. I say in theory because of course there are other errors in that signal path and the ADC will introduce errors of its own, but I think it will be an interesting exercise nonetheless.
- Vref is used to determine the internal reference voltage used to generate the DAC output as I'll need to account for that in any software compensation.
As the DAC outputs are being read and converted by the ADC, I can also characterise that and look for software compensation of its readings.
The aim of this is to determine the likelihood of improving accuracy of DAC output and ADC measurements through software and hardware. The three different approaches should give me some flexibility; I couldn't think what to do with the additional OPA192 input so I've tied it off. If anyone has any ideas, let me know.
In my linked post, Instrument Control Board - Component Selection, I make a comparison of three ADCs. The reality seems that there is little choice in the market and each seemed to have strengths and weaknesses so I thought I'd give them all a go (although in my full design schematic I've drawn it up with the MCP3428.) Each ADC's input signal path is through a jumper so I can test each individually, or any combination; the signal into each will be the same as it originates from a terminal block to which I can apply a signal. I'm also testing the OPA192 in various configurations as well:
- Ch1/0 is in a voltage follower set up with a LPF.
- Ch2/1 is using the Op Amp to apply a gain of x2 again with a LPT. This will hopefully give me a view on using the Op Amp to amplify the signal or the ADC's internal PGA.
- Ch3/2 is purely a voltage follower with no gain or LPF.
- Ch4/3 is without the Op Amp at all. This plus Ch3/2 will hopefully give me a view on whether an Op Amp improves the signal at all.
I've provided a jumper to give the Op Amp power range between -5V/+5V and -5V/+12V to give me some flexibility in signals that are close to the rail. For the MCP3428 that is irrelevant as its maximum input voltage is limited to 2.048V but the other two ADCs have a greater range.
The LPF is merely a placeholder as I've found it hard to calculate as the datasheet for the MCP3428 doesn't provide enough information. Admittedly, I didn't check the other two in great detail in this aspect but the LTC3487 datasheet does state a requirement for the RC filter to have a time constant of < 580nS. The values I have here give a TC of 10us, much greater than that - a 50nF capacitor with 10Ohm resistor would give a TC of 500ns (5e-7s) - so it will be interesting to see how that behaves compared to the inputs without the LPF filter. I can of course change these values to see how it impacts behaviour. In fact I may do some more work on that before the prototype PCB comes as 50nF is way greater than the MCP3428's sampling capacitor of 3pF and likely so for the other two ADCs. I think the balance will be providing enough of a resistance for the Op Amp whilst keeping the capacitor high enough to act as a reservoir for the sampling capacitor. 10nF and 50Ohm would still give a TC of 500ns.
The above describes what I hope is a workable design and a reasonable way of testing it - much of the core element has been verified on a breadboard and I've written snippets of software to prove communication and control. I have purposefully tried not to replicate what Jan et al are doing so that I can gain a better understanding of designing reasonably complex circuits myself and how they work in practice. I feel ready to continue prototyping with a PCB so I can make better assessments of accuracy, noise etc. and see what needs changing/improving. Now future weeks/months will be taken up playing around with the prototype and improving my experience of analysing and adjusting signals - should be a great deal of fun. I'll make further updates as comments to this post unless there is something that I deem warrants a separate one.
I've attached PDFs of the schematics and the KiCad files are in Github.
Creating an Instrument Control Board (this post)