I am developing a project using a Sparkfun SAMD21 board. It has a 3.3V logic level. I am using the Low Power Arduino library to put the processor to sleep when it is not in use. Every 20 seconds I use an interrupt to wake the board and do some processing.
The project is battery powered, and I want to use the fine library at GitHub by rlogiacco called BatterySense to determine the state of the battery. Since I am trying to make the battery last as long as possible, I am using the OnDemand example that activates the battery sensing only when a digital pin is set to HIGH.
The example includes a circuit that uses an NPN transistor and a p-channel mosfet as a switch to activate the sensing circuit when the pin goes HIGH.
What I have found is that the mosfet I have, and most that exist, apparently, need 5V logic to activate.
I am looking for help in developing a circuit that is similar but works with the 3.3V logic of my board.
Here is the code:
#include <Battery.h>
Battery battery(3000, 4200, A0); //battery is full at 4.2V, empty at 3.0V, input pin is A0
/**
* 1 cell li-ion/li-poly battery wired to A0, on demand activation on pin 9, sigmoidal mapping function
* https://github.com/rlogiacco/BatterySense#lesser-than-5v-with-voltage-booster
**/
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
SerialUSB.begin(9600);
while (!SerialUSB);
battery.onDemand(9, HIGH); //activation pin for meaurement is D9
battery.begin(3300, 1.49, &sigmoidal); //processor is 3.3V logic, voltage divider ratio is 1.49 (measured)
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
SerialUSB.print("Battery voltage is ");
SerialUSB.print(battery.voltage());
SerialUSB.print(" (");
SerialUSB.print(battery.level());
SerialUSB.println("%)");
}
And here is the existing circuit that does not activate:
Thank you for your quick response. Much appreciated. This is my first post on the Arduino forum and I am learning how it works. I think I could have been clearer with my question.
I have been successful in measuring battery level with my 3.3V board (powered by a single-cell Li-Ion battery) in "continuous" mode, thanks to the excellent description on the GitHub site.
I have not been able to make the "on demand" feature work, however. I have traced that problem, I think, to the p-channel mosfet in the "on-demand" circuit, which requires 5V logic. Specifically, the NTE2990 device I am using has a gate threshold voltage (Vgs) of 4 to 5.5 volts. The 3.3V board does not reach this threshold. P-channel mosfets that work at 3.3V or less threshold voltage appear to be rare.
I am not very familiar with transistor circuits. I am looking for help in creating a similar circuit which uses 3.3V devices and logic to accomplish the "on-demand" switching. Or, of course, any alternative methods of activating the battery level measurement only when needed.
It's such a common problem, that "logic level MOSFETs" have been used for that, for many years now. Just Google it, or search your transistor supplier web site.
The last logic level P-channel mosfet I used that came in a TO220 package was the NDP6020P. It had a typical threshold voltage of 0.7V. But it has been discontinued, and I don't think Digikey or Mouser have any left. They are still available on Ebay, etc., but with shipping are very expensive. I don't know of another logic level P-channel mosfet that comes in TO220.
The TP2104 comes in a through-hole TO92 package. It has a minimum threshold voltage of 1V and a maximum of 2V. If that means typical is 1.5V, then it should work ok. Actually, 2V would probably work fine too. $0.74 plus shipping at Digikey, and they have some in stock.
But to get really good performance, you'll need to get one that comes in an SOT23 package, which may be difficult to deal with because you'll need an SOT23-to-DIP adapter board to use it in a breadboard. The DMP1045U has a typical threshold of 0.5V, and very low DS resistance.
Really good performance mosfets are only found in surface mount packages these days. Improvements in through-hole parts ceased some years ago.
It sounds like I will be getting some practice in micro-soldering! Thank you for the suggestions on low-threshold mosfets. I think I will order a handful and also extra some adapter boards for learning the soldering techniques.
Another question: Can anyone explain to someone like me with limited electronics background what is the function of the NPN transistor Q1 in the above circuit? Some examples I have found on the internet attach the activation pin directly to the gate of the mosfet Q2, without the intervening NPN.
The NPN is used when the battery voltage is greater than the processor's Vcc. If you connected the I/O pin directly to the P-channel gate, current would flow from the battery through the gate pullup resistor and then through the protection diode that every I/O pin has from the pin to the Vcc pin at 3.3V. So the mosfet might never turn off.
But if you were using a boost converter to produce 5V, then you could do it that way, but then there would be a question of what to do with the pullup resistor - does it go to the battery, or to Vcc? The problem is that if you ever turn off the regulator and let Vcc go to ground, the mosfet will turn on.
Another way of doing it, as shown below, is to use a single N-channel mosfet in the middle of the voltage divider. But with that method, you would have to divide down the maximum 4.2V battery voltage to 1V or less to make sure the mosfet would turn on. A better mosfet than the 2N7000 would permit a somewhat higher voltage.
Thanks so much for your reply, and the suggested circuit. It seems that I will be best served, for the moment, to try the circuit with the NPN transistor, but substitute the low-threshold voltage p-channel mosfet you suggested. I will order some parts and report on my results.
In researching this subject, I found some good discussion in an Arduino forum post here. That forum thread also points to more discussion of battery level sensing for wireless sensors at:
» Zero-power measurement – part 2 » JeeLabs
Both good resources if somewhat over my head. The JeeLabs post suggests this variation on the circuit:
Both discussions refer to using the internal voltage reference of 1.1V, either calling it Aref or bandgap. Not sure how to access that, so may wait for another day and some more research before I try it.
Read the documentation for analogRead().
The capacitor is an interesting addition to the circuit. And I think it would work. You would just have to read the voltage quickly before the capacitor is recharged through the resistor and turns off the mosfet.
Basically, you can read the analog voltage with reference to Vcc, or with reference to the built-in 1.1V reference. But with the capacitor, I think you could just use Vcc.
Also the circuit is indifferent to polarity. You could place the MOSFET in the ground circuit and make it an N channel, if that's what you have on hand.
Well, you have to have the analog read pin below the mosfet. Otherwise you'll get current flow through its protection diode when the mosfet is off. You could put an N-channel in the middle, but then you don't really need the capacitor, and you have the problem of getting the source at a low enough voltage to get past threshold. I kinda like the P-channel at the top with the capacitor and a relatively high value pullup resistor. I can't think of a reason why it wouldn't work, and you can divide down to Vcc instead of 1V.
The circuit I'm suggesting, is a polarity wise exact mirror of the P-channel circuit. With the N channel MOSFET source to ground, gate tied to ground through the resistor, drain to the voltage divider. I can't see any voltage more negative than ground, that would cause the protection diode to conduct.
Then what voltage will the analog pin see when the mosfet is off? Will it not be Vbat?
I assumed the MCU in standby, not shut down. Then Vbat and Vdd/Vcc are the same, no voltage across the MCU protection diode.
I was assuming the OP was using a Li-ion battery with his SAMD21 running at a regulated 3.3V.
Thanks for pointing me in the right direction. From analogRead() I got to analogReference(). I see I have the option for my SAMD21 board for several different reference voltages, by making the below the argument for analogReference():
- AR_DEFAULT: the default analog reference of 3.3V
- AR_INTERNAL: a built-in 2.23V reference
- AR_INTERNAL1V0: a built-in 1.0V reference
- AR_INTERNAL1V65: a built-in 1.65V reference
- AR_INTERNAL2V23: a built-in 2.23V reference
- AR_EXTERNAL: the voltage applied to the AREF pin is used as the reference
Since I am using a single-cell LiIon battery, I think I will have my processor send me an alarm notice and then shut down if the battery voltage goes below 3.0V. That makes me think that the 2.23V reference will give me the best result by covering the lowest possible voltage and still providing good resolution.
Thanks for additional good input on the JeeLabs circuit with the capacitor. I see I have some fun experimenting ahead of me, as I think I will try prototyping the two different circuits, including using different reference voltages.
As I have mentioned before, my knowledge of transistor circuits is limited, so the discussion on n-channel vs. p-channel is over my head, sorry. But I will bumble along as best I can. I was able to order some TP2104 p-channel mosfets from digikey. Everything else was out of stock! The through hole form factor is probably best for me anyway. Looking forward to their arrival and some experiments.
So you would divide it down so that 4.2V on the battery would produce 2.23V in the middle of the divider? That will certainly work, but dividing down to 3.3V would also work.
I think there are a number of videos on Youtube about mosfets, and how to use them as switches.
Yes, I would divide it down so 4.2V on the battery would read 2.23 V on the divider. I was thinking about what would happen when the battery dropped down to 3.0 volts. My understanding is that the reference voltage would then drop also. You can't get a 3.3V reference voltage out of a 3.0 volt supply, my thinking goes. So I picked a reference voltage that is lower than the lowest supply voltage I will allow out of my battery. I arbitrarily picked 3.0 volts as the lowest I would allow in the programming so the battery doesn't discharge to a lower voltage and get damaged.
I assume your Sparkfun board has a voltage regulator on it that provides 3.3V to the SAMD21 processor. That regulator needs a minimum input voltage somewhat higher than 3.3V to provide regulated output. The additional voltage is the "dropout voltage". So you probably would want to shut down when the battery voltage falls below 3.5V, or whatever the dropout voltage calls for. It you take it down to 3V, just make sure the regulator will pass through the input voltage once it drops below the dropout voltage. It will no longer be regulated, but will probably still work.