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