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 |