Penn Electric Racing / Mbed 2 deprecated SystemManagement

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Libs/CoulombCounter/CoulombCounter.cpp

Committer:
pspatel321
Date:
2015-02-11
Revision:
39:ddf38df9699e
Parent:
38:8efacce315ae

File content as of revision 39:ddf38df9699e:

#include "CoulombCounter.h"

const float MSEC_HRS = 2.77778e-7;                          // Multiplier to convert milliseconds to hours
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
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

CoulombCounter::CoulombCounter(PinName _pin, int _mSec, unsigned int size) : BatISense(_pin)
{
    mSec = _mSec;
    _size = 0;
    errorPacket = 0;
    overChargeCurrent = 0;
    overDischargeCurrent = 0;
    
    // Default capacity if blank or corrupted
    float capReg = store.read(GPREG_AH_CAPACITY);
    if (capReg < MIN_CAPACITY_SETTING || capReg > MAX_CAPACITY_SETTING) {   // Bad, write default
        store.write(DEFAULT_AH, GPREG_AH_CAPACITY);
        errorPacket |= CAP_INIT;
    }

    // Default SOC if blank or corrupted
    float Ah = store.read(GPREG_AH_COUNTER);
    if (Ah < 0 || Ah > MAX_CAPACITY_SETTING) {                              // Bad, write default
        store.write(DEFAULT_SOC*DEFAULT_AH, GPREG_AH_COUNTER);
        errorPacket |= SOC_INIT;
    }

    // Allocate the buffer
    buffArr = new float [size];
    if (buffArr == 0) {
        error("Coulomb Counter failed to allocate memory");
    }
    _size = size;
    tracker = 0;

    // Take the initial readings, fill the buffer
    for (int i = 0; i < _size; i++) {
        buffArr[i] = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;
    }
    updateAvg();      // Get avg and fill out overCurrent flag
}
void CoulombCounter::setup(float *charge, float *discharge) {
    overChargeCurrent = charge;
    overDischargeCurrent = discharge;
}
bool CoulombCounter::size(unsigned int size)
{
    if (_size == size) return false;

    // Get a current sample, this will be used to fill the new buffer
    updateAvg();
    float avg = current();

    float* newArr = new float [size];
    if (newArr == 0) return false;
    else {
        delete[] buffArr;   // Free old
        __disable_irq();

        buffArr = newArr;   // Transfer
        _size = size;       // Set new size
        for (int i = 0; i < _size; i++) buffArr[i] = avg;   // Fill with old avg

        __enable_irq();
        return true;
    }
}
void CoulombCounter::sample()
{
    // Take the reading
    float currentSample = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;

    // Integrate
    float f = ampHours()-currentSample*mSec*MSEC_HRS;

    // Bound to valid range
    float cap = capacity();
    if (f > cap) f = cap;
    if (f < 0) f = 0;

    // Write
    store.write(f, GPREG_AH_COUNTER);

    // Add to filter
    buffArr[tracker++] = currentSample;
    tracker %= _size;
    
    // Update the avg, check for over-current
    updateAvg();
}

void CoulombCounter::updateAvg()
{
    float avg = 0;
    for (int i = 0; i < _size; i++) {
        avg += buffArr[i];
    }
    avg /= _size;
    currentFiltered = avg;
    
    errorPacket = 0;
    if (overChargeCurrent == 0) return;     // setup() not run yet

    if (avg > *overDischargeCurrent)    errorPacket |= OVER_DISCHARGE_I;
    else                                errorPacket &= ~OVER_DISCHARGE_I;
    if (avg < *overChargeCurrent)       errorPacket |= OVER_CHARGE_I;
    else                                errorPacket &= ~OVER_CHARGE_I;
}