Rev 12 | Rev 14 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 12 | Rev 13 | ||
---|---|---|---|
Line 16... | Line 16... | ||
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 . |
18 | // the TIM2 counter counts in 10uS increments, |
18 | // the TIM2 counter counts in 10uS increments, |
19 | #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300)) |
19 | #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300)) |
20 | 20 | ||
- | 21 | #define COUNT_FROM_RPM(RPM) ((1E6/(MICROSECS_PULSE * 30 / (RPM ) ))) |
|
- | 22 | ||
- | 23 | ||
21 | #define SAMPLE_BUFF_SIZE 256 |
24 | #define SAMPLE_BUFF_SIZE 256 |
- | 25 | uint16_t nominal = 0; |
|
22 | uint16_t halfRot; |
26 | uint16_t halfRot; |
23 | uint16_t nominal = 0; |
- | |
24 | uint16_t phase10 = 100; // 10 degrees |
27 | uint16_t phase10 = 100; // 10 degrees |
25 | volatile uint16_t sampleCount = 0; |
28 | volatile uint16_t sampleRefCount = 0; |
26 | uint16_t outSampleCount = 0; |
29 | uint16_t outSampleRefCount = 0; |
27 | volatile uint16_t sampleBuff[SAMPLE_BUFF_SIZE]; |
30 | volatile uint16_t sampleRefBuff[SAMPLE_BUFF_SIZE]; |
28 | typedef enum { WAIT_GAP, SKIP_BOUNCE, HAVE_SAMPLE } sampleState_t ; |
- | |
29 | sampleState_t sampleState = WAIT_GAP; |
31 | volatile uint16_t sampleVar; |
30 | // difference between samples |
- | |
31 | volatile uint16_t deltaTime; |
32 | volatile uint16_t sampleRef; |
32 | - | ||
33 | static signed pdI = 0; |
33 | volatile uint16_t sampleDiffBuff[SAMPLE_BUFF_SIZE]; |
34 | - | ||
35 | 34 | ||
36 | uint16_t rpm; |
35 | uint16_t rpm; |
- | 36 | uint16_t count; |
|
- | 37 | uint16_t delta; |
|
37 | 38 | ||
38 | void initTimer2() |
39 | void initTimer2() |
39 | { |
40 | { |
40 | rccEnableTIM2(FALSE); |
41 | rccEnableTIM2(FALSE); |
41 | rccResetTIM2(); |
42 | rccResetTIM2(); |
Line 67... | Line 68... | ||
67 | TIM3->ARR = 0xFFFF; |
68 | TIM3->ARR = 0xFFFF; |
68 | 69 | ||
69 | 70 | ||
70 | TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ; // filter 16, input |
71 | TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ; // filter 16, input |
71 | 72 | ||
72 | TIM3->CCER = TIM_CCER_CC1E; |
- | |
73 | 73 | ||
74 | // link TIM3 ITR1 to TIM2 reload |
74 | // link TIM3 ITR2 to TIM2 reload |
75 | // use CCR3 |
75 | // use TS = 001 to make TRC from Tim2 TRIGGER |
- | 76 | TIM3->SMCR &= ~(TIM_SMCR_TS_Msk ); |
|
- | 77 | TIM3->SMCR |= TIM_SMCR_TS_0; // select ITR2 as trigger source TRC |
|
- | 78 | ||
76 | TIM3->CCMR2 = TIM_CCMR2_CC3S_1 | TIM_CCMR2_CC3S_0 ; // The |
79 | TIM3->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0 ; // The CC2S bits are 11, use TRC |
77 | 80 | ||
- | 81 | TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; |
|
78 | 82 | ||
79 | TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE ); |
83 | TIM3->CR1 = ~TIM_CR1_CKD & (TIM_CR1_CEN | TIM_CR1_ARPE ); |
80 | 84 | ||
81 | 85 | ||
82 | nvicEnableVector(TIM3_IRQn, |
86 | nvicEnableVector(TIM3_IRQn, |
83 | 4); |
87 | 4); |
84 | 88 | ||
85 | 89 | ||
86 | 90 | ||
87 | TIM3->DIER |= TIM_DIER_CC1IE ; |
91 | TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE; |
88 | } |
92 | } |
89 | 93 | ||
90 | 94 | ||
91 | void recalcPhase(void) |
95 | void recalcPhase(void) |
92 | { |
96 | { |
Line 116... | Line 120... | ||
116 | uint16_t getRPM(void) |
120 | uint16_t getRPM(void) |
117 | { |
121 | { |
118 | return rpm; |
122 | return rpm; |
119 | } |
123 | } |
120 | 124 | ||
121 | uint16_t getDelta(void) |
125 | unsigned getDelta(void) |
122 | { |
126 | { |
123 | return pdI&0xFFFF; |
127 | return delta; |
124 | } |
128 | } |
125 | 129 | ||
126 | uint16_t wrapIndex(uint16_t index) |
130 | unsigned getCount(void) |
127 | { |
131 | { |
128 | if (index >= SAMPLE_BUFF_SIZE) |
- | |
129 | index -= SAMPLE_BUFF_SIZE; |
- | |
130 | return index; |
132 | return count; |
131 | } |
- | |
132 | - | ||
133 | // allows for wrapping |
- | |
134 | uint16_t getSampleBuff(uint16_t index) |
- | |
135 | { |
- | |
136 | chSysLock(); |
- | |
137 | return sampleBuff[wrapIndex(index)]; |
- | |
138 | chSysUnlock(); |
- | |
139 | } |
133 | } |
140 | 134 | ||
141 | 135 | ||
142 | // waits for ignition pulse , debounces readings, |
136 | // waits for ignition pulse , debounces readings, |
143 | // returns the pulse time, skips debounce time |
137 | // returns the pulse time, skips debounce time |
144 | uint16_t getNextPulse(void) |
138 | uint16_t getNextRefPulseIndex(void) |
145 | { |
139 | { |
146 | static uint16_t lastSampleIndex = 0; |
- | |
147 | while(1) |
- | |
148 | { |
- | |
149 | while (outSampleCount == sampleCount) |
140 | while (outSampleRefCount == sampleRefCount) |
150 | chThdSleep(10); |
141 | chThdSleep(10); |
151 | 142 | ||
152 | uint16_t thisTime = getSampleBuff(outSampleCount); |
143 | uint16_t sampleIndex = outSampleRefCount; |
153 | 144 | ||
154 | outSampleCount = wrapIndex(outSampleCount + 1); |
- | |
155 | while (outSampleCount == sampleCount) |
145 | if(++outSampleRefCount == SAMPLE_BUFF_SIZE) |
156 | chThdSleep(10); |
- | |
157 | - | ||
158 | uint16_t nextTime = getSampleBuff(outSampleCount); |
- | |
159 | - | ||
160 | // calculate wrapped time delta : should be > than bounce time to allow |
- | |
161 | uint16_t diffTime = nextTime - thisTime; |
- | |
162 | - | ||
163 | if(diffTime > BREAKER_COUNT_MIN) |
- | |
164 | { |
- | |
165 | lastSampleIndex = outSampleCount; |
146 | outSampleRefCount = 0; |
166 | return nextTime; |
147 | return sampleIndex; |
167 | } |
- | |
168 | - | ||
169 | } |
- | |
170 | return 0; |
- | |
171 | } |
148 | } |
172 | 149 | ||
173 | 150 | ||
- | 151 | ||
174 | void processNextPulse(uint16_t retVal) |
152 | void processNextPulse(uint16_t index) |
175 | { |
153 | { |
176 | 154 | ||
177 | static uint32_t VperiodAccumulator = 0; |
- | |
178 | // scale it up by 32 |
155 | // scale it up by 32 |
179 | static uint32_t periodEstimate = 2000 * 256 ; |
156 | static int32_t periodEstimate = 2000 * 256 ; |
180 | static uint16_t lastVal = 0; |
- | |
181 | // at this point we should try to phase lock |
157 | // at this point we should try to phase lock |
182 | deltaTime = retVal - lastVal; |
158 | static signed pdLast = 0; |
- | 159 | uint16_t sampleDiff = sampleDiffBuff[index]; |
|
183 | 160 | ||
184 | 161 | ||
- | 162 | signed pd = (sampleDiff < 32768 ? sampleDiff : sampleDiff - 65536L) ; |
|
185 | 163 | ||
186 | if(deltaTime > 10000) |
- | |
187 | { |
- | |
188 | __asm(" BKPT #0"); |
- | |
189 | } |
- | |
190 | 164 | ||
191 | lastVal = retVal; |
- | |
192 | 165 | ||
193 | // look at the values and try to pull them togwther |
166 | static float phase_offset = 0; |
- | 167 | float const wn = 0.01f; |
|
- | 168 | float const zeta = 0.707f; |
|
- | 169 | float const K = 100; |
|
194 | 170 | ||
195 | // accumulate phase |
171 | float const t1 = K/(wn*wn); |
196 | VperiodAccumulator += periodEstimate; |
172 | float const t2 = 2 * zeta/wn; |
- | 173 | float const b0 = (4*K/t1)*(1.+t2/2.0f); |
|
197 | VperiodAccumulator &= 0xFFFFFFF; |
174 | float const b1 = (8*K / t1); |
- | 175 | float const b2 = (4*K/t1)*(1.-t2/2.0f); |
|
198 | 176 | ||
199 | uint16_t accum_low = (VperiodAccumulator) >> 8; |
177 | float const a1 = -2.0f; |
200 | #define WINDOW 1000 |
178 | float const a2 = 1.0f; |
201 | 179 | ||
202 | #define LIMIT 2048 |
180 | static float v0=0.0f, v1 = 0.0f, v2 = 0.0f; |
203 | 181 | ||
204 | #define STEP 32 |
- | |
205 | 182 | ||
206 | uint16_t diff = accum_low - retVal; |
- | |
207 | if(diff < WINDOW && diff != 0) |
183 | static float phi_hat = 0.0f; |
208 | pdI += diff/10; |
- | |
209 | if(diff > 65536-WINDOW ) |
- | |
210 | pdI -= (65536-diff)/10; |
- | |
211 | 184 | ||
212 | if(pdI > LIMIT) |
- | |
213 | pdI = LIMIT; |
- | |
214 | if(pdI < -(LIMIT)) |
- | |
215 | pdI = -(LIMIT); |
185 | float delta_phi = pd/ 32768.0; |
216 | 186 | ||
- | 187 | v2=v1; v1=v0; |
|
- | 188 | v0 = delta_phi -v1 *a1 -v2 *a2; |
|
217 | 189 | ||
- | 190 | phi_hat = v0 * b0 + v1 * b1 + v2 * b2; |
|
218 | 191 | ||
219 | signed pd = (signed)(periodEstimate)- (signed)(deltaTime*256) + pdI; |
- | |
220 | 192 | ||
221 | 193 | ||
- | 194 | uint16_t arr = phi_hat < 100 ? 100 : phi_hat; |
|
- | 195 | // compute period error |
|
222 | periodEstimate -= pd / 100; |
196 | // periodErr += periodEstimate - (arr * 256); |
223 | 197 | ||
224 | 198 | ||
- | 199 | count = arr; |
|
- | 200 | delta = pd; |
|
225 | 201 | ||
226 | TIM2->ARR = (periodEstimate+128)/256 ; |
202 | TIM2->ARR = arr ; |
227 | recalcPhase(); |
203 | recalcPhase(); |
228 | 204 | ||
229 | 205 | ||
230 | 206 | ||
231 | // calculate RPM |
207 | // calculate RPM |
Line 252... | Line 228... | ||
252 | } |
228 | } |
253 | 229 | ||
254 | // timer 3 interrupt |
230 | // timer 3 interrupt |
255 | void VectorB4(void) |
231 | void VectorB4(void) |
256 | { |
232 | { |
- | 233 | static uint16_t lastSampleRef = 0; |
|
- | 234 | ||
- | 235 | static uint8_t refCount = 0; |
|
- | 236 | static uint8_t varCount = 0; |
|
- | 237 | ||
257 | uint16_t stat = TIM3->SR; |
238 | uint16_t stat = TIM3->SR; |
258 | if(stat & TIM_SR_CC1IF) |
239 | if(stat & TIM_SR_CC1IF) |
259 | { |
240 | { |
260 | TIM3->SR &= ~TIM_SR_CC1IF; |
241 | TIM3->SR &= ~TIM_SR_CC1IF; |
261 | uint16_t sample = TIM3->CCR1; |
242 | uint16_t sample = TIM3->CCR1; |
262 | sampleBuff[sampleCount++] = sample; |
243 | if(sample-lastSampleRef > 100 /*BREAKER_COUNT_MIN */) |
- | 244 | { |
|
263 | if (sampleCount >= SAMPLE_BUFF_SIZE) |
245 | sampleRef = sample; |
- | 246 | ++refCount; |
|
- | 247 | } |
|
264 | sampleCount = 0; |
248 | lastSampleRef = sample; |
265 | } |
249 | } |
- | 250 | if(stat & TIM_SR_CC2IF) |
|
- | 251 | { |
|
- | 252 | TIM3->SR &= ~TIM_SR_CC2IF; |
|
- | 253 | sampleVar = TIM3->CCR2; |
|
- | 254 | ++varCount; |
|
- | 255 | } |
|
- | 256 | ||
- | 257 | ||
- | 258 | ||
- | 259 | ||
- | 260 | if(refCount != 0 && varCount != 0 ) /*we have an R,V pair */ |
|
- | 261 | { |
|
- | 262 | ||
- | 263 | ||
- | 264 | if(refCount < varCount) |
|
- | 265 | sampleDiffBuff[sampleRefCount] = 32767; // indicate +ve max phase |
|
- | 266 | ||
- | 267 | if(refCount > varCount ) |
|
- | 268 | sampleDiffBuff[sampleRefCount] = 65536-32767 ; // indicate -ve max phase |
|
- | 269 | ||
- | 270 | if(varCount == refCount) |
|
- | 271 | sampleDiffBuff[sampleRefCount] = sampleRef - sampleVar; |
|
- | 272 | ||
- | 273 | if(sampleRef) |
|
- | 274 | sampleRefBuff[sampleRefCount] = sampleRef; |
|
- | 275 | if(++sampleRefCount == SAMPLE_BUFF_SIZE) |
|
- | 276 | sampleRefCount = 0; |
|
- | 277 | ||
- | 278 | refCount = 0; |
|
- | 279 | varCount = 0; |
|
- | 280 | } |
|
- | 281 | ||
- | 282 | ||
- | 283 | ||
266 | } |
284 | } |
267 | 285 | ||
268 | 286 | ||
269 | 287 |