Rev 18 | Rev 20 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 18 | Rev 19 | ||
|---|---|---|---|
| Line 7... | Line 7... | ||
| 7 | 7 | ||
| 8 | #include "ch.h" // needs for all ChibiOS programs |
8 | #include "ch.h" // needs for all ChibiOS programs |
| 9 | #include "hal.h" // hardware abstraction layer header |
9 | #include "hal.h" // hardware abstraction layer header |
| 10 | 10 | ||
| 11 | #include "timer2.h" |
11 | #include "timer2.h" |
| 12 | #define MICROSECS_PULSE 10 |
12 | #define MICROSECS_PULSE 1 |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000 |
15 | // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000 |
| 16 | // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the |
16 | // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the |
| 17 | // first pulse longer than 1/300 of a second as being a proper closure . |
17 | // first pulse longer than 1/300 of a second as being a proper closure . |
| Line 22... | Line 22... | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | uint16_t nominal = 0; |
24 | uint16_t nominal = 0; |
| 25 | uint16_t halfRot; |
25 | uint16_t halfRot; |
| 26 | uint16_t phase10 = 100; // 10 degrees |
26 | uint16_t phase10 = 100; // 10 degrees |
| 27 | volatile uint16_t sampleRefCount = 0; |
- | |
| 28 | volatile uint16_t sampleVar; |
27 | volatile uint16_t sampleVar; |
| 29 | volatile uint16_t sampleRef; |
28 | volatile uint16_t sampleRef; |
| 30 | 29 | ||
| - | 30 | volatile uint16_t lastSampleRef = 0; |
|
| 31 | 31 | ||
| 32 | int gainControl = 1000 ; |
32 | volatile uint8_t refCount = 0; |
| 33 | - | ||
| 34 | volatile uint8_t haveSlowPulse = 0; |
33 | volatile uint8_t varCount = 0; |
| 35 | - | ||
| 36 | uint16_t rpm; |
- | |
| 37 | signed count; |
- | |
| 38 | signed delta; |
- | |
| 39 | - | ||
| 40 | void initTimer2() |
- | |
| 41 | { |
- | |
| 42 | rccEnableTIM2(FALSE); |
- | |
| 43 | rccResetTIM2(); |
- | |
| 44 | - | ||
| 45 | TIM2->PSC = 72*MICROSECS_PULSE; |
- | |
| 46 | TIM2->ARR = 60000; |
- | |
| 47 | TIM2->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | |
- | |
| 48 | TIM_CR1_ARPE ); |
- | |
| 49 | - | ||
| 50 | /// pulse width 200 uS |
- | |
| 51 | TIM2->CCR1 = 200/MICROSECS_PULSE; |
- | |
| 52 | 34 | ||
| 53 | TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P ; //enabled and active high |
- | |
| 54 | 35 | ||
| 55 | TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | |
- | |
| 56 | TIM_CCMR1_OC1PE ; |
- | |
| 57 | 36 | ||
| 58 | 37 | ||
| 59 | TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update |
38 | volatile uint16_t samplePeriod = 0 ; |
| 60 | 39 | ||
| - | 40 | static signed phaseSamp = 0; |
|
| - | 41 | static uint8_t validPhaseSamp = 0; |
|
| 61 | 42 | ||
| 62 | // change the TIM2 CC2 to TIM3 CC1 |
- | |
| 63 | rccEnableTIM3(FALSE); |
- | |
| 64 | rccResetTIM3(); |
- | |
| 65 | // TIM3 on the PA6 ... pins : remap code 00 |
- | |
| 66 | AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP; |
- | |
| 67 | - | ||
| 68 | TIM3->PSC = 72*MICROSECS_PULSE; |
- | |
| 69 | TIM3->ARR = 0xFFFF; |
- | |
| 70 | - | ||
| 71 | - | ||
| 72 | TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ; // filter 16, input |
- | |
| 73 | - | ||
| 74 | - | ||
| 75 | // link TIM3 ITR2 to TIM2 reload |
- | |
| 76 | // use TS = 001 to make TRC from Tim2 TRIGGER |
- | |
| 77 | TIM3->SMCR &= ~(TIM_SMCR_TS_Msk ); |
- | |
| 78 | TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC |
- | |
| 79 | - | ||
| 80 | TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0 ; // The CC2S bits are 11, use TRC |
- | |
| 81 | - | ||
| 82 | TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; |
- | |
| 83 | - | ||
| 84 | TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE ); |
- | |
| 85 | - | ||
| 86 | - | ||
| 87 | nvicEnableVector(TIM3_IRQn, |
- | |
| 88 | 4); |
43 | int gainControl = 1000 ; |
| 89 | 44 | ||
| 90 | 45 | ||
| - | 46 | uint16_t rpm; |
|
| - | 47 | signed count; |
|
| - | 48 | signed delta; |
|
| 91 | 49 | ||
| 92 | TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE; |
- | |
| 93 | } |
- | |
| 94 | 50 | ||
| 95 | 51 | ||
| 96 | void recalcPhase(void) |
52 | void recalcPhase(void) |
| 97 | { |
53 | { |
| 98 | nominal = halfRot * (long) (phase10)/ 1800; |
54 | nominal = halfRot * (long) (phase10)/ 1800; |
| Line 136... | Line 92... | ||
| 136 | { |
92 | { |
| 137 | gainControl = gain; |
93 | gainControl = gain; |
| 138 | } |
94 | } |
| 139 | 95 | ||
| 140 | 96 | ||
| 141 | uint8_t slowPulse(void) |
- | |
| 142 | { |
- | |
| 143 | return haveSlowPulse; |
- | |
| 144 | } |
- | |
| 145 | 97 | ||
| 146 | 98 | ||
| 147 | void processPhase (int refCount,int varCount, int diff) |
99 | void processPhase ( void ) |
| 148 | { |
100 | { |
| - | 101 | // lpcl |
|
| - | 102 | chSysLock(); |
|
| 149 | 103 | ||
| - | 104 | signed pd; |
|
| - | 105 | pd = 0; |
|
| 150 | // scale it up by 32 |
106 | static unsigned sp = 0; |
| - | 107 | if(validPhaseSamp) |
|
| - | 108 | { |
|
| 151 | // at this point we should try to phase lock |
109 | pd = phaseSamp; |
| - | 110 | validPhaseSamp = 0; |
|
| 152 | 111 | ||
| - | 112 | delta = phaseSamp; |
|
| 153 | 113 | ||
| 154 | signed pd = 0; |
- | |
| 155 | bool lock = false; |
- | |
| 156 | // basically locked |
- | |
| 157 | if(refCount==1 && varCount==1 ) |
- | |
| 158 | { |
- | |
| 159 | lock = true; |
- | |
| 160 | pd = (diff < 32768 ? diff : diff - 65536L) ; |
- | |
| 161 | } |
- | |
| 162 | // frequency detector |
114 | sp = samplePeriod; |
| 163 | else if (refCount > 1) |
- | |
| 164 | { |
- | |
| 165 | pd = (refCount*32768L); |
- | |
| 166 | } |
- | |
| 167 | else if (varCount > 1) |
- | |
| 168 | { |
- | |
| 169 | pd = (-varCount * 32768L); |
- | |
| 170 | } |
115 | } |
| 171 | float delta_phi = pd/ (gainControl * 1.0); |
- | |
| 172 | - | ||
| 173 | 116 | ||
| 174 | delta = pd; |
117 | chSysUnlock(); |
| 175 | 118 | ||
| 176 | 119 | ||
| - | 120 | static int sampleAverage = 0; |
|
| 177 | 121 | ||
| - | 122 | static int phaseAverage = 0; |
|
| 178 | // phase detector returns +/ |
123 | const int freqScale = 40; |
| 179 | 124 | ||
| - | 125 | const int phaseScale = 200; |
|
| 180 | 126 | ||
| - | 127 | sampleAverage = sampleAverage + (sp - sampleAverage/freqScale); |
|
| 181 | 128 | ||
| 182 | float const wn = 0.01; |
- | |
| 183 | float const zeta = 0.707f; // was 0.707 |
- | |
| 184 | float const K = 1000; |
- | |
| 185 | 129 | ||
| 186 | float const t1 = K/(wn*wn); |
- | |
| 187 | float const t2 = 2 * zeta/wn; |
- | |
| 188 | float const b0 = (4*K/t1)*(1.+t2/2.0f); |
- | |
| 189 | float const b1 = (8*K / t1); |
- | |
| 190 | float const b2 = (4*K/t1)*(1.-t2/2.0f); |
- | |
| 191 | 130 | ||
| 192 | float const a1 = -2.0f; |
- | |
| 193 | float const a2 = 1.0f; |
- | |
| 194 | static float v0=0, v1 = 0, v2 = 0 ; |
- | |
| 195 | 131 | ||
| 196 | 132 | ||
| 197 | static float phi_hat = 100.0f; |
133 | int32_t arr; |
| 198 | 134 | ||
| - | 135 | // if(lock) |
|
| 199 | 136 | ||
| 200 | v2=v1; v1=v0; |
- | |
| 201 | v0 = delta_phi -v1 *a1 -v2 *a2; |
137 | int intSample = sampleAverage / freqScale; |
| 202 | 138 | ||
| - | 139 | static unsigned strange = 0; |
|
| 203 | 140 | ||
| 204 | phi_hat = v0 * b0 + v1 * b1 + v2 * b2 ; |
- | |
| 205 | 141 | ||
| 206 | 142 | ||
| - | 143 | int deltaPd= pd/10; |
|
| 207 | 144 | ||
| - | 145 | if(pd < -2000 || pd > 2000) |
|
| - | 146 | { |
|
| 208 | // 6.283 = 1.0 Hz |
147 | strange++; |
| - | 148 | } |
|
| 209 | 149 | ||
| 210 | // 62.2 = 10Hz |
- | |
| 211 | // decide on whether to go for forcing loop or to track |
150 | arr = intSample + deltaPd; |
| 212 | 151 | ||
| 213 | int32_t arr; |
- | |
| 214 | 152 | ||
| 215 | // if(lock) |
- | |
| 216 | 153 | ||
| 217 | 154 | ||
| 218 | arr = (6283000L/MICROSECS_PULSE)/ (phi_hat+60); |
- | |
| 219 | 155 | ||
| 220 | if(arr > 20000) |
156 | if(arr > 65535) |
| 221 | arr = 20000; |
157 | arr = 65535; |
| 222 | if(arr < 100) |
158 | if(arr < 1000) |
| 223 | arr = 100; |
159 | arr = 1000; |
| 224 | 160 | ||
| 225 | 161 | ||
| 226 | 162 | ||
| 227 | count = arr; |
163 | count = arr; |
| 228 | 164 | ||
| 229 | TIM2->ARR = arr ; |
165 | TIM2->ARR = arr -1; |
| 230 | recalcPhase(); |
166 | recalcPhase(); |
| 231 | 167 | ||
| 232 | 168 | ||
| 233 | 169 | ||
| 234 | float nomRPM = 30E6 / (MICROSECS_PULSE * arr); |
170 | float nomRPM = 30E6 / (MICROSECS_PULSE * arr); |
| Line 248... | Line 184... | ||
| 248 | phase10 = deg10; |
184 | phase10 = deg10; |
| 249 | recalcPhase(); |
185 | recalcPhase(); |
| 250 | 186 | ||
| 251 | } |
187 | } |
| 252 | 188 | ||
| - | 189 | ||
| - | 190 | ||
| - | 191 | // specialist timer setup : |
|
| - | 192 | void initTimer2() |
|
| - | 193 | { |
|
| - | 194 | rccEnableTIM2(FALSE); |
|
| - | 195 | rccResetTIM2(); |
|
| - | 196 | ||
| - | 197 | TIM2->PSC = 72*MICROSECS_PULSE; |
|
| - | 198 | TIM2->ARR = 60000; |
|
| - | 199 | TIM2->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | |
|
| - | 200 | TIM_CR1_ARPE ); |
|
| - | 201 | ||
| - | 202 | /// pulse width 200 uS |
|
| - | 203 | TIM2->CCR1 = 200/MICROSECS_PULSE; |
|
| - | 204 | ||
| - | 205 | TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P ; //enabled and active high |
|
| - | 206 | ||
| - | 207 | TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | |
|
| - | 208 | TIM_CCMR1_OC1PE ; |
|
| - | 209 | ||
| - | 210 | ||
| - | 211 | TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update |
|
| - | 212 | ||
| - | 213 | ||
| - | 214 | // change the TIM2 CC2 to TIM3 CC1 |
|
| - | 215 | rccEnableTIM3(FALSE); |
|
| - | 216 | rccResetTIM3(); |
|
| - | 217 | // TIM3 on the PA6 ... pins : remap code 00 |
|
| - | 218 | AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP; |
|
| - | 219 | ||
| - | 220 | TIM3->PSC = 72*MICROSECS_PULSE; |
|
| - | 221 | TIM3->ARR = 0xFFFF; |
|
| - | 222 | ||
| - | 223 | ||
| - | 224 | TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ; // filter 16, input |
|
| - | 225 | ||
| - | 226 | ||
| - | 227 | // link TIM3 ITR2 to TIM2 reload |
|
| - | 228 | // use TS = 001 to make TRC from Tim2 TRIGGER |
|
| - | 229 | TIM3->SMCR &= ~(TIM_SMCR_TS_Msk ); |
|
| - | 230 | TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC |
|
| - | 231 | ||
| - | 232 | TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0 ; // The CC2S bits are 11, use TRC |
|
| - | 233 | ||
| - | 234 | TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; |
|
| - | 235 | ||
| - | 236 | TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE ); |
|
| - | 237 | ||
| - | 238 | ||
| - | 239 | nvicEnableVector(TIM3_IRQn, |
|
| - | 240 | 4); |
|
| - | 241 | ||
| - | 242 | ||
| - | 243 | ||
| - | 244 | TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE; |
|
| - | 245 | } |
|
| - | 246 | ||
| - | 247 | ||
| 253 | // timer 3 interrupt |
248 | // timer 3 interrupt |
| 254 | void VectorB4(void) |
249 | void VectorB4(void) |
| 255 | { |
250 | { |
| 256 | static uint16_t lastSampleRef = 0; |
- | |
| 257 | static uint8_t refCount = 0; |
- | |
| 258 | static uint8_t varCount = 0; |
- | |
| 259 | uint16_t samplePeriod; |
- | |
| 260 | 251 | ||
| 261 | uint16_t stat = TIM3->SR; |
- | |
| 262 | if(stat & TIM_SR_CC1IF) |
252 | if(TIM3->SR & TIM_SR_CC1IF) |
| 263 | { |
253 | { |
| 264 | TIM3->SR &= ~TIM_SR_CC1IF; |
- | |
| 265 | uint16_t sample = TIM3->CCR1; |
254 | uint16_t sample = TIM3->CCR1; |
| 266 | if(sample-lastSampleRef > 100 /*BREAKER_COUNT_MIN */) |
255 | // if(sample-lastSampleRef > 1000 /*BREAKER_COUNT_MIN */) |
| 267 | { |
256 | { |
| - | 257 | ||
| - | 258 | samplePeriod = sample-sampleRef; |
|
| - | 259 | ||
| 268 | sampleRef = sample; |
260 | sampleRef = sample; |
| 269 | 261 | ||
| 270 | ++refCount; |
262 | ++refCount; |
| 271 | } |
263 | } |
| 272 | samplePeriod = sample-lastSampleRef; |
264 | lastSampleRef= sample; |
| 273 | 265 | ||
| 274 | chDbgCheck(samplePeriod != 65535); |
- | |
| 275 | lastSampleRef = sample; |
- | |
| 276 | } |
266 | } |
| 277 | if(stat & TIM_SR_CC2IF) |
267 | if(TIM3->SR & TIM_SR_CC2IF) |
| 278 | { |
268 | { |
| 279 | TIM3->SR &= ~TIM_SR_CC2IF; |
- | |
| 280 | sampleVar = TIM3->CCR2; |
269 | sampleVar = TIM3->CCR2; |
| 281 | ++varCount; |
270 | ++varCount; |
| 282 | } |
271 | } |
| 283 | 272 | ||
| - | 273 | if(refCount == 1 && varCount == 1) |
|
| - | 274 | { |
|
| - | 275 | if(sampleRef == sampleVar) |
|
| - | 276 | phaseSamp = 0; |
|
| - | 277 | else |
|
| - | 278 | { |
|
| - | 279 | ||
| - | 280 | uint16_t refToVar = sampleRef - sampleVar; |
|
| - | 281 | uint16_t varToRef = sampleVar - sampleRef; |
|
| 284 | 282 | ||
| - | 283 | if(refToVar < 32768) |
|
| - | 284 | phaseSamp = refToVar; |
|
| - | 285 | else if(varToRef < 32768) |
|
| - | 286 | phaseSamp = -varToRef; |
|
| 285 | 287 | ||
| - | 288 | } |
|
| 286 | 289 | ||
| 287 | if(refCount != 0 && varCount != 0 ) /*we have an R,V pair */ |
- | |
| 288 | { |
- | |
| 289 | 290 | ||
| 290 | // |
- | |
| 291 | processPhase (refCount,varCount,sampleRef-sampleVar); |
- | |
| 292 | haveSlowPulse = (varCount > 20); |
291 | validPhaseSamp = 1; |
| 293 | refCount = 0; |
292 | refCount=0; |
| 294 | varCount = 0; |
293 | varCount=0; |
| 295 | } |
- | |
| 296 | 294 | ||
| - | 295 | } |
|
| - | 296 | ||
| - | 297 | // frequency error, should deal with by direct period measurement |
|
| - | 298 | if(refCount > 1 || varCount > 1 ) |
|
| - | 299 | { |
|
| - | 300 | refCount = 0; |
|
| - | 301 | varCount = 0; |
|
| 297 | 302 | ||
| - | 303 | } |
|
| 298 | 304 | ||
| 299 | } |
305 | } |
| 300 | 306 | ||
| 301 | 307 | ||
| 302 | 308 | ||