14 Oct 2022 - tsp
Last update 06 Nov 2022
11 mins
The following blog article describes a small and pretty simple digitally controllable current source that is capable of outputting up to $500 mA$ at voltages up to $12V$ (this can simply be extended by choosing a proper MosFET and other sense resistor up into the $\approx 30A$ range though - but it stays a linear regulation circuit so is limited by supply voltage and heat production inside the MosFET). This has been designed for a particular application in which the current controller had to be able to:
This controller belongs to the slow control side (so no real time control with nanoseconds or milliseconds of resolution) of an experiment
To solve that problem one of the simplest OpAmp based solution has been used - a cheap LM358 operational amplifier drives an IRF540N (or similar) n-channel MosFET to which the load is attached on the high side. The current flows over a small sense resistor to ground - for the desired current range and a control voltage in the range from 0 to 5V a 10 Ohm resistor has been chosen. Depending on the desired output current one can simply choose the sense resistor according to
[ U = R * I \\ R = \frac{U}{I} \\ \to R = \frac{5V}{500 mA} = \frac{5}{0.5} = 10 \Omega ]Note that this solution does not compensate for thermal drift of the sense resistor which is required for larger loads or higher accuracy requirements. There is a simple and fascinating solution to that problem that one should prefer in this case.
The two $100 \Omega$ resistors one sees at the output of the LM358 into the MosFETs gate as well as in the feedback path to the inverting OpAmp input in theory have no effect since one usually assumes no current is flowing there. They’re there to prevent transient over current situations during loading of the MosFETs gate - this of course limits response time of the circuit also in case of highly adaptive loads - and to limit leakage currents into the OpAmp.
Note that the MosFET requires a heat sink for sure (calculate the thermal load in case) when operating at currents above $100 mA$ at a supply voltage around or above $12V$. Check with the MosFETs datasheet as usual. The heat dissipated can be estimated in the worst case - when one assumes that the whole power is dumped into the MosFET, i.e. $P_{worst} = U_{Vcc} * I_{max}$.
To measure the current using the ATMegas internal analog to digital converter (ADC) the analog input has been directly attached to the current sense resistor. This works despite the 12V input voltage on the load since the OpAmp drives the gate of the MosFET in a way that the voltage over the sense resistor is always as large as the voltage on its non inverting input provided by the DAC. Since the DAC can only output to $\approx 5V$ it’s guaranteed that the voltage at this point never exceeds 5V. Note that when using the OpAmp in an amplifying configuration (to achieve higher voltages over the sense resistor) one would have to provide a high impedance voltage divider in parallel to the sense resistor.
The output current is regulated by selecting the input voltage on the non inverting input of the operational amplifier. The outputted voltage (as long as the power supply is not saturated) is given by:
[ I = \frac{U}{R_{sense}} \\ I = \frac{U}{10} ]To provide the reference voltage a cheap MCP4822
14 bit digital to analog
converter (DAC) has been used. It’s 14 bit resolution in theory allows one - for the $500 mA$
configuration - to select the current with about $30 \mu A$ resolution. The second
DAC channel has not been used. The MCP4822 is pretty easy to use - it’s just attached
to an SPI port (only using a write only interface). The chip select has been pulled
high by a $10 k\Omega$ resistor to disable the SPI logic while the microcontroller
is in reset since the AVR used in this project is also programmed via it’s SPI
pins. The decoupling capacitors on the power supply rail as well as on the output
have to be mounted as close to the chip package as possible.
The LDAC
line could in theory also be pulled to ground in case one wants
to immediately update the output voltage after one has written a DAC register.
The usage of this line is usually interesting when one wants to update two channels
at the same synchronous time or have better control over timing - though I had
enough pins available on the used ATMega328P so I’ve just routed the pin to
a GPIO port.
The output line VA
has been directly connected to the non inverting input
of the LM358 OpAmp.
Power supply for logic and microcontroller has been done using a simple LM317 linear regulator. This is feasible since the input voltage is around 12V (with some neglectable ripple). The 12V are directly derived from a 230V to 12V transformer, a bridge rectifier built out of Schottky diodes and an about $10 mF$ large capacitor bank (this has been required due to other constraints on the load side of the setup). Note that of course also a fuse is part of this transformer assembly. Since the required supply voltage was 5V this of course means that the linear regulator will burn $\approx 60$ percent of power as thermal load - but since the current required by the OpAmp, DAC and microcontroller is pretty low the regulator does not even require a heat sink in this configuration.
Again place the capacitors as close to the regulator as possible or it will start to oscillate.
The last part is the microcontroller itself. A ATMega328P has been chosen (even if it’s a little bit of overkill). Communication with the outside world is handled by it’s USART - a serial port. This has been isolated using cheap PC816 opto couplers. Note that those are cheap but not the best choice for serial port isolation. It works for low BAUD rates though. The controller could be used with it’s internal RC oscillator (in this case one can leave out the 16 or 20 MHz quartz) and only requires a single additional reset network and decoupling capacitor on the AREF pin.
The remaining pin mappings that have been used are:
Pin on AVR | Usage |
---|---|
AVCC, VCC | 5V voltage supply |
AREF | Tied to ground via $0.1 \mu F$ ceramic capacitor |
GND | Ground reference pin |
nRESET/PC6 | Tied to 5V line via $10 k\Omega$ and ground via $0.1 \mu F$ to provide a reset pulse during power up |
XTAL1/XTAL2 | Connected to the quartz (if used) |
PC0 | This is the first ADC input so it’s connected to the voltage divider in parallel to the sense resistor |
PD0 | USART Receive pin |
PD1 | USART Transmit pin |
PD2 | Attached to LDAC to latch new DAC values |
PD3 | Chip select of the DAC tied to 5V to disable the DACs select while the ATMega is in tristate |
PB5 | Serial SPI clock for programming and DAC |
PB4 | SPI MISO (attached to programming interface) |
PB3 | SPI MOSI (attached to DAC and programming interface) |
Of course the serial programming interface can only be used while the controller is not biased to it’s $-2 kV$ potential and serial communication via the opto couplers works only pretty slow.
The full schematic looks like the following (note that this assumes about $100 \Omega$ pull downs on the low voltage side of the serial interfaces receive path or the opto couplers won’t even be fast enough for 2400 bits per second BAUD rate)
The following PCB is a simple realization for a low current version of the controller board. As one can see it:
TO-220
packaged high precision resistors
on the edge of the PCB with a heatsink. Thouse should be rated at least twice
the target current in this case.The layout of the PCB facilitates a copper filled ground plane on the high voltage and logic side. The PCB has been milled below the optocouplers as usual to prevent any residual solder or leakage currents from the high voltage to the low voltage side. One usually also does this between line power and low voltage sections for the same reason. Usually one could also have reduced the material amount between high and low voltage side further in the orthogonal direction above.
The connectors are standard raster size for all common types of screw clamps or pin headers.
Note that the mounting screws are close to the high voltage grond plane - i.e. when mounting to some non biased case you’d have to use Nylon screws and enough spacing.
The design files that have been used to order the PCB at PCBWay have been generated using the Gerber export method of KiCad. They are available in the GitHub repository. PCBWay has been choosen as a manufacturer because they offer a pretty cheap but high quality prototyping service - without shipping you can get for example 5 dual layer FR4 PCBs for about 5$ with 24 hours of manufacturing time. The PCBs still offer all features like high quality prepregs, uniform copper coating with the specified thickness, supported spacing down to BGA packages, different solder mask colors, printed silkscreen and passivation surface finish. The process of getting them ordered just takes a few minutes - enter the size of the PCB and requested properties at the intsant quote section, upload the ZIP file containing the exported Gerber files (make sure to not use extended V2 format, use minimal header, PostScript map file for the Excellon drill file and suppress leading zeros there) and you’re ready to go. After uploading the ZIP the PCB is manually reviewed by skilled engineers - when you request manufacturing that violates design rules, etc. you get a pretty quick response and when everything is ok the PCB goes into production usually within less than one or two hours. After at most 24 hours the PCBs get shipped so you can build them pretty fast (depends on the selected shipping method and your local customs though, that’s the main bottleneck).
The controller software has been developed in ANSI C, compiled with avr-gcc, and annotated using ACSL for static analysis with Frama-C as usual. All tests are automatically executed using a Jenkins pipeline though programming using avrdude is not automated using a pipeline due to the physical connection needed in this case.
The source code for the firmware is available on GitHub together with a Python library that allows one to invoke the functions of the microcontroller using a simple USB to TTL serial adapter.
This article is tagged: Tutorial, DIY, Electronics, Physics, Basics, OpAmp
Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)
This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/