Saturday, September 7, 2013

The Maiden Voyage!

(to the end of my street)

Took me a while to get this far since, of course, uni work takes up my time. A valid reason of course :)

Only have video of the end after i return to my driveway. Much too difficult monitor the laptop and a/f ratio displays and hold a phone AND drive the car without something really bad happening.

I decided to test it out on the road after creating a 16 point fuel map and making further improvements to the injector pulse timing. It actually ran pretty well, but not quite good enough to drive daily. I expect it wouldn't pass any EPA tests either.

The fuel map is made of 16 data points that correspond to a particular level of air flow into the engine. The reason it exists is that you can't just deliver more fuel when the voltage from the hotwire sensor (measures mass of air flowing into engine) increases.  The correlation is not 1-1 matched, so a fuel map has to be created. The data points are arranged in order with the first one sets the fuel to be delivered at lowest air flow and the last one sets the fuel to be delivered at the highest air flow. Because it's not ideal to have 16 discreet steps that determine the amount of fuel to be delivered, the final value that is used is calculated based on how far the measured hotwire value is from each of the two nearest data points.

I was able to improve the injector timing in two ways. First, I have some code which will determine when the next cam signal pulse will occur. This is used to determine when the next combustion stroke will start. That code has been altered to use a new algorithm, which is a continuously corrected estimation. In practice the new method seems to be no better or worse than the old method, but it requires less memory and fewer instruction to complete, which means more time can be spent processing other stuff.
It basically works like this:
  1. Cam pulse occurs (record timer value)
  2. Note the difference between recorded timer value and the previous estimation. Record this as an estimation error.
  3. Make a new estimation (also take into account previous error in estimation)
  4. repeat
Once I had those estimations I could determine when to start and stop each injector pulse. In theory, if your engine does not have direct injection, then it's best to start each injector pulse as late as possible during the intake stroke of the cylinder. The result is that the injected fuel is mostly in a mist form and does not have time to settle completely into a liquid at the bottom (someone correct me if i'm wrong!!). The evenly spread fuel mist should burn much more uniformly than a pool of liquid, resulting in improved power and efficiency. My old method was to look at when the next cam pulse would occur (using the previously mentioned estimation) and if my pulse was, for example, 300 timer ticks wide, then I would start my pulse 300 ticks before the estimation. The problem with this method was that i was ending the pulse when the actual cam pulse occurred. The difference between the estimation and the actual cam pulse meant that the duration of the injector pulse was not exactly what it should be.

The second improvement I made was to use an additional CCP module (remember, a CCP module can be used to execute some program code at a precise time), so that I had one CCP for the injector pulse start, and one CCP for the injector pulse end. This meant that the injector pulse was always exactly for the duration intended duration. The final change to make was to have it occur in the middle of the intake stroke instead of the end. While I still prefer it to happen right at the end of the intake stroke, the reality is that it's not possible to determine exactly when the end would occur. If I started, and ended the injector pulse too late, then the cylinder intake valve would close before all the fuel was delivered. That of course, would be bad! Additionally when more fuel is required than can be delivered in a single intake stroke, the injector pulse is started before the beginning of the intake stroke. When the intake valve is opened (approx at the beginning of the intake stroke), all the fuel is pulled in from the already-started-but-not-yet-completed injector pulse. The pulse continues (delivering more fuel) all the way to the end of the intake stroke.

Now that I have these two changes implemented and working well I can move on to the next tasks. Firstly, that extra CCP module was taken from part of the code used to detect a stalled engine. I'll have to come up with a new way to ensure injector and ignition pulses stop happening if the engine stops running. I'll also improve and make better use of the fuel map and create a usable ignition map to get better spark timing.