GenBoard/UnderDevelopment/FirmWare/KnockDetection (2008-03-26 22:01:35)

Currently we use a fixed Integrator Time Constant, but after thinking about this and discussing it with MembersPage/DavidBlades it has become apparent that the time constant actually needs to decrease as engine speed increases. The reason for this is that the knock window time decreases with engine speed, so we need to increase the resolution to view the events in that time period more closely.

David calculated the time constant and worked out that at 500rpm the Time constant would need to be ~600uSec which is the highest time constant available with the TPIC8101, at ~8250rpm the Time constant would need to be ~40uSec (the lowest available constant with the TPIC)

[Additional from dnb] The time constants I calculated are merely to make the best use of the range available in the chip. The "best fit" I could come up with has approximately 30 time constants per window. This is not certain to be optimal, but it is consistant across RPM. I suggest that a parameter be entered in the config called something like "timeconstants_per_window" In my case this is 30, but it is equally valid to use 15 or 20.

Using the data from the calculations with the fixed time constants the following RPM to Time Constants(TC)

TC Prog. ValueTC uSecRPM
31600555
30560595
29520640
28480694
27440757
26400833
25360926
243201042
233001111
222801190
212601282
202401388
192201515
182001666
171801851
161602083
151502222
141402380
131302564
121202777
111103030
101003333
9903703
8804166
7754444
6704761
5655128
4605555
3556060
2506666
1457407
0408135

When the TC uSec values are plotted you'll see that there are changes in the gradient this occurs every 8 cells at the RPM values of 1111, 2222, 4444 (I dont know if this is significant).

There seems little point in looking for detonation at points 25 to 31 (926rpm to 555rpm) so we need only deal with 24 values to map the RPM to the time constant.

The question is... how best to code this?

[dnb again] This is a very good question!

I thought about the following idea, but it's not exactly efficient to code!

Get RPM reading

Work out exact time constant from RPM (simple equation - something like ((window_length/360)*(60/RPM))/consts_per_window )

Look up from a table the index of the closest time constant (lookup table fits in the AVR flash easily) There's no really nice compact algorithm I can see at the moment to go from Tc to index.

Send SPI to chip containing new time constant

Now back to normal knock stuff...

Do capture etc...

[more thoughts]

Given the way the knock code works - by comparing the noise level outside the window to that of inside the window - the idea of changing integrator time constant with RPM is slightly less important as we are comparing like with like (as long as the windows are the same length), but it would still be VERY useful to investigate the benefits, as some of us don't have all that much "non-combustion" time to play with!

How about this lookup code ?\n

after each RPM recalculation...

uint8_t knockwin_rpmtable PROGMEM={ 81,74,66, 60, ... };
uint8_t knockwin_vs_rpm(uint8_t rpm){ /* 100 RPM resolution */
/* using upcounting instead of downcount so high RPM is found faster */
for(i=0; i<24; i++){
  uint8_t tablevalue = prg_readmem( &knockwin_rpmtable[i] );
  if (i <= rpm) return i;
}
return i;
}

[pf]

Why not save the position and the rpm that you used the last you were at the last time the table was called?

Compare the last rpm with the current rpm and then start counting up or down depending on whether it is negative or not.