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@36:0afc0fc8f86b, 2015-01-22 (annotated)
- 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?
| 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 | 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 | } |
