Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
Libs/CoulombCounter/CoulombCounter.cpp@33:6bc82b6b62e5, 2015-01-06 (annotated)
- Committer:
- pspatel321
- Date:
- Tue Jan 06 20:45:26 2015 +0000
- Revision:
- 33:6bc82b6b62e5
- Parent:
- 30:91af74a299e1
- Child:
- 34:18bcf276d3bf
Updated IDs to match AMS, added a constants.h file.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
pspatel321 | 30:91af74a299e1 | 1 | #include "CoulombCounter.h" |
pspatel321 | 30:91af74a299e1 | 2 | |
pspatel321 | 30:91af74a299e1 | 3 | const float MSEC_HRS = 2.77778e-7; // Multiplier to convert milliseconds to hours |
pspatel321 | 30:91af74a299e1 | 4 | const float BAT_ISENSE_MULTIPLIER = 6.2299; // Multiplier to convert float to amps |
pspatel321 | 30:91af74a299e1 | 5 | const float BAT_ISENSE_OFFSET = -0.5*BAT_ISENSE_MULTIPLIER; // Offset to convert float to amps |
pspatel321 | 30:91af74a299e1 | 6 | const float BAT_ISENSE_LIMS = 3.0; // Over-current limit = +/- 3A |
pspatel321 | 30:91af74a299e1 | 7 | |
pspatel321 | 30:91af74a299e1 | 8 | const int rtcGPREG_counter = 0; // RTC GPREG offset for the coulomb counter |
pspatel321 | 30:91af74a299e1 | 9 | const int rtcGPREG_capacity = 1; // RTC GPREG offset for the capacity spec |
pspatel321 | 30:91af74a299e1 | 10 | |
pspatel321 | 30:91af74a299e1 | 11 | CoulombCounter::CoulombCounter(PinName _pin, int _mSec) : BatISense(_pin) { |
pspatel321 | 30:91af74a299e1 | 12 | mSec = _mSec; |
pspatel321 | 30:91af74a299e1 | 13 | |
pspatel321 | 30:91af74a299e1 | 14 | // Default capacity if blank or corrupted |
pspatel321 | 30:91af74a299e1 | 15 | float capReg = store.read(rtcGPREG_capacity); |
pspatel321 | 30:91af74a299e1 | 16 | if (capReg < 1.0 || capReg > 5.0) { // Bad, write default |
pspatel321 | 30:91af74a299e1 | 17 | store.write(defaultAh, rtcGPREG_capacity); |
pspatel321 | 30:91af74a299e1 | 18 | } |
pspatel321 | 30:91af74a299e1 | 19 | |
pspatel321 | 30:91af74a299e1 | 20 | // Default SOC if blank or corrupted |
pspatel321 | 30:91af74a299e1 | 21 | float Ah = store.read(rtcGPREG_counter); |
pspatel321 | 33:6bc82b6b62e5 | 22 | if (Ah < 0 || Ah > defaultAh) { // Bad, write default |
pspatel321 | 33:6bc82b6b62e5 | 23 | store.write(defaultSOC*defaultAh, rtcGPREG_counter); |
pspatel321 | 30:91af74a299e1 | 24 | } |
pspatel321 | 30:91af74a299e1 | 25 | |
pspatel321 | 30:91af74a299e1 | 26 | // Take the initial readings, fill the buffer |
pspatel321 | 30:91af74a299e1 | 27 | for (int i = 0; i < CC_FILTER_TAPS; i++) { |
pspatel321 | 30:91af74a299e1 | 28 | buffArr[i] = BatISense.read() * BAT_ISENSE_MULTIPLIER + BAT_ISENSE_OFFSET; |
pspatel321 | 30:91af74a299e1 | 29 | } |
pspatel321 | 30:91af74a299e1 | 30 | current(); // Get avg and fill out overCurrent flag |
pspatel321 | 30:91af74a299e1 | 31 | tracker=0; |
pspatel321 | 30:91af74a299e1 | 32 | |
pspatel321 | 30:91af74a299e1 | 33 | // Start counting |
pspatel321 | 30:91af74a299e1 | 34 | // sampler.attach_us(this, &CoulombCounter::sample, mSec*1000); |
pspatel321 | 30:91af74a299e1 | 35 | } |
pspatel321 | 30:91af74a299e1 | 36 | |
pspatel321 | 30:91af74a299e1 | 37 | void CoulombCounter::sample() { |
pspatel321 | 30:91af74a299e1 | 38 | // Take the reading |
pspatel321 | 30:91af74a299e1 | 39 | currentSample = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET; |
pspatel321 | 30:91af74a299e1 | 40 | |
pspatel321 | 30:91af74a299e1 | 41 | // Integrate |
pspatel321 | 30:91af74a299e1 | 42 | float f = ampHours()-currentSample*mSec*MSEC_HRS; |
pspatel321 | 30:91af74a299e1 | 43 | |
pspatel321 | 30:91af74a299e1 | 44 | // Bound to valid range |
pspatel321 | 30:91af74a299e1 | 45 | float cap = capacity(); |
pspatel321 | 30:91af74a299e1 | 46 | if (f > cap) f = cap; |
pspatel321 | 30:91af74a299e1 | 47 | if (f < 0) f = 0; |
pspatel321 | 30:91af74a299e1 | 48 | |
pspatel321 | 30:91af74a299e1 | 49 | // Write |
pspatel321 | 30:91af74a299e1 | 50 | store.write(f, rtcGPREG_counter); |
pspatel321 | 30:91af74a299e1 | 51 | |
pspatel321 | 30:91af74a299e1 | 52 | // Add to filter |
pspatel321 | 30:91af74a299e1 | 53 | buffArr[tracker] = currentSample; |
pspatel321 | 30:91af74a299e1 | 54 | tracker++; |
pspatel321 | 30:91af74a299e1 | 55 | if (tracker >= CC_FILTER_TAPS) tracker = 0; |
pspatel321 | 30:91af74a299e1 | 56 | } |
pspatel321 | 30:91af74a299e1 | 57 | void CoulombCounter::resetToSOC(float SOC) { |
pspatel321 | 30:91af74a299e1 | 58 | store.write(SOC*capacity(), rtcGPREG_counter); |
pspatel321 | 30:91af74a299e1 | 59 | } |
pspatel321 | 30:91af74a299e1 | 60 | void CoulombCounter::resetToAh(float Ah) { |
pspatel321 | 30:91af74a299e1 | 61 | store.write(Ah, rtcGPREG_counter); |
pspatel321 | 30:91af74a299e1 | 62 | } |
pspatel321 | 30:91af74a299e1 | 63 | void CoulombCounter::changeCapacity(float capAh) { |
pspatel321 | 30:91af74a299e1 | 64 | store.write(capAh, rtcGPREG_capacity); |
pspatel321 | 30:91af74a299e1 | 65 | } |
pspatel321 | 30:91af74a299e1 | 66 | float CoulombCounter::current() { |
pspatel321 | 30:91af74a299e1 | 67 | float avg = 0; |
pspatel321 | 30:91af74a299e1 | 68 | for (int i = 0; i < CC_FILTER_TAPS; i++) { |
pspatel321 | 30:91af74a299e1 | 69 | avg += buffArr[i]; |
pspatel321 | 30:91af74a299e1 | 70 | } |
pspatel321 | 30:91af74a299e1 | 71 | avg /= CC_FILTER_TAPS; |
pspatel321 | 30:91af74a299e1 | 72 | if (abs(avg) > BAT_ISENSE_LIMS) overCurrent = true; |
pspatel321 | 30:91af74a299e1 | 73 | return avg; |
pspatel321 | 30:91af74a299e1 | 74 | } |
pspatel321 | 30:91af74a299e1 | 75 | float CoulombCounter::ampHours() { |
pspatel321 | 30:91af74a299e1 | 76 | return store.read(rtcGPREG_counter); |
pspatel321 | 30:91af74a299e1 | 77 | } |
pspatel321 | 30:91af74a299e1 | 78 | float CoulombCounter::capacity() { |
pspatel321 | 30:91af74a299e1 | 79 | return store.read(rtcGPREG_capacity); |
pspatel321 | 30:91af74a299e1 | 80 | } |
pspatel321 | 30:91af74a299e1 | 81 | float CoulombCounter::SOC() { |
pspatel321 | 30:91af74a299e1 | 82 | return ampHours()/capacity(); |
pspatel321 | 30:91af74a299e1 | 83 | } |
pspatel321 | 30:91af74a299e1 | 84 | bool CoulombCounter::overCurrentDetected() { |
pspatel321 | 30:91af74a299e1 | 85 | return overCurrent; |
pspatel321 | 30:91af74a299e1 | 86 | } |