Special Requirements For Timing/Output Event Scheduling

Official FreeEMS vanilla firmware development, the heart and soul of the system!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Special Requirements For Timing/Output Event Scheduling

Post by Fred »

OK, so this is to determine adjustability issues beyond the normal set of users that just have coils and injectors.

A normal user will be happy with:

Ignition, normal coil, dumb ignitors:
  • Each channel's timing is based around some reference angle for TDC
  • Ignition timing from 0 - 50 degrees BTDC
  • Timing is to the end of dwell
  • Dwell is based on battery voltage and can be exceeded to aid scheduling, dwell will always be as requested or more unless specifically configured otherwise:
  • Some sort of minimum spark duration window such that a maximally long spark can complete before dwell resumes
Injection, standard:
  • Injection pulse width fixed from fuel calcs, and never adjusted for the sake of timing
  • Each channel's timing is based around some reference angle for TDC (or other reference where appropriate)
  • Injection start timing settable to 0 - 50 degrees offset from reference angle
  • Timing observed where possible, but deviated from, for the sake of accurate pw, rather than the other way around as in ignition mode
  • Ability to smoothly step up to 100% duty cycle for extreme applications
However some setups require more than this, particular, off the top of my head:
  • Saimese port injection such as mini A series engine and Buick straight 8
  • Saab CDI ignition box
  • LS1 coils and other coils with fixed max dwell and other weirdness
They require the following:

Saimese:
  • Injection angle timing centre driven, not start, not end.
  • Full 3d timing curve required
  • How much range? Is 0 - 50 degrees enough?
Saab CDI
  • Variable spark duration time with rpm
Too-smart-for-their-own-good coils
  • Dwell extension cap, or disallow
So, to summarise, the following attributes are required:
  • Reference angle settable anywhere within decoder range
  • Timing aligned to start, centre, or end
  • Precision pulsewidth/dwell or timing, or both
  • Optional and limited (% or fixed) stretching of pulsewidth (when it is dwell and coils are normal) to aid scheduling with low event count decoders at low engine speeds
  • Optional and limited (time or angle) advancement of timing over desired (when it is fuel and not siamese) to aid scheduling with low event count decoders at low engine speeds
  • Timing tunable precision = 0 - 51 in 0.2 degree steps, OR, 0 - 63.75 in 0.25 degree steps, OR, 0 - 127.5 in 0.5 degree steps, 1 degree isn't enough IMO even with interpolation etc. I don't want to waste valuable RAM space on having timing in 16 bit tables when 8 is easily good enough for the majority of users. Do we need negative base timing ever? (antilag, retard limiters, etc not included)
  • Minimum off time/Maximum on time (% duty or fixed) to allow for spark discharge from inductive coils or capacitor recharge in CDI boxes.
  • Source of event duration is either dwell or injection pulsewidth
  • Source of dwell is either (V vs Time) OR (RPM vs Time) table, table shared, axis var configurable
  • Source of injection pulsewidth is a variety of algorithms to suit most needs
  • Source of timing is the combination of reference angle and one or more of the available timing tables, possibly combined in various ways?
Would anyone like to pick holes in my master plan? Speak now, or forever be without the features that you (think you) need! :-)

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
jbelanger
LQFP144 - On Top Of The Game
Posts: 387
Joined: Sat Feb 23, 2008 8:58 pm
Contact:

Re: Special Requirements For Timing/Output Event Scheduling

Post by jbelanger »

Limiting the injection timing to anything but the full 720 degrees does not make any sense. With the same trigger pattern, and therefore I assume the same reference angle, you can have vastly different engine configurations (intake manifold geometry, injector placement,...) that will require completely different timing.

Even on the same engine, you may need significantly different timing depending on the RPM and load since you may not want to inject at the same timing depending if you want to maximize economy or power. And if you have staged injection with low and high injectors, the propagation time will mean significant timing change.

