Wednesday, December 4, 2013

When I grow up, I want to be a real ECU.

Mmmm sparodic updates...

I've made a lot of changes since my last post and I'm much closer to having something I can drive daily.

MAP Sensor
I've ditched the hotwire setup for a 2 bar MAP sensor. What this means is that instead of measuring the air flow, I am measuring the air pressure. It complicates things, but there's a few reasons I went for the MAP sensor. With the hotwire sensor I had trouble figuring out how it'd be properly mounted and how I'd fit the existing (or make a replacement) air filter box. I also had the problem of very high air flows not being measured accurately. Higher voltage from the hotwire signal = more airflow and I was getting close to 5v (max voltage) before the turbo was even fitted. The MAP sensor can be anywhere as long as I can reach a vacuum line to it. It's also much smaller and easier to mount.
MAP sensor

The difficult part comes in software. In order to properly calculate the injector pulse width, you need to know how much air is flowing into the engine (the total mass of air). The MAP sensor only gives me the manifold air pressure. An increase in air pressure does mean more air is flowing into the engine, but an increase in RPM also means more air is flowing into the engine. Now instead of a 1D fuel map, I have a 2D fuel map. The first dimension related to air pressure and the 2nd related to RPM. I now have 256 data points where I used to have 16. The code needs to calculate the injector pulse width based on how far the current values (pressure and RPM) are from their nearest data points. It does a sort of "proportional averaging" or "local linearisation" (seriously I don't know what to call it) to get the final result. I'm using a lot of floating point numbers and there are a lot of calculations to be done!
Small portion of tuning data (top/left numbers). Also, yes! I know RPM isn't a percentage!

I'll also be doing the same thing for ignition timing. More advance as RPM increases, and less advance as air pressure increases.

Processing time
My complicated fuel map gave me a new problem. And that's required processing time. Engine peaked at 2200 rpm now, not because the tuning was poor, but because the next injector pulse width could not be calculated in time. I ended up confirming the duration of processing time by outputting the timer values at the beginning and end up the interrupt handler. The difference was the total processing time.

I'm using the free XC8 compiler to compile my C code. The free version has "limited optimisations" which result in the compiled code being slow to execute. The "standard" and "pro" editions are far too expensive for me to buy. Finally, there is SDCC a free and open source C compiler for PIC (and other) microcontollers, but is appears that my micro PIC18F46K80 is not properly supported yet. That leaves the following options:
  • Write optimised in-line assembly for the slowest sections of code
  • Crank up the MHz
I took the easy way out. Using the 4x PLL clock multiplier i'm now running the clock at 64MHz from 16MHz. This had the side effect of speeding up the timing for all the mcu peripherals (timers, USART). But I could fix this by adjusting some of the timer clock dividers and switching to the now 4x faster baud rate. Finally, in the case of the timer user for cam position timing, I used a seperate microcontroller PIC16F88 who's sole purpose was to provide a 500kHz signal for just that timer. Otherwise, only a 32.768 kHz watch crystal can be used (too slow). There's probably a way to provide a 500kHz clock with a few discreet components as well but it's much easier to write a couple of lines of code than it is to make up a new circuit.

The second micro could also be used for for secondary functions like turbo boost controller, or controlling the EGR valve. By removing these functions away from the main mcu I can simplify the code that it runs. Simpler code generally runs faster and is less bug-prone.

I've also moved the entire circuit from the broadboard to a veroboard. Soldered connections seem to be more reliable, except kynar wire is frikin fragile! There were some changes to the electrical characteristics of the circuit, especially with the 7805 regulator. I had to add a cap on the input side to smooth out the supply voltage. I think this has to do with the relatively high capacitance of the breadboard.
Messy Breadboard

I wasn't really sure of the best way to lay out the board, I just tried to keep the wires short. I made a couple of mistakes (miscounting pins) so I had to make some additional changes and the final result is a little messier than I wanted. Still, it is much better than the breadboard setup.
mmm blobbly solder

I also learned a very important lesson about proper connections. I spent a full day trying to fix an issue with serial communication between the mcu and my laptop. I thought the USB>serial adapter had died. I spent the night configuring a spare old laptop that had a serial port on it, when I should have realised the 4 pin header connecting to the MAX232 chip was damaged!! I would've liked to watch the signals coming in and out of the MAX232 chip with a scope, but I can't tell much with my analog scope and my cheapo USB digital scope is screwed.

So now I can start the car
Nope! for some reason the micro is acting a bit weird. I wasn't sure what version of my program was on it at the time, but I can't reprogram it. I know my programmer (PICkit 3) is working because I can program other chips. I'm hoping it's just a connection issue with the ICSP interface, but it looks OK. Could I have damaged the micro with either heat from the soldering iron or ESD? I'm not looking forward to replacing this micro on the board. So many pins. If only I had gone with a ZIF socket!

Edit on 2013-12-04: mcu is deaded. I can program a spare mcu on a breadboard, but if I replace it with the one desoldered from the veroboard, it will fail to program.