Arduino as ECU?
#41
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
Hmmm, ok, these uneven pulse rates on the CAS seem to be an effort to compensate for slow micro-controllers...
If I take the hardware side of this further, I would have to replace the CAS with something more useful, also the injector wiring would have to be replaced to get sequential injection... while I'm at it, I might as well replace the MAS with a MAP... This is far more than I wanted to do... I'm a software guy really![](https://www.miataturbo.net/images/smilies/smile.gif)
Ok, I guess what I want now is a diagram showing the piston no.1 position vs the CAS pulses for the NA (pre '93)... that way I can adjust my model to get it's timing from the original CAS.
Note: I discovered how noisy a car's electrical system is during my investigation regarding the throttle servo project I mentioned earlier. I decided to use a standard HItech HS422 servo (not ideal for the hot, dirty environment of a car engine bay, but can be easily protected, is very powerful and is very cheap). And I had to resort to shielded cabling and a simple low pass filter algorithm on my sampling code (the AVR328 is a powerful beast) to reduce the electrical noise on the analog lines to an acceptable amount...
If I take the hardware side of this further, I would have to replace the CAS with something more useful, also the injector wiring would have to be replaced to get sequential injection... while I'm at it, I might as well replace the MAS with a MAP... This is far more than I wanted to do... I'm a software guy really
![](https://www.miataturbo.net/images/smilies/smile.gif)
Ok, I guess what I want now is a diagram showing the piston no.1 position vs the CAS pulses for the NA (pre '93)... that way I can adjust my model to get it's timing from the original CAS.
Note: I discovered how noisy a car's electrical system is during my investigation regarding the throttle servo project I mentioned earlier. I decided to use a standard HItech HS422 servo (not ideal for the hot, dirty environment of a car engine bay, but can be easily protected, is very powerful and is very cheap). And I had to resort to shielded cabling and a simple low pass filter algorithm on my sampling code (the AVR328 is a powerful beast) to reduce the electrical noise on the analog lines to an acceptable amount...
#42
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
It is de rigeur in system design to bandlimit signals using analog lopass filters, to only the bandwidth you need. Translation: put an RC lopass filter for the signals that come from the outside world, at the entrances of your board. Spec the time constants so the rise times are only a bit faster than what you need, e.g. 15 uS for crank signals, because that's half a crank degree at 7500 RPM.
Even output signals should be bandlimited. For example, my Arduino board generates signals for my factory ECU crank input. The Arduino will put out pulses with rise times of only a few uS. Because the wire that carries this signal runs in parallel to the input from my crank sensor, a fast rise time on this wire will couple noise into my crank input. So I bandlimited it to ~20 us with an RC lopass.
Even output signals should be bandlimited. For example, my Arduino board generates signals for my factory ECU crank input. The Arduino will put out pulses with rise times of only a few uS. Because the wire that carries this signal runs in parallel to the input from my crank sensor, a fast rise time on this wire will couple noise into my crank input. So I bandlimited it to ~20 us with an RC lopass.
#43
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
To wit: the problem with multiple interrupts is:
- it's hard to determine how many clock cycles are used up getting in and out of the interrupt routine
- while in the interrupt, what if another interrupt occurs? This is another layer of complication
It is far easier to architect the system where you have a core dedicated for each time critical operation. It is also more predictable.
For example, ignition timing needs 10 us accuracy. That's not a lot of clock cycles for a midrange uC.
You guys are used to, and wedded to, the idea of interrupts.
I am now re-entering the world of uC's, so I have less bias than seasoned uC programmers, one may say.
Last edited by JasonC SBB; 09-24-2010 at 03:17 PM.
#44
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
It is de rigeur in system design to bandlimit signals using analog lopass filters, to only the bandwidth you need. Translation: put an RC lopass filter for the signals that come from the outside world, at the entrances of your board. Spec the time constants so the rise times are only a bit faster than what you need, e.g. 15 uS for crank signals, because that's half a crank degree at 7500 RPM.
![](https://www.miataturbo.net/images/smilies/smile.gif)
Even output signals should be bandlimited. For example, my Arduino board generates signals for my factory ECU crank input. The Arduino will put out pulses with rise times of only a few uS. Because the wire that carries this signal runs in parallel to the input from my crank sensor, a fast rise time on this wire will couple noise into my crank input. So I bandlimited it to ~20 us with an RC lopass.
#45
Boost Pope
![](/mt2011/images_td/ranks/supporter1.gif)
![](/mt2011/images_td/ranks/smod.png)
iTrader: (8)
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,339
Total Cats: 6,793
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
Without the two CMPs, you'd have to wait up to a maximum of two full crank rotations before a CMP pulse came around in order to start firing the ignition.
The speed of the CPU has no bearing at all on any of this. A quad-core i7 would still have to wait up to two full crank rotations before it could begin operating the ignition if there were only one CMP pulse per cam rotation.
If I take the hardware side of this further, I would have to replace the CAS with something more useful, also the injector wiring would have to be replaced to get sequential injection.
Now, I do recommend replacing the CAS with a crank-triggered pickup, but only because the flex of the timing belt causes a lot of spark scatter. Nothing at all to do with batch vs. sequential.
Ok, I guess what I want now is a diagram showing the piston no.1 position vs the CAS pulses for the NA (pre '93)... that way I can adjust my model to get it's timing from the original CAS.
![](http://img40.imagefra.me/img/img40/7/9/24/thraddax/f_sda3lb7jm_43feda1.jpg)
Last edited by Joe Perez; 09-24-2010 at 02:58 PM.
#46
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
I don't see why you think this. The uneven-pulse design allows you to have fully sequential injection while reducing the time it takes for the ECU to sync up while starting. You fire the injectors in full-batch mode while cranking (every injector on every CKP pulse) and then you only have to wait a maximum of one crank rotation to get a CMP reference so you can start firing the ignition.
Without the two CMPs, you'd have to wait up to a maximum of two full crank rotations before a CMP pulse came around in order to start firing the ignition.
The speed of the CPU has no bearing at all on any of this. A quad-core i7 would still have to wait up to two full crank rotations before it could begin operating the ignition if there were only one CMP pulse per cam rotation.
Without the two CMPs, you'd have to wait up to a maximum of two full crank rotations before a CMP pulse came around in order to start firing the ignition.
The speed of the CPU has no bearing at all on any of this. A quad-core i7 would still have to wait up to two full crank rotations before it could begin operating the ignition if there were only one CMP pulse per cam rotation.
for 0 degrees rotation, Signal A and Signal B would be HIGH.
For 90 degrees, Signal A would be LOW and Signal B would be HIGH.
For 180 degrees, Signal A would be HIGH and Signal B would be LOW.
for 240 degrees, Signal A would be LOW and Signal B would be HIGH.
This way you would only need a single interrupt on Signal A (testing the B signal in the interrupt service routine, if B is HIGH then we are at 0, if it is LOW we are at 180), to establish where you are in the cycle, i.e. only one crank rotation.
Wouldn't this work?
Nope. '94 to '97 MX5s have full sequential injection and they use this same CAS. Read what I wrote in my last post more carefully.
Also, I'm stuck with my '91 engine... so unless I replace the injector control hardware/relay board I'm stuck with batch injection.
Now, I do recommend replacing the CAS with a crank-triggered pickup, but only because the flex of the timing belt causes a lot of spark scatter. Nothing at all to do with batch vs. sequential.
![](http://i264.photobucket.com/albums/ii184/spyghost/4g15%20dohc%20build/timing.jpg)
#47
Boost Pope
![](/mt2011/images_td/ranks/supporter1.gif)
![](/mt2011/images_td/ranks/smod.png)
iTrader: (8)
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,339
Total Cats: 6,793
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
I see, sort of a balanced Grey code. Yeah, you're definitely a software guy.
My perspective on what you've described relative to the 4G63 design:
1: Assuming you are speaking of degrees at the camshaft, your design treats both the rising and falling edges of "Signal A" as triggers. Bear in mind that many (if not most) microprocessors can only see one side of a transition on their IRQ input- IOW, they can only see a falling edge or a rising edge, but not both.
2: If you were speaking of degrees at the crank, then your solution doesn't allow fully sequential injection.
3: It is desirable to have both a rising and a falling edge on the primary trigger for every ignition event. In the 4G63 design, the rising edge occurs at 75° BTDC, and the falling edge at 5° BTDC. The 75° BTDC edge is the primary trigger during normal operation, giving the timer plenty of room to achieve full ignition advance plus dwell. The 5° BTDC edge is used as an absolute reference for the spark event while cranking over on the starter, when RPM is too low and crankshaft angular velocity too unstable to accurately compute an ignition angle from 75° away.
(Note that in #3, I am speaking of degrees at the crankshaft.)
Well, yeah. I kind of assumed that you were replacing the whole ECU. The injector drivers are internal to the ECU. There is no separate "injector control hardware/relay board" in the stock engine control system.
![](https://www.miataturbo.net/images/smilies/smile.gif)
My perspective on what you've described relative to the 4G63 design:
1: Assuming you are speaking of degrees at the camshaft, your design treats both the rising and falling edges of "Signal A" as triggers. Bear in mind that many (if not most) microprocessors can only see one side of a transition on their IRQ input- IOW, they can only see a falling edge or a rising edge, but not both.
2: If you were speaking of degrees at the crank, then your solution doesn't allow fully sequential injection.
3: It is desirable to have both a rising and a falling edge on the primary trigger for every ignition event. In the 4G63 design, the rising edge occurs at 75° BTDC, and the falling edge at 5° BTDC. The 75° BTDC edge is the primary trigger during normal operation, giving the timer plenty of room to achieve full ignition advance plus dwell. The 5° BTDC edge is used as an absolute reference for the spark event while cranking over on the starter, when RPM is too low and crankshaft angular velocity too unstable to accurately compute an ignition angle from 75° away.
(Note that in #3, I am speaking of degrees at the crankshaft.)
Also, I'm stuck with my '91 engine... so unless I replace the injector control hardware/relay board I'm stuck with batch injection.
#48
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
See my Arduino interface schematic.
Opamp circuit is a lopass filter to convert PWM output into a DC voltage for the AFM input of the factory ECU.
The Schmitt inverter circuit is the input filter for the incoming 12-1 CKP signal.
The RCRC circuit is the input filter for the MAP sensor signal.
The 330 ohm / 33 nF filter is to filter the Arduino output which goes to the CKP input of the factory ECU.
Opamp circuit is a lopass filter to convert PWM output into a DC voltage for the AFM input of the factory ECU.
The Schmitt inverter circuit is the input filter for the incoming 12-1 CKP signal.
The RCRC circuit is the input filter for the MAP sensor signal.
The 330 ohm / 33 nF filter is to filter the Arduino output which goes to the CKP input of the factory ECU.
#49
Boost Pope
![](/mt2011/images_td/ranks/supporter1.gif)
![](/mt2011/images_td/ranks/smod.png)
iTrader: (8)
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,339
Total Cats: 6,793
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
If you mean how long it takes to actually run the interrupt routine, that's important regardless of architecture.
Let's look at how a Prop might be configured to do the job of an MS. We dedicate one cog to be the interrupt handler. Whatever time-critical activity the interrupt routine is doing must be executed on the same cog that's detecting the interrupt. There's no way for one cog to "interrupt" another, so you have to perform the whole interrupt routine on the interrupt cog, which, as you said, means you have to be certain that the whole interrupt routine "fits" into the window between interrupts, including the time it takes for the interrupt cog to write data into main memory so that the other cogs can read it. (Even the non-time-critical cogs need to know what the engine RPM is and what phase the crank is in.)
- while in the interrupt, what if another interrupt occurs? This is another layer of complication
Unless, of course, you are referring to a system with multiple interrupts, like a general-purpose PC. In that case, you handle the high-priority interrupt first, then service the lower-priority ones. But for an ECU, one IRQ is all you need. (Assuming your engine only has one crankshaft, which I think is a fair assumption.)
You guys are used to, and wedded to, the idea of interrupts.
![big grin](https://www.miataturbo.net/images/smilies/biggrin.gif)
#50
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
No, you dedicate one cog to do crank angle prediction / ignition. It continually polls the CKP and CMP, calculates crank position, and outputs the coil signals. It reads the desired timing from a shared mem location, which is updated by another cog. This way this cog does one task, and does not need to be interrupted by any, more important tasks.
Another cog does the same for injection.
And so on.
No interrupts necessary with this architecture.
Another cog does the same for injection.
And so on.
No interrupts necessary with this architecture.
#51
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
Just wish they'd ******* let us see the ******* schematics for the ******* MS3 and the ******* MS3X that they've been keeping so ******* secretive on fear that some ****** will clone the ******* thing, with no regard for all the ******* people out there who don't give a **** about copycats and just want to be able to properly optimize their ******* I/O circuits.
*******...
*******...
Ken
#52
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
For those who care, its the MC9S12XEP100, has 1M of program flash, 32k of data flash, and 64K of RAM.
We use the data flash for all our tuning data currently.
Ken
#53
Boost Pope
![](/mt2011/images_td/ranks/supporter1.gif)
![](/mt2011/images_td/ranks/smod.png)
iTrader: (8)
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,339
Total Cats: 6,793
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
![big grin](https://www.miataturbo.net/images/smilies/biggrin.gif)
Just needed to get a few things off my chest. I'm sure that when the time comes for my next ECU, the MS3 I/O circuits won't be terribly difficult to reverse-engineer. I just hate having to spend the time to do it.
#55
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
After studying the Timing diagrams provided by Joe, I found it quite easy to rewrite my synchroniser code and timing interrupt to work using the output of the standard CAS.
I was then able to run a simulation, using the following Ignition timing table:
RPM BTDC
500 10
1000 10
1500 12
2000 17
2500 22
3000 24
3500 28
4000 28
4500 31
5000 34
5500 36
6000 36
6500 36
7000 36
Which I believe is the stock timings... Are these any good? I would appreciate better ones.
Anyway during my simulation, I hit a big snag with the Arduino. The analog acquisition time is 100microseconds per analog pin (using the standard library), which at 8000rpm is about 5 degrees of crank rotation.
There simply isn't enough "dead time" in the cycle, in order to acquire the TPS and the Air flow.
I think I will have to write my own analog code that will read asynchronously, any better ideas?
-Edit- Actually, after playing around with it a bit, I think blinding the code for 10 degrees once per 2 crank revolutions isn't too bad, and that only happens at the VERY top of the engine's running speed... I don't think I've ever taken mine over 6000RPM... maybe once...
-Edit 2-
Here is the output of my current simulation; In this simulation the ignition fires at 10d BTDC and the injector open time is 90d of crank. I currently only check the cam position signal once, during startup to determine which CKP pulse is next, after that, all timings are derived from the CKP via an interrupt...
![](http://www.cutiemish.com/OneCycle.jpg)
Changes made to this model mean that that the crank angle now determines the position in the cycle, the units on the x axis are 10ths of a degree. At 1000RPM, there are 170 microseconds per degree of crank rotation.
I was then able to run a simulation, using the following Ignition timing table:
RPM BTDC
500 10
1000 10
1500 12
2000 17
2500 22
3000 24
3500 28
4000 28
4500 31
5000 34
5500 36
6000 36
6500 36
7000 36
Which I believe is the stock timings... Are these any good? I would appreciate better ones.
Anyway during my simulation, I hit a big snag with the Arduino. The analog acquisition time is 100microseconds per analog pin (using the standard library), which at 8000rpm is about 5 degrees of crank rotation.
There simply isn't enough "dead time" in the cycle, in order to acquire the TPS and the Air flow.
I think I will have to write my own analog code that will read asynchronously, any better ideas?
-Edit- Actually, after playing around with it a bit, I think blinding the code for 10 degrees once per 2 crank revolutions isn't too bad, and that only happens at the VERY top of the engine's running speed... I don't think I've ever taken mine over 6000RPM... maybe once...
-Edit 2-
Here is the output of my current simulation; In this simulation the ignition fires at 10d BTDC and the injector open time is 90d of crank. I currently only check the cam position signal once, during startup to determine which CKP pulse is next, after that, all timings are derived from the CKP via an interrupt...
![](http://www.cutiemish.com/OneCycle.jpg)
Changes made to this model mean that that the crank angle now determines the position in the cycle, the units on the x axis are 10ths of a degree. At 1000RPM, there are 170 microseconds per degree of crank rotation.
Last edited by bloodline; 09-25-2010 at 10:13 AM.
#57
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
Ok, to solve the Analog acquisition time problem, I decided to start the acquisition just after TDC of cylinder one then waiting to continue execution until the Cam signal goes low, that gives me at least 490micro seconds (at 8000RPM) to acquire my analog readings (plenty of time)
and also I know that the crank angle is 49deg at that point so I remain synchronized.
I know that overlaps with my injector timing, but frankly they are just junk at the moment until I get more info on how injectors work.
Note, I'm only timing from the falling edge of the CKP... I might time from both the rising edge and falling edge if I need more accuracy
![](https://www.miataturbo.net/images/smilies/smile.gif)
I know that overlaps with my injector timing, but frankly they are just junk at the moment until I get more info on how injectors work.
Note, I'm only timing from the falling edge of the CKP... I might time from both the rising edge and falling edge if I need more accuracy
![](https://www.miataturbo.net/images/smilies/smile.gif)
Last edited by bloodline; 09-25-2010 at 12:03 PM.
#58
Boost Pope
![](/mt2011/images_td/ranks/supporter1.gif)
![](/mt2011/images_td/ranks/smod.png)
iTrader: (8)
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,339
Total Cats: 6,793
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
Does this mean that the processor is essentially stalled for that entire time?
A few things to consider...
What are you planning to use TPS for? In a forced-induction application, MAP (or airflow) are considered be some to be a more useful predictor of load for the purposes of accel enrichment. So if you're only going to sample it for things live overrun or idle threshold, it's not necessary to sample it every single cycle. You could probably do a round-robin scheme with the analog inputs, one per cycle, such as:
1: Airflow
2: TPS
3: Airlow
4: CLT
5: Airflow
6: IAT
7: Airflow
8: O2
9: Airflow
10: TPS
11: (...)
They contain a coil of wire which forms an electromagnet. You pass current through them, and some period of time later they start flowing fuel. You remove the current, and some period of time later they stop flowing fuel.
If you're going for full sequential, the injectors should be timed such that the end of the fuel spray always occurs at the same point in the cycle, some distance before BDC on the intake cycle for a given cylinder.
For spark prediction? This means that, on average, you will have nearly half a full crank revolution elapse while the timer is running.
A few things to consider...
What are you planning to use TPS for? In a forced-induction application, MAP (or airflow) are considered be some to be a more useful predictor of load for the purposes of accel enrichment. So if you're only going to sample it for things live overrun or idle threshold, it's not necessary to sample it every single cycle. You could probably do a round-robin scheme with the analog inputs, one per cycle, such as:
1: Airflow
2: TPS
3: Airlow
4: CLT
5: Airflow
6: IAT
7: Airflow
8: O2
9: Airflow
10: TPS
11: (...)
If you're going for full sequential, the injectors should be timed such that the end of the fuel spray always occurs at the same point in the cycle, some distance before BDC on the intake cycle for a given cylinder.
Note, I'm only timing from the falling edge of the CKP...
#59
![Default](https://www.miataturbo.net/images/icons/icon1.gif)
A few things to consider...
What are you planning to use TPS for? In a forced-induction application, MAP (or airflow) are considered be some to be a more useful predictor of load for the purposes of accel enrichment. So if you're only going to sample it for things live overrun or idle threshold, it's not necessary to sample it every single cycle. You could probably do a round-robin scheme with the analog inputs, one per cycle, such as:
1: Airflow
2: TPS
3: Airlow
4: CLT
5: Airflow
6: IAT
7: Airflow
8: O2
9: Airflow
10: TPS
11: (...)
What are you planning to use TPS for? In a forced-induction application, MAP (or airflow) are considered be some to be a more useful predictor of load for the purposes of accel enrichment. So if you're only going to sample it for things live overrun or idle threshold, it's not necessary to sample it every single cycle. You could probably do a round-robin scheme with the analog inputs, one per cycle, such as:
1: Airflow
2: TPS
3: Airlow
4: CLT
5: Airflow
6: IAT
7: Airflow
8: O2
9: Airflow
10: TPS
11: (...)
If I still want a throttle servo, I'll need to serve it at least every 40milliseconds
![](https://www.miataturbo.net/images/smilies/smile.gif)
They contain a coil of wire which forms an electromagnet. You pass current through them, and some period of time later they start flowing fuel. You remove the current, and some period of time later they stop flowing fuel.
If you're going for full sequential, the injectors should be timed such that the end of the fuel spray always occurs at the same point in the cycle, some distance before BDC on the intake cycle for a given cylinder.
![](https://www.miataturbo.net/images/smilies/smile.gif)
For spark prediction? This means that, on average, you will have nearly half a full crank revolution elapse while the timer is running.
![](https://www.miataturbo.net/images/smilies/smile.gif)