So having only a partial cycle range for injection timing is an unacceptable limitation in my view that will come and bite you in the ass at one point or another. Even limiting the ignition range to 50 degrees doesn't make sense if you want to do some form of anti-lag at some point. You're better off planning to be able to cover the whole cycle range for any timing value right now rather than dealing with a completely arbitrary and potentially crippling limitation later.

So with that in mind, the siamese port injection timing range becomes irrelevant since you should be able to cover the entire cycle. One thing that will be necessary is to have different timing on the inner and outer cylinders. It might even be good to be able to have different timing references for the two, for example middle-of-pulse for one and end-of-pulse for the other, but that's not essential.

Another thing that doesn't make sense is this:
Fred wrote:
  • Dwell is based on battery voltage and can be exceeded to aid scheduling, dwell will always be as requested or more
  • Some sort of minimum spark duration window such that a maximally long spark can complete before dwell resumes
The 2 statements contradict each other at some point. You can't have dwell always as requested or more and have a minimum spark duration always respected. And if the list shows the order of priority then it doesn't make sense since you can't always respect dwell duration and continue to have a running engine under certain situations. At some point you will need to reduce dwell to even be able to have spark. And saying that this is a badly designed engine is not an excuse for not reducing the dwell and the minimum spark duration when you run into a spark event collision. Or at least mention what will need to be done in that case such as spark cut. But that would be a poor option in my view; it would be much better to share the available time between the spark duration and dwell rather than introduce an artificial and unexpected spark cut.

Jean
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Special Requirements For Timing/Output Event Scheduling

Post by Fred »

jbelanger wrote:Limiting the injection timing to anything but the full 720 degrees does not make any sense.
Who is limiting it? :-p
With the same trigger pattern, and therefore I assume the same reference angle, you can have vastly different engine configurations (intake manifold geometry, injector placement,...) that will require completely different timing.
You assume FAR too much, that's not like you, I must have pissed you off recently, sorry if so.

Here is how it works:
  • A decoder has it's own zero angle, and total angle range (unique crank wheels are 360, unique cam are 720, dizzy style are 720/cyls, etc)
  • There is a full cycle decoder to engine offset angle to align the decoder with the engine (to bring number 1 TDC to zero degrees for a typical piston engine)
  • Each channel (and in future virtual channel) has its own full cycle centre angle (to find each cylinder's TDC for ignition use, or some arbitrary centre/base for fuel use)
  • Timing input from various sources is compounded upon this base, the main one being table tuned angle, which is what I was asking about, whether it was clear or not.
Even on the same engine, you may need significantly different timing depending on the RPM and load since you may not want to inject at the same timing depending if you want to maximize economy or power. And if you have staged injection with low and high injectors, the propagation time will mean significant timing change.
Now we're getting to it, talk ball-park numbers, I'm interested! Hmm, I just realised who else I should link here!
So having only a partial cycle range for injection timing is an unacceptable limitation in my view that will come and bite you in the ass at one point or another.
We're only talking about timing relative to an arbitrarily per channel centre timing which is full cycle (720, 460, 180, 90, etc), for a given decoder. And by that I mean, it's configurable independent of the decoder, but must not exceed the full angle of the decoder that is in use.
Even limiting the ignition range to 50 degrees doesn't make sense if you want to do some form of anti-lag at some point.
Again, see above, this is not the total range, just the NORMAL case tunable range, maybe a little ATDC timing is desirable at low rpm and high load, perhaps it should be the 63.75 option with 5 or 10 ATDC and the balance BTDC? Things like antilag, spark retard limiters, etc can and will use their own separate offsets to achieve this and do not need to care about the limited range of the tunable dynamic adjustment tables.
You're better off planning to be able to cover the whole cycle range for any timing value right now rather than dealing with a completely arbitrary and potentially crippling limitation later.
It can, but last time I checked, if you fire a plug on the intake cycle it blows your intake manifold off ;-) The timing range questions are mainly about fuel injection timing, which I'm not an expert on, esp not siamese, which you ARE an expert on.
So with that in mind, the siamese port injection timing range becomes irrelevant since you should be able to cover the entire cycle.
Nothing is irrelevant, please please, give me some info on this, even if it is an RTFM and link! :-) Before designing something you should fully understand it, and that is what this thread is about. There is working code, but it is inadequate in various ways, and before I change it further I want to know as accurately as possible which direction I should be heading in. Your stuff is the weirdest stuff, so please, educate me on centres, timing range, etc, anything and everything. You started below, I'll try to get you to clarify that now.
One thing that will be necessary is to have different timing on the inner and outer cylinders.
Can you do a detailed post on the different possible configurations? It's been a long time since we discussed this, but if you want it doable with FreeEMS, now is the time to speak up and lay down detailed requirements. We're talking 2 injectors or 4? If 2 I would assume their timing would be different, but the same relative to the valve movements. So we must be talking 4, at which point I would assume that each of the four channels would be centred independently and tunable around that centre in two pairs?
It might even be good to be able to have different timing references for the two, for example middle-of-pulse for one and end-of-pulse for the other
Sure, that would be on a per channel/virtual channel basis anyway, consider it done.

