Wednesday, February 5, 2014

POWERR!!!

I've reached a critical point in my project where the focus is no longer on prototyping, experimenting and testing. The most important functions of my ECU are working well and now i can move on to my next goal. I want something with more of a professional finish, rather than a hobbyist's experiment. I'll polish up the software used to send config and tuning data to my ECU. Making the software easier to use means I can focus on tuning the engine, not on using the program. I can start considering secondary functions too like flood clear, idle speed control and hot/cold start.

Injector and Coil Timing
Injector and coil timing is calculated based on blocks of time that correspond to one piston stroke. The square wave signal from the cam sensor gives 4 pulses per revolution, which correspond to the 4 piston strokes of a 4 stroke engine. Within the time frame of these strokes certain things need to happen. Fuel injectors need to turned on and off, and so do ignition coils. This is handled by loading specific values into CCP modules of the microcontroller (this post roughly explains CCPs http://fuzzymonkey87.blogspot.com.au/2013/09/the-maiden-voyage.html) to trigger events to happen at specific times.

A variable to keep track of the cylinder on power stroke and 4 CCP modules are available. This works well enough when 4 events are specified:
  • Injector on
  • Injector off
  • Coil on
  • Coil off
But there are two problems with this approach:
  1. The coil or injector being turned on, must be turned off in the same piston stroke. This is no good when a coil or injector pulse has a longer duration than the entire piston stroke.
  2. CCP events can be missed in a few ways, but most commonly if the specified time occurs before it is being set. Example: timer = 123, set CCP to trigger at 127 (this takes a short time), timer = 140. Setting the trigger takes too long, so the trigger time is missed.
I had problem #1 partly solved by using additional variables to keep seperate index on the injector and coil that is being switched on or off. In practice it didn't work reliably at first, even though I could not see a fault in my logic. Injector patterns looked weird (watching LED indicators connected to injectors). After a few days of trying to debug I decided to rewrite the entire thing from scratch... in exactly the same way... and it worked perfectly. Obviously I made some silly mistake somewhere, but no idea what it is!

With this algorithm implemented for both the coils and injectors i was getting a the most power i have had so far!

Problem #2 was solved firstly by hard coding the coil to turn off at the end of the cylinder compression stroke and the injector to turn off at the end of the cylinder intake stroke (the intake valve is closed anyways!). Typically both the coil and injector would already be switched off at this time, so either there will be no effect, or the missed CCP event would be taken care of. Secondly, the process of calculating timer values for CCP modules does take some time. To compensate for this i've also implemented a fast "guestimation" to be used when the more accurate (but slower) coil and injector calculations cannot be used. Whenever a CCP module generates an interrupt, it will first execute its standard function (eg: turn off coil), then it will do a very simple operation, to shift its trigger time to be at the equivalent point in the next piston stroke. This could be a slightly different(not accurate) time than what is calculated by the slower, more accurate algorithm. The difference seems to be so small that it doesn't make a difference. Finally, while guestimation is calculated each time the CCP is triggered, the guestimation is automatically overridden by the more accurate calculation as long as it is done quickly enough.

While testing I found it ran noticeably smoother and I have even more power again. I estimate around 70% of the original power output of the car. SO EXCITE!!!

Fuel Map and Dyno
An ECU is useless if it doesn't have proper tuning data. There's no point in being able to precisely control spark timing if it gets precisely set too late in the combustion cycle. This is where I need to set ideal values in the fuel and ignition advance map for the ECU to base its calculations on. For the moment i've been setting them based on and limited "road tunes". The idea is you try to drive your car with a constant engine speed and manifold pressure which corresponds to a data point in your fuel map (for programmers: it's an item in an array). Once there you adjust the value for that data point until you achieve the desired air/fuel ratio (or ignition advance value if doing ignition map). This is a lot harder than it sounds. It's near impossible to maintain a constant manifold pressure. RPM will change as you encounter a gradient, and as you make adjustments to the map! If RPM changes, then that data point is no longer being referenced. To keep RPM steady you need to adjust acceleration - but this changes the manifold pressure! If the manifold pressure changes, then again that data point is no longer being referenced.
Road tuned fuel map
I had also partially implemented a method for the ECU to tune itself. It would use the oxygen sensor to determine current air/fuel ratio and make adjustments to the current data points being referenced. Because the sensor has a delay I need to determine what the delay is and make adjustments to the data points at that time. So if the sensor has a 1.5 second delay and it measures that the car is running rich. I need to check which data points were being used 1.5 seconds ago and make them leaner. Great... so what is the actual delay? Well there's the problem. The delay is always changing because of exhaust gas speed (and maybe temperature). My method for determining the delay was to periodically cut the injectors count how long it took for the oxygen sensor to register it. While I can measure the delay, I haven't been able to do it in a way that isn't a major disruption to the running of the engine.

To do this properly I need to put my car on a Dyno, like everyone else that gets their car modded and tuned.

Knock sensing
I'm not going to explain knocking/pinging/detonation in detail because you can find heaps of information out there in internet land. Basically it refers to uneven and turbulent combustion of fuel that will cause the piston to smack into the cylinder wall instead of being driven straight down. As you can imagine this is very bad! As far as I know the possible causes are:
  • bad fuel
  • too much ignition advance
  • air/fuel ratio too lean
  • dirty plugs
  • carbon build up
Knocking makes a distinctive metalic "ping" noise and most cars have a knock sensor to pick up this noise. If it happens then the ECU will make adjustments to prevent damage. Typically it will retard the ignition timing.

My model MX5 doesn't have a knock sensor, so I don't have a way to detect knock yet. At the moment my engine is knocking pretty badly despite producing a decent amount of power and me tuning it as well as I can for now. I've addressed each of these possible causes and managed to minimise the problem, but not remove it completely.

I'm not yet sure if I will implement knock detection myself or use an aftermarket device. Knock sensing itself is sort of complicated and requires some filtering and isolating specific frequencies. The signal processing would probably be complex enough to require a seperate device to handle the computations. A separate microcontroller or DSP or something. I really don't know at this stage and will need to learn more before I come up with anything.

Multilock
That's the name of the plug/socket that connects the ECU to the rest of the wiring in the car. I've modified and hacked up the wiring to the point that the original ECU will no longer function and that's no good to me since I want to swap back and forth between ECUs if needed.
New sockets and original ECU
Since the original ECU does not use all pins of the plug I can use those for things that are specific to the PIT ECU. So far that's the MAP sensor and the 2 extra wires for the injectors in multipoint configuration. Will also need to modify the original ECU so that the 2 extra injector wires get bridged to the 2 original injector outputs. Then it should run in banked injector configuration (firing in pairs) as normal.

PCB 
Fuckit PCB time! The breadboard and even veroboard provided a lot of freedom to make changes. But it did restrict the shape of the board and layout slightly, and there is no way to properly connect the multilock socket. I think the most important advantage with PCBs is the physical robustness. There's no wires to rip out and it's resistant to vibrations. I'm temporarily converting everything back to the original ECU while I learn about PCB design. I have zero experience, but there's a lot of great looking free software available and lots of cool tutorials too. I'll most likely use KiCad http://www.kicad-pcb.org. Also, I expect my first PCB to have some mistake that makes it useless, but there's a few companies that do small runs of boards so that's no big waste of $ for me :)