Building a very basic car injection computer.

Hi everyone ! I'm a new learner on this platform but I think I got the hang of it !

I am trying to make a computer for an old car to inject gas simultaneously on the central injector. I made a hole with a magnet inside the crankshaft pulley 40 degrees BTDC to tweak the timing when I will be ready to code it.

When the engine spins, the magnet cause the hall effect sensor to be LOW but momentary. I'm averaging the time it takes to trigger again and dividing by the number of cylinders to get fuel injected at the right time.

unsigned long timerstart;
unsigned long timerstop;
unsigned long trigger;

int inj = 2;
int ckp = 3;
int current = 0;
int adjust = 0;
int cylinders = 4;
int injtime = 2;

void setup()
{
Serial.begin(9600);
pinMode(inj, OUTPUT);
pinMode(ckp, INPUT);
}

void loop()
{
timerstart = millis();

if(digitalRead(ckp) == LOW)
{
timerstop = millis();
trigger = timerstop - timerstart;
adjust = injtime * cylinders;
trigger = trigger - adjust;
trigger = trigger / cylinders;

while(current != cylinders)
{
digitalWrite(inj, HIGH);
delay(injtime);
digitalWrite(inj, LOW);
delay(trigger);
current = current + 1;
}
current = 0;
}
}

Is my code OK ? I can't test it on my vehicle because I'm out of town but I will be ready to modify my code.

EDIT : I see where I went wrong ! If the car accelerates, the program will not be able to keep up because the delay function stops the program from getting my hall effect input !

I think your program needs more inputs:

How much air is flowing into the engine? More air means more gas needed to keep the same mixture.

What is the current throttle position? Pushing the throttle should inject more gas to produce more power but not more gas than can be burned with the air flow.

The throttle position sensor and MAP/MAF sensor are not required to run an engine. I'm building a VERY basic injection system to show to students the effect of timing and duration of injection on a scope. And later incorporate ignition timing because at idle the car should run just fine. And it's a TBI, nothing very fancy there.

expertmax:
The throttle position sensor and MAP/MAF sensor are not required to run an engine. I'm building a VERY basic injection system to show to students the effect of timing and duration of injection on a scope. And later incorporate ignition timing because at idle the car should run just fine. And it's a TBI, nothing very fancy there.

What's all this about dividing by number of cylinders to inject at the 'right time'? You're trying to do sequential injection with TBI?

I don't understand what you mean by injecting gas 'simultaneously'.

If you have any hope of managing the spark by this solution, you really want to use a trigger wheel with an MVR pickup, not just a hall effect sensor.

You seem quite positive that you don't need a throttle or load sensor, but you need to control the fuel according to throttle and load if you want the air fuel ratio to be anywhere near correct. Of course, if you just want to bung some fuel in and have the engine not actually stall, you can afford to be crude about it. But that depends what you're trying to achieve. Maybe not stalling is all you need.

The spark is controlled by a distributor with an internal breaker point so no need to code it.

Now my issue is that the car will not rev up because I use "delay()". What can I do to prevent this ?

I'm not trying to make a street car I have an engine on a engine mount that is laying around and I want to fire it up a bit, only for fun. The car should idle fine without any air/fuel ratio because I am not under load.

Allright can someone tell me if my code makes sense ! When the hall effect is triggered, the duration of the total rotation is calculated, then it is averaged (so it fires the injector 2 times each hall effect trigger.

unsigned long timerstart;
unsigned long timerstop;
unsigned long trigger;
unsigned long timenow;
unsigned long timethen;

int inj = 2;
int ckp = 3;
int current = 0;
int adjust = 0;
int cylinders = 4;
int injtime = 1;

void setup()
{
  Serial.begin(9600);
  pinMode(inj, OUTPUT);
  pinMode(ckp, INPUT);
}

void loop()
{
  timerstart = millis();
  timethen = millis();

  if(digitalRead(ckp) == HIGH)
  {
    timerstop = millis();
    timenow = millis();

    trigger = timerstop - timerstart;
    cylinders = cylinders / 2;
    adjust = injtime * cylinders;
    trigger = trigger - adjust;
    trigger = trigger / cylinders;

    while(current != cylinders)
    {
      if(timenow - timethen < trigger)
      {
        digitalWrite(inj, HIGH);
        delay(injtime);
        digitalWrite(inj, LOW);
        current = current + 1;
      }
    }
    current = 0;
  }
}

I don't think that will work well. You are blocking the whole sketch while you trigger all the injection events, which presumably will take a sizeable chunk of the engine cycle.

I haven't followed all the logic you're using to time the injection events, it doesn't look like the sort of thing I was expecting. From a brief glance it look as if all your injection events will happen immediately after each other which is probably not what you intended. What I expected to see is the 'blink without delay' technique used to trigger the start and end of each injection event without delaying the sketch, and while polling those timed events the sketch also polls the crank position sensor and load sensor and derives RPM and the injection trigger pulse from the crank sensor.

In any case, since you have no load sensing and no EGO feedback I don't see anything to control the AFRs so if the fuel is anywhere near correct at idle it will lean out as soon as you open the throttle. Whatever else the sketch does, this will never get the fuelling right.

I suggest you need to have a load sensor, and if you're intending this to have any throttle response you also need a throttle position sensor to trigger your transient enrichment (if you use the TPS as a load sensor too it could serve both functions). Of course you need to map the fuel requirements against rpm and load - and it would be hard to do that without any feedback about the actual AFRs.

This is how I would write code to open an injector for a fixed time when the sensor hits and at intervals to open at the same relative time for the remaining cylinders.

// Constants
const int CYLINDERS = 4;
const int INJECTOR_PIN = 2;
const int SENSOR_PIN = 3;

// Variables
int InjectorOpen_Microseconds = 1000;  // 1 millisecond
volatile unsigned long LastSensorTime = 0;

volatile unsigned long NextInjectorTime;
volatile unsigned long InjectorInterval;
volatile byte InjectorCount;

void setup()
{
  Serial.begin(9600);
  attachInterrupt(1, sensorPulse, RISING);  // Sensor triggers interrupt
  pinMode(INJECTOR_PIN, OUTPUT);
}

void sensorPulse()
{
  unsigned long currentTime = micros();
  unsigned long rotationInterval = currentTime - LastSensorTime;
  LastSensorTime = currentTime;
  NextInjectorTime = currentTime;  // Inject immediately
  InjectorCount = 0;
  InjectorInterval = rotationInterval / CYLINDERS;
}

void loop()
{
  unsigned long currentTime = micros();
  if (currentTime - NextInjectorTime >= 0 && InjectorCount < (CYLINDERS-1))
  {
    digitalWrite(INJECTOR_PIN, HIGH);
    delayMicroseconds(InjectorOpen_Microseconds);
    digitalWrite(INJECTOR_PIN, LOW);
    InjectorCount++;
    NextInjectorTime += InjectorInterval;
  }
}

The injection events don't need to be associated with any cylinders, they just need to spread the fuel out through the engine cycle. In fact the more injection events you have the better fuel/air mixture preparation you'd get. But injectors don't like being used with very short pulses and somewhere around 1ms you'll find the amount of fuel actually injected starts fluctuating because you're getting below the mechanical response time of the injector. The bigger the injectors the shorter the pulse needed and the sooner you'd hit this limit. But if you have an injector with a relatively low flow rate (relative to the engine's fuel requirements) you can probably afford to hit the injector multiple times per injector, and that will give more even fuel distribution.

Still, without any way to detect engine load and no way to vary the fuelling with load and revs, the AFRs are going to be all over the place and it will probably only run at all within a very narrow band of conditions.