What else? How much range??? :-)
Another thing that doesn't make sense is this:
Fred wrote:
  • Dwell is based on battery voltage and can be exceeded to aid scheduling, dwell will always be as requested or more
  • Some sort of minimum spark duration window such that a maximally long spark can complete before dwell resumes
The 2 statements contradict each other at some point. You can't have dwell always as requested or more and have a minimum spark duration always respected. And if the list shows the order of priority then it doesn't make sense since you can't always respect dwell duration and continue to have a running engine under certain situations. At some point you will need to reduce dwell to even be able to have spark. And saying that this is a badly designed engine is not an excuse for not reducing the dwell and the minimum spark duration when you run into a spark event collision. Or at least mention what will need to be done in that case such as spark cut. But that would be a poor option in my view; it would be much better to share the available time between the spark duration and dwell rather than introduce an artificial and unexpected spark cut.
I've added an "unless otherwise configured" clause to remove the contradiction, thanks! :-) Yes, I'm well aware of shitty distributor car limitations, I'm driving one on FreeEMS every day ;-)

Mild launch and 1st/2nd gear pulls to a low end-of-torque at 5500 (redline is 6k but there was never any point revving it there...) :

Image

Excuse the noise, it's for a known and intentional reason :-)

Thanks for your input so far, I hope we can get some better info and clarifications on the siamese situation in the next post!

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
em_knaps
QFP80 - Contributor
Posts: 99
Joined: Wed Jan 16, 2008 11:09 am
Location: New Zealand

Re: Special Requirements For Timing/Output Event Scheduling

Post by em_knaps »

Chaps,
for give my noobness, if i make a nonsense statement please humor me.

"Timing tunable precision = 0 - 51 in 0.2 degree steps, OR, 0 - 63.75 in 0.25 degree steps, OR, 0 - 127.5 in 0.5 degree steps,"

is this an 8 bit table? what are the options with a 16 bit table?

otherwise the 63.75dg option seams the most practical, with maybe 5-10 deg of that in ATDC,


As for injector timing, and this does not take into consideration Siamese ported engines,

timing the injector PW end with the intake valve closing seams to me the only sensible option,

another option would have it centered untill such time as the PW time is larger than the valve opening time at which point it could start earlier, but never end later, having fuel pool on a valve that has just closed seams pointless, having it pool on a valve that is about to open seams more sensible.
this could perhaps be hard written and not adjustable as I think it is the BEST.....
therefore inputs could be limited to valve opening and closing angles

this is all that came to mind just having speed read the last posts.
more may pop into my head as it churns there during the day

Daniel.
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Special Requirements For Timing/Output Event Scheduling

Post by Fred »

