I hope someone can help me, I'm at an impasse on my Battery Charger project. I'm using an arduino Mega.
I've written a BatteryHolder 'class', for each of four slots of my charger holding an individual AA, AA or Lithium battery. takes the following variables to control the charging independently; Requiring a constructor something like this;
BatteryHolder(int slot, int PWM, int relay, uint8_t highside, uint8_t lowside, uint8_t temperature, int batteryType, float capacity, float chargeDivider, uint8_t address);
the variables are:
slot, batteryType, capacity, chargeDivider (numbers, both int & float)). PWM, relay(two digital outputs on arduino) highside, lowside, temperature(analog inputs on arduino) address(an itc address for measuring current.
BatteryHolder::BatteryHolder(int slot, int PWM, int relay, uint8_t highside, uint8_t lowside, uint8_t temperature, int batteryType, float capacity, float chargeDivider, uint8_t address) { _slot = slot; _PWM = PWM; _relay = relay; _highside = highside; _lowside = lowside; _temperature = temperature; _batteryType = batteryType; _capacity = capacity; _chargeDivider = chargeDivider; _address = address; long startTime = chargeTime + millis(); //note the start of charging pinMode(PWM, OUTPUT); //Sets the gate voltage for MOSFET pinMode(relay, OUTPUT); pinMode(highside, INPUT); //Low side voltage of battery pinMode(lowside, INPUT); //High side voltage of battery pinMode(temperature, INPUT); //TEMPERATURE of battery
Adafruit_INA219 slotCurrent(_address); if (! slotCurrent.begin()) { Serial.println("Failed to find first INA219 chip"); while (1) { delay(10); } }
I then want to initiate the class by something like this:
Once constructed I don't want to replicate the same instructions for EACH slot, requiring four times the code to do the same thing to EACH class member.
I hope someone can help me, I'm at an impasse on my Battery Charger project. I'm using an arduino Mega.
I've written a BatteryHolder 'class', for each of four slots of my charger holding an individual AA, AA or Lithium battery. takes the following variables to control the charging independently; Requiring a constructor something like this;
BatteryHolder(int slot, int PWM, int relay, uint8_t highside, uint8_t lowside, uint8_t temperature, int batteryType, float capacity, float chargeDivider, uint8_t address);
the variables are:
slot, batteryType, capacity, chargeDivider (numbers, both int & float)). PWM, relay(two digital outputs on arduino) highside, lowside, temperature(analog inputs on arduino) address(an itc address for measuring current.
[SNIP]...
I then want to initiate the class by something like this:
Once constructed I don't want to replicate the same instructions for EACH slot, requiring four times the code to do the same thing to EACH class member.
For some reason it won't let me attach my '.CPP' file? So I've just attached it below
Thank you again, for the assist, & I hope you can see where I've gone wrong, as I'm two steps from checking myself into a assylm! 😜
/* Battery Holder library
Copyright 2020 Christine Whybrow
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
This library takes care of all the code to charge an individual battery, either AAA, AA. Example of constructors for NiMH AA Battery in each slot. You can of course change this, & in that eventuality, you should vary the following
float maxVoltage = 4200.0; //cut off in millivolts float XL005Set = 5.00; //manually adjust XL005 to this voltage for niMH float XL00518650set = 6.2; //manually adjust XL005 to this voltage for 18650 int slot_Number = 1; //holds which slot is active
float voltageHighAverage = 0; //this will hold ten high readings of battery voltage float voltageLowAverage = 0; //this will hold ten low readings of battery voltage float targetCurrent = Capacity18650 / 4;//416.0 mA float trickleCharge = Capacity18650 / 20.0; //CapacityNiMH / 20, which is around 125.0 mA float currentAverage = 0; //allow averaging of current readings float nowCurrent = 0; //will hold the averaage current readings float highVolts = 0; //low side analog pin for slot 1 float lowVolts = 0; //high side analog pin for slot 1 float voltageOverCount = 0; double tempHolder = 0; //holds calculation of temperature double celsius = 0; //holds final celsius temperature int temperatureAverage = 0; //holds average of multiple temperature readings int temperatureCount = 0; //ensures through multtiple readings that temp must 'STOP' int temperatureOverCount = 0; //if temp over limit 3 times,we'STOP', & go to trickle float TemperatureCutOff = 37.0; //Battery should go to trickle at this temp bool overTemp = false; //these will be set to 'true' if these conditions are met bool overVolt = false; bool overTime = false;
char *errorMsg[] = { "\t\t\tCurrent hasn't been changed", "\t\t\tCurrent has been increased", "\t\t\tCurrent has been decreased", "\t\t\tBattery charged, going to trickle", "\t\t\tTemperature exceeded, going to trickle","\t\t\tCharging STOPPED, time exceeded"};
BatteryHolder::BatteryHolder (int slot, int PWM, int relay, uint8_t highside, uint8_t lowside, uint8_t temperature, int batteryType, float capacity, float chargeDivider, uint8_t address) { _slot = slot; _PWM = PWM; _relay = relay; _highside = highside; _lowside = lowside; _temperature = temperature; _batteryType = batteryType; _capacity = capacity; _chargeDivider = chargeDivider; _address = address; long startTime = chargeTime + millis(); //note the start of charging pinMode(PWM, OUTPUT); //Sets the gate voltage for MOSFET pinMode(relay, OUTPUT); pinMode(highside, INPUT); //Low side voltage of battery pinMode(lowside, INPUT); //High side voltage of battery pinMode(temperature, INPUT); //TEMPERATURE of battery
Adafruit_INA219 slotCurrent(_address); if (! slotCurrent.begin()) { Serial.println("Failed to find first INA219 chip"); while (1) { delay(10); } }
bool BatteryHolder::batteryUpdate() { if (overTime) { return false; //charging has been stopped, go no further } analogWrite(_PWM, nowOutput); digitalWrite(_relay, HIGH); delay(50); //allow time for mosfet to settle
float currentAverage = 0; //reset average tally for (int i =0; i<10; i++) { currentAverage +=Slot1ina219.getCurrent_mA();//get another reading delay(50); //allow MOSFET to settle between readings } nowCurrent = currentAverage / 10; //we now have ten readings to average
analogWrite(_PWM, 0); //temporarially stop charging digitalWrite(_relay, LOW); //switch relay 'OFF' to allow precision measure of voltage delay(50); //allow time to settle
temperatureAverage = 0; voltageHighAverage = 0; //reset average tally voltageLowAverage = 0; for (int i =0; i<10; i++) { voltageHighAverage += analogRead(_highside);//get another high reading voltageLowAverage += analogRead(_lowside);//get another low reading temperatureAverage += analogRead(_temperature); delay(50); //allow probes to settle between readings }
if (voltage > maxVoltage) { if (voltageOverCount > 3) { Serial.println(errorMsg[3]); targetCurrent = trickleCharge; //need to stop heavy charging nowOutput = VGSminSet; overVolt = true; voltageOverCount = 0; } voltageOverCount++; return true; } if (celsius > TemperatureCutOff) {
if (temperatureOverCount > 3) { nowOutput = VGSminSet; //drop PWM output back to lowest output temperatureOverCount = 0; //reset the count overTemp = true; Serial.println(errorMsg[4]); return false; } overTemp = false; //charging CAN go back to full rate, after cooling temperatureOverCount++; return true; //keep charging for now
} if (millis() > chargeTime) //Out of time { Serial.println(errorMsg[5]); digitalWrite(_relay, LOW); //switch off charging circuit nowOutput = 0; //turn off PWM output overTime = true; //no more charging allowed return false; }
if (abs(nowCurrent - targetCurrent) > 25) //Don't change output unless greater than 25mA difference { if ((nowCurrent > targetCurrent) && (nowOutput > VGSminSet)) { nowOutput--; Serial.println(errorMsg[2]); return true; }
Sorry, in my example I just copied your's and added the temporaries, but forgot to remove the multiples - Of course there will be conflicts having 4 slots 🙂 Try either of the following, should work:
I had a quick look at your header file, and you may need a default constructor, if so, you should get a warning message stating something to that nature. Hopefully it's all good this time 🙂 Cheers
The first iteration you provided led to these errors;
IRF540_Test_take_2:48:21: error: no matching function for call to 'BatteryHolder::BatteryHolder()' BatteryHolder Slot[4]; ^ In file included from /Users/christine/Documents/Arduino/IRF540_Test_take_2/IRF540_Test_take_2.ino:41:0: sketch/BatteryHolder.h:42:5: note: candidate: BatteryHolder::BatteryHolder(int, int, int, uint8_t, uint8_t, uint8_t, int, float, float, uint8_t) BatteryHolder (int slot, int PWM, int relay, uint8_t highside, uint8_t lowside, ^~~~~~~~~~~~~ sketch/BatteryHolder.h:42:5: note: candidate expects 10 arguments, 0 provided sketch/BatteryHolder.h:39:7: note: candidate: constexpr BatteryHolder::BatteryHolder(const BatteryHolder&) class BatteryHolder ^~~~~~~~~~~~~ sketch/BatteryHolder.h:39:7: note: candidate expects 1 argument, 0 provided IRF540_Test_take_2:49:1: error: 'Slot' does not name a type Slot[0] = BatteryHolder(1, 4, 5, A0, A1, A2, 3, 2300.0, 5.0, 0X40); ^~~~ IRF540_Test_take_2:50:1: error: 'Slot' does not name a type Slot[1] = BatteryHolder(2, 6, 7, A3, A4, A5, 3, 2300.0, 5.0, 0X41); ^~~~ IRF540_Test_take_2:51:1: error: 'Slot' does not name a type Slot[2] = BatteryHolder(3, 8, 9, A6, A7, A8, 3, 2300.0, 5.0, 0X42); ^~~~ IRF540_Test_take_2:52:1: error: 'Slot' does not name a type Slot[3] = BatteryHolder(4, 10, 11, A9, A10, A11, 3, 2300.0, 5.0, 0X43); ^~~~ exit status 1 no matching function for call to 'BatteryHolder::BatteryHolder()'
The second, resulted in the following;
IT WORKS!!
I couldn't believe it, as my slot[i].doesExist() returned that the class had been created!
Any idea why the first didn't work, was it reliant on my having a second 'default constructor'?
In any event, thank you, I hope I can now get this thing to work, & finally be able to get this 'weekend task' working. My code does charge NiMH Lithium batteries, I just have to get that done with my newly created class!
The first iteration you provided led to these errors;
IRF540_Test_take_2:48:21: error: no matching function for call to 'BatteryHolder::BatteryHolder()' BatteryHolder Slot[4]; ^ In file included from /Users/christine/Documents/Arduino/IRF540_Test_take_2/IRF540_Test_take_2.ino:41:0:
IRF540_Test_take_2:48:21: error: no matching function for call to 'BatteryHolder::BatteryHolder()'
...you see, the moment you declare your own constructor, the implementation no longer provides a default one for you, so an object(s) such as:
BatteryHolder Slot; // Requires default constructor BatteryHolder Slot[4]; // 4 objects that require the default constructor
...will not compile.
So, for your class, just declare a default constructor as well: "BatteryHolder();", with the body in the .cpp implementation file like your custom constructor, and it should also work.
In any event, thank you, I hope I can now get this thing to work, & finally be able to get this 'weekend task' working. My code does charge NiMH Lithium batteries, I just have to get that done with my newly created class!
I'm using a INA219 current sensor, to track the current applied to the rechargeable battery, & have four of them, each of which I've soldered tracks to give all four possible units.
As such, as I called every BatteryHolder constructor 'object' I also called the Adafruit class like this;
Adafruit_INA219 slotCurrent(_address); if (! slotCurrent.begin()) { Serial.println("Failed to find first INA219 chip"); while (1) { delay(10); } }
I had hoped that would mean for every call to BatteryHolder::BatteryUpdate, would mean I was referring to those distinct objects, so I would be able to use something like this;
float currentAverage = 0; //reset average tally for (int i =0; i<10; i++) { currentAverage +=slotCurrent.getCurrent_mA();//get another reading delay(50); //allow MOSFET to settle between readings }
I thought that having initialized the objects within my constructor, I could thereafter just refer to slotCurrent.whatever(), the class would ensure the right getCurrent() but alas, I get this error;
BatteryHolder.cpp:169:25: error: 'slotCurrent' was not declared in this scope currentAverage +=slotCurrent.getCurrent_mA();//get another reading ^~~~~~~~~~~
Could I perhaps initialize the Adafruit sensor by returning a Adafruit_INA218 'object' or a ->'pointer' so that the other calls to BatteryHolder subroutines, would know exactly WHICH sensor is being used at that time?
Or am I just getting myself confused? WHY can't I upload a '.cpp' file to here, now I'm confused bout THAT too.? I'll just attach it to the end here. This must be the MOST drawn out 'weekend build' in all history! 😜
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
This library takes care of all the code to charge an individual battery, either AAA, AA. Example of constructors for NiMH AA Battery in each slot. You can of course change this, & in that eventuality, you should vary the following
//#define I2C_ADDRESS1 0x40 //address of INA219 current sensor //#define I2C_ADDRESS2 0x41 //#define I2C_ADDRESS3 0x42 //#define I2C_ADDRESS4 0x43
//Adafruit_INA219 slotCurrent(I2C_ADDRESS1); //One ina219 per battery
const float VGSmin = 2.0; //in volts for irf510 const float VGSmax = 4.2; //in VGS conductive range int VGSminSet = VGSmin * 255/ 5.0;//Converts figures to PWM Output values int VGSmaxSet = VGSmax * 255 / 5.0; int startOutput = (VGSmaxSet + VGSminSet) / 2; //Pick an arbitrary mid point float nowOutput = startOutput; //float CapacityNiMH = 2300; //in mAh //float Capacity18650 = 3600; //maximum charge rate 1250mA //float targetVoltage = 4200.0; //cut off in millivolts float XL005Set = 5.00; //manually adjust XL005 to this voltage for niMH float XL00518650set = 6.2; //manually adjust XL005 to this voltage for 18650 int slot_Number = 1; //holds which slot is active
float voltageHighAverage = 0; //this will hold ten high readings of battery voltage float voltageLowAverage = 0; //this will hold ten low readings of battery voltage //float targetCurrent = Capacity18650 / 4;//416.0 mA //float trickleCurrent = Capacity18650 / 20.0;//CapacityNiMH / 20, which is around 125.0 mA float currentAverage = 0; //allow averaging of current readings float nowCurrent = 0; //will hold the averaage current readings float highVolts = 0; //low side analog pin for slot 1 float lowVolts = 0; //high side analog pin for slot 1 float voltageOverCount = 0; double tempHolder = 0; //holds calculation of temperature double celsius = 0; //holds final celsius temperature int temperatureAverage = 0; //holds average of multiple temperature readings int temperatureCount = 0; //ensures through multtiple readings that temp must 'STOP' int temperatureOverCount = 0; //if temp over limit 3 times,we'STOP', & go to trickle float TemperatureCutOff = 37.0; //Battery should go to trickle at this temp bool overTemp = false; //these will be set to 'true' if these conditions are met bool overVolt = false; bool overTime = false;
char *errorMsg[] = { "\t\t\tCurrent hasn't been changed", "\t\t\tCurrent has been increased", "\t\t\tCurrent has been decreased", "\t\t\tBattery charged, going to trickle", "\t\t\tTemperature exceeded, going to trickle","\t\t\tCharging STOPPED, time exceeded"};
pinMode(PWM, OUTPUT); //Sets the gate voltage for MOSFET pinMode(relay, OUTPUT); pinMode(highside, INPUT); //Low side voltage of battery pinMode(lowside, INPUT); //High side voltage of battery pinMode(temperature, INPUT); //temperature of battery
Adafruit_INA219 slotCurrent(_address); if (! slotCurrent.begin()) { Serial.println("Failed to find first INA219 chip"); while (1) { delay(10); } }
}
bool BatteryHolder::setLimits(float targetCurrent, float targetVoltage, float trickleCurrent) { _targetCurrent = targetCurrent; //setlimits _targetVoltage = targetVoltage; _trickleCurrent = trickleCurrent; } BatteryHolder::~BatteryHolder() { // set a destructor here if needed }
bool BatteryHolder::setTimeToStop(double stopTime) //When battery inserted, note time to STOP { _timeToStop = stopTime + millis(); //note the start of chargingstartTime return true; }
bool BatteryHolder::batteryUpdate() { if (overTime) { return false; //charging has been stopped, go no further } analogWrite(_PWM, nowOutput); digitalWrite(_relay, HIGH); delay(50); //allow time for mosfet to settle
float currentAverage = 0; //reset average tally for (int i =0; i<10; i++) { currentAverage +=slotCurrent.getCurrent_mA();//get another reading delay(50); //allow MOSFET to settle between readings } nowCurrent = currentAverage / 10; //we now have ten readings to average
analogWrite(_PWM, 0); //temporarially stop charging digitalWrite(_relay, LOW); //switch relay 'OFF' to allow precision measure of voltage delay(50); //allow time to settle
temperatureAverage = 0; voltageHighAverage = 0; //reset average tally voltageLowAverage = 0; for (int i =0; i<10; i++) { voltageHighAverage += analogRead(_highside);//get another high reading voltageLowAverage += analogRead(_lowside);//get another low reading temperatureAverage += analogRead(_temperature); delay(50); //allow probes to settle between readings }
if (voltage > _targetVoltage) { if (voltageOverCount > 3) { Serial.println(errorMsg[3]); _targetCurrent = _trickleCurrent; //need to stop heavy charging nowOutput = VGSminSet; overVolt = true; voltageOverCount = 0; } voltageOverCount++; return true; } if (celsius > TemperatureCutOff) {
if (temperatureOverCount > 3) { nowOutput = VGSminSet; //drop PWM output back to lowest output temperatureOverCount = 0; //reset the count overTemp = true; Serial.println(errorMsg[4]); return false; } overTemp = false; //charging CAN go back to full rate, after cooling temperatureOverCount++; return true; //keep charging for now
} if (millis() > _timeToStop) //Out of time { Serial.println(errorMsg[5]); digitalWrite(_relay, LOW); //switch off charging circuit nowOutput = 0; //turn off PWM output overTime = true; //no more charging allowed return false; }
if (abs(nowCurrent - _targetCurrent) > 25) //Don't change output unless greater than 25mA difference { if ((nowCurrent > _targetCurrent) && (nowOutput > VGSminSet)) { nowOutput--; Serial.println(errorMsg[2]); return true; }
I'm using a INA219 current sensor, to track the current applied to the rechargeable battery, & have four of them, each of which I've soldered tracks to give all four possible units.
As such, as I called every BatteryHolder constructor 'object' I also called the Adafruit class like this;
Adafruit_INA219 slotCurrent(_address); if (! slotCurrent.begin()) { Serial.println("Failed to find first INA219 chip"); while (1) { delay(10); } }
I had hoped that would mean for every call to BatteryHolder::BatteryUpdate, would mean I was referring to those distinct objects, so I would be able to use something like this;
float currentAverage = 0; //reset average tally for (int i =0; i<10; i++) { currentAverage +=slotCurrent.getCurrent_mA();//get another reading delay(50); //allow MOSFET to settle between readings }
I thought that having initialized the objects within my constructor, I could thereafter just refer to slotCurrent.whatever(), the class would ensure the right getCurrent() but alas, I get this error;
BatteryHolder.cpp:169:25: error: 'slotCurrent' was not declared in this scope currentAverage +=slotCurrent.getCurrent_mA();//get another reading ^~~~~~~~~~~
Could I perhaps initialize the Adafruit sensor by returning a Adafruit_INA218 'object' or a ->'pointer' so that the other calls to BatteryHolder subroutines, would know exactly WHICH sensor is being used at that time?
Or am I just getting myself confused? WHY can't I upload a '.cpp' file to here, now I'm confused bout THAT too.? I'll just attach it to the end here. This must be the MOST drawn out 'weekend build' in all history!
The error message is correct... having a quick look, you have declared and defined the "slotCurrent" variable of type "Adafruit_INA219", local to your constructor "BatteryHolder::BatteryHolder(...)". Once your constructor runs, and your BatteryHolder objects are instantiated, this variable goes out of scope, therefore it is not visible in other parts of the code.
If you want it to be part of the class, add it is as a member variable of the class, and then dereference it with an object (or without and object if made static), or place it in the global namespace area which will make it easier to use overall.
then within my BatterHolder.cpp tells me that a call to slotCurrent[].whatever is 'out of scope'.
If i put those same lines in BatteryHolder.CPP at the top, then a call to slotcurrent[].whatever is met with the same error, in Battery_Charger_v2.INO.
Can you tell me what I'm doing wrong? I think I've tried just about everything....except the RIGHT thing apparently!
Thanks again, sorry my C++ experience is limited, I'd mostly just thought this project would allow me to learn Fusion360, though now, that's been the EASIER part.
I've found the problem, I have declared the Adafruit_INA219 as a private member of the BatteryHolder.h file. I've altered lots of things, I have to now check what i THINK it does, is what it ACTUALLY does;
but at least it's stopped drowning me in 'error messages'!
I'm not sure what you mean by that, because as an experienced C++ programmer, the error message that I confirmed to you previously, was pretty accurate and very clear!
Can you tell me what I'm doing wrong? I think I've tried just about everything....except the RIGHT thing apparently!
Thanks again, sorry my C++ experience is limited, I'd mostly just thought this project would allow me to learn Fusion360, though now, that's been the EASIER part.
I'm trying to help you, but you're changing your code without really understanding what's going on, and at the same time, you're not providing us with the details of the changes you have made in your code!
Please elaborate, provide your latest code changes and error messages, and lets take it from there, OK?
Okay, I'm so sorry, I'm not doing this intentionally, I'm trying to learn C++. I even bought a second hand copy of 'C++ Primer' by Lippmam, Lajoie & Moo(imagine going through life with that name).
It's supposed to be the C++ bible, but not exactly the Rosetta stone, easily translated to my experience level.
I'm attaching my .INO.h files, & will have to copy my .cpp file(is there a way to upload that, other than by 'pasting' it?)
About two months go, I started designing the display portion of my charger design, & had succeeded in making the display.
The battery charging portion, that you had helped me with, finally had no errors while compiling. So, earlier today, I put both together, & it has refused to work for me. I'm getting ridiculous current readings of "inf mA", regardless of the PWM input I'm feeding it. I'm guessing I'm not actually linking the INA219, & am receiving some built in value.
Again, I'm sorry. I'm trying to understand your help, but am not up to the task.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
This library takes care of all the code to charge an individual battery, either AAA, AA. Example of constructors for NiMH AA Battery in each slot. You can of course change this, & in that eventuality, you should vary the following
//const float VGSmin = 2.0; //in volts for irf510 //const float VGSmax = 4.2; //in VGS conductive range //int VGSminSet = VGSmin * 255/ 5.0;//Converts figures to PWM Output values //int VGSmaxSet = VGSmax * 255 / 5.0; //int startOutput = (VGSmaxSet + VGSminSet) / 2; //Pick an arbitrary mid point //float nowOutput = startOutput; //float CapacityNiMH = 2300; //in mAh //float Capacity18650 = 3600; //maximum charge rate 1250mA //float targetVoltage = 4200.0; //cut off in millivolts //float XL005Set = 5.00; //manually adjust XL005 to this voltage for niMH //float XL00518650set = 6.2; //manually adjust XL005 to this voltage for 18650 //int slot_Number = 1; //holds which slot is active
//float voltageHighAverage = 0; //this will hold ten high readings of battery voltage //float voltageLowAverage = 0; //this will hold ten low readings of battery voltage ////float targetCurrent = Capacity18650 / 4;//416.0 mA ////float trickleCurrent = Capacity18650 / 20.0;//CapacityNiMH / 20, which is around 125.0 mA //float currentAverage = 0; //allow averaging of current readings //float nowCurrent = 0; //will hold the averaage current readings //float highVolts = 0; //low side analog pin for slot 1 //float lowVolts = 0; //high side analog pin for slot 1 //float voltageOverCount = 0; //double tempHolder = 0; //holds calculation of temperature //double celsius = 0; //holds final celsius temperature //int temperatureAverage = 0; //holds average of multiple temperature readings //int temperatureCount = 0; //ensures through multtiple readings that temp must 'STOP' //int temperatureOverCount = 0; //if temp over limit 3 times,we'STOP', & go to trickle //float TemperatureCutOff = 37.0; //Battery should go to trickle at this temp //bool overTemp = false; //these will be set to 'true' if these conditions are met //bool _overVolt = false; //bool overTime = false;
char *errorMsg[] = { "\t\t\tCurrent hasn't been changed", "\t\t\tCurrent has been increased", "\t\t\tCurrent has been decreased", "\t\t\tBattery charged, going to trickle", "\t\t\tTemperature exceeded, going to trickle","\t\t\tCharging STOPPED, time exceeded"};
pinMode(PWM, OUTPUT); //Sets the gate voltage for MOSFET pinMode(relay, OUTPUT); pinMode(highside, INPUT); //Low side voltage of battery pinMode(lowside, INPUT); //High side voltage of battery pinMode(temperature, INPUT); //temperature of battery
void BatteryHolder::setTimeToStop(unsigned long stopTime) //When battery inserted, note time to STOP { _timeToStop = stopTime + millis(); //note the start of charging return true; } /* * This is the main program, doing the bulk of the work to charge the battery * ************************************************************************** */ bool BatteryHolder::batteryUpdate() {
if (millis() > _timeToStop) { Serial.print("at start of time loop ");Serial.print(_timeToStop);Serial.print("\t\t"); Serial.println(millis()); return false; //charging has been stopped, go no further } digitalWrite(_relay, HIGH); analogWrite(_PWM, _nowOutput); Serial.print(_PWM); Serial.print("\t");Serial.println( _nowOutput); delay(50); //allow time for mosfet to settle
float currentAverage = 0; //reset average tally for (int i =0; i<10; i++) { currentAverage += slotCurrent[_slot - 1].getCurrent_mA();//get another reading delay(60); //allow MOSFET to settle between readings } float _nowCurrent = currentAverage / 10; //we now have ten readings to average
analogWrite(_PWM, 0); //temporarially stop charging digitalWrite(_relay, LOW); //switch relay 'OFF' to allow precision measure of voltage delay(50); //allow time to settle
float temperatureAverage = 0; float voltageHighAverage = 0; //reset average tally float voltageLowAverage = 0; for (int i =0; i<10; i++) { voltageHighAverage += analogRead(_highside);//get another high reading voltageLowAverage += analogRead(_lowside);//get another low reading temperatureAverage += analogRead(_temperature); delay(50); //allow probes to settle between readings }
if (voltage > _targetVoltage) { if (_voltageOverCount > 3) { Serial.println(errorMsg[3]); _targetCurrent = _trickleCurrent; //need to stop heavy charging _nowOutput = _VGSminSet; _overVolt = true; _voltageOverCount = 0; } _voltageOverCount++; return true; } if (celsius > _temperatureCutOff) {
if (_temperatureOverCount > 3) { _nowOutput = _VGSminSet; //drop PWM output back to lowest output _temperatureOverCount = 0; //reset the count _overTemp = true; Serial.println(errorMsg[4]); return false; } _overTemp = false; //charging CAN go back to full rate, after cooling _temperatureOverCount++; return true; //keep charging for now
} if (millis() > _timeToStop) //Out of time { Serial.println(errorMsg[5]); digitalWrite(_relay, HIGH); //switch off charging circuit _nowOutput = 0; //turn off PWM output //overTime = true; //no more charging allowed return false; }
if (abs(_nowCurrent - _targetCurrent) > 25) //Don't change output unless greater than 25mA difference { if ((_nowCurrent > _targetCurrent) && (_nowOutput > _VGSminSet)) { _nowOutput--; Serial.println(errorMsg[2]); return true; }
OK, I've largely got this working now, both the INA219 & BatteryHolder classes are finally playing nice. Now i just have to work out how to have four of these instances running 'virtually' in my battery slots of the charger.
Thnx for the help!
Christine
ReplyQuote
We use cookies on the DroneBot Workshop Forums to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.