advice needed for arduino as diesel injection brain...

japie:
Only I don't think I can share the timer between all 4 injectors

If you have an even firing engine then you could just generate the interrupt at the total injection frequency rather than the per-cylinder frequency, and cycle through the cylinders in the appropriate order.

I've missed/forgotten how you're going to synchronise the injection with the engine physical position. Do you already have the crank position and engine phase sensing sorted out? Presumably you'll have some sort of phase locked loop tracking where (you think) the engine is.

@japie

Could you post the code that you used to find this

Very disturbing is the fact that reading analog and writing to pwm takes over 200uS,

I am not saying your wrong but, I can bench mark the Uno, Teensy 3.0, and the Due for comparison. I also have a Maple clone but, it is not as easy for me to put it to good use.

With some clever coding and dividing those 2 actions the times can probably be brought down but the main issue is that the time critical stuff is done in the loop, it should be real time...

The injection moment is in sync with the engine trough an alternator, I have a pcb with 4 IR transmitters on it and one with 4 receivers, between those there is a rotating plate with a little hole so at every TBP one of the receivers gets a pulse.
The casing with the PCB's in it can be attached to the throttle to create more advance when giving more throttle. (the above system has been used in the past by me and works flawless)
Nothing fancy, if receiver1 gets a pulse injector1 has to spray.

japie:
The injection moment is in sync with the engine trough an alternator, I have a pcb with 4 IR transmitters on it and one with 4 receivers, between those there is a rotating plate with a little hole so at every TBP one of the receivers gets a pulse.

I don't know what a TBP is. When you say alternator, do you mean the alternator that provides electrical power for the vehicle? How is that connected to the crank?

CrossRoads:
For sure there are only 2 External Interrupts.
But almost every pin also supports PCINT, whichNick Gammon has a great page on and even shows them as being a little faster:
Gammon Forum : Electronics : Microprocessors : Interrupts

Nice link, thanks. Just nit-picking, but I believe that Timer1 Capture is also an external interrupt pin, making for a total of 3.

@cyclegadget

I did timings by adding stuff between lines like:

int readthrottle = micros();

and at the end of the loop print all of them in one line, substracting manually gave me the readings...

@PeterH

Sorry 4 misleading you, I am pretty busy with labour so most of the time I do computer stuff early in the morning before going to work.
I meant TDP or TDC: Top Dead Center, when the piston is in it's most uprising/compression point.
Also I don't mean alternator but distributor.
So I can give an electronical pulse at exactly the moment I want to inject, in the past I used almost the same setup with an NE555 as timer for injection duration but since I got involved with the arduino while building a data logger I thought it was a nice idea to use it for injecting.
In my old setup the distributor :wink: was connected to the throttle so when giving more throttle the timing would advance from -10 to -50 degree TDP.