em_knaps wrote:having fuel pool on a valve that has just closed seams pointless, having it pool on a valve that is about to open seams more sensible.
Consider that the intake valve is hot, and that if we had an ideal engine, we would inject vapour, not liquid fuel, then realise that the longer the fuel sits pooled on the valve the more vapourised it will be, some OEMs do this on purpose, for emissions and idle quality. Once up to speed, I imagine things would work better going through an open valve than a closed one until PW is too large. Also, recognise that at high loads the injector is open for the entire 720 degrees and the timing makes fuck all difference. This is all offtopic anyhow, the main question is about what things are required to fulfill the various requirements with one piece of code for all timed output events, and the range of timing adjustment necessary to achieve a good tune on all engines.

Rotary enthusiats? How much timing do those things like to get?

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Special Requirements For Timing/Output Event Scheduling

Post by Fred »

Jean, due to a lack of reply, I took some dev time out and did some reading (not the most productive use of my time, really, but...). I found this link from your site:

http://www.starchak.ca/efi/siamese.htm

And from reading it, and looking at this image:

Image

It would appear that you are fairly restricted in where you can inject (the entire problem domain is that, actually) and thus your timing requirements are more narrow than some other setups potentially. It would seem like having the start of injection for the "outside valve" fixed or close to fixed would be optimal, and dump in the other fuel opposite that in the cycle. This could easily be achieved with a limited timing table and per channel/event base timing figure.

If any of that is untrue, please correct me! When it comes to the mini A series, you're not only my only advisor, you're also the only person that cares! (more or less) :-)

However:

I just had a chat with mops about this and he pointed a few things out.

1) For a standard port injection engine the "best" timing is as follows:

If pw is less than valve open time, start injecting with the valve opening and finish mid intake.
If pw is more than the valve open time, finish injecting with the valve closing and start wherever is required.

2) The timing resolution required for fuel injection is MUCH less precise than for ignition, SO, the 0 - 255 for an 8 bit table could be not only scaled down, but also up, perhaps a change of 1 in the table could mean 3 degrees timing change, or 1, or 0.25, or whatever.

And I realised the following while chatting:

3) The fuel timing tables could be just "timing" and unit-less, with a configurable scale and offset variable for fueling tables. Then you could get things like "128 to -127" or "0 - 510" or whatever suits you. You'd have to think a bit to tune them unless the display sw could scale the values for you, but other than that, it's the best of all worlds.

4) The fuel timing could have two small 2d tables, one for timing vs RPM and one for timing vs PW or %DC

5) Rather than having "sched end, middle, start" i'll have "sched X% of pw" with 0 = start, 50 = centre, 100 = end, and so on. This could be in two small tables based on RPM and PW or %DC too.

The RPM tables could account for time delays (outboard injectors, etc), and the PW or %DC ones could account for where the pulse happens relative to the valve opening.

Thoughts?

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
jbelanger
LQFP144 - On Top Of The Game
Posts: 387
Joined: Sat Feb 23, 2008 8:58 pm
Contact:

Re: Special Requirements For Timing/Output Event Scheduling

Post by jbelanger »

Fred wrote:Jean, due to a lack of reply, I took some dev time out and did some reading (not the most productive use of my time, really, but...). I found this link from your site:

http://www.starchak.ca/efi/siamese.htm

And from reading it, and looking at this image:

Image

It would appear that you are fairly restricted in where you can inject (the entire problem domain is that, actually) and thus your timing requirements are more narrow than some other setups potentially. It would seem like having the start of injection for the "outside valve" fixed or close to fixed would be optimal, and dump in the other fuel opposite that in the cycle. This could easily be achieved with a limited timing table and per channel/event base timing figure.

If any of that is untrue, please correct me! When it comes to the mini A series, you're not only my only advisor, you're also the only person that cares! (more or less) :-)
The illustration above is good for somethings and the work done by Marcel was a good start but it is somewhat outdated. There is a need to have different fueling for the inner and outer cylinders since the wall wetting contribution is not the same for both for the same reason you need to time the injection: the inner cylinder will receive up to 3/4 of the wall wetting fueling. And since you don't have the same pulsewidth, you also don't necessarily want the same timing especially if you want to minimize wall wetting and still leave some margin between the 2 pulses. So if you want to take all that into consideration, you need full sequential injection with the obligatory cam sensor.

