Penn Electric Racing / Mbed 2 deprecated SystemManagement

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Libs/DC_DC/DC_DC.cpp

Committer:
pspatel321
Date:
2015-01-22
Revision:
36:0afc0fc8f86b
Parent:
34:18bcf276d3bf
Child:
38:8efacce315ae

File content as of revision 36:0afc0fc8f86b:

#include "DC_DC.h"
#include <math.h>

#define TURN_OFF dcdcControl = 1; isControlPinOn = false;
#define TURN_ON  dcdcControl = 0; isControlPinOn = true;

const float CURRENT_MULTIPLIER_DEFAULT = 41.35338345864663;      // Full scale amps
const float CURRENT_OFFSET_DEFAULT = 0.0909090909090909;         // Float adc reading for 0 amps

const float DC_DC_ON_THRESHOLD     = 0.5;                    // Current draw required in order to declare it as on
const int   STARTUP_DELAY_MS       = 1000;                   // DC-DC converter startup time in milliseconds
const float OVER_CURRENT_THRESHOLD = 25;                     // Overcurrent threshold
const float CURRENT_SENSOR_LLIM    = -1.0;                   // Lowest allowable reading before declaring sensor broken
const float CURRENT_SENSOR_ULIM    = 33;                     // Sensor is at 5V rail, broken
const int   STOP_DELAY_MS          = 1000;                   // Amount of time given to turn-off before flagging error

DC_DC::DC_DC(PinName _dcdcPin, PinName _dcdcCurrent, PinName _fan1, PinName _fan2, PinName _pump1, PinName _pump2, float period, float slew) :
    dcdcControl(_dcdcPin, 1), dcdcCurrent(_dcdcCurrent), fan1(_fan1, period, slew), fan2(_fan2, period, slew), pump1(_pump1, period, slew), pump2(_pump2, period, slew)
{
    TURN_OFF
    currentOffset = CURRENT_OFFSET_DEFAULT;
    starting = false;
    stopping = false;
    buffTracker = 0;
    wait_ms(10);            // Make sure Hall effect IC is ready
    startTimer.reset();
    stopTimer.reset();
    status=0;
    
    // Fill up the buffer
    for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
        filterBuff[i] = (dcdcCurrent - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;
        wait_ms(10);
    }
    updateCurrent();                // Compute avg
    sample();                       // Use sample() function to check for errors
    
    if (!critError) {               // If no errors, zero the sensor
        currentOffset = (current / CURRENT_MULTIPLIER_DEFAULT) + CURRENT_OFFSET_DEFAULT;
    }
    
    // Correct the buffer for the new zero
    for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
       filterBuff[i] = ((CURRENT_OFFSET_DEFAULT - currentOffset) * CURRENT_MULTIPLIER_DEFAULT) + filterBuff[i];
    }
}

void DC_DC::updateCurrent()
{
    float avg=0;
    for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
        avg += filterBuff[i];
    }
    avg /= DC_DC_FILTER_TAPS;
    current = avg;
}

void DC_DC::set(bool on)
{
    // Do nothing if already on
    if (on && isControlPinOn) return;
    
    // Do nothing if already off
    if (!on && !isControlPinOn) return;

    // If start requested and no error
    if (on && !critError) {
        starting = true;
        TURN_ON
        startTimer.reset();
        startTimer.start();
        stopTimer.stop();
        stopTimer.reset();
        stopping = false;

        // If stop requested
    } else {
        stopping = true;
        fan1.directOff();
        fan2.directOff();
        pump1.directOff();
        pump2.directOff();
        TURN_OFF
        stopTimer.reset();
        stopTimer.start();
        startTimer.stop();
        startTimer.reset();
        starting = false;
    }
}

void DC_DC::sample()
{
    // Get next current sample
    float curr = (dcdcCurrent.read() - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;    

    filterBuff[buffTracker] = curr;                             // Add to buffer filter
    buffTracker++;
    if (buffTracker >= DC_DC_FILTER_TAPS) buffTracker = 0;
    updateCurrent();                                            // Compute average
    
    // Update status
    register char stat = status & 0xF0;                         // The upper 4 bits (locking errors)
    if (current >= DC_DC_ON_THRESHOLD) stat |= ConvOn;          // The converter is actually on (positive current)
    if (isControlPinOn) stat |= SetOn;                          // The converter is set on

    // During Timed Startup Phase
    if (starting) {
        stat |= PowerUp;                                        // Indicate state in status byte
        if (startTimer.read_ms() >= STARTUP_DELAY_MS) {         // Start time elapsed
            if (stat & ConvOn) {                                // Positive current detected
                startTimer.stop();      // Stop timer
                startTimer.reset();     // Reset to zero
                starting = false;       // Indicate running
            } else {
                startTimer.stop();
                startTimer.reset();
                stat |= FailStart;      // Failed to start
            }
        }
    } else stat &= ~PowerUp;

    // During Timed Stopping Phase
    if (stopping) {
        stat |= PowerDown;                                      // Indicate state in status byte
        if (stopTimer.read_ms() >= STOP_DELAY_MS) {             // Stop time elapsed
            if (stat & ConvOn) {                                // Converter still on
                stopTimer.stop();
                stopTimer.reset();
                stat |= FailStop;         // It didn't turn off even after timer expired!
            } else {                      // Its actually off
                stopping = false;
                stopTimer.stop();
                stopTimer.reset();
            }
        }
    } else stat &= ~PowerDown;

    // While in steady state
    if (!stopping && !starting) {
        if ((stat & SetOn) && !(stat & ConvOn)) stat |= FailStart;    // Should be running but its not
        else                                    stat &= ~FailStart;
        if (!(stat & SetOn) && (stat & ConvOn)) stat |= FailStop;     // Should be stopped but its not
        else                                    stat &= ~FailStop;
    }
    
    if (current < CURRENT_SENSOR_LLIM || current > CURRENT_SENSOR_ULIM) stat |= SensorFault;    // Sensor out of range
    else if (current > OVER_CURRENT_THRESHOLD) stat |= OverCurrent;                             // Over current

    // Process critical error conditions
    if (stat & (SensorFault | OverCurrent)) critError = true;
    else critError =  false;
    status = stat;

    // Arrest error, all channels off, DC-DC off
    if (critError) {
        fan1.directOff();
        fan2.directOff();
        pump1.directOff();
        pump2.directOff();
        TURN_OFF
        startTimer.stop();
        startTimer.reset();
        starting = false;
    }
}

void DC_DC::setPwm(enum Channel_T chan, float duty)
{
    // Do nothing if error present, starting in startup, or DC-DC not actually on, or not set on
    if (critError || starting || stopping || !(status & ConvOn) || !isControlPinOn) return;

    else {
        if (chan == FAN1)  fan1.write(duty);
        if (chan == FAN2)  fan2.write(duty);
        if (chan == PUMP1) pump1.write(duty);
        if (chan == PUMP2) pump2.write(duty);
    }
}
float DC_DC::readPwm(enum Channel_T chan)
{
    if (chan == FAN1) return fan1.readRaw();
    if (chan == FAN2) return fan2.readRaw();
    if (chan == PUMP1) return pump1.readRaw();
    if (chan == PUMP2) return pump2.readRaw();
    else return 0;
}