Well this is one was a good
one. While trying to figure out how the code was supposed to work
I came across a routine that looked like its purpose was to detect the
narrow pulse coming from the distributor. This narrow shutter pulse
is supposed to signal the code when number one cylinder is firing so that
the program can synchronize the firing of the injectors at a point in time
before the intake valve opens. Well I struggled with this routine
for quite a while and never could make any sense out of. More I worked
on the code the more convinced I was that this was the narrow pulse detector.
I new the relationship and timing of the edges that the ignition trigger
was feeding the code so I feed in some numbers and it seemed to never detect
the number one cylinder. I must have spent close to a week fussing
with this area of code to no end (this was before I realized that there
were numerous oversights in the code and I was still believing that is
was always correct). Finally got to a point where I needed to prove
one way or another if it worked or not. Went to the car and setup
the scope so one channel triggered off of the #1 ignition wire and the
other channel off of the #1 injector. I didn't know what the relationship
was going to be between them but I knew it should be fixed. Fired
up the car and setup the triggering to view what was happening. The
plug would fire and some time before it the injector would. Turned
off the motor and fired it up again and the injector firing happened at
a different time during the rotation ! Did it again and the injectors
were firing someplace else ! Well I guess I had my answer.
The routine did not work at all. Darn frustrating. After I
finished the first pass on commenting the code and got it to assemble correctly
I ran it on my simulator. If you
look at its display you can see
a colored line with a lot of 'ppp''eee''iiii''ccc' displayed. These
represent the Power, Exhaust, Intake, and Compression cycles of the number
one cylinder. The start of the blue bar just below it is when the
#1 injector fires and how long this bar is represents how many crank degrees
it is spraying. This made it very easy to visualize what was going
on. Sometimes the injector would fire well before the intake would
open, sometimes well after it closed, sometimes while it was closing.
I don't think that the exact time when the injectors fire is super critical.
Look at all the motors that fire the injectors in batch mode (4 at a time)
or the ones that are spraying 100% of the time. They all work.
But what all of these other systems have in common that this one does not
is that they fire consistently. How do you tune this thing if one
time when you start the motor it is firing 90 degrees before the intake
opens and the next time it is spraying on a half open or closing valve.
Now all I had to was fix it. At first I approached
this as if there was one small error that made it not work. I made
flow charts and fed numbers in to find the single error. No Go !
Well maybe someone screwed up and got the edges
backwards. Some mis-communication between software tech and mechanical
tech that got the duty cycle of the shutter wheel backwards.
I fed in these timing numbers... Still No Go. It just didn't work
at all. One set of numbers I never fed in was the duty cycle of the
physical shutter wheel. There is another uncertainly here because
the Hall Effect Sensor does not change state when the edge of a shutter
paddle is at is 50% point. Check out the Ignition
Trigger waveforms.
What we have to do here is detect the narrow pulse
out of a group of wider ones. You can't use the timing counts directly
because they are always changing so we need to look at the difference of
duty cycles of the pulses to detect the narrow one. A little ground
work on how the distributor trigger handler works (or at least key to this
discussion) are in order. The pulse train coming from the distributor
is fed into the 68HC11's IC1 (Input Capture 1) interrupt handler.
This interrupt is setup to detect edges only, both rising and falling,
coming from the hall effect switch in the distributor. The rising
edge is the actual ignition timing event. When this edge is comes
through, the handler will continue setting up a variety of events, like
setting up the timer to file the coil for the next cylinder. The negative
going edge is used to determine the total time period and the ratio of
high to low. So when an edge arrives the handler grabs the current
count from the main system timer. The XTAL in this unit is running
at 8 MHz which put the CPU's internal 'E' clock at 2 MHz (everything in
the 68HC11 is referenced to the 'E' Clock). The main system timer's
prescaler is set to four (4) which gives us a frequency of 500 KHz.
What this means that each tic of the main system timer is 2us. After
some initial verification, like what edge was just detected, the distributor
handler takes these system timer count values and further divides them
by four (4) and from this point on all calculations are done in 8us units
(our system timer counts divided by four). This is done to keep low
RPM timer counts, which can be very large, 16 bit integers of a more manageable
size. There are other calculation done with these numbers and if
they were kept their original size they would overflow normal 16 bit arithmetic
(more than 16 bit math takes more time to deal with).
These are the key stash going into the number one detector routine:
Assuming that the motor was turning at 1000 RPM, which would give us a total period count of 1875, the below displays the relationships of the pulse edges and stashes, also puts some numbers to them.
So this is basically what I had to do to make it work with the shutter wheel supplied...
Well after I applied my corrections the code would always bring the injectors into sync within several revolutions of the motor. Below is the modified code. Just take the 'mis3x' conditional assembly code to get it to work....
; ; The following must be used to detect the number one cylinder being fired. ; The distributor shutter for number one is 75% the width of all the others. ; There is one slight problem, the darn routine does NOT work. Spent over ; a week trying to figure it out. Even simulated it and couldn't get it to ; work. Finally put a scope on the car. One channel triggering off the ; number one ignition wire and the the other on the number injector. Every ; time I fired up the engine the phase would be different between the two ! ; The duty cycle of a normal period is 55% (55% high, 45% low). ; mis3: ldy L004aw ; get the time the trigger pulse was low ldd L003e ; get current timing period ; ; Compute a percentage of the total period. ; What we have here is L004aw = (PW/32 + PW/16) / 2 ~4.6% ; This seems too narrow when later we try to determine if the difference between ; low and high periods (which is 10% of the total period) to a number that is ; ~9.2% calculated. Most of the time it does not detect a normal duty cycle ; and bails. I think if I increase this to say 5.5~ then it should work ; better. ; lsrd ; / 2 lsrd ; / 4 lsrd ; / 8 lsrd ; / 16 std L004aw ; hold in work stash lsrd ; / 32 addd L004aw lsrd std L004aw ; L004a = timing event * ~.0467 ; ; purposed.......................... ; if mis3x lsrd ; 6.9% total PW lsrd ; if stopped here we'd have 5.7% of pulse width ; lsrd ; if stopped here we'd have 5.1% of pulse width addd L004aw std L004aw endif ; ................................. ldd L003a bpl L8dd7 ; positive now coma ; change signs negb sbca #$ff subd L004aw ; is L003a < 5% of the Timing Period ? bcs L8ddf ldd L004aw coma ; make a positive number negb sbca #$ff std L003a bra L8ddf ; L8dd7: subd L004aw bcs L8ddf ldd L004aw std L003a ; ; At this point abs(L003A) < 5% Timing Period ; Its value is either the calculated one or 5% limited..... ; L8ddf: rol L004bw ; L004aw = 10% Timing Period rol L004aw xgdy ; D = Period_Low subd L0036 ; less the time when the input was high subd L003a ; less accumulator pshb ; D = Period_Low - Period_High - L003a psha puly ; save in IY ; ; D and IY = the difference between the Period_low and Period_Hi - L003a ; bmi L8e03 ; The High period is shorter than the low so ; ; it can not be the #1 shutter..... ; subd L004aw ; is Duty Cycle difference < 10% Timing Period ? bcs L8e0b ; yes - not narrow pulse ; ; Just loose the next two lines, don't know what they except screw things up... ; if not mis3x subd L0036 ; less the time when the input was high bcc L8e50 ; unknown pulse - clear flags endif ; ; The next two addd's should be subd's....... ; if mis3x subd L004aw ; less 10% Timing Period else addd L004aw ; plus 10% Timing Period endif ; bcs L8e43 ; Narrow pulse detected ; if mis3x subd L004aw ; less 10% Timing Period else addd L004aw ; plus 10% more endif ; bcs L8e43 ; Narrow Pulse ; if mis3x bra clear_3a ; unknown - clr accumulator and start again else bra L8e50 ; unknown pulse - clear flags endif ; ; It is not the #1 shutter. If the difference between hi/low is less than ; 10% of the total period then we don't know where we are at. ; L8e03: coma ; change signs negb sbca #$ff subd L004aw ; is Duty Cycle difference < 10% Timing Period ? ; if mis3x bcc clear_3a ; unknown - clr accumulator and start again else bcc L8e50 ; yes - don't know where we are at then endif ; L8e0b: xgdy ; get the difference between pulses back ; ; 25% of delta-L003a ; asra ; divide by two but preserve the sign on the rorb ; ....number asra ; / 4 rorb addd L003a ; plus what was there already std L003a ; stash new accumulator ; ; At this point we have a non-narrow duty cycle detected ; bset L005b %00000001 ; signal non-number one found brclr L005b %00000010 L8e40 ; didn't find #1 last time - just continue bclr L005b %00000010 ; clear #1 found last time flag brset L005b %00010000 L8e2d ; check if we are in sync now bset L005b %00010000 ; signal in sync for the first time ; ; To set the sequencer we have had to detect a non-narrow (#1) pulse, then ; the narrow #8 pulse, followed immediately with another confirmed non-narrow ; pulse (#4). So when we set this we have just hit TDC #4..... ; L8e26: ldaa #$02 ; set the sequencer to #4 staa L0044 ; reset firing order sequencer now jmp L8eab ; read ADC and continue ; L8e2d: ldab L0044 ; get the current sequence value cmpb #$02 ; are we still in sync (#4) ? bne L8e39 ; nope - clear in sync bit and wait for next bset L005b %00001000 ; signal that we are in sync jmp L8eab ; read ADC and continue ; L8e39: brclr L005b %00001000 L8e26 ; need to sync up now bclr L005b %00001000 ; signal out of sync L8e40: jmp L8eab ; read ADC and continue ; L8e43: brclr L005b %00000001 L8e50 ; didn't get a normal pulse last time bclr L005b %00000001 ; clear normal pulse found bset L005b %00000010 ; signal narrow pulse found jmp L8eab ; read ADC and continue ; ; If we got here then couldn't determine if it was a narrow pulse or a wide one ; if mis3x clear_3a: ldd #0 ; clear the accumulator so bad data in it won't std L003a ; stop us from ever synching again....... endif ; L8e50: bclr L005b %00000011 ; clear pulse type found flags bra L8eab ; read ADC and continue ; ; ---------------------------------------------------------------------------- ;