Since the fuel transit time is not constant under all loads and RPM you won't have a fixed timing for the outer cylinders and the range is considerable from work done by people on the turbominis forum (more than 90 degrees over the load/RPM range IIRC).

And from the graph and what I mention above, you may be able to understand why I was mentioning being able to specify the timing with respect to the middle of the pulse for the outer cylinders and the end of the pulse for the inner cylinders. But again that is not a necessity but a nice to have.

There is also another mode that is possible where you actually merge the 2 pulses into a single one covering the entire open valve events. This has the advantage of allowing a single opening event to maximize the injection window size. And you can take advantage of the open valve overlap between the 2 cylinders and time the injection pulse to distribute the fuel equally between the cylinders (or more precisely in a matter to equalize AFR). The disadvantage is that with cams with a lot of overlap, a significant amount of fuel may go to the exhaust during the intake event overlap. And at low load/RPM most of the fuel would be injected during the intake overlap which might lead to instability so it is necessary to use 2 distinct pulses under those conditions.

I should also mention that the way to tune the injection timing is to have 2 WBO2 sensors: one in the outer exhaust branch and one in the middle exhaust branch (which services the 2 inner cylinders). This way you can monitor the AFR to tune fueling and timing. If you inject outside the injection window for the outer cylinders, the inner cylinder will get richer while the outer cylinder becomes leaner. So you adjust timing to minimize the AFR difference between the cylinders and then fueling to compensate for the different wall wetting contributions. And finally you adjust fueling to have the correct AFR. And this has to be done at different load and RPM sites.
Fred wrote:However:

I just had a chat with mops about this and he pointed a few things out.

1) For a standard port injection engine the "best" timing is as follows:

If pw is less than valve open time, start injecting with the valve opening and finish mid intake.
If pw is more than the valve open time, finish injecting with the valve closing and start wherever is required.
That is a very limited definition of best timing and is optimized for maximum power and some engine configurations. There are a lot of other strategy for maximum economy (inject on a closed valve, for example) and other engine configurations. Limiting the code to satisfy the above would be very shortsighted.
Fred wrote:2) The timing resolution required for fuel injection is MUCH less precise than for ignition, SO, the 0 - 255 for an 8 bit table could be not only scaled down, but also up, perhaps a change of 1 in the table could mean 3 degrees timing change, or 1, or 0.25, or whatever.

And I realised the following while chatting:

3) The fuel timing tables could be just "timing" and unit-less, with a configurable scale and offset variable for fueling tables. Then you could get things like "128 to -127" or "0 - 510" or whatever suits you. You'd have to think a bit to tune them unless the display sw could scale the values for you, but other than that, it's the best of all worlds.

4) The fuel timing could have two small 2d tables, one for timing vs RPM and one for timing vs PW or %DC

5) Rather than having "sched end, middle, start" i'll have "sched X% of pw" with 0 = start, 50 = centre, 100 = end, and so on. This could be in two small tables based on RPM and PW or %DC too.

The RPM tables could account for time delays (outboard injectors, etc), and the PW or %DC ones could account for where the pulse happens relative to the valve opening.

Thoughts?

Fred.
While I agree that you could have arbitrary angular units and present them as degrees through an interface translation, I don't agree with much of the rest. I think that all timing information should be 16 bit. Having 8-bit data will create annoying side effects of not being able to enter the values you want. You could save memory by having smaller tables since some effects are quite linear without creating these issues. But I don't think you can really cover everything correctly with two 2D tables (arrays) instead of one 3D table.

