ni-mh battery charger Vin problem

jremington:
Just barely workable, with the indicated, non-logic-level MOSFET.

I don't think it is necessary to use a logic level MOSFET in this design.

The 10MΩ resistor and 0.1μF capacitor form a low pass filter to convert the PWM output from D9 to a DC voltage.
The MOSFET is used in it's linear operating region to control the charging current.

Also if the MOSFET wasn't used in a linear mode, then it would be a lot more difficult to monitor the current by measuring the voltage across the 10Ω resistor.

markba633csi:
I see a value of 15000 so 15 volts. Is this correct for your 3 batteries in series? Then your main supply should be more than 15 volts.

In the article referred to by the OP in reply #1, the cut-off voltage is set to 1.6V for a single cell.
See the code below from the original author:

int batteryCapacity = 2500;     //capacity rating of battery in mAh
float resistance = 10.0;     //measured resistance of the power resistor
int cutoffVoltage = 1600;     //maximum battery voltage (in mV) that should not be exceeded
float cutoffTemperatureC = 35;     //maximum battery temperature that should not be exceeded (in degrees C)
//float cutoffTemperatureF = 95;     //maximum battery temperature that should not be exceeded (in degrees F)
long cutoffTime = 46800000;     //maximum charge time of 13 hours that should not be exceeded

int outputPin = 9;     // Output signal wire connected to digital pin 9
int outputValue = 150;     //value of PWM output signal 

int analogPinOne = 0;     //first voltage probe connected to analog pin 1
float valueProbeOne = 0;     //variable to store the value of analogPinOne
float voltageProbeOne = 0;     //calculated voltage at analogPinOne

int analogPinTwo = 1;     //second voltage probe connected to analog pin 2
float valueProbeTwo = 0;     //variable to store the value of analogPinTwo
float voltageProbeTwo = 0;     //calculated voltage at analogPinTwo

int analogPinThree = 2;     //third voltage probe connected to analog pin 2
float valueProbeThree = 0;     //variable to store the value of analogPinThree
float tmp36Voltage = 0;     //calculated voltage at analogPinThree
float temperatureC = 0;     //calculated temperature of probe in degrees C
//float temperatureF = 0;     //calculated temperature of probe in degrees F

float voltageDifference = 0;     //difference in voltage between analogPinOne and analogPinTwo
float batteryVoltage = 0;     //calculated voltage of battery
float current = 0;     //calculated current through the load (in mA)
float targetCurrent = batteryCapacity / 10;     //target output current (in mA) set at C/10 or 1/10 of the battery capacity per hour
float currentError = 0;     //difference between target current and actual current (in mA)



void setup()
{
  Serial.begin(9600);     //  setup serial
  pinMode(outputPin, OUTPUT);     // sets the pin as output
}



void loop()
{
    
  analogWrite(outputPin, outputValue);  //Write output value to output pin

  Serial.print("Output: ");     //display output values for monitoring with a computer
  Serial.println(outputValue); 

  valueProbeOne = analogRead(analogPinOne);    // read the input value at probe one
  voltageProbeOne = (valueProbeOne*5000)/1023;     //calculate voltage at probe one in milliVolts
  Serial.print("Voltage Probe One (mV): ");     //display voltage at probe one
  Serial.println(voltageProbeOne);  
  
  valueProbeTwo = analogRead(analogPinTwo);    // read the input value at probe two
  voltageProbeTwo = (valueProbeTwo*5000)/1023;     //calculate voltage at probe two in milliVolts
  Serial.print("Voltage Probe Two (mV): ");     //display voltage at probe two
  Serial.println(voltageProbeTwo);  
  
  batteryVoltage = 5000 - voltageProbeTwo;     //calculate battery voltage
  Serial.print("Battery Voltage (mV): ");     //display battery voltage
  Serial.println(batteryVoltage); 

  current = (voltageProbeTwo - voltageProbeOne) / resistance;     //calculate charge current
  Serial.print("Target Current (mA): ");     //display target current 
  Serial.println(targetCurrent);  
  Serial.print("Battery Current (mA): ");     //display actual current
  Serial.println(current);  
      
  currentError = targetCurrent - current;     //difference between target current and measured current
  Serial.print("Current Error  (mA): ");     //display current error 
  Serial.println(currentError);     

  valueProbeThree = analogRead(analogPinThree);    // read the input value at probe three  
  tmp36Voltage = valueProbeThree * 5.0;     // converting that reading to voltage
  tmp36Voltage /= 1024.0; 
 
  temperatureC = (tmp36Voltage - 0.5) * 100 ;     //converting from 10 mv per degree wit 500 mV offset to degrees ((voltage - 500mV) times 100)
  Serial.print("Temperature (degrees C) ");     //display the temperature in degrees C
  Serial.println(temperatureC); 
 
 /*
  temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;     //convert to Fahrenheit
  Serial.print("Temperature (degrees F) ");
  Serial.println(temperatureF); 
 */
 
  Serial.println();     //extra spaces to make debugging data easier to read
  Serial.println();  



  if(abs(currentError) > 10)     //if output error is large enough, adjust output
   {
    outputValue = outputValue + currentError / 10;

    if(outputValue < 1)    //output can never go below 0
     {
      outputValue = 0;
     }

    if(outputValue > 254)     //output can never go above 255
     {
      outputValue = 255;
     }
    
    analogWrite(outputPin, outputValue);     //write the new output value
   }
 
 
  if(temperatureC > cutoffTemperatureC)     //stop charging if the battery temperature exceeds the safety threshold
   {
    outputValue = 0;
    Serial.print("Max Temperature Exceeded");
   }
   
  /*
  if(temperatureF > cutoffTemperatureF)     //stop charging if the battery temperature exceeds the safety threshold
   {
    outputValue = 0;
   }
   */
   
   if(batteryVoltage > cutoffVoltage)     //stop charging if the battery voltage exceeds the safety threshold
   {
    outputValue = 0;
    Serial.print("Max Voltage Exceeded");
   }  
 
   if(millis() > cutoffTime)     //stop charging if the charge time threshold
   {
    outputValue = 0;
    Serial.print("Max Charge Time Exceeded");
   }  

   delay(10000);     //delay 10 seconds before next iteration
}

It is my belief that the original design and code might work correctly for charging a single cell from a 5V supply.

During correct operation I would expect the following typical voltages across the NiMH cell, 10Ω resistor, and MOSFET:

NiMH cell 1.0V - 1.6V
10Ω resistor 2.5V
MOSFET VDS 1.5V - 0.9V

The voltages across the 3 components will add up to 5V.

Clearly if 3 cells are put in series, then the majority of the 5V is across the 3 cells, and the circuit cannot operate as desired with 2.5V across the 10Ω resistor (for 250mA charging current).

Yes John is correct, I thought the battery voltage was much higher. The very high impedance gate circuit bothers me because even a small amount of moisture in and around the gate connection could cause a malfunction. I would have scaled the circuit so that the resistors were smaller and the cap was larger- by a factor of 10 at least.
Mark