STM32F302R8 with Konrad's inverter boards for senior design.
Fork of Blue_Board_Ticker by
main.cpp@23:cb38086e8695, 2016-04-15 (annotated)
- Committer:
- vicyap
- Date:
- Fri Apr 15 22:44:53 2016 +0000
- Revision:
- 23:cb38086e8695
- Parent:
- 22:72905102b50d
Added note about implementing on a high-side/low-side topology (Konrad's board)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
BVanderWilp | 0:d445abf9a8e9 | 1 | #include "mbed.h" |
BVanderWilp | 0:d445abf9a8e9 | 2 | |
BVanderWilp | 1:69c06d3676fd | 3 | PwmOut phaseA(PA_8); //Out1, Green |
BVanderWilp | 0:d445abf9a8e9 | 4 | DigitalOut phaseAEN(PC_10); |
BVanderWilp | 1:69c06d3676fd | 5 | PwmOut phaseB(PA_9); //Out2, Blue |
BVanderWilp | 0:d445abf9a8e9 | 6 | DigitalOut phaseBEN(PC_11); |
BVanderWilp | 1:69c06d3676fd | 7 | PwmOut phaseC(PA_10); //Out3, White |
BVanderWilp | 0:d445abf9a8e9 | 8 | DigitalOut phaseCEN(PC_12); |
BVanderWilp | 0:d445abf9a8e9 | 9 | |
BVanderWilp | 5:6110655353ad | 10 | AnalogIn pot(PB_1); |
BVanderWilp | 5:6110655353ad | 11 | |
BVanderWilp | 0:d445abf9a8e9 | 12 | InterruptIn button(USER_BUTTON); |
BVanderWilp | 0:d445abf9a8e9 | 13 | |
BVanderWilp | 0:d445abf9a8e9 | 14 | DigitalOut redLed(PB_2); |
BVanderWilp | 0:d445abf9a8e9 | 15 | DigitalOut led(LED1); |
BVanderWilp | 1:69c06d3676fd | 16 | InterruptIn hallA(PA_15); //H1, Green |
BVanderWilp | 1:69c06d3676fd | 17 | InterruptIn hallB(PB_3); //H2, Blue |
BVanderWilp | 1:69c06d3676fd | 18 | InterruptIn hallC(PB_10); //H3, White |
BVanderWilp | 0:d445abf9a8e9 | 19 | |
BVanderWilp | 6:e401c592d2c3 | 20 | Ticker rpmInterrupt; |
vicyap | 12:d34b96d7f997 | 21 | Ticker spinTicker; |
BVanderWilp | 6:e401c592d2c3 | 22 | int revCount = 0; |
BVanderWilp | 6:e401c592d2c3 | 23 | int rpmPrintFlag = 0; |
BVanderWilp | 6:e401c592d2c3 | 24 | int currentRPM; |
BVanderWilp | 0:d445abf9a8e9 | 25 | |
vicyap | 20:029a58eb24ab | 26 | int ADCCountMax = 1000; // tune for responsiveness vs. stability, higher value -> less responsive -> more stable |
vicyap | 22:72905102b50d | 27 | float ADCSum = 0; |
vicyap | 22:72905102b50d | 28 | int ADCCount = 0; |
vicyap | 22:72905102b50d | 29 | |
vicyap | 20:029a58eb24ab | 30 | float pwmMax = 0.9; // tune for max pwmDuty. higher value -> more power available |
BVanderWilp | 5:6110655353ad | 31 | float pwmDuty; |
vicyap | 22:72905102b50d | 32 | int start = 0; |
BVanderWilp | 7:9d90184335aa | 33 | int reverse = 0; |
BVanderWilp | 6:e401c592d2c3 | 34 | |
vicyap | 19:085eb0579185 | 35 | int spinTickerCounter = 0; |
vicyap | 20:029a58eb24ab | 36 | int spinTickerPeriod_us = 50; // tune for how often hall sensors are checked |
vicyap | 19:085eb0579185 | 37 | int ticksPerHall = 0; |
vicyap | 19:085eb0579185 | 38 | int prevHallState = 0; |
vicyap | 19:085eb0579185 | 39 | |
vicyap | 21:2bf65c29a3c6 | 40 | float reverseThreshold = 0.4f; // tune for minimum duty cycle to allow reverse |
vicyap | 21:2bf65c29a3c6 | 41 | |
vicyap | 20:029a58eb24ab | 42 | int pole_pairs = 2; // tune for proper mech rpm calculation |
vicyap | 19:085eb0579185 | 43 | |
vicyap | 22:72905102b50d | 44 | int hallToStateNumber(int h1, int h2, int h3) |
vicyap | 22:72905102b50d | 45 | { |
vicyap | 22:72905102b50d | 46 | return (h1 << 2) + (h2 << 1) + h3; |
vicyap | 22:72905102b50d | 47 | } |
vicyap | 22:72905102b50d | 48 | |
vicyap | 21:2bf65c29a3c6 | 49 | void init() |
vicyap | 21:2bf65c29a3c6 | 50 | { |
vicyap | 21:2bf65c29a3c6 | 51 | phaseA.period_us(50); |
vicyap | 21:2bf65c29a3c6 | 52 | phaseB.period_us(50); |
vicyap | 21:2bf65c29a3c6 | 53 | phaseC.period_us(50); |
vicyap | 21:2bf65c29a3c6 | 54 | |
vicyap | 21:2bf65c29a3c6 | 55 | phaseA.write(0); |
vicyap | 21:2bf65c29a3c6 | 56 | phaseB.write(0); |
vicyap | 21:2bf65c29a3c6 | 57 | phaseC.write(0); |
vicyap | 21:2bf65c29a3c6 | 58 | |
vicyap | 21:2bf65c29a3c6 | 59 | phaseAEN = 0; |
vicyap | 21:2bf65c29a3c6 | 60 | phaseBEN = 0; |
vicyap | 21:2bf65c29a3c6 | 61 | phaseCEN = 0; |
vicyap | 21:2bf65c29a3c6 | 62 | |
vicyap | 21:2bf65c29a3c6 | 63 | // init the prevHallState |
vicyap | 21:2bf65c29a3c6 | 64 | int h1 = hallA.read(); |
vicyap | 21:2bf65c29a3c6 | 65 | int h2 = hallB.read(); |
vicyap | 21:2bf65c29a3c6 | 66 | int h3 = hallC.read(); |
vicyap | 22:72905102b50d | 67 | prevHallState = hallToStateNumber(h1, h2, h3); |
vicyap | 21:2bf65c29a3c6 | 68 | } |
vicyap | 21:2bf65c29a3c6 | 69 | |
BVanderWilp | 6:e401c592d2c3 | 70 | void rpmCalc() |
BVanderWilp | 6:e401c592d2c3 | 71 | { |
vicyap | 19:085eb0579185 | 72 | currentRPM = revCount * 60; // 60 seconds in 1 minute |
vicyap | 19:085eb0579185 | 73 | currentRPM /= pole_pairs; // account for elec vs mech rpm |
vicyap | 21:2bf65c29a3c6 | 74 | if (reverse == 1) |
vicyap | 21:2bf65c29a3c6 | 75 | { |
vicyap | 21:2bf65c29a3c6 | 76 | currentRPM = -currentRPM; // indicate a reverse direction |
vicyap | 21:2bf65c29a3c6 | 77 | } |
BVanderWilp | 6:e401c592d2c3 | 78 | revCount = 0; |
BVanderWilp | 6:e401c592d2c3 | 79 | rpmPrintFlag = 1; |
BVanderWilp | 6:e401c592d2c3 | 80 | } |
vicyap | 21:2bf65c29a3c6 | 81 | |
vicyap | 23:cb38086e8695 | 82 | /* |
vicyap | 23:cb38086e8695 | 83 | L6320 |
vicyap | 23:cb38086e8695 | 84 | High : Enabled and Pulsing |
vicyap | 23:cb38086e8695 | 85 | Low : Enabled not Pulsing |
vicyap | 23:cb38086e8695 | 86 | Null : Disabled |
vicyap | 23:cb38086e8695 | 87 | |
vicyap | 23:cb38086e8695 | 88 | Konrad's Board (6 step) |
vicyap | 23:cb38086e8695 | 89 | High : high-side pulsing, low-side off |
vicyap | 23:cb38086e8695 | 90 | Low : high-side off, low-side on |
vicyap | 23:cb38086e8695 | 91 | Null : high-side off, low-side off |
vicyap | 23:cb38086e8695 | 92 | |
vicyap | 23:cb38086e8695 | 93 | high-side are PwmOuts |
vicyap | 23:cb38086e8695 | 94 | low-side are DigitalOuts |
vicyap | 23:cb38086e8695 | 95 | */ |
vicyap | 23:cb38086e8695 | 96 | |
BVanderWilp | 9:af60c737a93e | 97 | //original names: CBA CBA, new names: BAC BAC |
vicyap | 21:2bf65c29a3c6 | 98 | void Output_ANull_BLow_CHigh() //state1, A0 B- C+ |
vicyap | 15:dddb511c39b4 | 99 | { |
vicyap | 17:5e27edd3d8e6 | 100 | phaseA.write(0); |
vicyap | 17:5e27edd3d8e6 | 101 | phaseB.write(0); |
vicyap | 17:5e27edd3d8e6 | 102 | phaseC.write(pwmDuty); |
BVanderWilp | 0:d445abf9a8e9 | 103 | phaseAEN = 0; |
BVanderWilp | 1:69c06d3676fd | 104 | phaseBEN = 1; |
BVanderWilp | 3:2bcc36fe4de5 | 105 | phaseCEN = 1; |
BVanderWilp | 1:69c06d3676fd | 106 | } |
BVanderWilp | 1:69c06d3676fd | 107 | |
vicyap | 21:2bf65c29a3c6 | 108 | void Output_AHigh_BLow_CNull() //state2, A+ B- C0 |
BVanderWilp | 1:69c06d3676fd | 109 | { |
vicyap | 17:5e27edd3d8e6 | 110 | phaseA.write(pwmDuty); |
vicyap | 17:5e27edd3d8e6 | 111 | phaseB.write(0); |
BVanderWilp | 1:69c06d3676fd | 112 | phaseC.write(0); |
BVanderWilp | 1:69c06d3676fd | 113 | phaseAEN = 1; |
BVanderWilp | 3:2bcc36fe4de5 | 114 | phaseBEN = 1; |
vicyap | 17:5e27edd3d8e6 | 115 | phaseCEN = 0; |
BVanderWilp | 1:69c06d3676fd | 116 | } |
BVanderWilp | 1:69c06d3676fd | 117 | |
vicyap | 21:2bf65c29a3c6 | 118 | void Output_AHigh_BNull_CLow() //state3, A+ B0 C- |
BVanderWilp | 1:69c06d3676fd | 119 | { |
vicyap | 17:5e27edd3d8e6 | 120 | phaseA.write(pwmDuty); |
vicyap | 17:5e27edd3d8e6 | 121 | phaseB.write(0); |
vicyap | 17:5e27edd3d8e6 | 122 | phaseC.write(0); |
vicyap | 17:5e27edd3d8e6 | 123 | phaseAEN = 1; |
BVanderWilp | 1:69c06d3676fd | 124 | phaseBEN = 0; |
BVanderWilp | 1:69c06d3676fd | 125 | phaseCEN = 1; |
BVanderWilp | 1:69c06d3676fd | 126 | } |
BVanderWilp | 1:69c06d3676fd | 127 | |
vicyap | 21:2bf65c29a3c6 | 128 | void Output_ANull_BHigh_CLow() //state4, A0 B+ C- |
BVanderWilp | 1:69c06d3676fd | 129 | { |
BVanderWilp | 0:d445abf9a8e9 | 130 | phaseA.write(0); |
BVanderWilp | 0:d445abf9a8e9 | 131 | phaseB.write(pwmDuty); |
vicyap | 17:5e27edd3d8e6 | 132 | phaseC.write(0); |
vicyap | 17:5e27edd3d8e6 | 133 | phaseAEN = 0; |
BVanderWilp | 0:d445abf9a8e9 | 134 | phaseBEN = 1; |
BVanderWilp | 3:2bcc36fe4de5 | 135 | phaseCEN = 1; |
BVanderWilp | 0:d445abf9a8e9 | 136 | } |
BVanderWilp | 0:d445abf9a8e9 | 137 | |
vicyap | 21:2bf65c29a3c6 | 138 | void Output_ALow_BHigh_CNull() //state5, A- B+ C0 |
BVanderWilp | 0:d445abf9a8e9 | 139 | { |
vicyap | 17:5e27edd3d8e6 | 140 | phaseA.write(0); |
vicyap | 17:5e27edd3d8e6 | 141 | phaseB.write(pwmDuty); |
vicyap | 17:5e27edd3d8e6 | 142 | phaseC.write(0); |
BVanderWilp | 0:d445abf9a8e9 | 143 | phaseAEN = 1; |
vicyap | 17:5e27edd3d8e6 | 144 | phaseCEN = 0; |
BVanderWilp | 3:2bcc36fe4de5 | 145 | phaseBEN = 1; |
BVanderWilp | 0:d445abf9a8e9 | 146 | } |
BVanderWilp | 0:d445abf9a8e9 | 147 | |
vicyap | 21:2bf65c29a3c6 | 148 | void Output_ALow_BNull_CHigh() //state6, A- B0 C+ |
BVanderWilp | 0:d445abf9a8e9 | 149 | { |
vicyap | 17:5e27edd3d8e6 | 150 | phaseAEN = 1; |
BVanderWilp | 0:d445abf9a8e9 | 151 | phaseBEN = 0; |
vicyap | 17:5e27edd3d8e6 | 152 | phaseCEN = 1; |
vicyap | 17:5e27edd3d8e6 | 153 | phaseA.write(0); |
BVanderWilp | 0:d445abf9a8e9 | 154 | phaseB.write(0); |
BVanderWilp | 0:d445abf9a8e9 | 155 | phaseC.write(pwmDuty); |
BVanderWilp | 0:d445abf9a8e9 | 156 | } |
BVanderWilp | 0:d445abf9a8e9 | 157 | |
vicyap | 14:0f50e85bd463 | 158 | void toggleRedLed() |
vicyap | 14:0f50e85bd463 | 159 | { |
vicyap | 15:dddb511c39b4 | 160 | redLed = !redLed; |
vicyap | 14:0f50e85bd463 | 161 | } |
BVanderWilp | 0:d445abf9a8e9 | 162 | |
vicyap | 23:cb38086e8695 | 163 | void SixStepNext(int h1, int h2, int h3) |
BVanderWilp | 7:9d90184335aa | 164 | { |
vicyap | 22:72905102b50d | 165 | // compute next outputs |
vicyap | 16:792055c232a5 | 166 | if (reverse == 0) |
vicyap | 16:792055c232a5 | 167 | { |
vicyap | 16:792055c232a5 | 168 | if(h1 == 0 && h2 == 1 && h3 == 1) { //state1 |
vicyap | 21:2bf65c29a3c6 | 169 | Output_AHigh_BLow_CNull(); |
vicyap | 16:792055c232a5 | 170 | } else if(h1 == 0 && h2 == 0 && h3 == 1) { //state2 |
vicyap | 21:2bf65c29a3c6 | 171 | Output_AHigh_BNull_CLow(); |
vicyap | 16:792055c232a5 | 172 | } else if(h1 == 1 && h2 == 0 && h3 == 1) { //state3 |
vicyap | 21:2bf65c29a3c6 | 173 | Output_ANull_BHigh_CLow(); |
vicyap | 16:792055c232a5 | 174 | } else if(h1 == 1 && h2 == 0 && h3 == 0) { //state4 |
vicyap | 21:2bf65c29a3c6 | 175 | Output_ALow_BHigh_CNull(); |
vicyap | 16:792055c232a5 | 176 | } else if(h1 == 1 && h2 == 1 && h3 == 0) { //state5 |
vicyap | 21:2bf65c29a3c6 | 177 | Output_ALow_BNull_CHigh(); |
vicyap | 21:2bf65c29a3c6 | 178 | } else if (h1 == 0 && h2 == 1 && h3 == 0) { //state6 |
vicyap | 21:2bf65c29a3c6 | 179 | Output_ANull_BLow_CHigh(); |
vicyap | 16:792055c232a5 | 180 | } |
vicyap | 16:792055c232a5 | 181 | } |
vicyap | 18:d7033a38f20b | 182 | else if (reverse == 1) // to go in reverse, shift the mappings by 180 degrees |
vicyap | 16:792055c232a5 | 183 | { |
vicyap | 16:792055c232a5 | 184 | if(h1 == 0 && h2 == 1 && h3 == 1) { //state1 |
vicyap | 21:2bf65c29a3c6 | 185 | Output_ALow_BHigh_CNull(); |
vicyap | 18:d7033a38f20b | 186 | } else if(h1 == 0 && h2 == 0 && h3 == 1) { //state2 |
vicyap | 21:2bf65c29a3c6 | 187 | Output_ALow_BNull_CHigh(); |
vicyap | 18:d7033a38f20b | 188 | } else if(h1 == 1 && h2 == 0 && h3 == 1) { //state3 |
vicyap | 21:2bf65c29a3c6 | 189 | Output_ANull_BLow_CHigh(); |
vicyap | 18:d7033a38f20b | 190 | } else if(h1 == 1 && h2 == 0 && h3 == 0) { //state4 |
vicyap | 21:2bf65c29a3c6 | 191 | Output_AHigh_BLow_CNull(); |
vicyap | 18:d7033a38f20b | 192 | } else if(h1 == 1 && h2 == 1 && h3 == 0) { //state5 |
vicyap | 21:2bf65c29a3c6 | 193 | Output_AHigh_BNull_CLow(); |
vicyap | 21:2bf65c29a3c6 | 194 | } else if (h1 == 0 && h2 == 1 && h3 == 0) { //state6 |
vicyap | 21:2bf65c29a3c6 | 195 | Output_ANull_BHigh_CLow(); |
vicyap | 16:792055c232a5 | 196 | } |
vicyap | 22:72905102b50d | 197 | } |
vicyap | 22:72905102b50d | 198 | } |
vicyap | 22:72905102b50d | 199 | |
vicyap | 22:72905102b50d | 200 | void SpinTicker_callback() |
vicyap | 22:72905102b50d | 201 | { |
vicyap | 22:72905102b50d | 202 | int h1 = hallA.read(); |
vicyap | 22:72905102b50d | 203 | int h2 = hallB.read(); |
vicyap | 22:72905102b50d | 204 | int h3 = hallC.read(); |
vicyap | 22:72905102b50d | 205 | //check where we start |
vicyap | 22:72905102b50d | 206 | int currentHallState = hallToStateNumber(h1, h2, h3); |
vicyap | 22:72905102b50d | 207 | if (currentHallState != prevHallState) |
vicyap | 22:72905102b50d | 208 | { |
vicyap | 22:72905102b50d | 209 | ticksPerHall = spinTickerCounter; |
vicyap | 22:72905102b50d | 210 | spinTickerCounter = 0; // reset the number of ticks per hall sensor change |
vicyap | 22:72905102b50d | 211 | if (prevHallState == 1) // arbitrarily choose state 1 |
vicyap | 22:72905102b50d | 212 | { |
vicyap | 22:72905102b50d | 213 | revCount += 1; |
vicyap | 22:72905102b50d | 214 | } |
vicyap | 14:0f50e85bd463 | 215 | } |
vicyap | 22:72905102b50d | 216 | prevHallState = currentHallState; |
vicyap | 22:72905102b50d | 217 | spinTickerCounter += 1; // count the number of times spinTicker runs per hall sensor |
vicyap | 22:72905102b50d | 218 | |
vicyap | 23:cb38086e8695 | 219 | SixStepNext(h1, h2, h3); |
vicyap | 22:72905102b50d | 220 | |
vicyap | 14:0f50e85bd463 | 221 | toggleRedLed(); |
BVanderWilp | 7:9d90184335aa | 222 | } |
BVanderWilp | 7:9d90184335aa | 223 | |
vicyap | 21:2bf65c29a3c6 | 224 | void user_button_callback() |
BVanderWilp | 7:9d90184335aa | 225 | { |
vicyap | 22:72905102b50d | 226 | if(start == 0) |
vicyap | 21:2bf65c29a3c6 | 227 | { |
vicyap | 22:72905102b50d | 228 | start = 1; |
vicyap | 21:2bf65c29a3c6 | 229 | } |
vicyap | 21:2bf65c29a3c6 | 230 | else |
vicyap | 21:2bf65c29a3c6 | 231 | { |
vicyap | 21:2bf65c29a3c6 | 232 | if (pwmDuty < reverseThreshold) |
vicyap | 16:792055c232a5 | 233 | { |
vicyap | 16:792055c232a5 | 234 | reverse = reverse ^ 1; |
vicyap | 16:792055c232a5 | 235 | } |
BVanderWilp | 7:9d90184335aa | 236 | } |
BVanderWilp | 7:9d90184335aa | 237 | } |
BVanderWilp | 7:9d90184335aa | 238 | |
vicyap | 22:72905102b50d | 239 | float buffered_ADC_read() |
vicyap | 22:72905102b50d | 240 | { |
vicyap | 22:72905102b50d | 241 | if(ADCCount == ADCCountMax) { |
vicyap | 22:72905102b50d | 242 | ADCSum = ADCSum - (ADCSum / ADCCountMax); |
vicyap | 22:72905102b50d | 243 | ADCSum += pot.read(); |
vicyap | 22:72905102b50d | 244 | return ADCSum / ADCCountMax; |
vicyap | 22:72905102b50d | 245 | } |
vicyap | 22:72905102b50d | 246 | else |
vicyap | 22:72905102b50d | 247 | { |
vicyap | 22:72905102b50d | 248 | ADCSum += pot.read(); |
vicyap | 22:72905102b50d | 249 | ADCCount++; |
vicyap | 22:72905102b50d | 250 | return 0.0; |
vicyap | 22:72905102b50d | 251 | } |
vicyap | 22:72905102b50d | 252 | } |
vicyap | 22:72905102b50d | 253 | |
vicyap | 15:dddb511c39b4 | 254 | int main() |
vicyap | 15:dddb511c39b4 | 255 | { |
BVanderWilp | 7:9d90184335aa | 256 | //wait until button push to start |
BVanderWilp | 7:9d90184335aa | 257 | rpmInterrupt.attach(&rpmCalc, 1); |
vicyap | 21:2bf65c29a3c6 | 258 | button.rise(&user_button_callback); |
vicyap | 22:72905102b50d | 259 | while(start == 0) { |
BVanderWilp | 7:9d90184335aa | 260 | led = !led; |
BVanderWilp | 7:9d90184335aa | 261 | wait(1); |
BVanderWilp | 7:9d90184335aa | 262 | } |
vicyap | 21:2bf65c29a3c6 | 263 | |
vicyap | 21:2bf65c29a3c6 | 264 | init(); |
vicyap | 15:dddb511c39b4 | 265 | |
vicyap | 22:72905102b50d | 266 | spinTicker.attach_us(&SpinTicker_callback, spinTickerPeriod_us); |
BVanderWilp | 0:d445abf9a8e9 | 267 | while(1) { |
BVanderWilp | 0:d445abf9a8e9 | 268 | led = !led; |
vicyap | 22:72905102b50d | 269 | |
vicyap | 22:72905102b50d | 270 | pwmDuty = buffered_ADC_read() * pwmMax; |
vicyap | 22:72905102b50d | 271 | |
vicyap | 15:dddb511c39b4 | 272 | if(rpmPrintFlag == 1) { |
vicyap | 19:085eb0579185 | 273 | printf("%d rpm; %f duty; reverse: %d; ticksPerHall = %d\r\n", currentRPM, pwmDuty, reverse, ticksPerHall); |
BVanderWilp | 6:e401c592d2c3 | 274 | rpmPrintFlag = 0; |
BVanderWilp | 6:e401c592d2c3 | 275 | } |
BVanderWilp | 0:d445abf9a8e9 | 276 | } |
BVanderWilp | 0:d445abf9a8e9 | 277 | } |