And I don't like the sched X% of pw instead of start, end, middle of pulse. The timing strategy will definitely be based on start, middle, or end of pulse depending on what you chose or what you need. And you don't want the timing to change because the pulse width changes but because the load and RPM changes. And you want that to be clear when looking at the interface and log which doesn't seem to be the case with what you propose but I'm still not clear on how it would work. But a timing table with load vs RPM axis together with a start, middle, end of pulse setting is definitely clear and unambiguous.

Jean
User avatar
BenFenner
LQFP144 - On Top Of The Game
Posts: 360
Joined: Wed Jul 09, 2008 3:15 pm

Re: Special Requirements For Timing/Output Event Scheduling

Post by BenFenner »

Jumping in here without all the facts or reading everything.

We're talking about the main timing table only, yes? (Anti-lag being add/subtract OR absolute elsewhere.)

Re: Timing range.
Plenty of uses for timing more advanced than 50 degrees BTDC during cruising for high fuel efficiency. I believe I have 55 on my timing map right now in spots. Plenty of uses for timing more retarded than 0 degrees BTDC! Easily required for any high flowing turbo build.

Don't limit the timing range at all. Allow the full monty. Am I not even on topic?

I think a normal user might be happy with 60 degrees BTDC to 20 degrees ATDC if that's what you're thinking. And normal users in my opinion would require the ability to trim ignition timing on a per cylinder basis. I consider myself a normal user.

That is all.
User avatar
BenFenner
LQFP144 - On Top Of The Game
Posts: 360
Joined: Wed Jul 09, 2008 3:15 pm

Re: Special Requirements For Timing/Output Event Scheduling

Post by BenFenner »

I've just read some more.
Fred wrote:0 - 127.5 in 0.5 degree steps
If you're keeping it 8-bit then this is my preference. 0.5 degree resolution is plenty decent, and the range is really required. You could squeeze 55 degrees BTDC through 8.75 degrees ATDC in with the "0 - 63.75 in 0.25 degree steps" scheme and maybe that would be acceptable. What about 0.3 or 0.4 degree increments? Slower math?
Fred wrote:Do we need negative base timing ever? (antilag, retard limiters, etc not included)
Yes. Absolutely yes. Aside from the ridiculous turbo DSM guys and their ATDC timing in boost, those of us with high flowing setups need negative timing. I'm at 11 psi. At around 16 psi I'd start to need negative numbers and 16 psi is very common my turbo.
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Special Requirements For Timing/Output Event Scheduling

Post by Fred »

We're talking about the main timing table only, yes? (Anti-lag being add/subtract OR absolute elsewhere.)
Yes, and: Good idea on the absolute/+/- thing.

With all due respect, Ben, (quite a lot) if you need TDC or ATDC timing in a normal load region, your setup SUCKS, and by setup, i mean the combination of the following:
  • combustion chamber design (inc piston dome)
  • fuel octane level
  • cooling system efficiency
  • boost level
  • compression ratio
  • AFR
16psi on 10:1 comp with 93aki/98ron would STILL not need TDC timing, doing so would cook your head and turbo, especially when you consider the flame propagation speed vs the RPM you're talking about having boost in. (typically higher revs). The SR20 chamber is very nice, it's my favourite part of that engine ;-)

TDC timing with HUGE boost and high comp on pump gas, sure, but these people could find they make more power with less boost and less stress and more advance, the rest the same...

The main area for TDC or ATDC timing is at VERY low revs and very high loads, 100kpa at 300rpm requires some retarded timing.

Re 0.3 or 0.4 or other increments, sure, this is an OK idea, but it will result in the inability to choose exact degree timing figures at various levels. I'd prefer something that divided into 1 cleanly inside our precision level.

Right now I'm leaning towards 10 - 53.75, but I'd be just as happy with 8.75 to 55, really. I've got to ask, though, would the difference between 53.75 and 55 be measurable? How many kpa is that at? How can your octane level support that, and NOT support reasonable in boost timing???...

I still need to find time to respond to your post, Jean.

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
Post Reply