ECUs and Tuning Discuss Engine Management, Tuning, & Programming

Arduino as ECU?

Thread Tools
 
Search this Thread
 
Old 09-24-2010, 01:31 PM
  #41  
Junior Member
 
bloodline's Avatar
 
Join Date: Sep 2010
Location: London, England
Posts: 91
Total Cats: 0
Default

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

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...
bloodline is offline  
Old 09-24-2010, 02:36 PM
  #42  
Elite Member
 
JasonC SBB's Avatar
 
Join Date: Jul 2005
Posts: 6,420
Total Cats: 84
Default

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.
JasonC SBB is offline  
Old 09-24-2010, 02:42 PM
  #43  
Elite Member
 
JasonC SBB's Avatar
 
Join Date: Jul 2005
Posts: 6,420
Total Cats: 84
Default

Originally Posted by neogenesis2004
I agree with Joe on the lack of interrupts. To me it sounds like they are saying, "since you have 8 cores, there is no need for interrupts because you have so much more resources to waste polling inputs!"
The purpose is to make the software design easier, for real time control. I can see the advantage, while writing my Arduino code for decoding my 12-1 crank input.

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.
JasonC SBB is offline  
Old 09-24-2010, 02:43 PM
  #44  
Junior Member
 
bloodline's Avatar
 
Join Date: Sep 2010
Location: London, England
Posts: 91
Total Cats: 0
Default

Originally Posted by JasonC SBB
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.
Yes, it costs little to stick a capacitor on the line... I was just trying to push the Arduino as hard as I could from a software point of view... This is the most powerful £2.80 Micro controller chip I've ever used

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.
Good call... The hardware side of this is a real challenge for me, I'm very keen to hear how others have got on!
bloodline is offline  
Old 09-24-2010, 02:45 PM
  #45  
Boost Pope
iTrader: (8)
 
Joe Perez's Avatar
 
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,019
Total Cats: 6,587
Default

Originally Posted by bloodline
Hmmm, ok, these uneven pulse rates on the CAS seem to be an effort to compensate for slow micro-controllers...
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.



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.
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.

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.

Last edited by Joe Perez; 09-24-2010 at 02:58 PM.
Joe Perez is offline  
Old 09-24-2010, 03:03 PM
  #46  
Junior Member
 
bloodline's Avatar
 
Join Date: Sep 2010
Location: London, England
Posts: 91
Total Cats: 0
Default

Originally Posted by Joe Perez
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.
I would, instinctively, do it slightly differently... Imagine a two signal Cam angle sensor:

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.
Apologies if I'm slow on the uptake. I do appreciate your advice, I am enjoying learning this.

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.


I think this will help me a lot! I can't thank you enough for helping me understand this! I hope my questions and ignorance don't annoy!
bloodline is offline  
Old 09-24-2010, 03:42 PM
  #47  
Boost Pope
iTrader: (8)
 
Joe Perez's Avatar
 
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,019
Total Cats: 6,587
Default

Originally Posted by bloodline
I would, instinctively, do it slightly differently...
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.)


Also, I'm stuck with my '91 engine... so unless I replace the injector control hardware/relay board I'm stuck with batch injection.
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.
Joe Perez is offline  
Old 09-24-2010, 03:54 PM
  #48  
Elite Member
 
JasonC SBB's Avatar
 
Join Date: Jul 2005
Posts: 6,420
Total Cats: 84
Default

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.
Attached Thumbnails Arduino as ECU?-arduino-sleeve-schematic.gif  
JasonC SBB is offline  
Old 09-24-2010, 04:13 PM
  #49  
Boost Pope
iTrader: (8)
 
Joe Perez's Avatar
 
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,019
Total Cats: 6,587
Default

Originally Posted by JasonC SBB
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
By "getting in and out", you mean the actual process of receiving and interrupt and switching to the interrupt routine, then returning from it? This is documented for every uC. All you gotta do is drop a pointer on the stack and then jump to a new address location.

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
As I illustrated above, this breaks the system regardless of how many cores you have.

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.
Not wedded to them, it's just an office romance.
Joe Perez is offline  
Old 09-24-2010, 05:07 PM
  #50  
Elite Member
 
JasonC SBB's Avatar
 
Join Date: Jul 2005
Posts: 6,420
Total Cats: 84
Default

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.
JasonC SBB is offline  
Old 09-24-2010, 05:28 PM
  #51  
Junior Member
 
muythaibxr's Avatar
 
Join Date: May 2007
Location: Columbia, MD
Posts: 248
Total Cats: 0
Default

Originally Posted by Joe Perez
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.

