| Electronics > Projects, Designs, and Technical Stuff |
| Non Inverting adjustable gain amplifier using digital pots |
| (1/1) |
| OM222O:
I have been needing all sorts of amplifiers for different things and usually I would just use an op amp and a few resistors to do the job but that's time consuming and I usually end up losing the resistors afterwards XD So I decided to look into making a programmable gain amplifier. The obvious choice was using digital pots so I had a look at a few microchip application notes in order to have some idea about accuracy and stability of different designs. This one was exactly what I was searching for: http://ww1.microchip.com/downloads/en/Appnotes/01316A.pdf If you look at figure 6 (page 15) they show a tempco compensated, wide range amplifier which uses 2 pots. I already have a few 10K MCP4652 digital pots which are also perfect for this application, but there are 2 issues: 1) There is no easy way to calculate the gain, unlike other designs, which led me to do a basic analysis to see the range of available gains (using python). This first graph is the gain vs R1 (I didn't know how to do a 3D graph, ideally it would be a graph of gain vs R1 vs R2): Just wow! it's pretty obvious that a lot of gain values are repeated and multiple resistor values yield the same result. so I made another graph, this time it only includes gain values that are repeated more than once and how many times they have been repeated. For gains of 1 and 2, there are 256 repeats since all values of the pots works, but even for really high gain values, repeated values exist. I'm not sure how I should go about implementing the software. easiest way seems to be removing the duplicates and sorting the list, then storing it in the MCU memory, then using a lookup table to find the nearest gain to the desired value. this will also allow going through the list iteratively with a manual encoder or similar! but this will use a ton of memory.there are a total of 39896 different gain values. if stored as floats (each takes 4 bytes), they will take 159584 bytes (almost 156KB), each of the gain values needs two resistor values and since the pot has 257 taps, they need to be int or unsigned int, tripling the memory usage (468KB)! now that is not optimized by any means and I can probably reduce it to a third or half of that (by storing only one of the resistor values and calculating the second, using one byte per resistor value except the 257th one, etc) but that still requires a decently expensive EEPROM. Please let me know if there are better ways of doing this. 2) the more important issue would be the current through R1+R2. the pot is rated for an absolute maximum of 10mA current. for an op amp powered from +/-18V (a very typical supply voltage) this can easily happen if the resistor values are too low (I know the MCP4652 is not rated for 18V operation, but other variations such as the MCP42HV pots exist which can tolerate 40 volts). I think using 100K pots instead of 10K, and only saving the highest combination of resistor values for a particular gain should solve that, but again, if there is another way to limit the current, please let me know. I know op amps "can't drive much current" but they can most certainly drive 10mA with ease. Here is a graph showing current through the resistors when minimum resistance combination is used (18V supply, 10K pots): The maximum current is 3.5mA as you can see. Now the same graph, just using the maximum resistance combination possible: This can exceed 400mA! the op amp can't drive that much current, but this is surely susceptible to damaging the pot. If I want to pre-compute the list, I should be careful to not choose small values. Is there a circuit which I can use to limit the current when prototyping? I don't want to just whack a large resistor in series, rather something like a digital fuse would be more suitable that trips at lets say 5mA which is above the max calculated current. |
| OM222O:
In case anyone wants to check my python code, here it is, otherwise just ignore this post: --- Code: ---from matplotlib import pyplot as plt def calc_gain (r1,r2): return float(1.0+(r1/r2)) R=10000.0 gains = {} R1s=[i*(R/256) for i in range(257)] R2s= list.copy(R1s) plt.figure(figsize=(18,9)) for r1 in R1s: ys = [] for r2 in R2s[1:]: gain = calc_gain(r1,r2) ys.append(gain) if gain in gains: gains[gain]["n"]+=1 if sum((r1,r2))>sum(gains[gain]["r"]): gains[gain]["r"]=(r1,r2) else: gains[gain]={"n":1,"r":(r1,r2)} plt.plot([r1]*len(ys), ys, 'k,') plt.title("Gain Vs R1") plt.show() ys=[] xs=[] plt.figure(figsize=(18,9)) for gain in gains: if gains[gain]["n"]>1: xs.append(gain) ys.append(gains[gain]["n"]) plt.plot(xs, ys, 'r,') plt.title("Repeated gains") plt.show() ys=[] xs=[] V=18 plt.figure(figsize=(18,9)) for gain in gains: xs.append(gain) ys.append(1000*V/sum(gains[gain]["r"])) plt.plot(xs, ys, 'b,') plt.title("Current vs Gain") plt.show() print("Maximum current is: %.3f mA" %max(ys)) print(len(gains)) --- End code --- this will calculate the current with max value of resistor combination for each gain, if you want to plot the minimum, just change this line: --- Code: ---if sum((r1,r2))>sum(gains[gain]["r"]): --- End code --- to: --- Code: ---if sum((r1,r2))<sum(gains[gain]["r"]): --- End code --- |
| Navigation |
| Message Index |