UVW 3 phases Brushless DC motor control
Dependencies: QEI mbed-rtos mbed
Fork of BLDCmotor by
UVWpwm.cpp@12:a4b17bb682eb, 2012-12-21 (annotated)
- Committer:
- kosaka
- Date:
- Fri Dec 21 22:06:56 2012 +0000
- Revision:
- 12:a4b17bb682eb
- Child:
- 13:791e20f1af43
121222a
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kosaka | 12:a4b17bb682eb | 1 | #include "mbed.h" |
kosaka | 12:a4b17bb682eb | 2 | #include "controller.h" |
kosaka | 12:a4b17bb682eb | 3 | #include "UVWpwm.h" |
kosaka | 12:a4b17bb682eb | 4 | |
kosaka | 12:a4b17bb682eb | 5 | #define DEADTIME_US (unsigned long)(DEADTIME*1000000) // [us], deadtime to be set between plus volt. to/from minus |
kosaka | 12:a4b17bb682eb | 6 | |
kosaka | 12:a4b17bb682eb | 7 | Timeout pwm[3]; |
kosaka | 12:a4b17bb682eb | 8 | |
kosaka | 12:a4b17bb682eb | 9 | DigitalOut pwm_upper[] = {(U_UPPER_PORT), (V_UPPER_PORT),(W_UPPER_PORT)}; |
kosaka | 12:a4b17bb682eb | 10 | DigitalOut pwm_lower[] = {(U_LOWER_PORT), (V_LOWER_PORT),(W_LOWER_PORT)}; |
kosaka | 12:a4b17bb682eb | 11 | |
kosaka | 12:a4b17bb682eb | 12 | pwm_parameters uvw[3]; // UVW pwm の定数、変数 |
kosaka | 12:a4b17bb682eb | 13 | |
kosaka | 12:a4b17bb682eb | 14 | // 関数配列: NG |
kosaka | 12:a4b17bb682eb | 15 | //void (*pwmUVWout[])(int) = {pwmout,pwmout,pwmout}; |
kosaka | 12:a4b17bb682eb | 16 | // pwmUVWout[i](i); |
kosaka | 12:a4b17bb682eb | 17 | |
kosaka | 12:a4b17bb682eb | 18 | #if PWM_WAVEFORM==0 // 0: saw tooth wave comparison |
kosaka | 12:a4b17bb682eb | 19 | void pwmUout() { // pwm out using timer |
kosaka | 12:a4b17bb682eb | 20 | unsigned char i=0; |
kosaka | 12:a4b17bb682eb | 21 | uvw[i].mode += 1; |
kosaka | 12:a4b17bb682eb | 22 | if( uvw[i].mode==1 ){ |
kosaka | 12:a4b17bb682eb | 23 | pwm_upper[i] = 1; |
kosaka | 12:a4b17bb682eb | 24 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 25 | uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper |
kosaka | 12:a4b17bb682eb | 26 | pwm[i].attach_us(&pwmUout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 27 | uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower |
kosaka | 12:a4b17bb682eb | 28 | }else if( uvw[i].mode==2 ){ |
kosaka | 12:a4b17bb682eb | 29 | pwm[i].attach_us(&pwmUout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 30 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 31 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 32 | }else if( uvw[i].mode==3 ){ |
kosaka | 12:a4b17bb682eb | 33 | pwm[i].attach_us(&pwmUout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 34 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 35 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 36 | }else{// if( u.mode==4 ){ |
kosaka | 12:a4b17bb682eb | 37 | pwm[i].attach_us(&pwmUout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 38 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 39 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 40 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 41 | } |
kosaka | 12:a4b17bb682eb | 42 | } |
kosaka | 12:a4b17bb682eb | 43 | |
kosaka | 12:a4b17bb682eb | 44 | void pwmVout() { // pwm out using timer |
kosaka | 12:a4b17bb682eb | 45 | unsigned char i=1; |
kosaka | 12:a4b17bb682eb | 46 | uvw[i].mode += 1; |
kosaka | 12:a4b17bb682eb | 47 | if( uvw[i].mode==1 ){ |
kosaka | 12:a4b17bb682eb | 48 | pwm_upper[i] = 1; |
kosaka | 12:a4b17bb682eb | 49 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 50 | uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper |
kosaka | 12:a4b17bb682eb | 51 | pwm[i].attach_us(&pwmVout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 52 | uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower |
kosaka | 12:a4b17bb682eb | 53 | }else if( uvw[i].mode==2 ){ |
kosaka | 12:a4b17bb682eb | 54 | pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 55 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 56 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 57 | }else if( uvw[i].mode==3 ){ |
kosaka | 12:a4b17bb682eb | 58 | pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 59 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 60 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 61 | }else{// if( u.mode==4 ){ |
kosaka | 12:a4b17bb682eb | 62 | pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 63 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 64 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 65 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 66 | } |
kosaka | 12:a4b17bb682eb | 67 | } |
kosaka | 12:a4b17bb682eb | 68 | |
kosaka | 12:a4b17bb682eb | 69 | void pwmWout() { // pwm out using timer |
kosaka | 12:a4b17bb682eb | 70 | unsigned char i=2; |
kosaka | 12:a4b17bb682eb | 71 | uvw[i].mode += 1; |
kosaka | 12:a4b17bb682eb | 72 | if( uvw[i].mode==1 ){ |
kosaka | 12:a4b17bb682eb | 73 | pwm_upper[i] = 1; |
kosaka | 12:a4b17bb682eb | 74 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 75 | uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper |
kosaka | 12:a4b17bb682eb | 76 | pwm[i].attach_us(&pwmWout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 77 | uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower |
kosaka | 12:a4b17bb682eb | 78 | }else if( uvw[i].mode==2 ){ |
kosaka | 12:a4b17bb682eb | 79 | pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 80 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 81 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 82 | }else if( uvw[i].mode==3 ){ |
kosaka | 12:a4b17bb682eb | 83 | pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 84 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 85 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 86 | }else{// if( u.mode==4 ){ |
kosaka | 12:a4b17bb682eb | 87 | pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 88 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 89 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 90 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 91 | } |
kosaka | 12:a4b17bb682eb | 92 | } |
kosaka | 12:a4b17bb682eb | 93 | #elif PWM_WAVEFORM==1 // 1: triangler wave comparison |
kosaka | 12:a4b17bb682eb | 94 | void pwmUout() { // pwm out using timer |
kosaka | 12:a4b17bb682eb | 95 | unsigned char i=0; |
kosaka | 12:a4b17bb682eb | 96 | uvw[i].mode += 1; |
kosaka | 12:a4b17bb682eb | 97 | if( uvw[i].mode==1 ){ |
kosaka | 12:a4b17bb682eb | 98 | uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper |
kosaka | 12:a4b17bb682eb | 99 | uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower |
kosaka | 12:a4b17bb682eb | 100 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 101 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 102 | uvw[i].lower_us /= 2; |
kosaka | 12:a4b17bb682eb | 103 | pwm[i].attach_us(&pwmUout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 104 | }else if( uvw[i].mode==2 ){ |
kosaka | 12:a4b17bb682eb | 105 | pwm[i].attach_us(&pwmUout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 106 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 107 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 108 | }else if( uvw[i].mode==3 ){ |
kosaka | 12:a4b17bb682eb | 109 | pwm[i].attach_us(&pwmUout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 110 | pwm_upper[i] = 1; |
kosaka | 12:a4b17bb682eb | 111 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 112 | }else if( uvw[i].mode==4 ){ |
kosaka | 12:a4b17bb682eb | 113 | pwm[i].attach_us(&pwmUout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 114 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 115 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 116 | }else{// if( uvw[i].mode==5 ){ |
kosaka | 12:a4b17bb682eb | 117 | pwm[i].attach_us(&pwmUout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 118 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 119 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 120 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 121 | } |
kosaka | 12:a4b17bb682eb | 122 | } |
kosaka | 12:a4b17bb682eb | 123 | void pwmVout() { // pwm out using timer |
kosaka | 12:a4b17bb682eb | 124 | unsigned char i=1; |
kosaka | 12:a4b17bb682eb | 125 | uvw[i].mode += 1; |
kosaka | 12:a4b17bb682eb | 126 | if( uvw[i].mode==1 ){ |
kosaka | 12:a4b17bb682eb | 127 | uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper |
kosaka | 12:a4b17bb682eb | 128 | uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower |
kosaka | 12:a4b17bb682eb | 129 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 130 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 131 | uvw[i].lower_us /= 2; |
kosaka | 12:a4b17bb682eb | 132 | pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 133 | }else if( uvw[i].mode==2 ){ |
kosaka | 12:a4b17bb682eb | 134 | pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 135 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 136 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 137 | }else if( uvw[i].mode==3 ){ |
kosaka | 12:a4b17bb682eb | 138 | pwm[i].attach_us(&pwmVout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 139 | pwm_upper[i] = 1; |
kosaka | 12:a4b17bb682eb | 140 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 141 | }else if( uvw[i].mode==4 ){ |
kosaka | 12:a4b17bb682eb | 142 | pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 143 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 144 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 145 | }else{// if( uvw[i].mode==5 ){ |
kosaka | 12:a4b17bb682eb | 146 | pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 147 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 148 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 149 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 150 | } |
kosaka | 12:a4b17bb682eb | 151 | } |
kosaka | 12:a4b17bb682eb | 152 | |
kosaka | 12:a4b17bb682eb | 153 | void pwmWout() { // pwm out using timer |
kosaka | 12:a4b17bb682eb | 154 | unsigned char i=2; |
kosaka | 12:a4b17bb682eb | 155 | uvw[i].mode += 1; |
kosaka | 12:a4b17bb682eb | 156 | if( uvw[i].mode==1 ){ |
kosaka | 12:a4b17bb682eb | 157 | uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper |
kosaka | 12:a4b17bb682eb | 158 | uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower |
kosaka | 12:a4b17bb682eb | 159 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 160 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 161 | uvw[i].lower_us /= 2; |
kosaka | 12:a4b17bb682eb | 162 | pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 163 | }else if( uvw[i].mode==2 ){ |
kosaka | 12:a4b17bb682eb | 164 | pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 165 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 166 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 167 | }else if( uvw[i].mode==3 ){ |
kosaka | 12:a4b17bb682eb | 168 | pwm[i].attach_us(&pwmWout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 169 | pwm_upper[i] = 1; |
kosaka | 12:a4b17bb682eb | 170 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 171 | }else if( uvw[i].mode==4 ){ |
kosaka | 12:a4b17bb682eb | 172 | pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 173 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 174 | pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 175 | }else{// if( uvw[i].mode==5 ){ |
kosaka | 12:a4b17bb682eb | 176 | pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] |
kosaka | 12:a4b17bb682eb | 177 | pwm_upper[i] = 0; |
kosaka | 12:a4b17bb682eb | 178 | pwm_lower[i] = 1; |
kosaka | 12:a4b17bb682eb | 179 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 180 | } |
kosaka | 12:a4b17bb682eb | 181 | } |
kosaka | 12:a4b17bb682eb | 182 | #endif |
kosaka | 12:a4b17bb682eb | 183 | |
kosaka | 12:a4b17bb682eb | 184 | |
kosaka | 12:a4b17bb682eb | 185 | void start_pwm(){ |
kosaka | 12:a4b17bb682eb | 186 | unsigned char i; |
kosaka | 12:a4b17bb682eb | 187 | for( i=0;i<3;i++ ){ |
kosaka | 12:a4b17bb682eb | 188 | uvw[i].duty = 0.5; |
kosaka | 12:a4b17bb682eb | 189 | pwm_upper[i] = pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 190 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 191 | } |
kosaka | 12:a4b17bb682eb | 192 | pwmUout(); |
kosaka | 12:a4b17bb682eb | 193 | pwmVout(); |
kosaka | 12:a4b17bb682eb | 194 | pwmWout(); |
kosaka | 12:a4b17bb682eb | 195 | } |
kosaka | 12:a4b17bb682eb | 196 | |
kosaka | 12:a4b17bb682eb | 197 | void stop_pwm(){ |
kosaka | 12:a4b17bb682eb | 198 | unsigned char i; |
kosaka | 12:a4b17bb682eb | 199 | for( i=0;i<3;i++ ){ |
kosaka | 12:a4b17bb682eb | 200 | pwm_upper[i] = pwm_lower[i] = 0; |
kosaka | 12:a4b17bb682eb | 201 | uvw[i].mode = 0; |
kosaka | 12:a4b17bb682eb | 202 | pwm[i].detach(); |
kosaka | 12:a4b17bb682eb | 203 | } |
kosaka | 12:a4b17bb682eb | 204 | } |