*******...
Regardless of F-bombs, B&G seemed open to NDA for those who really need to see the schems. It's not really up to James and I though.

Ken
muythaibxr is offline  
Old 09-24-2010, 05:30 PM
  #52  
Junior Member
 
muythaibxr's Avatar
 
Join Date: May 2007
Location: Columbia, MD
Posts: 248
Total Cats: 0
Default

Originally Posted by neogenesis2004
The MS3 is 32bit so the comparable Atmel chip would be from the AVR32 family.
MS3 is NOT 32-bit. It's from the same chip family as the ms2, so 16-bit. It just runs at 2x the clock speed, has optimizations that make certain instructions take less clock ticks, and has the XGATE coprocessor running at 100MHz built in.

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
muythaibxr is offline  
Old 09-24-2010, 05:39 PM
  #53  
Boost Pope
iTrader: (8)
 
Joe Perez's Avatar
 
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,019
Total Cats: 6,587
Default

Originally Posted by muythaibxr
Regardless of F-bombs, B&G seemed open to NDA for those who really need to see the schems. It's not really up to James and I though.
Wow, I'd completely forgotten that rant was part of this thread.

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.
Joe Perez is offline  
Old 09-24-2010, 06:33 PM
  #54  
Elite Member
iTrader: (12)
 
neogenesis2004's Avatar
 
Join Date: Aug 2006
Posts: 4,413
Total Cats: 20
Default

The 32bit thing was just a shot in the dark guess. I didn't actually Google it back when I posted that.
neogenesis2004 is offline  
Old 09-25-2010, 07:06 AM
  #55  
Junior Member
 
bloodline's Avatar
 
Join Date: Sep 2010
Location: London, England
Posts: 91
Total Cats: 0
Default

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...



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.
bloodline is offline  
Old 09-25-2010, 10:25 AM
  #56  
I'm Miserable!
 
Techsalvager's Avatar
 
Join Date: Jun 2009
Location: albany, ga
Posts: 1,866
Total Cats: 0
Default

I like where this thread is going, gonna keep an eye on it
Techsalvager is offline  
Old 09-25-2010, 11:32 AM
  #57  
Junior Member
 
bloodline's Avatar
 
Join Date: Sep 2010
Location: London, England
Posts: 91
Total Cats: 0
Default

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

Last edited by bloodline; 09-25-2010 at 12:03 PM.
bloodline is offline  
Old 09-25-2010, 01:51 PM
  #58  
Boost Pope
iTrader: (8)
 
Joe Perez's Avatar
 
Join Date: Sep 2005
Location: Chicago. (The less-murder part.)
Posts: 33,019
Total Cats: 6,587
Default

Originally Posted by bloodline
The analog acquisition time is 100microseconds per analog pin
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: (...)


Originally Posted by bloodline
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.
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.



Note, I'm only timing from the falling edge of the CKP...
For spark prediction? This means that, on average, you will have nearly half a full crank revolution elapse while the timer is running.
Joe Perez is offline  
Old 09-25-2010, 02:22 PM
  #59  
Junior Member
 
bloodline's Avatar
 
Join Date: Sep 2010
Location: London, England
Posts: 91
Total Cats: 0
Default

Originally Posted by Joe Perez
Does this mean that the processor is essentially stalled for that entire time?
Yeah, using the standard Arduino I/O library... It would be quite easy to write my own free running ADC function, but I would prefer something compatible with future systems.

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: (...)
Yes, scheduling the sensors is a good idea. I would also use different schemes for different RPM.

If I still want a throttle servo, I'll need to serve it at least every 40milliseconds


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.
I understand the mechanics, I need to know the flow rate per microsecond (I have found a webpage that claims 212cc per min on a standard injector, is this right?), what voltage/amperage they run at, and also if they need to be pulsed (i.e. if I supply continuous power will it burn out the solenoid?).

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.
Ah, ok so it is the start time that should be altered, rather than start time... that makes timing easier

For spark prediction? This means that, on average, you will have nearly half a full crank revolution elapse while the timer is running.
hmmm, timing from rising and falling edge would be much better... I'll add an option for it in my code, so it can be activated if needed.
bloodline is offline  
Old 09-25-2010, 03:26 PM
  #60  
Elite Member
iTrader: (10)
 
Reverant's Avatar
 
Join Date: Jun 2006
Location: Athens, Greece
Posts: 5,976
Total Cats: 355
Default

Originally Posted by Joe Perez
Does this mean that the processor is essentially stalled for that entire time?
Normally, no. You start the conversion process and from there poll for a flag to check if the conversion had ended.
Reverant is offline  


Quick Reply: Arduino as ECU?



All times are GMT -4. The time now is 03:23 AM.