Electronic – LM358P output saturation around 6.05V (root cause turned out to be related to Arduino protection diodes)

constant-currentmosfetoperational-amplifier

For a constant current drain using a PWM input I am using the following setup:

schematic

simulate this circuit – Schematic created using CircuitLab

For small currents it seems to work as expected – the op-amp producing a voltage to the MOSFET which causes the current flow over the battery be such that the voltage drop over the 3.3 Ohm sense resistor becomes exactly the configured voltage, as expected.

But there must be something I have missed, because the current I can get maxes out much earlier than expected. This happens around 150 mA corresponding to an input voltage to the op-amps positive input (via PWM) of around 0.45V. At this point, the output from the opamp to the MOSFET seems to saturate around 6.05V. The problem is that further increases in the op-amps positive input has no effect. The opamp keeps producing a 6.05V output even though there is a large difference between the positive and negative input. I can see the opamp is getting, say, 0.8V at the positive input and is only seeing 0.45V at the negative input, yet it refuses to output more than 6.05-6.1V.

The Vcc to the op-amp is 12V so there should be plenty of headroom for it to output higher voltages even though it isnt a rail-to-rail opamp. I have looked in the datasheet but I cant seem to find a limitation that would explain this behavior, so I hope someone can explain what I am missing.


Update! I am a bit closer to resolving the mystery. I had a wire (not on the drawing) going from the output of the op-amp and to an analog input on the Arduino. I thought the analog inputs were high impedance so it wouldnt affect anything. But with that wire there I am seeing the 6V saturation (as measured by a multimeter, the Arduino only measures to 5V), but if I disconnect it everything works. Is this some type of oscillation involving the Arduino? Or is the Arduino draining the voltage?

NOTE! The root cause of this problem turned out to be different. I had connected a measuring wire from the op-amp output to the Arduinos analog input. My thinking was that it was high impedance and hence wouldnt affect outcome. I had noticed the measurements topping out after 5V but thought that was simply due to it being unable to report more than value 1023 and that it wouldnt actually affect the behavior of the circuit. This assumption was wrong; due to a protection diode in the Arduino inputs, the extra voltage was drained (the LM358P has a short-circuit voltage of 40-50 mA) causing the drop in the measured voltage (even with a multimeter) at the op-amp output. But the real culprit was the protection diode in the Arduino. Removing this measurement wire resolved the problem. I am leaving the original problem description in place so other people can find this report in case they encounter similar issues.

Best Answer

I had first imagined that your problem was that the opamp was oscillating and suggested that you try something like this (thanks to Spehro, too):

schematic

simulate this circuit – Schematic created using CircuitLab

Per further discussion, where you added that you were supplying the output of the opamp to an MCU input pin on your Arduino, it's also clear that even if you did (or would have had) an oscillation problem (and you would, I'm pretty sure) it is more likely now that your measured limit of around \$6V\$ was due to a heavily loaded protection diode at your MCU's analog input pin. The protection diode limitations for any given MCU can usually be found under the "Absolute Maximum Ratings" section of the datasheet, where that section will include a line described as something similar to: "diode current at any device terminal." Usually, the value listed there will be around \$2mA\$ or less.

If you must measure the opamp output voltage, then you will need to consider a different circuit arrangement to condition the opamp output (without disturbing its MOSFET control behavior) and make it suitable for input to the Arduino analog input pin.