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 | ||