Actually there is nothing wrong with that, in my current conventional plunger Bosch A-pump I modified the plungers by grinding the top in an angle and the helix flat so when giving more throttle injection moment will advance. (normally the top of the plunger is flat, halfway down there is a groove in an angle (the helix) that is connected via another groove to the top, when the plunger moves upwards the helix will pass a hole and bleeds fuel from the top so at that point the injection stops. Since that helix is under an angle you can turn the plunger so the effective stroke of the plunger is extended and therefore delivering more fuel. http://transportation.centennialcollege.ca/oduffy/fuels/HD%20fuels%203/inline.pdf)

@afremont

The other timers also all connect to a pin so that would mean they are not useable.
When looking at the example code it looks like the timers can be used without using the pin attached to it, no clue.
Also no clue how to use the other 3...

If I can't find out I will use a microsecond delay, bad coding leaving the arduino doing a lot of nothing but see no reason why it should not work.

Hello there, got the basic timer code working:

#include "TimerOne.h"
#include "TimerThree.h"

int ledPin = 13;
volatile int state = LOW;
volatile int InjectionCycle1  = false;

void setup() 
{
  pinMode(ledPin, OUTPUT);
  attachInterrupt(0, Inject1, RISING); // interrupt 0 = pin 2
  Timer1.initialize(1000000);
  Timer1.stop(); //stop the counter
  Timer1.disablePwm(9); // disables PWM on pin 9
  Timer1.disablePwm(10); // disables PWM on pin 10
  Serial.begin(9600);
}
 
void loop()
{
}

void Inject1()
{
  if (InjectionCycle1 == false)
  {
    Serial.print("start injection cycle: ");
    Serial.println (millis());
    InjectionCycle1 = true;
    Timer1.setPeriod(1000000);
    Timer1.attachInterrupt(OpenInjector1);
  }
}

void OpenInjector1()
{
  if (InjectionCycle1 == true)
  {
    Serial.print("open injector: ");
    Serial.println (millis());
    digitalWrite(ledPin, HIGH);
    Timer1.stop();
    Timer1.detachInterrupt();
    Timer1.setPeriod(2000000);
    Timer1.attachInterrupt(CloseInjector1);
  }
}

void CloseInjector1()
{
  if (InjectionCycle1 == true)
  {
    Serial.print("close injector: ");
    Serial.println (millis());
    Serial.println ("");
    digitalWrite(ledPin, LOW);
    InjectionCycle1 = false;
    Timer1.stop();
    Timer1.detachInterrupt();
  }
}

Tested this and it works as expected, next step integrate all other stuff, will port when I have it complete.
In this setup the timer replace delay. (and is not stalling the loop like delay)

edited since in first instance I used Timer1 and Timer3 both for both delays:
Using one timer for the cycle works also good so I can use Timer1 for cylinders 1 and 4 and Timer3 for cylinders 2 and 3.
Since the firing order is 1-3-4-2 there is 180 crank degree extra time between interrupt firing cycles, better would be a per cylinder dedicated timer but rewriting the Timer1 code for the extra timers on the mega is out off my league...

Finished the total code for the injection system based on 2 timers.
Included idle revving, soft rpm limit for over-revving and hard rpm limit in case of driveline breakage.

cuprumV2.ino (10.7 KB)

Japie, where did you download the timerone and timerthree libraries?

I was wanting to do some testing with your code but, I think maybe I am missing the correct library.

I am glad you have been sticking with your project and making it work!

Also, I want to say that you should speed up your serial baud rate to 115,200, which is the maximum that the IDE can use. If you have a terminal program, you maybe able to choose a much higher rate. Serial communication can really hurt the performance of your sketch. I will make a sketch to show you the difference. I will post it here soon.

Test code using 9600 baud:

int ledPin = 13;

//variables to keep track of time of injection code////
unsigned long time1 = 0;
unsigned long time2 = 0;


void setup() 
{
  pinMode(ledPin, OUTPUT); 
  digitalWrite(ledPin, LOW);
  Serial.begin(9600);
}

void loop()
{

  digitalWrite(ledPin, HIGH);
  time1 = micros();
  Serial.print("light the LED for all to see! ");
  Serial.println(time1);

  Serial.print("Turn off the LED it does not need to be ");
  digitalWrite(ledPin, LOW);
  time2 = micros();
  Serial.println(time2);

  Serial.print("total time = ");
  Serial.print(time2 - time1);
  Serial.println("micros");
  delay(5000);  
}

Typical output in micros():

light the LED for all to see! 35358256
Turn off the LED it does not need to be 35373908
total time = 15652micros

Using 115200 baud:

light the LED for all to see! 35029036
Turn off the LED it does not need to be 35030356
total time = 1320micros

Removing all but total time print, code:

int ledPin = 13;

//variables to keep track of time of injection code////
unsigned long time1 = 0;
unsigned long time2 = 0;

void setup() 
{
  pinMode(ledPin, OUTPUT); 
  digitalWrite(ledPin, LOW);
  Serial.begin(115200);
}

void loop()
{
  digitalWrite(ledPin, HIGH);
  time1 = micros();

  digitalWrite(ledPin, LOW);
  time2 = micros();

  Serial.print("micros = ");
  Serial.println(time2 - time1);

  delay(5000);  
}

results:

micros = 12
micros = 12
micros = 8
micros = 8
micros = 8

Hi cyclegadget,

The timer libs came from the playground: Arduino Playground - HomePage

I know about the serial port speed but I have an arduino data logger spitting out it's reading true the serial port to my FriendlyARM dashboard.
The arm reads the serial port with a bash script (simple cat) and writes the data on the screen, when using 115200 I ran into problems on that so I stepped back in speed and somehow kept that for other projects...

If all works out well I remove the serial stuff completely...

japie:
Hello there, got the basic timer code working:

#include "TimerOne.h"

#include "TimerThree.h"

int ledPin = 13;
volatile int state = LOW;
volatile int InjectionCycle1  = false;

void setup()
{
  pinMode(ledPin, OUTPUT);
  attachInterrupt(0, Inject1, RISING); // interrupt 0 = pin 2
  Timer1.initialize(1000000);
  Timer1.stop(); //stop the counter
  Timer1.disablePwm(9); // disables PWM on pin 9
  Timer1.disablePwm(10); // disables PWM on pin 10
  Serial.begin(9600);
}

void loop()
{
}

void Inject1()
{
  if (InjectionCycle1 == false)
  {
    Serial.print("start injection cycle: ");
    Serial.println (millis());
    InjectionCycle1 = true;
    Timer1.setPeriod(1000000);
    Timer1.attachInterrupt(OpenInjector1);
  }
}

void OpenInjector1()
{
  if (InjectionCycle1 == true)
  {
    Serial.print("open injector: ");
    Serial.println (millis());
    digitalWrite(ledPin, HIGH);
    Timer1.stop();
    Timer1.detachInterrupt();
    Timer1.setPeriod(2000000);
    Timer1.attachInterrupt(CloseInjector1);
  }
}

void CloseInjector1()
{
  if (InjectionCycle1 == true)
  {
    Serial.print("close injector: ");
    Serial.println (millis());
    Serial.println ("");
    digitalWrite(ledPin, LOW);
    InjectionCycle1 = false;
    Timer1.stop();
    Timer1.detachInterrupt();
  }
}




Tested this and it works as expected, next step integrate all other stuff, will port when I have it complete.
In this setup the timer replace delay. (and is not stalling the loop like delay)

edited since in first instance I used Timer1 and Timer3 both for both delays:
Using one timer for the cycle works also good so I can use Timer1 for cylinders 1 and 4 and Timer3 for cylinders 2 and 3.
Since the firing order is 1-3-4-2 there is 180 crank degree extra time between interrupt firing cycles, better would be a per cylinder dedicated timer but rewriting the Timer1 code for the extra timers on the mega is out off my league...

When I want to run this, I get: Timer1 was not declared in this scope.
I'm very new to arduino and elektronics, sorry.

And Japie I found more stuf injectors and pump. I even have a pump and four of the six injectors, aextra Uno an a Mega to start with.

Panther95

Hello Panther, did you install the timer libs?

For this project you need a mega and lucky you it seem to have 6 hardware interrupts so you should be good.
Must say that I am not sure at all it will work, currently I finished my output dirver board (the 4 injector drivers and 1 PWM output for the pump pressure) but the PWM doesn't work. (the arduino does drive PWM but I made an error on the PCB)

Got my tiny automotive pump connected to an 0,75Kw motor but when making pressure it stalls (so the pump will ask for over 2HP I think) I will set it up in my lathe which should be powerfull enough.
Since the PWM doesn't work I use a car battery and some big fat resistors to control pump pressure, from the past I know that with 3V it delivers about 600bar and with the full battery load (13.8V) over 2300bar.

Also have some trouble with the injectors, they have been laying in stock for 2 years and they are jammed despite being filled with diesel. (hardware troubles it is, got one going now, will open them this weekend I suspect the diesel has turned into grease :wink:

The arduino addon hardware I am making in Fritzing, one output board and one input board, when both finished and working I will post the files here to, OK?

@Panther
@anybody_else, sorry for being off-topic in an arduino forum...

Found some documentation about the parts I use for the PSA 2.0Hdi engine (RHY type) with Bosch CR system:

Pump CR/CP1S3/R65/10-16S
According to a benchmark from a pump testing/overhauling company this pump delivers; 1350bar@2000rpm - 1200cc/min. In conventional pumps we speak off cc. injection amount per 1000 injections so assume we run 1000 rotations so the pump delivers 600cc.
Since we have a four stroke four cylinder that means that one pump rotation we have to feed 4 cylinders, 600/4=150cc per injector at 1000rpm but that means we have to inject 90 pump degrees/180 crank degrees to get it all in.

A bigger one is: CR/CP3S3/L110/30-789S: 1350bar@2000rpm - 2000cc/min. (AUDI 4.x/Iveco/Mitsubishi/MAN/Sisu)

Also found scope readings from the injectors:
@idle 200uS pre-inject, 2.2mS wait and 400uS main injection.
@3000rpm one injection 400uS
So it seems in automotive use we don't use injection duration for power...

And scope readings from the pump PWM (1khz):
@2000rpm 25% duty cycle
@3000rpm 35% duty cycle
Accelerating 45% duty cycle
Which is also strange, one would expect 100% when power is needed.

It seems all knowledge gathered with conventional injection is off, I know I inject 160cc. currently over 35 degree crank duration. (45btdc till 10btdc)

Wrote a test program with timer pulses relative to pump rpm (must see first how strong/fast my lathe is with the pump attached) that injects 1000 times 500uS with PWM@50% and will collect the amount of fuel while monitoring pump pressure sensor..

If someone takes offense about me posting arduino-irrelevant information please let me know... (but from my point of view it belongs to the "package" and maybe someone not familiar to diesel injections creates a new and fresh point of view)

A small update for whoever is following this subject.
2 weeks ago I finished the injectordriver addon board for the mega.
I used the LM1949 injector driver but since it was intended for 1A gasoline injectors it is not good enough for the 12A common rail injectors.
There is a resistor used for measuring Amps which is stock at 0.1ohm and currently I am using 0.005ohm and got 6-10 amps running or so, I did try to use 2 of those resistors parallel but that didn't made a difference so I think the chip thinks it's enough.

However the injectors are working!
Despite the opening "lag" of ~450uS they open and close at my arduino's wish and command!
The lag can be easily worked around in the main program since I am using a delay before injecting, it means that delay will become 450uS shorter...

I did some tests:

And summed them up:

One of the key factors for getting a well-behaved engine is to manage the fuel injection quantity accurately and repeatably. That's why people use fancy peak-and-hold drivers and voltage compensation and fuel temperature compensation and so on. A driver that barely manages to open the injector is going to put you at a real disadvantage. It sounds to me as if your driver is not providing as much current as you need, and if so you should consider uprating it.

That is correct Peter, not enough amps.
Unfortunatly the LM1949 can't do better but maybe I can fool it with a voltage divider but I am not going to test that with my good injectors...

The LM1949 is a peak and hold driver, peak is 4 times the hold and currently the driver is delivering 4 times the amps that where needed to open the injector but when I look at some scope reading I found on the net of a running engine with those injectors I am still half way when I compare it to my scope. (but mine wasn't that expensive and is a bit hard to read :wink:

Jape, how is your progress?

I'm interested in the whole concept. If its up and running, can you report on the conclusion.

Thanks