Rev 21 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 21 | Rev 23 | ||
---|---|---|---|
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 1 |
12 | #define MICROSECS_PULSE 4 |
13 | - | ||
14 | 13 | ||
15 | // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000 |
14 | // 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 |
15 | // 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 . |
16 | // first pulse longer than 1/300 of a second as being a proper closure . |
18 | // the TIM2 counter counts in 1uS increments, |
17 | // the TIM2 counter counts in 1uS increments, |
19 | #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300)) |
18 | #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300)) |
20 | 19 | ||
21 | #define COUNT_FROM_RPM(RPM) ((1E6/(MICROSECS_PULSE * 30 / (RPM ) ))) |
20 | #define COUNT_FROM_RPM(RPM) ((1E6/(MICROSECS_PULSE * 30 / (RPM ) ))) |
22 | 21 | ||
23 | - | ||
24 | int16_t nominal = 0; |
22 | int16_t nominal = 0; |
25 | uint16_t halfRot; |
23 | uint16_t halfRot; |
26 | int16_t phase10 = 100; // 10 degrees |
24 | int16_t phase10 = 100; // 10 degrees |
27 | volatile uint16_t sampleVar; |
25 | volatile uint16_t sampleVar; |
28 | volatile uint16_t sampleRef; |
26 | volatile uint16_t sampleRef; |
Line 30... | Line 28... | ||
30 | volatile uint16_t lastSampleRef = 0; |
28 | volatile uint16_t lastSampleRef = 0; |
31 | 29 | ||
32 | volatile uint8_t refCount = 0; |
30 | volatile uint8_t refCount = 0; |
33 | volatile uint8_t varCount = 0; |
31 | volatile uint8_t varCount = 0; |
34 | 32 | ||
35 | - | ||
36 | - | ||
37 | - | ||
38 | volatile uint16_t samplePeriod = 0 ; |
33 | volatile uint16_t samplePeriod = 0; |
39 | 34 | ||
40 | static signed phaseSamp = 0; |
35 | static signed phaseSamp = 0; |
41 | static uint8_t validPhaseSamp = 0; |
36 | static uint8_t validPhaseSamp = 0; |
42 | 37 | ||
43 | int gainControl = 1000 ; |
38 | int gainControl = 1000; |
44 | - | ||
45 | 39 | ||
46 | uint16_t rpm; |
40 | uint16_t rpm; |
47 | signed count; |
41 | signed count; |
48 | signed delta; |
42 | signed delta; |
49 | 43 | ||
50 | - | ||
51 | 44 | void |
|
52 | void recalcPhase() |
45 | recalcPhase () |
53 | { |
46 | { |
54 | nominal = halfRot * (long) (phase10)/ 3600; |
47 | nominal = halfRot * (long) (phase10) / 3600; |
55 | } |
48 | } |
56 | 49 | ||
- | 50 | void |
|
57 | void adjustRPM(void) |
51 | adjustRPM (void) |
58 | { |
52 | { |
59 | if(rpm < 600) |
53 | if (rpm < 600) |
60 | rpm = 600; |
54 | rpm = 600; |
61 | if(rpm > 5000) |
55 | if (rpm > 5000) |
62 | rpm = 5000; |
56 | rpm = 5000; |
63 | - | ||
64 | 57 | ||
65 | } |
58 | } |
66 | 59 | ||
- | 60 | uint16_t |
|
67 | uint16_t setRPM(uint16_t rpm_ ) |
61 | setRPM (uint16_t rpm_) |
68 | { |
62 | { |
69 | if(rpm_ >= 600 && rpm_ < 6000) |
63 | if (rpm_ >= 600 && rpm_ < 6000) |
70 | { |
64 | { |
71 | rpm = rpm_; |
65 | rpm = rpm_; |
72 | adjustRPM(); |
66 | adjustRPM (); |
73 | } |
67 | } |
74 | return halfRot; |
68 | return halfRot; |
75 | } |
69 | } |
76 | 70 | ||
- | 71 | uint16_t |
|
77 | uint16_t getRPM(void) |
72 | getRPM (void) |
78 | { |
73 | { |
79 | return rpm; |
74 | return rpm; |
80 | } |
75 | } |
81 | 76 | ||
- | 77 | signed |
|
82 | signed getDelta(void) |
78 | getDelta (void) |
83 | { |
79 | { |
84 | return delta; |
80 | return delta; |
85 | } |
81 | } |
86 | 82 | ||
- | 83 | signed |
|
87 | signed getCount(void) |
84 | getCount (void) |
88 | { |
85 | { |
89 | return count; |
86 | return count; |
90 | } |
87 | } |
91 | 88 | ||
- | 89 | void |
|
92 | void setGain(int gain) |
90 | setGain (int gain) |
93 | { |
91 | { |
94 | gainControl = gain; |
92 | gainControl = gain; |
95 | } |
93 | } |
96 | 94 | ||
97 | - | ||
98 | - | ||
99 | 95 | void |
|
100 | void processPhase ( void ) |
96 | processPhase (void) |
101 | { |
97 | { |
102 | // lpcl |
98 | // lpcl |
103 | chSysLock(); |
- | |
104 | - | ||
105 | const signed pdClip = 10000; |
99 | const signed pdClip = 10000; |
106 | static signed pd; |
100 | static signed pd; |
107 | if(validPhaseSamp) |
101 | if (validPhaseSamp) |
108 | { |
- | |
109 | pd = phaseSamp - nominal; |
- | |
110 | validPhaseSamp = 0; |
- | |
111 | if(pd > pdClip) |
- | |
112 | pd = pdClip; |
- | |
113 | if(pd < -pdClip) |
- | |
114 | pd = -pdClip; |
- | |
115 | - | ||
116 | - | ||
117 | } |
102 | { |
118 | - | ||
119 | - | ||
120 | - | ||
121 | chSysUnlock(); |
103 | chSysLock (); |
122 | - | ||
123 | - | ||
124 | delta = pd; |
- | |
125 | - | ||
126 | - | ||
127 | static int sampleAverage = 0; |
- | |
128 | - | ||
129 | static int phaseAverage = 0; |
- | |
130 | const int freqScale = 6; |
- | |
131 | - | ||
132 | const int phaseScale = 50; |
- | |
133 | 104 | ||
134 | sampleAverage = sampleAverage + (samplePeriod - sampleAverage/freqScale); |
105 | pd = phaseSamp - nominal; |
135 | 106 | ||
- | 107 | validPhaseSamp = 0; |
|
- | 108 | chSysUnlock (); |
|
136 | 109 | ||
- | 110 | if (pd > pdClip) |
|
- | 111 | pd = pdClip; |
|
- | 112 | if (pd < -pdClip) |
|
- | 113 | pd = -pdClip; |
|
137 | 114 | ||
- | 115 | } |
|
- | 116 | else |
|
- | 117 | return; |
|
138 | 118 | ||
- | 119 | delta = pd; |
|
139 | 120 | ||
140 | int32_t arr; |
121 | static int sampleAverage = 0; |
141 | 122 | ||
- | 123 | static int phaseAverage = 0; |
|
142 | // if(lock) |
124 | const int freqScale = 16; |
143 | 125 | ||
- | 126 | const int periodScale= 4; // 1/periodScale of difference between period measured and average is added to period. |
|
144 | int intSample = sampleAverage / freqScale; |
127 | const int phaseScale = 50; |
145 | 128 | ||
- | 129 | // measure sample period devi |
|
- | 130 | sampleAverage = sampleAverage + (samplePeriod *freqScale - sampleAverage) / periodScale; |
|
146 | 131 | ||
- | 132 | int32_t arr; |
|
147 | 133 | ||
148 | int deltaPd= pd/ phaseScale; |
134 | // if(lock) |
149 | 135 | ||
- | 136 | int intSample = sampleAverage / freqScale; |
|
150 | 137 | ||
151 | if(deltaPd == 0) |
- | |
152 | { |
- | |
153 | if(pd > 0) |
- | |
154 | deltaPd =1; |
138 | int deltaPd = pd / phaseScale; |
155 | 139 | ||
156 | if(pd< 0) |
140 | if (deltaPd == 0) |
- | 141 | { |
|
157 | deltaPd =-1; |
142 | if (pd > 0) |
158 | } |
143 | deltaPd = 1; |
159 | 144 | ||
160 | arr = intSample + deltaPd; |
145 | if (pd < 0) |
- | 146 | deltaPd = -1; |
|
- | 147 | } |
|
161 | 148 | ||
- | 149 | arr = intSample + deltaPd; |
|
162 | 150 | ||
163 | // clamp values |
151 | // clamp values |
164 | 152 | ||
- | 153 | if (arr > 65535) |
|
- | 154 | arr = 65535; |
|
- | 155 | if (arr < 1000) |
|
- | 156 | arr = 1000; |
|
165 | 157 | ||
166 | if(arr > 65535) |
- | |
167 | arr = 65535; |
- | |
168 | if(arr < 1000) |
- | |
169 | arr = 1000; |
- | |
170 | - | ||
171 | count = arr; |
158 | count = arr; |
172 | - | ||
173 | TIM2->ARR = arr -1; |
- | |
174 | 159 | ||
175 | nominal = intSample * (long) (phase10)/ 3600; |
160 | TIM2->ARR = arr - 1; |
176 | 161 | ||
177 | float nomRPM = 30E6 / (MICROSECS_PULSE * arr); |
162 | nominal = intSample * (long) (phase10) / 3600; |
178 | - | ||
179 | rpm = nomRPM ; |
- | |
180 | - | ||
181 | adjustRPM(); |
- | |
182 | } |
- | |
183 | 163 | ||
- | 164 | float nomRPM = 30E6 / (MICROSECS_PULSE * arr); |
|
184 | 165 | ||
- | 166 | rpm = nomRPM; |
|
185 | 167 | ||
- | 168 | adjustRPM (); |
|
- | 169 | } |
|
186 | 170 | ||
187 | // set the timing advance from reference in 0.1 degrees units |
171 | // set the timing advance from reference in 0.1 degrees units |
- | 172 | void |
|
188 | void setAdvance(int16_t deg10) |
173 | setAdvance (int16_t deg10) |
189 | { |
174 | { |
190 | phase10 = deg10; |
175 | phase10 = deg10; |
191 | 176 | ||
192 | } |
177 | } |
193 | 178 | ||
194 | - | ||
195 | - | ||
196 | // specialist timer setup : |
179 | // specialist timer setup : |
197 | // timer 2 is a reloading counter with a cycle period controlled by its ARR register. |
180 | // timer 2 is a reloading counter with a cycle period controlled by its ARR register. |
198 | // Just before terminal count it produces a pulse of 200 microseconds using its CCR1 count compare register, |
181 | // Just before terminal count it produces a pulse of 200 microseconds using its CCR1 count compare register, |
199 | // used to drive the strobe LED. |
182 | // used to drive the strobe LED. |
200 | // Timer 3 is then used to count the time of the reload of Timer 2 via its Trigger Out being selected as reload. |
183 | // Timer 3 is then used to count the time of the reload of Timer 2 via its Trigger Out being selected as reload. |
201 | // The time is latched in TIM3 CCR2 |
184 | // The time is latched in TIM3 CCR2 |
202 | // and ignition pulses are latched on TIM3 CCR1, to allow it to be used in a PLL. |
185 | // and ignition pulses are latched on TIM3 CCR1, to allow it to be used in a PLL. |
203 | // |
186 | // |
- | 187 | void |
|
204 | void initTimers() |
188 | initTimers () |
205 | { |
189 | { |
206 | rccEnableTIM2(FALSE); |
190 | rccEnableTIM2 (FALSE); |
207 | rccResetTIM2(); |
191 | rccResetTIM2 (); |
208 | - | ||
209 | TIM2->PSC = 72*MICROSECS_PULSE; |
- | |
210 | TIM2->ARR = 60000; |
- | |
211 | TIM2->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | |
- | |
212 | TIM_CR1_ARPE ); |
- | |
213 | - | ||
214 | /// pulse width 200 uS |
- | |
215 | TIM2->CCR1 = 200/MICROSECS_PULSE; |
- | |
216 | - | ||
217 | TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P ; //enabled and active high |
- | |
218 | - | ||
219 | TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | |
- | |
220 | TIM_CCMR1_OC1PE ; |
- | |
221 | - | ||
222 | - | ||
223 | TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update |
- | |
224 | 192 | ||
- | 193 | TIM2->PSC = 72 * MICROSECS_PULSE; |
|
- | 194 | TIM2->ARR = 60000; |
|
- | 195 | TIM2->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE); |
|
225 | 196 | ||
226 | rccEnableTIM3(FALSE); |
197 | /// pulse width 200 uS |
227 | rccResetTIM3(); |
- | |
228 | // TIM3 on the PA6 ... pins : remap code 00 |
- | |
229 | AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP; |
198 | TIM2->CCR1 = 200 / MICROSECS_PULSE; |
230 | 199 | ||
231 | TIM3->PSC = 72*MICROSECS_PULSE; |
200 | TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P; //enabled and active high |
232 | TIM3->ARR = 0xFFFF; |
- | |
233 | 201 | ||
- | 202 | TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
|
- | 203 | | TIM_CCMR1_OC1PE; |
|
234 | 204 | ||
235 | TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ; // filter 16, input |
205 | TIM2->CR2 = TIM_CR2_MMS_1; // trigger out is 010 = update |
236 | 206 | ||
- | 207 | rccEnableTIM3 (FALSE); |
|
- | 208 | rccResetTIM3 (); |
|
- | 209 | // TIM3 on the PA6 ... pins : remap code 00 |
|
- | 210 | AFIO->MAPR &= ~AFIO_MAPR_TIM3_REMAP; |
|
237 | 211 | ||
238 | // link TIM3 ITR2 to TIM2 reload |
212 | TIM3->PSC = 72 * MICROSECS_PULSE; |
239 | // use TS = 001 to make TRC from Tim2 TRIGGER |
- | |
240 | TIM3->SMCR &= ~(TIM_SMCR_TS_Msk ); |
213 | TIM3->ARR = 0xFFFF; |
241 | TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC |
- | |
242 | 214 | ||
- | 215 | TIM3->CCMR1 = |
|
243 | TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0 ; // The CC2S bits are 11, use TRC |
216 | TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */; // filter 16, input |
244 | 217 | ||
- | 218 | // link TIM3 ITR2 to TIM2 reload |
|
- | 219 | // use TS = 001 to make TRC from Tim2 TRIGGER |
|
245 | TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; |
220 | TIM3->SMCR &= ~(TIM_SMCR_TS_Msk); |
- | 221 | TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC |
|
246 | 222 | ||
247 | TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE ); |
223 | TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0; // The CC2S bits are 11, use TRC |
248 | 224 | ||
- | 225 | TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; |
|
249 | 226 | ||
250 | nvicEnableVector(TIM3_IRQn, |
227 | TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE); |
251 | 4); |
- | |
252 | 228 | ||
- | 229 | nvicEnableVector (TIM3_IRQn, 4); |
|
253 | 230 | ||
254 | - | ||
255 | TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE; |
231 | TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE; |
256 | } |
232 | } |
257 | 233 | ||
258 | - | ||
259 | // timer 3 interrupt |
234 | // timer 3 interrupt |
- | 235 | void |
|
260 | void VectorB4(void) |
236 | VectorB4 (void) |
261 | { |
237 | { |
262 | 238 | ||
263 | if(TIM3->SR & TIM_SR_CC1IF) |
239 | if (TIM3->SR & TIM_SR_CC1IF) |
264 | { |
240 | { |
265 | uint16_t sample = TIM3->CCR1; |
241 | uint16_t sample = TIM3->CCR1; |
266 | // if(sample-lastSampleRef > 1000 /*BREAKER_COUNT_MIN */) |
242 | // if(sample-lastSampleRef > 1000 /*BREAKER_COUNT_MIN */) |
267 | { |
243 | { |
268 | - | ||
269 | samplePeriod = sample-sampleRef; |
- | |
270 | 244 | ||
271 | sampleRef = sample; |
245 | samplePeriod = sample - sampleRef; |
272 | 246 | ||
273 | ++refCount; |
- | |
274 | } |
- | |
275 | lastSampleRef= sample; |
247 | sampleRef = sample; |
276 | 248 | ||
- | 249 | ++refCount; |
|
277 | } |
250 | } |
278 | if(TIM3->SR & TIM_SR_CC2IF) |
- | |
279 | { |
- | |
280 | sampleVar = TIM3->CCR2; |
251 | lastSampleRef = sample; |
281 | ++varCount; |
- | |
282 | } |
- | |
283 | 252 | ||
- | 253 | } |
|
284 | if(refCount == 1 && varCount == 1) |
254 | if (TIM3->SR & TIM_SR_CC2IF) |
285 | { |
255 | { |
286 | if(sampleRef == sampleVar) |
256 | sampleVar = TIM3->CCR2; |
287 | phaseSamp = 0; |
257 | ++varCount; |
288 | else |
- | |
289 | { |
258 | } |
290 | 259 | ||
291 | uint16_t refToVar = sampleRef - sampleVar; |
260 | if (refCount == 1 && varCount == 1) |
- | 261 | { |
|
292 | uint16_t varToRef = sampleVar - sampleRef; |
262 | if (sampleRef == sampleVar) |
- | 263 | phaseSamp = 0; |
|
- | 264 | else |
|
- | 265 | { |
|
293 | 266 | ||
294 | if(refToVar < varToRef) |
267 | uint16_t refToVar = sampleRef - sampleVar; |
295 | phaseSamp = refToVar; |
- | |
296 | else if(varToRef <= refToVar) |
268 | uint16_t varToRef = sampleVar - sampleRef; |
297 | phaseSamp = -varToRef; |
- | |
298 | 269 | ||
- | 270 | if (refToVar < varToRef) |
|
299 | } |
271 | phaseSamp = refToVar; |
- | 272 | else if (varToRef <= refToVar) |
|
- | 273 | phaseSamp = -varToRef; |
|
300 | 274 | ||
- | 275 | } |
|
301 | 276 | ||
302 | validPhaseSamp = 1; |
277 | validPhaseSamp = 1; |
303 | refCount=0; |
278 | refCount = 0; |
304 | varCount=0; |
279 | varCount = 0; |
305 | 280 | ||
306 | } |
281 | } |
307 | 282 | ||
308 | // frequency error, should deal with by direct period measurement |
283 | // frequency error, should deal with by direct period measurement |
309 | if(refCount > 1 || varCount > 1 ) |
284 | if (refCount > 1 || varCount > 1) |
310 | { |
285 | { |
311 | refCount = 0; |
286 | refCount = 0; |
312 | varCount = 0; |
287 | varCount = 0; |
313 | 288 | ||
314 | } |
289 | } |
315 | 290 | ||
316 | } |
291 | } |
317 | 292 | ||
318 | - | ||
319 | - |