Design and build a color accurate LED flashlight for high end applications.
At right is a simple LED driver with a simple digital control system. It's documented here.
It appears to be a current controlled topology. It's constant frequency and turns off when the sense voltage (driven by the output current) exceeds $V_{ref}$.
The eventual goal is to replace much of the digital side with an FPGA, but it's illustrative here to get a general idea of a simplified control loop.
It uses a GaN Mosfet, EPC8010 datasheet and runs about \$2 in 100 quantity. This part allows very high frequency switching.
For efficiency reasons D1 should probably be replaced by another Mosfet making it a synchronous switcher.
An additional supply (perhaps just a capacitor) to supply the gate drive with a high drive voltage.
This uses a Mosfet to replace D1 (the catch diode) resulting in much less power loss since the $\small RDS_{on}$ is much smaller than even a schottky diode.
Example of a 'protection IC'. This gives a naive implementation that can be used as a guide.
Video for understanding the specifications of protection ICs.
This is Herman's P-Channel high side gate driver, part number IRS10752LTRPBF datasheet. We are using a low side driver so this is to see a gate driver in situ. We will need a similar compensation network before the gate.
After a discussion with Herman, putting a small resistor (100mOhm) in the Source to ground leg is Ok.
It will only raise the gate voltage requirement a small amount.
The circuit is from a TI App Note. High side sensing has noise advantages also I believe (I'll check with Herman) that we can't use low side because the gate drive would have to go through the sense resistor which would limit the current! Something we are desparately trying to increase.
Here's a shi-shi-foo-foo (albeit excellent) op amp, OPA2991IDGKR datasheet
Fundamentals of Gate Drivers .. 48 pages!
Low Side Gate Driver with Totem Pole. We don't want a totem pole. There are issues. See Doc.
Type | Part | Manuf | Datasheet | Source | Price (100) | Spice | Comments |
---|---|---|---|---|---|---|---|
FET | RQ6E045TM | Rohm | (datasheet) | Digikey | \$ 0.44 | model | Next Try |
FET | CSD17484F4 | TI | (datasheet) | Mouser | \$ 0.65 | model | Excellent |
FET | FDMS8622 | OnSemi | (datasheet) | mouser | \$ 0.99 | model | Slow? |
Current Sense | INA180A4 / B4 | TI | (datasheet) | Mouser | \$ 0.38 | model | Cheaper than Discrete |
Current Sense | INA180A2 / B2 | TI | (datasheet) | Mouser | \$ 0.38 | model | Cheaper than Discrete |
Current Sense | INA180A1 / B1 | TI | (datasheet) | Mouser | \$ ?? | model | Cheaper than Discrete |
Gate Driver | FAN3111E | Fairchild | (datasheet) | Mouser | \$ 0.67 | model.zip) | Looks good |
Gate Driver | IRS44273L | Infineon | (datasheet) | src | price | Y | Need more info |
Gate Driver | ZXGD3009W6 | Diodes Inc | (datasheet) | src | price | model | Need more data |
Gate Driver | NCP51100 | N | |||||
Gate Driver | TPS2819QDBVRQ1 | N | |||||
Gate Driver | TPS2816 | N | |||||
Gate Driver | IRS44273L | Infineon | (datasheet) | src | price | Y | more info |
OpAmp | OPA2990IDR | TI | (datasheet) | Digikey | \$ 1.14 | model | App Note Recommends |
OpAmp | BU7487 | ROHM | (datasheet) | Mouser | \$ 0.84 | model | Quad Opamp |
OpAmp | MC33274 | OnSemi | (datasheet) | Mouser | \$ 0.77 | model | Quad Opamp |
I will send the .asc Sim file to you via email.
The image here is for reference.
Below is what you have to do to get it running.
To add the FDMS8622 FET model to LTSpice (spice here) follow these instructions.
To add the ZXGD3009W6 Gate Driver model (spice here) to LTSpice follow these instructions
Note ..
R1 and R4 should be matched, as well as R2 and R3 for improved accuracy.
Now let's look at the common mode voltage ..
import Text.Printf
r1 = 10e3
r2 = 1e3
r3 = 1e3
r4 = 10e3
vBus = 15
vCM = (vBus * r1) / (r1 + r2)
printf "Common Mode Voltage = %4.2f volts" vCM
Common Mode Voltage = 13.64 volts
From the App note has an output voltage calculation including the error from offset voltage and shunt resistance.
Vo = (Gain+1) Voffset + GainVshunt
If the voltage across the shunt is 200mv, the offset error and shunt resistance cause an error shown below.
gain = 200
vOffset = 300e-6 -- typical
vShunt = 0.01
vo = (gain + 1) * vOffset + (gain * vShunt)
printf "Percent Error with Vshunt = %4.2f is %4.2f percent" vShunt (100 * (abs vo - (gain *vShunt)))
Percent Error with Vshunt = 0.01 is 6.03 percent
The error would be about 0.33 percent if the shunt resistor was 0.2 ohms.
Here's an IC .. INA180A4 (200 gain) or the INA180A2 (50 gain) from TI ... \$ 0.38 in hundreds (priced increased to $ 0.41). Uses either a 5V or 3.3V supply.
See the parts table above for details.
The 'A' in 'A4' is the package type. The '4' in 'A4' is the gain, here 200V/V
Mouser has no stock
import Text.Printf
gain = 200
rSense = 0.005
measuredI = 1.844
actI = 24/(1 + 12 + rSense)
vSense = actI * rSense
withGain = vSense * 200
iErr = abs (measuredI - withGain)
printf "At %4.2f Amps, CurrentError -> %4.2f milliamps or %4.2f percent" actI (iErr*1000) (iErr*100/actI)
At 1.85 Amps, CurrentError -> 1.44 milliamps or 0.08 percent
The chip has matched resistors (likely) , a known gain, a 3.3V supply, and it's cheaper than just the opamp unless I go reallycheap. It claims 350Khz response. I'm not sure how much we can calibrate out (unless we do a table). The chip should be more well behaved if it matches the internal resistors. We can probably go for a 100mOhm shunt instead of a 10mOhm one and go for the 'A3' part (gain.
TI Does it Again ....as long as the shunt common-mode voltage is greater than VS when the device is powered up ... It does some sensing at power up and modifies it's behavior .. dunno how important that is yet.
Determine Gain Required
doCalcs :: Double -> Double -> Double -> Double -> IO ()
doCalcs iMax iMin rSense gain =
let vSenseH = iMax * rSense
vOutH = vSenseH * gain
vSenseL = iMin * rSense
vOutL = vSenseL * gain
s1 = printf "%4.2f V" vOutH
s2 = printf "%4.2f mv" (vOutL * 1000)
s3 = printf "%4.2f mOhms" (rSense * 1000)
s4 = printf "%4.2f" gain
in
putStrLn $ "rSense = " ++ s3 ++ ", Gain = " ++ s4 ++ ", vOutL = " ++ s2 ++ ", vOutH = " ++ s1
-- So let's try a few options
-- doCalcs iMax iMin rSense gain
doCalcs 1.8 1e-3 0.008 200
doCalcs 1.8 1e-3 0.015 100
doCalcs 1.8 1e-3 0.03 50
doCalcs 1.8 1e-3 0.08 20
rSense = 8.00 mOhms, Gain = 200.00, vOutL = 1.60 mv, vOutH = 2.88 V
rSense = 15.00 mOhms, Gain = 100.00, vOutL = 1.50 mv, vOutH = 2.70 V
rSense = 30.00 mOhms, Gain = 50.00, vOutL = 1.50 mv, vOutH = 2.70 V
rSense = 80.00 mOhms, Gain = 20.00, vOutL = 1.60 mv, vOutH = 2.88 V
Maybe the sweet spot is 30 milliohms with a gain of 50.
For fun here's what the discrete version looks like ...
The integrated version doesn't have the 4 resistors around it, and a 5V or 3.3V supply instead of the 24V one.
TSM104 is a cheap quad op amp at $ 0.61. Could be good but no model! This would make, with two sensors per channel about \\$ 0.30.
After a phone conversation with Jay we decided to just use the INA180 .. with two chips per channel it's a bit expensive but we can get it and it has a model ...
LTSpice .step and .meas, for efficiency, and normal
.step param Iload .2 1.2 .1 .tran 0 2.1m 2m startup .meas Pin AVG -V(IN)I(V1) .meas Pout AVG V(OUT)I(I1) .meas Eff param Pout/Pin
Ctrl+L hotkey to see log
Schematic Portability
I found another way to do it but really the easiest way is to do what we have been doing.
FYI here's the workaround ..
I do it the 'regular' way and ship off the .asc file to you, meaning that I create the symbol and right click on the subcircuit statement ... yada yada.
I include the .lib (or .txt) file of the model in the schematic
I send you the .asc file
I edit the lib/AutoGenerated/{part_name}.asy file to remove the ModelFile attribute.
You download this and place it in the same directory as your .asc file
Hopefully you can now run the sim.
-- xxx :!stack build csv
csv> configure csv> Configuring csv-0.1.2... csv> build csv> Preprocessing library for csv-0.1.2.. csv> Building library for csv-0.1.2.. csv> [1 of 1] Compiling Text.CSV csv> copy/register csv> Installing library in /opt/stack/snapshots/x86_64-linux-tinfo6/fd0da228ad83198fb9b570bf01319b58da7bd0f851d7a4b8c218dddf6ae74b9f/8.10.7/lib/x86_64-linux-ghc-8.10.7/csv-0.1.2-Tuxv9xiiviErUGWvI9wDB csv> Registering library for csv-0.1.2..
import Text.CSV
getCSVStr :: String -> IO String
getCSVStr filepath =
do
eitherCSV <- parseCSVFromFile filepath
return $ getString eitherCSV
where
getString :: (Either a CSV) -> String
getString (Left err) = "Bad or No CSV File"
getString (Right theCSV) = printCSV theCSV
theCSVStr <- getCSVStr "linear-results01.csv"
putStrLn $ filter (\c -> c /= '"') theCSVStr
on,pinput,pout,eff,ledi 5.0e-6,8.43764e-2,7.88486e-2,0.934486,8.63554e-3 5.4e-5,3.04731,2.90032,0.951765,0.214559 1.03e-4,6.34257,6.03162,0.950973,0.434331 1.52e-4,9.63931,9.16471,0.950764,0.654148 2.01e-4,12.9402,12.3017,0.950663,0.874234 2.5e-4,16.2346,15.4327,0.950604,1.0939 2.99e-4,19.5342,18.5686,0.950572,1.31391 3.48e-4,22.8292,21.6999,0.950533,1.5336 3.97e-4,26.1192,24.8268,0.95052,1.75297 4.46e-4,29.4107,27.9549,0.950503,1.97243 4.95e-4,32.6515,31.0366,0.950542,2.18847
</
Let's try some isolated pulses and compare the filter output to a simple single pole RC filter (see schematic above).
Let's try some pulse trains .. 10% duty cycle at various frequencies
Below is 1khz pulse train with 10% duty cycle.
</
Below is 10Khz pulse train with 10% duty cycle.
</
Below is 100Khz pulse train with 10% duty cycle.
</
Below is 1Mhz pulse train with 10% duty cycle.
</
Below is a one percent duty cycle at one megahertz ..
</
Below is the above plot zoomed in to see details.
</
Crap Opamp Filter Response
Good Opamp Filter Response.
I don't think this is right!
I'm digging
Here's the datasheet
Spec Type | Red | Grn | Blu |
---|---|---|---|
Avg Vf | 1.9V | 2.9V | 2.9V |
Max Vf | 2.5V | 3.6V | 3.6V |
The above table is at 5ma.
Here's the Green LED Drive from the Nordic.
It's strange. The specs say that the Blue and Green LEDs should have the same $V_f$ but the waveforms are substantially different.
Is there a difference in the pin drive levels?
The 3.8V is what I was worried about but Herman told me it would be Ok .. Well, maybe it is since I'm guessing you haven't smoked any Nordic pins (yet). The idea was that even though there was 5V present any significant current flowing through the LED would substantially drop the voltage, thus protecting the pin from any excess (i.e. bad) energy level(s).
Ok, what is happening.
Looking at the plot we have 1.1V when the Nordic tries to go low (LED on). This is higher than anticipated. So either the Nordic is slacking (weak pulldown ability) or the $V_f$ is way low. I need some more info.
Can you measure the LED cathode voltages?
Now le't look at the 3.8V when the Nordic tries to go high (LED off). This means that there is,
$ V_{LED} = 5V - 3.8V$
$ V_{LED} = 1.2V$
But it's typical $V_f$ is 2.9V, so it seems like it should be just about off (maybe they're more efficient than I think. Are we wishing for the LED current source?
I doubt if increasing the resistances will make a big difference (maybe). A better approach would be to put a diode in place of the Zero ohm resistor from the 5V (anode to the 5V). This will get us down to 0.5V across the LED (or at least another 100K until it gets a higher voltage).
Cathode voltages will help a bit. I have some small signal diodes (1N4148).
Set PWM to 100us period 1us pulses.
Neither sensor can see 3.6ma ..
I'll work on it.
Problem above was apparently due to a bad op amp model.
Let's try another op amp .. MC33272 .. (see parts table above).
Why does the response go up past 30Khz?
Here is the datasheet
Supposedly the GBP is 24Mhz and I've got a gain of two.