Originally Posted by
vilefly
Well, technically all I need is an output pulse every 16*ATDC (74*BTDC) as a single point of reference for all the cylinders. I will either manually scope or "arduino-scope" the ion sense signal to find out if peak pressure occurs at the right time using a second arduino-pro to do so. Eventually, it may evolve into a closed loop system that can more accurately detect knock as well. It might be worth something to others to make that output timing changeable so that they can enact their own evil plans triggered by this pulse.
That's easy enough - I'll add something for this to take over the tach output pin b/c I don't think it will be needed on any of the flash based cars. Or there are four other spare outputs.
Fair warning, the arduino only has one ADC that uses a multiplexer. The ADC itself is fairly slow to stabilize after you switch the multiplexer input from one analog pin to another. So if you need to look at all eight cylinders in real time it might necessitate 8 AVRs each polling one analog pin.
Originally Posted by
Terminal_Crazy
I don't know the chip architecture but I thought i'd read this was speed ctritical.
Is the chip 16 / 32 bit on the data bus?
Is reading a single 8 bit and multiply noticably faster than reading a 16 bit value or not? I don't know.
Older 8 bit micros could take half a dozen cycles to calculate a 16bit no.
This is 8 bit all the way. You make a valid point. The only math that's happening to this are comparisons and additions. I'll have to look into the instruction set to see how many cycles a 16 bit add consumes. At 16 mhz each cpu tick takes 0.0625 us.
What really gets ugly is doing floating point operations, which is one of the reasons I didn't try any smoothing / interpolation on table lookups.
Originally Posted by
dzidaV8
When you place data in program (flash) memory (PROGMEM attribute), you have to inform the code that tries to read it, that the data is in fact in flash, not in RAM.
I noticed this immediately when I tried accessing the array directly. Oddly I didn't notice anything like this when using a static initializer on my 0.9.6 version, but it's possible I didn't test thoroughly.
Originally Posted by
dzidaV8
Important thing I noticed and changed. There even were warnings about it during compilation. When using pointers to port addresses in "cylinders" structure, you MUST retain the volatile attribute for port addresses:
Thanks for mentioning this as I probably would have overlooked it. I guess I need to look at the compiler options in arduino and make sure it's not suppressing any. Either way it's nice to have another set of eyes on my work.
Originally Posted by
dzidaV8
Without volatile, compiler could optimize out some output pin operations.
This could explain why my stall detection wasn't turning the coils off.
Originally Posted by
dzidaV8
One more thing, of course I mislabelled RPM_TO_MS macro - it should be called RPM_TO_US.
We won't sweat the small stuff. Also that formula was off by a power of 10. This gives results similar to what the populate routine was outputting.
Code:
#define RPM_TO_US(x) (( 250000UL * 60UL / ( x ) ))
Sunday I found a small rounding error caused by casting the float on the right hand side of the formula into an int.
Code:
dwellDegrees = uint16_t (((CRANK_DWELL_TGT + VOLT_COMP_8) * 1000) / (rpmTable[i] / 90));
This gave more exact results.
Code:
dwellDegrees = uint16_t (((CRANK_DWELL_TGT + VOLT_COMP_8) * 1000.0) / (float (rpmTable[i] / 90)) + 0.5);
What I did to test all these is to convert the populate routines to dump routines so I could see what the mcu was seeing.
Code:
dump of rpmTable[RPM_DIVS] = {
600000, 300000, 200000, 150000, 120000, 100000, 85714, 75000, 37500, 25000, 18750, 15000, 12500, 10714, 9375, 8333, 7500, 6818, 6250, 5769, 5357, 5000, 4687, 4411, 4166, 3947, 3750, 3409, 3125, 2884, 2678, 2500, 2343, 2205 };
dump of dwellTable[RPM_DIVS][VOLT_DIVS] = {
{ 0, 0, 0, 1, 1, 1, 2, 2, 5, 12, 16, 21, 25, 29, 33, 37, 42, 46, 50, 54, 58, 63, 67, 71, 75, 79, 84, 92, 100, 109, 117, 126, 134, 142 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
This is what I'm expecting (output of my previous populate routine).
Code:
const uint64_t rpmTable[RPM_DIVS] PROGMEM= {
600000, 300000, 199999, 150000, 119999, 99999, 85714, 75000, 37500, 24999, 18750, 14999, 12499, 10714, 9375, 8333, 7499, 6818, 6249, 5769, 5357, 4999, 4687, 4411, 4166, 3947, 3749, 3409, 3124, 2884, 2678, 2499, 2343, 2205 };
const uint8_t dwellTable[VOLT_DIVS][RPM_DIVS] PROGMEM = {
{ 1, 2, 3, 3, 4, 5, 6, 7, 13, 25, 33, 42, 50, 58, 66, 75, 83, 92, 100, 108, 117, 125, 133, 141, 150, 160, 168, 186, 203, 216, 238, 255, 255, 255 },
{ 1, 1, 2, 3, 4, 4, 5, 6, 11, 22, 29, 36, 43, 50, 58, 65, 72, 80, 87, 94, 102, 109, 115, 122, 130, 140, 146, 162, 176, 188, 207, 222, 231, 250 },
{ 1, 1, 2, 2, 3, 4, 4, 5, 10, 19, 26, 33, 39, 45, 52, 59, 65, 72, 78, 84, 92, 98, 104, 110, 117, 126, 132, 146, 159, 169, 186, 200, 208, 225 },
{ 1, 1, 2, 2, 3, 3, 4, 4, 9, 18, 24, 30, 36, 41, 47, 53, 59, 65, 71, 77, 83, 89, 94, 100, 107, 114, 120, 132, 144, 153, 169, 181, 188, 204 },
{ 1, 1, 1, 2, 2, 3, 3, 4, 8, 16, 22, 27, 33, 38, 43, 49, 54, 60, 65, 70, 76, 82, 87, 92, 98, 105, 110, 122, 132, 141, 155, 167, 173, 188 },
{ 1, 1, 1, 2, 2, 3, 3, 4, 7, 16, 21, 26, 31, 36, 41, 47, 52, 57, 62, 67, 73, 78, 83, 88, 93, 100, 105, 116, 126, 134, 148, 159, 165, 179 },
{ 1, 1, 1, 2, 2, 2, 3, 3, 6, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 63, 68, 73, 77, 82, 87, 93, 98, 108, 118, 125, 138, 148, 154, 167 },
{ 1, 1, 1, 2, 2, 2, 3, 3, 6, 14, 18, 23, 28, 32, 37, 41, 46, 51, 55, 59, 64, 69, 73, 78, 83, 88, 93, 103, 112, 119, 131, 141, 146, 158 },
{ 1, 1, 1, 1, 2, 2, 2, 3, 6, 13, 17, 22, 26, 30, 35, 39, 43, 48, 52, 56, 61, 65, 69, 73, 78, 84, 88, 97, 106, 113, 124, 133, 138, 150 },
{ 1, 1, 1, 1, 2, 2, 2, 3, 5, 13, 17, 21, 25, 29, 34, 38, 42, 47, 51, 55, 59, 64, 67, 71, 76, 81, 85, 95, 103, 109, 121, 130, 135, 146 }
};
I can live without the extra rounding fix, but unless I'm doing something dumb iterating the array it looks like the array is only getting populated in one dimension / subscript.
In case your'e wondering about the zeros in the first thee cells of the 17v subscript - I had the populate routine artificially rounding those up. But I can change the getDwell() routine to handle turning zeros into ones.
Snippet of dump routine - sorry, I know it's terrible spaghetti.
Code:
// print out the dwell table to uart
Serial.println("dump of dwellTable[RPM_DIVS][VOLT_DIVS] = {");
Serial.print(" { ");
for (int i=0; i<RPM_DIVS; i++) {
Serial.print(pgm_read_word(&dwellTable[i][0]));
if (i < RPM_DIVS - 1) Serial.print(", ");
}
Serial.println(" },");
Serial.print(" { ");
for (int i=0; i<RPM_DIVS; i++) {
Serial.print(pgm_read_word(&dwellTable[i][1]));
if (i < RPM_DIVS - 1) Serial.print(", ");
}
Serial.println(" },");
Bookmarks