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@39:ddf38df9699e, 2015-02-11 (annotated)
- Committer:
- pspatel321
- Date:
- Wed Feb 11 23:09:57 2015 +0000
- Revision:
- 39:ddf38df9699e
- Parent:
- 38:8efacce315ae
Updated CAN IDs for datalogging. Changed profile encoding.
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 | 38:8efacce315ae | 4 | const float BAT_ISENSE_MULTIPLIER = 6.640114; // Multiplier to convert float to amps, calibrated using 3 points with Fluke 87V meter and code on 1/9/15 |
pspatel321 | 38:8efacce315ae | 5 | const float BAT_ISENSE_OFFSET = -3.344968; // Offset to convert float to amps, calibrated using 3 points with Fluke 87V meter and code on 1/9/15 |
pspatel321 | 30:91af74a299e1 | 6 | |
pspatel321 | 38:8efacce315ae | 7 | CoulombCounter::CoulombCounter(PinName _pin, int _mSec, unsigned int size) : BatISense(_pin) |
pspatel321 | 38:8efacce315ae | 8 | { |
pspatel321 | 30:91af74a299e1 | 9 | mSec = _mSec; |
pspatel321 | 38:8efacce315ae | 10 | _size = 0; |
pspatel321 | 38:8efacce315ae | 11 | errorPacket = 0; |
pspatel321 | 38:8efacce315ae | 12 | overChargeCurrent = 0; |
pspatel321 | 38:8efacce315ae | 13 | overDischargeCurrent = 0; |
pspatel321 | 30:91af74a299e1 | 14 | |
pspatel321 | 30:91af74a299e1 | 15 | // Default capacity if blank or corrupted |
pspatel321 | 38:8efacce315ae | 16 | float capReg = store.read(GPREG_AH_CAPACITY); |
pspatel321 | 38:8efacce315ae | 17 | if (capReg < MIN_CAPACITY_SETTING || capReg > MAX_CAPACITY_SETTING) { // Bad, write default |
pspatel321 | 38:8efacce315ae | 18 | store.write(DEFAULT_AH, GPREG_AH_CAPACITY); |
pspatel321 | 38:8efacce315ae | 19 | errorPacket |= CAP_INIT; |
pspatel321 | 30:91af74a299e1 | 20 | } |
pspatel321 | 38:8efacce315ae | 21 | |
pspatel321 | 30:91af74a299e1 | 22 | // Default SOC if blank or corrupted |
pspatel321 | 38:8efacce315ae | 23 | float Ah = store.read(GPREG_AH_COUNTER); |
pspatel321 | 38:8efacce315ae | 24 | if (Ah < 0 || Ah > MAX_CAPACITY_SETTING) { // Bad, write default |
pspatel321 | 38:8efacce315ae | 25 | store.write(DEFAULT_SOC*DEFAULT_AH, GPREG_AH_COUNTER); |
pspatel321 | 38:8efacce315ae | 26 | errorPacket |= SOC_INIT; |
pspatel321 | 30:91af74a299e1 | 27 | } |
pspatel321 | 38:8efacce315ae | 28 | |
pspatel321 | 38:8efacce315ae | 29 | // Allocate the buffer |
pspatel321 | 38:8efacce315ae | 30 | buffArr = new float [size]; |
pspatel321 | 38:8efacce315ae | 31 | if (buffArr == 0) { |
pspatel321 | 38:8efacce315ae | 32 | error("Coulomb Counter failed to allocate memory"); |
pspatel321 | 38:8efacce315ae | 33 | } |
pspatel321 | 38:8efacce315ae | 34 | _size = size; |
pspatel321 | 38:8efacce315ae | 35 | tracker = 0; |
pspatel321 | 38:8efacce315ae | 36 | |
pspatel321 | 30:91af74a299e1 | 37 | // Take the initial readings, fill the buffer |
pspatel321 | 38:8efacce315ae | 38 | for (int i = 0; i < _size; i++) { |
pspatel321 | 36:0afc0fc8f86b | 39 | buffArr[i] = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET; |
pspatel321 | 30:91af74a299e1 | 40 | } |
pspatel321 | 36:0afc0fc8f86b | 41 | updateAvg(); // Get avg and fill out overCurrent flag |
pspatel321 | 38:8efacce315ae | 42 | } |
pspatel321 | 38:8efacce315ae | 43 | void CoulombCounter::setup(float *charge, float *discharge) { |
pspatel321 | 38:8efacce315ae | 44 | overChargeCurrent = charge; |
pspatel321 | 38:8efacce315ae | 45 | overDischargeCurrent = discharge; |
pspatel321 | 30:91af74a299e1 | 46 | } |
pspatel321 | 38:8efacce315ae | 47 | bool CoulombCounter::size(unsigned int size) |
pspatel321 | 38:8efacce315ae | 48 | { |
pspatel321 | 38:8efacce315ae | 49 | if (_size == size) return false; |
pspatel321 | 30:91af74a299e1 | 50 | |
pspatel321 | 38:8efacce315ae | 51 | // Get a current sample, this will be used to fill the new buffer |
pspatel321 | 38:8efacce315ae | 52 | updateAvg(); |
pspatel321 | 38:8efacce315ae | 53 | float avg = current(); |
pspatel321 | 38:8efacce315ae | 54 | |
pspatel321 | 38:8efacce315ae | 55 | float* newArr = new float [size]; |
pspatel321 | 38:8efacce315ae | 56 | if (newArr == 0) return false; |
pspatel321 | 38:8efacce315ae | 57 | else { |
pspatel321 | 38:8efacce315ae | 58 | delete[] buffArr; // Free old |
pspatel321 | 38:8efacce315ae | 59 | __disable_irq(); |
pspatel321 | 38:8efacce315ae | 60 | |
pspatel321 | 38:8efacce315ae | 61 | buffArr = newArr; // Transfer |
pspatel321 | 38:8efacce315ae | 62 | _size = size; // Set new size |
pspatel321 | 38:8efacce315ae | 63 | for (int i = 0; i < _size; i++) buffArr[i] = avg; // Fill with old avg |
pspatel321 | 38:8efacce315ae | 64 | |
pspatel321 | 38:8efacce315ae | 65 | __enable_irq(); |
pspatel321 | 38:8efacce315ae | 66 | return true; |
pspatel321 | 38:8efacce315ae | 67 | } |
pspatel321 | 38:8efacce315ae | 68 | } |
pspatel321 | 38:8efacce315ae | 69 | void CoulombCounter::sample() |
pspatel321 | 38:8efacce315ae | 70 | { |
pspatel321 | 30:91af74a299e1 | 71 | // Take the reading |
pspatel321 | 36:0afc0fc8f86b | 72 | float currentSample = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET; |
pspatel321 | 38:8efacce315ae | 73 | |
pspatel321 | 30:91af74a299e1 | 74 | // Integrate |
pspatel321 | 30:91af74a299e1 | 75 | float f = ampHours()-currentSample*mSec*MSEC_HRS; |
pspatel321 | 38:8efacce315ae | 76 | |
pspatel321 | 30:91af74a299e1 | 77 | // Bound to valid range |
pspatel321 | 30:91af74a299e1 | 78 | float cap = capacity(); |
pspatel321 | 30:91af74a299e1 | 79 | if (f > cap) f = cap; |
pspatel321 | 30:91af74a299e1 | 80 | if (f < 0) f = 0; |
pspatel321 | 38:8efacce315ae | 81 | |
pspatel321 | 30:91af74a299e1 | 82 | // Write |
pspatel321 | 38:8efacce315ae | 83 | store.write(f, GPREG_AH_COUNTER); |
pspatel321 | 38:8efacce315ae | 84 | |
pspatel321 | 38:8efacce315ae | 85 | // Add to filter |
pspatel321 | 38:8efacce315ae | 86 | buffArr[tracker++] = currentSample; |
pspatel321 | 38:8efacce315ae | 87 | tracker %= _size; |
pspatel321 | 30:91af74a299e1 | 88 | |
pspatel321 | 38:8efacce315ae | 89 | // Update the avg, check for over-current |
pspatel321 | 36:0afc0fc8f86b | 90 | updateAvg(); |
pspatel321 | 30:91af74a299e1 | 91 | } |
pspatel321 | 34:18bcf276d3bf | 92 | |
pspatel321 | 38:8efacce315ae | 93 | void CoulombCounter::updateAvg() |
pspatel321 | 38:8efacce315ae | 94 | { |
pspatel321 | 30:91af74a299e1 | 95 | float avg = 0; |
pspatel321 | 38:8efacce315ae | 96 | for (int i = 0; i < _size; i++) { |
pspatel321 | 38:8efacce315ae | 97 | avg += buffArr[i]; |
pspatel321 | 30:91af74a299e1 | 98 | } |
pspatel321 | 38:8efacce315ae | 99 | avg /= _size; |
pspatel321 | 36:0afc0fc8f86b | 100 | currentFiltered = avg; |
pspatel321 | 38:8efacce315ae | 101 | |
pspatel321 | 38:8efacce315ae | 102 | errorPacket = 0; |
pspatel321 | 38:8efacce315ae | 103 | if (overChargeCurrent == 0) return; // setup() not run yet |
pspatel321 | 34:18bcf276d3bf | 104 | |
pspatel321 | 38:8efacce315ae | 105 | if (avg > *overDischargeCurrent) errorPacket |= OVER_DISCHARGE_I; |
pspatel321 | 38:8efacce315ae | 106 | else errorPacket &= ~OVER_DISCHARGE_I; |
pspatel321 | 38:8efacce315ae | 107 | if (avg < *overChargeCurrent) errorPacket |= OVER_CHARGE_I; |
pspatel321 | 38:8efacce315ae | 108 | else errorPacket &= ~OVER_CHARGE_I; |
pspatel321 | 30:91af74a299e1 | 109 | } |