Penn Electric Racing / Mbed 2 deprecated SystemManagement

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Committer:
pspatel321
Date:
Thu Jan 22 07:58:51 2015 +0000
Revision:
36:0afc0fc8f86b
Parent:
34:18bcf276d3bf
Child:
38:8efacce315ae
Tested in car with other systems.  Most features are good to go.  Except xbees need work.  The DC-DC protection features were giving problems due to spurious current measurements.  They have been edited to reduce glitchy errors.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pspatel321 30:91af74a299e1 1 #include "DC_DC.h"
pspatel321 30:91af74a299e1 2 #include <math.h>
pspatel321 30:91af74a299e1 3
pspatel321 36:0afc0fc8f86b 4 #define TURN_OFF dcdcControl = 1; isControlPinOn = false;
pspatel321 36:0afc0fc8f86b 5 #define TURN_ON dcdcControl = 0; isControlPinOn = true;
pspatel321 30:91af74a299e1 6
pspatel321 30:91af74a299e1 7 const float CURRENT_MULTIPLIER_DEFAULT = 41.35338345864663; // Full scale amps
pspatel321 30:91af74a299e1 8 const float CURRENT_OFFSET_DEFAULT = 0.0909090909090909; // Float adc reading for 0 amps
pspatel321 30:91af74a299e1 9
pspatel321 36:0afc0fc8f86b 10 const float DC_DC_ON_THRESHOLD = 0.5; // Current draw required in order to declare it as on
pspatel321 36:0afc0fc8f86b 11 const int STARTUP_DELAY_MS = 1000; // DC-DC converter startup time in milliseconds
pspatel321 36:0afc0fc8f86b 12 const float OVER_CURRENT_THRESHOLD = 25; // Overcurrent threshold
pspatel321 36:0afc0fc8f86b 13 const float CURRENT_SENSOR_LLIM = -1.0; // Lowest allowable reading before declaring sensor broken
pspatel321 36:0afc0fc8f86b 14 const float CURRENT_SENSOR_ULIM = 33; // Sensor is at 5V rail, broken
pspatel321 36:0afc0fc8f86b 15 const int STOP_DELAY_MS = 1000; // Amount of time given to turn-off before flagging error
pspatel321 30:91af74a299e1 16
pspatel321 36:0afc0fc8f86b 17 DC_DC::DC_DC(PinName _dcdcPin, PinName _dcdcCurrent, PinName _fan1, PinName _fan2, PinName _pump1, PinName _pump2, float period, float slew) :
pspatel321 36:0afc0fc8f86b 18 dcdcControl(_dcdcPin, 1), dcdcCurrent(_dcdcCurrent), fan1(_fan1, period, slew), fan2(_fan2, period, slew), pump1(_pump1, period, slew), pump2(_pump2, period, slew)
pspatel321 36:0afc0fc8f86b 19 {
pspatel321 36:0afc0fc8f86b 20 TURN_OFF
pspatel321 30:91af74a299e1 21 currentOffset = CURRENT_OFFSET_DEFAULT;
pspatel321 30:91af74a299e1 22 starting = false;
pspatel321 30:91af74a299e1 23 stopping = false;
pspatel321 30:91af74a299e1 24 buffTracker = 0;
pspatel321 30:91af74a299e1 25 wait_ms(10); // Make sure Hall effect IC is ready
pspatel321 30:91af74a299e1 26 startTimer.reset();
pspatel321 30:91af74a299e1 27 stopTimer.reset();
pspatel321 30:91af74a299e1 28 status=0;
pspatel321 30:91af74a299e1 29
pspatel321 30:91af74a299e1 30 // Fill up the buffer
pspatel321 30:91af74a299e1 31 for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
pspatel321 30:91af74a299e1 32 filterBuff[i] = (dcdcCurrent - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;
pspatel321 36:0afc0fc8f86b 33 wait_ms(10);
pspatel321 30:91af74a299e1 34 }
pspatel321 36:0afc0fc8f86b 35 updateCurrent(); // Compute avg
pspatel321 36:0afc0fc8f86b 36 sample(); // Use sample() function to check for errors
pspatel321 36:0afc0fc8f86b 37
pspatel321 36:0afc0fc8f86b 38 if (!critError) { // If no errors, zero the sensor
pspatel321 36:0afc0fc8f86b 39 currentOffset = (current / CURRENT_MULTIPLIER_DEFAULT) + CURRENT_OFFSET_DEFAULT;
pspatel321 36:0afc0fc8f86b 40 }
pspatel321 36:0afc0fc8f86b 41
pspatel321 36:0afc0fc8f86b 42 // Correct the buffer for the new zero
pspatel321 36:0afc0fc8f86b 43 for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
pspatel321 36:0afc0fc8f86b 44 filterBuff[i] = ((CURRENT_OFFSET_DEFAULT - currentOffset) * CURRENT_MULTIPLIER_DEFAULT) + filterBuff[i];
pspatel321 36:0afc0fc8f86b 45 }
pspatel321 30:91af74a299e1 46 }
pspatel321 30:91af74a299e1 47
pspatel321 36:0afc0fc8f86b 48 void DC_DC::updateCurrent()
pspatel321 36:0afc0fc8f86b 49 {
pspatel321 30:91af74a299e1 50 float avg=0;
pspatel321 30:91af74a299e1 51 for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
pspatel321 30:91af74a299e1 52 avg += filterBuff[i];
pspatel321 30:91af74a299e1 53 }
pspatel321 30:91af74a299e1 54 avg /= DC_DC_FILTER_TAPS;
pspatel321 30:91af74a299e1 55 current = avg;
pspatel321 30:91af74a299e1 56 }
pspatel321 30:91af74a299e1 57
pspatel321 36:0afc0fc8f86b 58 void DC_DC::set(bool on)
pspatel321 36:0afc0fc8f86b 59 {
pspatel321 30:91af74a299e1 60 // Do nothing if already on
pspatel321 36:0afc0fc8f86b 61 if (on && isControlPinOn) return;
pspatel321 30:91af74a299e1 62
pspatel321 36:0afc0fc8f86b 63 // Do nothing if already off
pspatel321 36:0afc0fc8f86b 64 if (!on && !isControlPinOn) return;
pspatel321 36:0afc0fc8f86b 65
pspatel321 34:18bcf276d3bf 66 // If start requested and no error
pspatel321 34:18bcf276d3bf 67 if (on && !critError) {
pspatel321 30:91af74a299e1 68 starting = true;
pspatel321 36:0afc0fc8f86b 69 TURN_ON
pspatel321 30:91af74a299e1 70 startTimer.reset();
pspatel321 30:91af74a299e1 71 startTimer.start();
pspatel321 30:91af74a299e1 72 stopTimer.stop();
pspatel321 30:91af74a299e1 73 stopTimer.reset();
pspatel321 30:91af74a299e1 74 stopping = false;
pspatel321 36:0afc0fc8f86b 75
pspatel321 36:0afc0fc8f86b 76 // If stop requested
pspatel321 30:91af74a299e1 77 } else {
pspatel321 36:0afc0fc8f86b 78 stopping = true;
pspatel321 30:91af74a299e1 79 fan1.directOff();
pspatel321 30:91af74a299e1 80 fan2.directOff();
pspatel321 30:91af74a299e1 81 pump1.directOff();
pspatel321 30:91af74a299e1 82 pump2.directOff();
pspatel321 36:0afc0fc8f86b 83 TURN_OFF
pspatel321 30:91af74a299e1 84 stopTimer.reset();
pspatel321 30:91af74a299e1 85 stopTimer.start();
pspatel321 30:91af74a299e1 86 startTimer.stop();
pspatel321 30:91af74a299e1 87 startTimer.reset();
pspatel321 30:91af74a299e1 88 starting = false;
pspatel321 30:91af74a299e1 89 }
pspatel321 30:91af74a299e1 90 }
pspatel321 30:91af74a299e1 91
pspatel321 36:0afc0fc8f86b 92 void DC_DC::sample()
pspatel321 36:0afc0fc8f86b 93 {
pspatel321 30:91af74a299e1 94 // Get next current sample
pspatel321 36:0afc0fc8f86b 95 float curr = (dcdcCurrent.read() - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;
pspatel321 36:0afc0fc8f86b 96
pspatel321 36:0afc0fc8f86b 97 filterBuff[buffTracker] = curr; // Add to buffer filter
pspatel321 30:91af74a299e1 98 buffTracker++;
pspatel321 30:91af74a299e1 99 if (buffTracker >= DC_DC_FILTER_TAPS) buffTracker = 0;
pspatel321 36:0afc0fc8f86b 100 updateCurrent(); // Compute average
pspatel321 30:91af74a299e1 101
pspatel321 30:91af74a299e1 102 // Update status
pspatel321 36:0afc0fc8f86b 103 register char stat = status & 0xF0; // The upper 4 bits (locking errors)
pspatel321 36:0afc0fc8f86b 104 if (current >= DC_DC_ON_THRESHOLD) stat |= ConvOn; // The converter is actually on (positive current)
pspatel321 36:0afc0fc8f86b 105 if (isControlPinOn) stat |= SetOn; // The converter is set on
pspatel321 36:0afc0fc8f86b 106
pspatel321 30:91af74a299e1 107 // During Timed Startup Phase
pspatel321 30:91af74a299e1 108 if (starting) {
pspatel321 30:91af74a299e1 109 stat |= PowerUp; // Indicate state in status byte
pspatel321 36:0afc0fc8f86b 110 if (startTimer.read_ms() >= STARTUP_DELAY_MS) { // Start time elapsed
pspatel321 30:91af74a299e1 111 if (stat & ConvOn) { // Positive current detected
pspatel321 30:91af74a299e1 112 startTimer.stop(); // Stop timer
pspatel321 30:91af74a299e1 113 startTimer.reset(); // Reset to zero
pspatel321 30:91af74a299e1 114 starting = false; // Indicate running
pspatel321 30:91af74a299e1 115 } else {
pspatel321 30:91af74a299e1 116 startTimer.stop();
pspatel321 30:91af74a299e1 117 startTimer.reset();
pspatel321 30:91af74a299e1 118 stat |= FailStart; // Failed to start
pspatel321 30:91af74a299e1 119 }
pspatel321 30:91af74a299e1 120 }
pspatel321 36:0afc0fc8f86b 121 } else stat &= ~PowerUp;
pspatel321 36:0afc0fc8f86b 122
pspatel321 30:91af74a299e1 123 // During Timed Stopping Phase
pspatel321 30:91af74a299e1 124 if (stopping) {
pspatel321 36:0afc0fc8f86b 125 stat |= PowerDown; // Indicate state in status byte
pspatel321 36:0afc0fc8f86b 126 if (stopTimer.read_ms() >= STOP_DELAY_MS) { // Stop time elapsed
pspatel321 36:0afc0fc8f86b 127 if (stat & ConvOn) { // Converter still on
pspatel321 30:91af74a299e1 128 stopTimer.stop();
pspatel321 30:91af74a299e1 129 stopTimer.reset();
pspatel321 30:91af74a299e1 130 stat |= FailStop; // It didn't turn off even after timer expired!
pspatel321 30:91af74a299e1 131 } else { // Its actually off
pspatel321 30:91af74a299e1 132 stopping = false;
pspatel321 30:91af74a299e1 133 stopTimer.stop();
pspatel321 36:0afc0fc8f86b 134 stopTimer.reset();
pspatel321 30:91af74a299e1 135 }
pspatel321 30:91af74a299e1 136 }
pspatel321 36:0afc0fc8f86b 137 } else stat &= ~PowerDown;
pspatel321 36:0afc0fc8f86b 138
pspatel321 36:0afc0fc8f86b 139 // While in steady state
pspatel321 36:0afc0fc8f86b 140 if (!stopping && !starting) {
pspatel321 36:0afc0fc8f86b 141 if ((stat & SetOn) && !(stat & ConvOn)) stat |= FailStart; // Should be running but its not
pspatel321 36:0afc0fc8f86b 142 else stat &= ~FailStart;
pspatel321 36:0afc0fc8f86b 143 if (!(stat & SetOn) && (stat & ConvOn)) stat |= FailStop; // Should be stopped but its not
pspatel321 36:0afc0fc8f86b 144 else stat &= ~FailStop;
pspatel321 30:91af74a299e1 145 }
pspatel321 30:91af74a299e1 146
pspatel321 36:0afc0fc8f86b 147 if (current < CURRENT_SENSOR_LLIM || current > CURRENT_SENSOR_ULIM) stat |= SensorFault; // Sensor out of range
pspatel321 36:0afc0fc8f86b 148 else if (current > OVER_CURRENT_THRESHOLD) stat |= OverCurrent; // Over current
pspatel321 36:0afc0fc8f86b 149
pspatel321 30:91af74a299e1 150 // Process critical error conditions
pspatel321 36:0afc0fc8f86b 151 if (stat & (SensorFault | OverCurrent)) critError = true;
pspatel321 30:91af74a299e1 152 else critError = false;
pspatel321 30:91af74a299e1 153 status = stat;
pspatel321 30:91af74a299e1 154
pspatel321 30:91af74a299e1 155 // Arrest error, all channels off, DC-DC off
pspatel321 30:91af74a299e1 156 if (critError) {
pspatel321 30:91af74a299e1 157 fan1.directOff();
pspatel321 30:91af74a299e1 158 fan2.directOff();
pspatel321 30:91af74a299e1 159 pump1.directOff();
pspatel321 30:91af74a299e1 160 pump2.directOff();
pspatel321 36:0afc0fc8f86b 161 TURN_OFF
pspatel321 30:91af74a299e1 162 startTimer.stop();
pspatel321 30:91af74a299e1 163 startTimer.reset();
pspatel321 30:91af74a299e1 164 starting = false;
pspatel321 30:91af74a299e1 165 }
pspatel321 30:91af74a299e1 166 }
pspatel321 30:91af74a299e1 167
pspatel321 36:0afc0fc8f86b 168 void DC_DC::setPwm(enum Channel_T chan, float duty)
pspatel321 36:0afc0fc8f86b 169 {
pspatel321 30:91af74a299e1 170 // Do nothing if error present, starting in startup, or DC-DC not actually on, or not set on
pspatel321 36:0afc0fc8f86b 171 if (critError || starting || stopping || !(status & ConvOn) || !isControlPinOn) return;
pspatel321 36:0afc0fc8f86b 172
pspatel321 30:91af74a299e1 173 else {
pspatel321 34:18bcf276d3bf 174 if (chan == FAN1) fan1.write(duty);
pspatel321 34:18bcf276d3bf 175 if (chan == FAN2) fan2.write(duty);
pspatel321 30:91af74a299e1 176 if (chan == PUMP1) pump1.write(duty);
pspatel321 36:0afc0fc8f86b 177 if (chan == PUMP2) pump2.write(duty);
pspatel321 30:91af74a299e1 178 }
pspatel321 30:91af74a299e1 179 }
pspatel321 36:0afc0fc8f86b 180 float DC_DC::readPwm(enum Channel_T chan)
pspatel321 36:0afc0fc8f86b 181 {
pspatel321 30:91af74a299e1 182 if (chan == FAN1) return fan1.readRaw();
pspatel321 30:91af74a299e1 183 if (chan == FAN2) return fan2.readRaw();
pspatel321 30:91af74a299e1 184 if (chan == PUMP1) return pump1.readRaw();
pspatel321 30:91af74a299e1 185 if (chan == PUMP2) return pump2.readRaw();
pspatel321 30:91af74a299e1 186 else return 0;
pspatel321 30:91af74a299e1 187 }