STM32F302R8 with Konrad's inverter boards for senior design.

Dependencies:   mbed

Fork of Blue_Board_Ticker by Brad VanderWilp

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?

UserRevisionLine numberNew 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 }