Bringing TBI and Multi Port Fuel Injection to a New Level.     EFI Conversions and Tuning! Seattle to Portland! E-mail Tuning Consultant!
Page 20 of 26 FirstFirst ... 101516171819202122232425 ... LastLast
Results 286 to 300 of 382

Thread: DIY LTCC or similar system for LT1s

  1. #286
    Fuel Injected! vilefly's Avatar
    Join Date
    Sep 2017
    Age
    48
    Posts
    119
    According to my research, peak pressure must occur at 16 deg. ATDC, regardless of stroke, but I do wonder about this with different fuels and such. Might have to play with it, but I have no dynometer.....the researchers had one. Just one thing, it lost the ion sense signal above 3500 rpm. Should still be useful, since racing engines are at max timing 3000rpm and up.

  2. #287
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    Quote Originally Posted by Terminal_Crazy View Post
    can you not just scale the values in the table?
    I can see the end of the 1st line reads: should be 346.9 which is the highest value ithink in your table.
    If you scaled the table by 2 it would allow 512 range of units in 2's.
    The issue here is that I defined the table with 8 bit cell values in hopes of saving memory, which for unsigned values limits the maximum value to 255 (binary 11111111) = 256. It's not a problem - what I said at the end is I can make the table store each cell in 16 bit 'buckets' and that will fix the clipping - B1111111111111111 = 65536.

    Quote Originally Posted by vilefly View Post
    I just need to sift through the code and find the cylinder specific degree counters in it, so I can have the ion sense subsystem target 16 deg. ATDC, or at the very least, tell me hit or miss so I can narrow down the changes I will make in the timing tables.
    I don't want to get lost on a wild goose chase here, but if you can give me a birds-eye-view of what you're wanting to do here or point me to where you explained it / posted info that would help. If I can at least try to wrap my head around what you're needing to do electrically and logically it would help. If I have a handle on what you need to support your goal it will help so that the next round of optimizations doesn't eliminate the possibility of meeting those goals.

    Incidentally, ATDC isn't currently tracked, nor is angular velocity at any resolution higher than every 90 degrees. As the code stands now, it counts down from 90 after each TDC (low res rising edge) signal. So 16 ATDC would be 74 degrees BTDC (of the next cylinder).

  3. #288
    Fuel Injected! vilefly's Avatar
    Join Date
    Sep 2017
    Age
    48
    Posts
    119
    Quote Originally Posted by spfautsch View Post
    I don't want to get lost on a wild goose chase here, but if you can give me a birds-eye-view of what you're wanting to do here or point me to where you explained it / posted info that would help. If I can at least try to wrap my head around what you're needing to do electrically and logically it would help. If I have a handle on what you need to support your goal it will help so that the next round of optimizations doesn't eliminate the possibility of meeting those goals.

    Incidentally, ATDC isn't currently tracked, nor is angular velocity at any resolution higher than every 90 degrees. As the code stands now, it counts down from 90 after each TDC (low res rising edge) signal. So 16 ATDC would be 74 degrees BTDC (of the next cylinder).
    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.
    ion sense ignition waveform.jpg
    ion-sense-ignition.png
    The ion-sense power supply/circuitry might change to the Delphi method of capturing the 400v kickback and using it to power up the spark plug, but for now, this is a crude representation that has already worked for me in the past......but my 300v power supply was very noisy last time, and I will see about regulating it and smoothing it out.
    delphi ion-sense ignition.jpg
    Last edited by vilefly; 01-22-2018 at 10:30 PM. Reason: another picture

  4. #289
    Fuel Injected! Terminal_Crazy's Avatar
    Join Date
    Oct 2015
    Location
    Lancashire England
    Posts
    225
    The issue here is that I defined the table with 8 bit cell values in hopes of saving memory, which for unsigned values limits the maximum value to 255 (binary 11111111) = 256.
    It's not a problem - what I said at the end is I can make the table store each cell in 16 bit 'buckets' and that will fix the clipping - B1111111111111111 = 65536.
    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.

    Mitch
    '95 Z28 M6 -Just the odd mod.
    '80 350 A3 C3 Corvette - recent addition.

  5. #290
    Fuel Injected!
    Join Date
    Jan 2012
    Location
    Poland
    Posts
    118
    Glad I could help :)

    Quote Originally Posted by spfautsch View Post
    Quick question - it should probably be obvious but why are you using these read functions 'pgm_read_word(&rpmReference[rpmIndex])' to read the table cells?
    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. That's why we use pgm_read_xxx functions. Without this, the program would fail as the code would try to read from RAM using FLASH addressing.

    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:
    Code:
    typedef struct {
      int cylNo;          // user readable cylinder no
      int armed;          // set to 1 = armed for dwell, set to 0 = est signal caught - prevents dwell routine from dwelling recently fired coil
      volatile uint8_t *portAddr;  // used at a pointer to the output registers so coil drivers can be controlled directly (faster than using digital[write/read]() arduino functions)
      byte bitMask;       // the bit mask of each output pin - see the ATmega datasheet for more info on this and timers
    } cylinders;
    Without volatile, compiler could optimize out some output pin operations.

    One more thing, of course I mislabelled RPM_TO_MS macro - it should be called RPM_TO_US.
    Last edited by dzidaV8; 01-23-2018 at 03:33 AM.

  6. #291
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    Quote Originally Posted by vilefly View Post
    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.

    Quote Originally Posted by Terminal_Crazy View Post
    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.

    Quote Originally Posted by dzidaV8 View Post
    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.

    Quote Originally Posted by dzidaV8 View Post
    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.

    Quote Originally Posted by dzidaV8 View Post
    Without volatile, compiler could optimize out some output pin operations.
    This could explain why my stall detection wasn't turning the coils off.

    Quote Originally Posted by dzidaV8 View Post
    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(" },");

  7. #292
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    Quote Originally Posted by spfautsch View Post
    it looks like the array is only getting populated in one dimension / subscript.
    This is solved. There were too many parens around the fill macro definition.

    Replaced this:
    Code:
    #define FILL_DWELL_COLUMN(rpm) {(((CALC_DWELL(rpm, 8)),  \
                                     (CALC_DWELL(rpm, 9)),  \
                                     (CALC_DWELL(rpm, 10)), \
                                     (CALC_DWELL(rpm, 11)), \
                                     (CALC_DWELL(rpm, 12)), \
                                     (CALC_DWELL(rpm, 13)), \
                                     (CALC_DWELL(rpm, 14)), \
                                     (CALC_DWELL(rpm, 15)), \
                                     (CALC_DWELL(rpm, 16)), \
                                     (CALC_DWELL(rpm, 17))))}
    With this:
    Code:
    #define FILL_DWELL_COLUMN(rpm) { (CALC_DWELL(rpm, 8)), \
                                     (CALC_DWELL(rpm, 9)),  \
                                     (CALC_DWELL(rpm, 10)), \
                                     (CALC_DWELL(rpm, 11)), \
                                     (CALC_DWELL(rpm, 12)), \
                                     (CALC_DWELL(rpm, 13)), \
                                     (CALC_DWELL(rpm, 14)), \
                                     (CALC_DWELL(rpm, 15)), \
                                     (CALC_DWELL(rpm, 16)), \
                                     (CALC_DWELL(rpm, 17))}
    Thanks for this - I'd never in a million years figured out how to do this with the precompiler!

    I just need to convert the accel comp table to using this method and test.

    Found this in arduino/preferences.txt: compiler.warning_level=none Switch none to all and lots of ugliness popped up. Very helpful.

  8. #293
    Fuel Injected! vilefly's Avatar
    Join Date
    Sep 2017
    Age
    48
    Posts
    119
    Quote Originally Posted by spfautsch View Post
    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.
    I think I will keep the tach output to "arm" the ion sensing circuitry, and the separate 16*BTDC output to disarm/reference it.

  9. #294
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    That'll be easy enough as well. Will try to work on that before the weekend.

    0.9.7 tested and uploaded to github (link in sig).

    Also updated partial schematic (also in sig).

    dzidav8: Thanks again for the help with the precompiler macros / table generation. I was able to take what you put together and improve on it slightly (i.e. populating any cells in the dwell table that were rounding to zero with 1). I was surprised at how difficult it was to find good info about how to handle stuff like modulo and simple decision trees this way. This seems to be one of the dark arts of code compilation. Also thanks for the hint to look into un-muting the compiler warnings in the arduino ide.

    I have a laundry list of items to test and debug such as whether the system will restart after a stall condition without removing power (switching the key off). Also if increasing the size of the dwell table to 16 bits, and adding an accel compensation table has had a measurable impact on speed. I'd also like to implement a scheduling state machine for the main loop. Lastly testing at higher RPMs and in real-world driving conditions. I do have a short log I made over the past weekend where I blipped the throttle to 4400. I also had the audacity to stomp the pedal all the way down after a few glasses of liquid courage / stupidity, and I'm not sure if I hit the rev limiter (6800) or if the controller crashed (I turned the ignition off immediately). Disclaimer: I was running an experimental build of 0.9.6 at the time that could have had a serious bug in the way table data was being accessed (once again, thanks dzidav8).

    When I feel confident that this project isn't going to crash and burn (i.e. after some real-word testing) I have a list of credits for the source.

    But...

    I also have an oil leak I'd like to fix, and about a quart of Mobil 1 to scrub off that's been caramelized onto my exhaust and floorpan. U-joints, ball joints and tie rod ends that are original to the car. You get the picture. So other than vilefly's ion sense trigger I probably won't be doing a lot of coding for a few weeks (at least that I'll be able to test). I also need to yank the rotor out of my opti, make coil brackets and remove all the opti wire routing parts. Incidentally, if anyone wants to buy a nearly complete wire retainer set they're only a year old.

  10. #295
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    The meteorologists were talking up the forecast for today so I postponed tear-down with the anticipation of taking a short test drive.

    Duct tape holding the breadboard to the windshield, I managed to get these logs.

    There is a serious problem that presents as hard hesitation right around several RPM bands, starting around 1800-2200. In the controller log I noticed several lines around 2200 RPM like:

    Code:
    R2200:S33:D56:C2:V13.42:E0:L56
    L56 is indicating that dwell started 56 degrees later than requested - possibly for a few microseconds before the EST signal was caught, if at all.

    I found that if I accelerate through this range the problem went away. Watching my tach this seemed to be starting around 1800 so I suspect my tach reads lower than actual.

    Managed to get a short pass at my "private drag strip" - peak RPM in the .eedata file was 6329 @ frame 2590 / timestamp 246.6. I wanted to push it all the way to the rev limiter but had a run-in with johnny law 15 minutes earlier when I was running late for a hair cut appoint (41 in a 35), so I thought it best not to push my luck. I felt the same type of hesitation again in a higher (4000-5000 rpm) band but I haven't looked for this in the log yet.

    I'm feeling optimistic this could be an issue introduced with the most recent changes, but there's really no telling until I have time to test thoroughly which will unfortunately be several weeks out. It could however have been always present because don't recall revving slowly through the first 2200 rpm "problem" band when testing previously. Whatever the case, I'm still going to pull my rotor out out of the opti when I have the engine out. If that doesn't give me ample motivation to fix this nothing will.

  11. #296
    Fuel Injected!
    Join Date
    Mar 2013
    Posts
    457
    Is
    R=rpm
    S=spark advance
    D=dwell
    C=cylinder
    V=??
    E=??
    L=degree later than requested

    I noticed that around and above 3400 rpm L becomes very unstable.
    That corresponds with some dwell calculations in dwell time at PCM.
    3E99 ldd word_204E ; DWELL vs volts
    RESERVED:3E99 ; ABOVE 3400rpm
    RESERVED:3E9C subd word_135
    RESERVED:3E9F lsrd ; 4.35ms - current low res time /2
    RESERVED:3EA0 adcb #0
    RESERVED:3EA2 adca #0
    RESERVED:3EA4 std word_143
    RESERVED:3EA7 xgdx ; X goes to D
    RESERVED:3EA8 subd word_143 ; D[55f0] /X [fil ad Volt] - {4.35ms - current low res time /2}
    RESERVED:3EAB bcc loc_3EB0
    RESERVED:3EAD ldd #0
    RESERVED:3EB0
    RESERVED:3EB0 loc_3EB0: ; CODE XREF: OC4I+4B1j
    RESERVED:3EB0 xgdx
    That code is executed above 3400rpm and it corrects some of the dwell time.
    Dwell is modified with high map accelaration too, Voltage correction or with rpm threshold for high rpm situation.
    So it is not perfectly linear and predictable.

    You can still consider PCM modification for constant dwell time and for development purpose. It can be done that way, but can be perfectly tuned with some PCM mods too.
    At the last stage of development we need to do some spark match tests. Does actuall spark is the same as commanded spark from PCM.
    Can you hook the arduino to aldl line to get spark advance from the data PCM streams all the time. It wont be used all the time, but for relaxed cruise is good.
    The line should be fast enough since traction request on f-body is done on the ALDL bus.

    Pulling the engine is not that bad, if you pull the optispark too. Than you can make a test bench. All you need is spinning opti with a drill at variable rpms and hooked PCM. Than you can simulate all kind of conditions, change the spark with eehack and measure est line for intermitten signal at high rpm.

  12. #297
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    R=rpm
    S=spark advance
    D=dwell
    C=cylinder
    V=system voltage
    E=cumulative degree count error over last 10 messages
    L=cumulative dwell lag over last 10 messages

    These last two error stats are going to look misleading because they're reset based on the # of messages that are sent over the uart. At idle that's approximately one message per power stroke. At higher RPM I'm scaling the time interval so it's inversely proportional to engine speed, so messages are sent less frequently (see explanation of log snippet below).

    Feel free to look at the source - link is in sig. The .ino file is plaintext and can be viewed in your favorite text editor. I can also post a disassembly of the byte code if it would be helpful.

    Essentially, after sequence is detected there are four things happening in the main program loop that are critical to operation.

    1) calculating the microseconds between the last two low res TDC signals < this is very CPU intensive b/c it's a 64 bit integer

    2) using that calculation to find the correct index in the rpm table

    3) using the system voltage index (also happens in main loop) lookup dwell requirement for current operating condition and store in a global variable

    4) using that dwell figure to decide when and which coils need to be turned on to charge

    #4 is something that needs to happen at the highest priority. I suspect the miss / stumble I was noticing is being caused because for some reason this routine isn't getting executed in a timely manner and coils aren't being turned on before the EST line goes low to command fire. I have an idea for a scheduler routine that may improve this, but another factor here is that the uart traffic may be bogging down the mcu and causing some of this. A very simple way to find out would be to disable the uart messages completely and see if the stumble goes away. Unfortunately that will have to wait a few weeks as I dismantled everything and cut off the factory coil and ICM connectors <GASP!> last night.

    Another thing to note is that I'm relatively sure the way I'm implementing the dwellCoils() routine (#4) is probably not very efficient.

    Quote Originally Posted by kur4o View Post
    I noticed that around and above 3400 rpm L becomes very unstable.
    That corresponds with some dwell calculations in dwell time at PCM.

    That code is executed above 3400rpm and it corrects some of the dwell time.
    Dwell is modified with high map accelaration too, Voltage correction or with rpm threshold for high rpm situation.
    I haven't had time to look over the log very thoroughly yet, but what I can tell you from feeling how the stumble was happening it was banding very consistently with RPM. I don't recall it banding around that range, but it could have been. Another factor that has to be considered is that I'm using the RPM index from #2 above as the overflow comparator for the timer that triggers uart messages and the ADC conversion for voltage measurement. This causes these functions to happen less frequently as RPM increases. It's possible that simply reducing the amount uart traffic further would have a positive effect on this.

    I would like to also use MAP to boost dwell with load, but I don't think it would be possible to monitor two ADC inputs quickly enough to be beneficial while not slowing down the main loop further.

    Quote Originally Posted by kur4o View Post
    You can still consider PCM modification for constant dwell time and for development purpose. It can be done that way, but can be perfectly tuned with some PCM mods too.
    After feeling how things worked under load I'm absolutely certain PCM tuning / patches won't be required. All that the controller needs to see out of the PCM is for the EST line to float high for two or more degrees to arm the debouncing logic before the falling edge triggers the firing event.


    Quote Originally Posted by kur4o View Post
    At the last stage of development we need to do some spark match tests. Does actuall spark is the same as commanded spark from PCM.
    I wouldn't discourage someone from doing that, but I won't be bothering with it. Primarily because I don't have access to the necessary equipment, but also because the controller isn't manipulating spark advance or the firing event in any significant way. When controller sees the EST line go low the interrupt does one 8 bit comparison against the debouncer register and if it's > 2 the next instruction turns the pin off for the coil / cylinder that's approaching it's power stroke. So the most delay that should be introduced between the PCM commanding fire and the controller commanding fire is going to be around 125 nanoseconds.

    Quote Originally Posted by kur4o View Post
    Can you hook the arduino to aldl line to get spark advance from the data PCM streams all the time. It wont be used all the time, but for relaxed cruise is good.

    The line should be fast enough since traction request on f-body is done on the ALDL bus.
    I especially don't want to mess with the ALDL. Mainly because there aren't enough interrupts for another uart, but also because doing so on the y-body gets complicated due to the CCM wanting to be the bus master. It would necessitate a second mcu talking to the primary one over SPI, which would complicate things incredibly for something I feel would provide little benefit.

    Quote Originally Posted by kur4o View Post
    change the spark with eehack and measure est line for intermitten signal at high rpm.
    I'm fairly certain the only intermittent problem I have is that the main loop isn't getting the coils turned on in a timely and consistent manner.

    I'm feeling pretty good about how the controller was able to keep track of things at 6000+ RPM. I'm going to need to double-check my math, but I believe the fastest uart logging interval possible at 6000 RPM is 381 milliseconds. So in the following snippet of the log the crankshaft was making about 15 revolutions between each log message. Yet the largest degree count error (E) accumulated in this neighborhood was 5 at the lower RPM of 5600.

    EDIT: I don't know where I came up with 15 revolutions / 381 milliseconds. Trying to do three things at once I guess. 6000 rpm = 2.5ms between combustion events, or 10ms per crank revolution right? So that would be 38 revolutions per log message?


    EDIT2: None of this is right - the prescaler I'm using for that timer should give 381ms interval at that RPM, but it's obviously far less than that. This might explain some of the problem.

    EDIT3: After some research I believe the prescaler constants I was erroneously using resulted in a 95.2ms interval. I updated the log dissection below to what I believe is more likely correct (9.5 revolutions per log message). I've fixed this so it's using prescalers for the correct timer. This could potentially fix the dwell lag problem. I'll post an updated sketch after I get the ion sense trigger added.

    Code:
    R5600:S35:D167:C5:V13.43:E4:L62
    R5600:S35:D160:C2:V13.43:E1:L3 < error stats reset
    R5600:S35:D160:C1:V12.56:E1:L5
    R5600:S35:D144:C4:V12.56:E1:L7
    R5600:S35:D144:C6:V13.36:E2:L17
    R5600:S35:D160:C7:V13.36:E2:L23
    R5600:S35:D160:C1:V13.43:E3:L27
    R5600:S35:D160:C4:V13.43:E5:L27
    R5600:S35:D160:C6:V12.84:E5:L27
    R5600:S35:D160:C7:V12.84:E5:L29
    R6000:S35:D172:C8:V12.70:E5:L35
    R6000:S35:D172:C6:V12.70:E0:L0 < error stats reset
    R6000:S35:D172:C2:V12.32:E0:L0 < 9.5 revolutions
    R6000:S35:D162:C4:V12.32:E0:L1 < 19 revs
    R6000:S35:D180:C5:V12.37:E0:L1 < 28.5 revs
    R6000:S35:D180:C1:V12.37:E0:L1 < 38 revs
    R6000:S35:D162:C3:V12.03:E0:L1 < 47.5 revs
    R6000:S35:D162:C7:V12.03:E0:L2 < 57 revs
    R6000:S35:D162:C8:V11.78:E2:L17 < 66.5 revs
    R6000:S37:D180:C5:V11.78:E2:L17 < 76 revs
    R6000:S35:D162:C1:V12.56:E2:L19 < 85.5 revs - these cumulative errors seem acceptable over 30,700 degrees of rotation
    R6000:S35:D154:C6:V12.56:E0:L0 < error stats reset
    R6000:S35:D172:C2:V12.67:E0:L0
    R6000:S35:D154:C3:V12.67:E0:L17
    R6000:S35:D154:C7:V12.76:E0:L17
    R6000:S35:D172:C4:V12.76:E0:L17
    R6000:S35:D172:C5:V12.50:E2:L17
    R6000:S35:D154:C8:V12.50:E2:L17
    R6000:S35:D172:C5:V13.47:E2:L17
    R6000:S41:D154:C8:V13.47:E2:L123
    R6000:S35:D172:C6:V12.04:E2:L125
    R6000:S35:D180:C2:V12.04:E0:L3 < error stats reset
    Remember that this is simply a proof of concept. C is not a programming language I consider myself proficient in, so I believe there is a lot of room for optimization.

    The last thing on my list of tests is to confirm or disprove whether the PCM can command negative spark advance. As it works now much of the controller's functionality hinges around the assumption that it will not see ATDC spark. I'm going to continue working towards optimizing everything with this assumption. If perfect operation cannot be achieved with the assumption being true, it certainly won't be attainable if it proves false.

  13. #298
    Fuel Injected!
    Join Date
    Mar 2013
    Posts
    457
    I noticed some huge voltage variations on the arduino logs. You got intermitten drops to 11.8,12.5 and so on.
    Where you get voltage reference. Maybe the coils overload the B+ cable or the ground source is weak.

    You don`t have voltage drop on the PCM side. At PCM you have constant 13.8-14.2 voltage.

    64 bit interger for time isn`t too much. PCM use 16 bit value and the range is $4000-$88 and the conversion is 983040/x = rpm
    0.015234*x = msec.

    Maybe some scaling can help optimize the routine.

    I do compare the logs and the spark calculation are fairly accurate. At constant 28 degree at PCM you get 28-27 at arduino.
    If you consider ALDL streamed data can save substantial cpu time at a later stage I will give you precise instructions.
    The data is streamed all the time from the PCM{so called idle traffic] so you just need to listen {passive} for the correct frame. The message can be reconfigured to provide any data:rpm,voltage,spark,dwell,map,afr,coolant.

    Maybe a basic version that works with all system and platforms 92-97 and enhanced version developed later for specific platform with all the limitations overcomed for extreme accuracy.


    I think that matching commanded spark with the spark calculated from the arduino will be good enough. A good indicator will be engine start time. A few degrees off at cruising is alot so it needs fine tuning and calibration.

    I guess the hesitation was due to spark retarded too much, since nothing in the log indicates something wrong.

    I am not that good at C++ but will take a look. Hope there are some comments.


    I will try to log some data with negative spark soon. Will remove the spark correction limit form eehack and force some negative spark.
    Negative spark looks possible but for very limited conditions. I do some maths and -17 degrees is the max you can get, than the PCM will freak out and command the max advance of 46 degree.
    In the logs -1 will be $80 or 128 since $ff is slashed by 2. I figured it out later.

  14. #299
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    I just uploaded untested v 0.9.8 to github with ion sense option and fixed timer prescaler.

    Quote Originally Posted by kur4o View Post
    I noticed some huge voltage variations on the arduino logs. You got intermitten drops to 11.8,12.5 and so on.
    Where you get voltage reference. Maybe the coils overload the B+ cable or the ground source is weak.
    I'll worry about that if I notice variations when I have it properly wired and working on a real circuit board that's not taped to my windshield. What I've been testing is on two experimenter boards (aka breadboards). The wiring was a enormous mess of 22ga solid wire and I didn't have any filtering caps on the ADC reference or the measuring pin.

    Quote Originally Posted by kur4o View Post
    I do compare the logs and the spark calculation are fairly accurate. At constant 28 degree at PCM you get 28-27 at arduino.
    There's no spark calculation going on. Look at the source in isr_est() where I'm picking up spark advance from the EST line negative edge - there's no way it could get any simpler or save cpu time by sniffing the ALDL.

    Quote Originally Posted by kur4o View Post
    If you consider ALDL streamed data can save substantial cpu time at a later stage I will give you precise instructions.
    The data is streamed all the time from the PCM{so called idle traffic] so you just need to listen {passive} for the correct frame. The message can be reconfigured to provide any data:rpm,voltage,spark,dwell,map,afr,coolant.
    The biggest difficulty here is needing a second hardware / interrupt based uart, which the mcu I'm using doesn't have.

    Quote Originally Posted by kur4o View Post
    I think that matching commanded spark with the spark calculated from the arduino will be good enough. A good indicator will be engine start time. A few degrees off at cruising is alot so it needs fine tuning and calibration.
    I don't think you're following completely - for all intents and purposes the PCM is still directly controlling when the spark event is triggered.

    Quote Originally Posted by kur4o View Post
    I guess the hesitation was due to spark retarded too much, since nothing in the log indicates something wrong.
    I posted an example from the log of what was causing the hesitation. I've since looked more closely and found a bunch of this which I'm sure is the first RPM band where the stumble became noticeable.

    Quote Originally Posted by spfautsch View Post
    Code:
    R2200:S33:D56:C2:V13.42:E0:L56
    L56 is indicating that dwell started 56 degrees later than requested - possibly for a few microseconds before the EST signal was caught, if at all.
    It should be well commented - maybe too well commented.

    Having evidence of negative spark advance would be very helpful.

  15. #300
    Fuel Injected! spfautsch's Avatar
    Join Date
    Apr 2015
    Posts
    254
    Quote Originally Posted by kur4o View Post
    64 bit interger for time isn`t too much. PCM use 16 bit value and the range is $4000-$88 and the conversion is 983040/x = rpm
    0.015234*x = msec.
    I'm glad you brought that up - it occurred to me while working on the pull what the bounds of a 64 bit integer are. I started wondering what the heck I needed that for and couldn't find a single instance. The biggest I need to store / reference is 600,000 in the rpm table. So all the 64 bit ints have been reduced to 32.

    I could probably use a different timer configuration and reduce this by another power (max 60,000) and stay in a 16 bit space but I have an idea for a method of measuring cylinder balance that will make having the extra precision of counting microseconds useful.

Similar Threads

  1. Which TBI system is better?
    By KeyAir in forum GM EFI Systems
    Replies: 39
    Last Post: 01-13-2016, 12:18 PM
  2. Hard start 93 LT1 with LTCC Ignition Mod
    By beestoys in forum GM EFI Systems
    Replies: 0
    Last Post: 05-17-2015, 10:58 PM
  3. ABS system?
    By K1500ss4x4 in forum Gear Heads
    Replies: 3
    Last Post: 02-05-2014, 08:21 PM
  4. Vortec EGR System?
    By EagleMark in forum OBDII Tuning
    Replies: 40
    Last Post: 06-02-2013, 12:07 PM
  5. Quicker way to do Spark Hook test on the street for LT1s and others?
    By sherlock9c1 in forum Fuel Injection Writeups Articles and How to New and Old
    Replies: 15
    Last Post: 03-02-2013, 03:52 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •