Go Down

Topic: ni-mh battery charger Vin problem (Read 1 time) previous topic - next topic

raptor

#15
Aug 02, 2017, 07:13 pm Last Edit: Aug 02, 2017, 07:22 pm by raptor
well I have the 12V 2A as the main power supply and attached the Vin the a 7805 with a 100uf cap connected to the 12V and the input of the 7805, a 10uf cap to the output of the 7805. both caps have a common ground.
the link light is lit but dim the on and TX are fine but my readings are weird.

Code: [Select]
int batteryCapacity = 2500;     //capacity rating of battery in mAh (was 2500)
float resistance = 10.0;     //measured resistance of the power resistor
int cutoffVoltage = 15000;     //maximum battery voltage (in mV) that should not be exceeded (was1600)
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 = 14000 - voltageProbeTwo;     //calculate battery voltage (was 500)
  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 was 10)
   {
    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
}



   
 
I think jremington is right and I might just scrap it.

markba633csi

#16
Aug 03, 2017, 02:51 am Last Edit: Aug 03, 2017, 02:58 am by markba633csi
It should be a workable circuit but the cutoff voltage should be equal to the total battery pack voltage + about 5-8% or so.
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.
The gate resistor should be a lower value, say 10k ohm and there should be a resistor from gate to ground of about 100k ohm.
Remember that power mosfet transistors are sensitive and can be destroyed by static and careless handling. The original circuit puts the gate in a perilous position in that regard- the fet could be damaged already.
If your supply needs to be more that 12 volts there should be a current limiting/voltage dropping  resistor between the supply and the arduino Vin.  Use ohm's law to calculate the value.  Desired voltage drop divided by the expected arduino input current in amps equals the value in ohms. It may have to be a fairly hefty resistor like 1 watt or more.
Mark
 

jremington

Quote
It should be a workable circuit
Just barely workable, with the indicated, non-logic-level MOSFET.

raptor

thank you so much mark I'm going to try that out soon, but I'm a noob. when you say "gate" do you mean the emitter, collector, or base?

srnet

thank you so much mark I'm going to try that out soon, but I'm a noob. when you say "gate" do you mean the emitter, collector, or base?
Gate was the correct term.

MOSFETS (Metal Oxide Semiconductor Field Effect Transistors) have gate, drain and source connections.
Bipolar Transistors have base, emitter and collector.

Incidently if you get the circuit or code foe the charger wrong, NiMh batteries get hot very quickly if charge is not stopped when full charge is reached.
No PMs please, they dont get answered.

JohnLincoln

#20
Aug 03, 2017, 07:29 pm Last Edit: Aug 03, 2017, 08:06 pm by JohnLincoln
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.

JohnLincoln

#21
Aug 03, 2017, 09:19 pm Last Edit: Aug 03, 2017, 09:52 pm by JohnLincoln
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:
Code: [Select]
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 VDS1.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).




markba633csi

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

Go Up