What they are really measuring with the capacitive model of a battery is not the 'equivalent capacitance' of the battery but the capacitance needed to store x kJ of energy at that voltage range which means that value is much higher than the actual battery capacitance. For measuring peak discharge rates it's fairly accurate (10%) with good internal lookup tables but it can be wildly inaccurate for total battery Ah capacity when used with worn lead acid batteries.
https://doc.utwente.nl/64556/1/BatteryRep4.pdf
Hi,
Yes that's what i meant by (quote) "capacitance correlates to the Ampere Hour capacity".
?.... For measuring peak discharge rates it's fairly accurate (10%) with good internal lookup tables but it can be wildly inaccurate for total battery Ah capacity when used with worn lead acid batteries.
https://doc.utwente.nl/64556/1/BatteryRep4.pdf
When you say wildly inaccurate, what sort of figure are you thinking ? I've found it to be a good indicator, but never crossed referenced with a discharge test
Thanks all for the answers.
..
Now this will not be the true Ampere Hour rating because we did not take into account the effects of different load currents on the same battery. Thus we' d have to adjust this factor using what is known as the "P" factor or "Peukert Factor".
Also note that we loaded this battery with a huge current (10 amps) relative to it's capacity, which we would not want to do either. The manufacturers usually use a C/20 discharge when rating the batteries, where C is the capacity in Ampere Hours here. We probably do have to use a higher current than that however in order to make the test method much faster.
This gives an idea how to go about doing this kind of test and is not meant to be exact.
#if defined(__18CXX)
typedef struct celltype { // C18 uses byte alignment
#else
typedef struct __attribute__((aligned(1))) celltype { // force C32 to byte alignment, 32bit alignment is still critical
#endif
uint16_t id, model; // battery cell type S,M,L
int32_t voltage, current, charge, cycles, noload, date;
uint8_t cconline, online, discharged, dead, critical, valid, fresh, misc;
float weight;
}
volatile celltype;
/* hist[x].h[x]
* h0 Peukert Factor adjusted Ah usage this cycle, MUST BE INTERGER variable type!
* h1 Lowest discharge ever,
* h2 current lowest discharge,
* h3 avg discharge
* h4 Number of full charge cycles, h5 Number of full discharge cycles
* h6 Real Ah usage this cycle, MUST BE INTERGER variable type!
* h7 Min Batt Voltage
* h8 Max Batt Voltage
* h9 Lowest ESR Pre
* h10 Lowest ESR Post
*/
#if defined(__18CXX)
typedef struct histtype { // C18 uses byte alignment
#else
typedef struct __attribute__((aligned(1))) histtype { // force C32 to byte alignment, 32bit alignment is still critical
#endif
uint16_t rate, udod, bsoc, bound_rate, bound_factor, samplei, sampleo, ah, drate, esr, rest_rate, rest_factor, esrp;
int16_t h[HPARAM_SIZE]; // h[6]=cumulative battery Ah cc and inv (real),h[0]=cumulative battery Ah cc and inv (p_adj)
int32_t kwi, kwo, ttg, btest;
int32_t ahi, aho, ahir, ahop, thermo; // A stored in battery, A taken from battery, A from raw pv, peukert adjusted A
int32_t pv_eff, tot_eff; // pv generation eff factor, total system eff factor
float peukert, cef, peukert_adj, cef_calc, cef_save;
}
volatile histtype;
typedef struct R_data { // set only in adc_read
int32_t current, currentin, currentcharger, thermo_batt;
uint32_t systemvoltage, ccvoltage, inputvoltage, primarypower[POWER_SLOTS];
} R_data;
typedef struct V_data { // OS Counters
uint32_t highint_count, lowint_count, eeprom_count, timerint_count, adc_count, mbmcdata_count, c1rx_int, c1tx_int, c2_int, buttonint_count,
clock50, pwm4int_count;
} V_data;
typedef struct C_data { // set only in adc_read
int32_t currentload;
int temp_drate;
float t_comp;
} C_data;
typedef struct B_data {
int16_t start_ahu, cef_raw; // must be int TYPE
uint32_t start_ahi, start_aho, absorp_ahi, absorp_time, charge_time_left; // uint32_t TYPE
uint8_t yesterday, today, r_soc[DATA_SLOTS]; // Harvest quality for the whole day, 0..100, uses time of harvest (seconds) -> input power (watts) -> max power (watts).
int32_t diversion;
} volatile B_data; // of each measurement during that period.
I then do a sanity check on the results by comparison and select or blend the models results depending on the current mode of operation (rest, charge, discharge).
The code base is a mess and the amount of parameters is unwieldy but it works fairly well to keep track of capacity and 'time to go' with dynamic loading and charging after fine tuning
I do straight coloumb counting on my batteries with 3kHz sampling rate and minor corrections introduced at higher voltages. Works fairly well too. Accuracy is within 1% most of the time (3.5% worst case I have on record).
... program defines
/* The number of samples must be high to sample several complete PWM cycles from the CC to get stable voltage and current measurements at lower ranges. */
#define ADC_SAMP_F 128
#define ADC_SAMP_S 512
#define ADC_CHAN_DELAY 100 // delay in 10X chip cycles after switching ADC channels
... Daq header
extern uint32_t Vin, rawp1, rawp2, rawp3, vbatol_t, solar_t;
... Daq code functions
ADC_zero();
SetChanADC(ADC_CH1); // Smooth the voltage from the CC as it contains PWM pulses.
Delay10TCYx(ADC_CHAN_DELAY);
Vin = 0;
for (i = 0; i < ADC_SAMP_S; i++) {
ConvertADC();
while (BusyADC());
Vin += (uint16_t) ReadADC();
}
Vin /= ADC_SAMP_S; // very long measurement sample time to get several PWM cycles from CC
Yea, I do fast sampling with averaging in the ADC routines to integrate the PWM cycles from the charge controller into a stable signal then send it to a digital LP filter later.
That 'estimate' is only good for early life in batteries. As batteries' age the 'knee' voltage moves and this can lead to unpredictable results with a sudden drop off of Ah.I have an ACT gold battery tester. In the space of a few seconds it displays capacity in Ah for 6 or 12 volt batteries. Can anyone explain how it does it?
Hi,
Just to note, a physical RC filter is often not as good as doing it in software because a physical RC filter reduces the noise content of the signal. I wont say that this will always be the case, but i think it is most often the case
Can you explain why you'd want noise to hit an ADC? I can imagine very fast real time control, not wanting to lose the higher end, but for almost everything else I'd lean towards a simple external filter....maybe wrongly?
Can you explain why you'd want noise to hit an ADC? I can imagine very fast real time control, not wanting to lose the higher end, but for almost everything else I'd lean towards a simple external filter....maybe wrongly?
I Can't understand How this Individual Cell Test is done?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?