Obviously to run the whole thing I need a microprocessor. There are some great products out there to help in a build like this. Most of the work I have done in the past has been using PIC products. This required working in Assembly which I don’t particularly care for. I don’t know what the current state of affairs is with PIC these days so I really can’t say. Fortunately there are a number of suites to build a system using C++ as the programming language. I’ve used both the ST Micro STM32 system and the Arduino based system in various builds. I prefer the Arduino system because a lot of work has been done by other people and various routines are freely available. I also like the Arduino IDE suite. One other important factor is the footprint required. I chose to use two Arduino Nano boards for this build.
Board# | Firmware | Board# | Firmware | Board# | Firmware | Board# | Firmware |
1 | Engine | 1 | Engine | 2 | Monitor | 2 | Monitor |
Pin 1 | NC | Pin 16 | NC | Pin 1 | NC | Pin 16 | NC |
Pin 2 | NC | Pin 17 | NC | Pin 2 | NC | Pin 17 | NC |
Pin3 | NC | Pin 18 | NC | Pin 3 | NC | Pin 18 | NC |
Pin 4 | GND | Pin 19 | MAP In | Pin 4 | GND | Pin 19 | MAP In |
Pin 5 | CYL In | Pin 20 | IAT In | Pin 5 | CYL In | Pin 20 | IAT In |
Pin 6 | TDC In | Pin 21 | OXY In | Pin 6 | Relay 1 Out | Pin 21 | OXY In |
Pin 7 | CPS In | Pin 22 | NC | Pin 7 | Relay 2 Out | Pin 22 | Fuel In |
Pin 8 | Spark Plug 1 | Pin 23 | NC | Pin 8 | Relay 3 Out | Pin 23 | Oil In |
Pin 9 | Spark Plug 2 | Pin 24 | NC | Pin 9 | Relay 4 Out | Pin 24 | ECT In |
Pin 10 | Spark Plug 3 | Pin 25 | NC | Pin 10 | Relay 5 Out | Pin 25 | Idle Control |
Pin 11 | Spark Plug 4 | Pin 26 | NC | Pin 11 | Relay 6 Out | Pin 26 | Idle Set |
Pin 12 | Injector 1 | Pin 27 | NC | Pin 12 | Relay 7 Out | Pin 27 | NC |
Pin 13 | Injector 2 | Pin 28 | NC | Pin 8 | Relay 8 Out | Pin 28 | NC |
Pin 14 | Injector 3 | Pin 29 | GND | Pin 14 | Relay 9 Out | Pin 29 | GND |
Pin 15 | Injector 4 | Pin 30 | +5V In | Pin 15 | Relay 10 Out | Pin 30 | +5V In |
Engine monitor for readout and rpm control
created 2020
by Allen J. Lindfors
*/
#include <digitalWriteFast.h>
//pin assignments
//cycle control
const byte inCYL = 2; // the number of the pin for the input CYL signal
//analog inputs
const int inMAP = A0;
const int inIAT = A1;
const int inOXY = A2;
const int inFuel = A3;
const int inOIL = A4;
const int inECT = A5;
const int idleControl = A6;
const byte idleSetPoint = A7;
//fuel control
const byte fuelOut = 3;
//fast idle start up
const byte outIACV = 4;
//evap canister purge control
const byte purgeOut = 5;
const byte motorCon1 = 6;
const byte motorCon2 = 7;
const byte motorCon3 = 8;
const byte motorCon4 = 9;
//fan control
const byte coolingFans = 10;
bool setEnable, setIACVEnable;
//integer variables for controls
int pulseCYL = LOW; //initialize
int stateCYL = LOW; //initialize
int lastCYL = LOW; //initialize
int countCYL = 0; //initialize
//timing and claculation variables
//timing and sensor values
//Sensor fits variable = C + S*(value)
//IAT
float C1 = 164, S1 = -0.15;
//ECT
float C2 = 164, S2 = -0.15;
//MAP
float C3 = 0, S3 = 0.302;
//single cylinder volume
float cylVolume = 400.0;
//fuel values
float rho = 0.72; //for gasoline
//other densities propane=0.58, ethanol = 0.78, methane = 0.42, methanol = 0.78,
//fuel air value
float fuelAirRatio = 14.7; //for gasoline
//other fuel/air value propane=15.5, ethanol = 9.0, methane = 17.2, methanol = 6.4
//injector flow rate
float flowRate = 225; //injector flow rate in cc/min
//injection calculation values
float massAir, massFuel, injectionTime;
//time values
unsigned long injTime;
unsigned long intervalCYL, startCYLTime, stopCYLTime;
unsigned long currentMillis, previousMillis;
unsigned long interval = 2000;
//read usage variables
float engFuel, fuelPressure, fuelAir, oilPressure;
float airPressure, airTemperature, coolantTemperature;
float engMAP, engIAT, engOXY, engECT, engRPM, engOIL, totalRPM, averageRPM;
void setup() {
// put your setup code here, to run once:
pinModeFast(inCYL, INPUT);
pinModeFast(fuelOut, OUTPUT);
pinModeFast(outIACV, OUTPUT);
pinModeFast(purgeOut, OUTPUT);
pinModeFast(motorCon1, OUTPUT);
pinModeFast(motorCon2, OUTPUT);
pinModeFast(motorCon3, OUTPUT);
pinModeFast(motorCon4, OUTPUT);
pinModeFast(coolingFans, OUTPUT);
Serial.begin(9600);
digitalWriteFast(fuelOut, HIGH);
digitalWriteFast(outIACV, HIGH);
digitalWriteFast(purgeOut, HIGH);
digitalWriteFast(motorCon1, HIGH);
countCYL = 0;
}
void initial_calculations() {
//make the calculations
airTemperature = 273 + C1 + engIAT * S1;
airPressure = C3 + engMAP * S3;
massAir = cylVolume * 0.0289 / 8.314; //mass air without P & T
massFuel = massAir / fuelAirRatio; //mass fuel without P & T
injectionTime = 1000 * massFuel / (rho * (flowRate / 60)); //in microseconds 00;
}
void loop() {
//do the initial calculations
initial_calculations();
injTime = 1000 * injectionTime * airPressure / airTemperature;
// put your main code here, to run repeatedly:
//get the fuel pressure and turn the pump on if necessary
engFuel = analogRead(inFuel);
fuelPressure = (engFuel * .0921) - 8.569;
if (fuelPressure <= 36.0)digitalWriteFast(fuelOut, LOW);
if (fuelPressure >= 40.0)digitalWriteFast(fuelOut, HIGH);
//enable/disable the IACV
if (setEnable == true)digitalWriteFast(outIACV, LOW);
if (setEnable == false)digitalWriteFast(outIACV, HIGH);
//check the coolant temperature and turn on fans if needed
engECT = analogRead(inECT);
coolantTemperature = 164 - (engECT * 0.150);
engMAP = analogRead(inMAP);
airPressure = engMAP * 0.302;
engIAT = analogRead(inIAT);
airTemperature = 273 + (164 - (0.15 * engIAT));
engOXY = analogRead(inOXY);
fuelAir = 15.11 - (0.004 * engOXY);
engOIL = analogRead(inOIL);
oilPressure = (engOIL / 10.0) - 9.0;
currentMillis = millis();
//print at 2 second intervals
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
Serial.println(" ");
Serial.print("RPM = ");
Serial.println(round(averageRPM));
Serial.print("Manifold Pressure = ");
Serial.print(round(airPressure));
Serial.println(" kPa ");
Serial.print("Intake Temperature = ");
Serial.print(round(airTemperature));
Serial.println(" K ");
Serial.print("Coolant Temperature = ");
Serial.print(round(coolantTemperature));
Serial.println(" C ");
Serial.print("Fuel Pressure = ");
Serial.print(fuelPressure);
Serial.println(" PSI ");
Serial.print("Oil Pressure = ");
Serial.print(oilPressure);
Serial.println(" PSI ");
Serial.print("Fuel Air Ratio = ");
Serial.println(fuelAir);
Serial.print("Injection Time = ");
Serial.print(injTime);
Serial.println(" us ");
}
stateCYL = digitalReadFast(inCYL);
if (stateCYL != lastCYL) {
if (stateCYL == LOW) {
startCYLTime = micros();
intervalCYL = startCYLTime - stopCYLTime;
pulseCYL++;
countCYL++;
engRPM = 120000000 / intervalCYL;
totalRPM = totalRPM + engRPM;
if (countCYL == 10) {
averageRPM = totalRPM / 10;
countCYL = 0;
totalRPM = 0;
}
if (pulseCYL == 1)setEnable = true;
if (pulseCYL == 100)setEnable = false;
}
lastCYL = stateCYL;
stopCYLTime = startCYLTime;
rpm_control();
}
}
void rpm_control() {
/*if (engRPM >= 1850) {
digitalWriteFast(motorCon1, HIGH);
digitalWriteFast(motorCon2, HIGH);
digitalWriteFast(motorCon3, LOW);
digitalWriteFast(motorCon4, LOW);
}
if (engRPM <= 1750) {
digitalWriteFast(motorCon1, LOW);
digitalWriteFast(motorCon2, LOW);
digitalWriteFast(motorCon3, HIGH);
digitalWriteFast(motorCon4, HIGH);
}
else {
digitalWriteFast(motorCon1, LOW);
digitalWriteFast(motorCon2, LOW);
digitalWriteFast(motorCon3, LOW);
digitalWriteFast(motorCon4, LOW);
}*/
}
Engine controller for a generator.
created 2020
by Allen J. Lindfors
#include >digitalWriteFast.h<
//set the pins for nano board, change pin #s for mega
const byte inCYL = 2; // // the number of the pin for the input CYL signal
const byte inTDC = 3; // the number of the pin for the input TDC signal
const byte inCPS = 4; // the number of the pin for the input CPS signal
const byte inMAP = A0;
const byte inIAT = A1;
const byte inOXY = A2;
bool setEnable, setFlowRateEnable;
//outputs
//firing order 1 3 4 2 the pulseCPS and pulseTDC selection configures this
const int sp[4] = {5, 6, 7, 8};
const int fi[4] = {9, 10, 11, 12};
//integer variables for controls
int pulseCYL = 0; //initialize
int stateCYL = LOW; //initialize
int lastCYL = LOW; //initialize
int pulseTDC = 0; //initialize
int stateTDC = LOW; //initialize
int lastTDC = LOW; //initialize
int pulseCPS = 0; //initialize
int stateCPS = LOW; //initialize
int lastCPS = LOW; //initialize
//timing and sensor values
//Sensor fits variable = C + S*(value)
//IAT
float C1 = 164, S1 = -0.15;
//ECT float C2 = 164, S2 = -0.15;
//MAP
float C3 = 0, S3 = 0.302;
//injector flow rate in cc/min see startup below
float flowRate;
//single cylinder volume
float cylVolume = 400.0;
//fuel values
float rho = 0.72; //for gasoline
//other densities propane=0.58, ethanol = 0.78, methane = 0.42, methanol = 0.78,
//fuel air value
float fuelAirRatio = 14.7; //for gasoline
//other fuel/air value propane=15.5, ethanol = 9.0, methane = 17.2, methanol = 6.4
//injection calculation values
float massAir, massFuel, injectionTime;
//timing and claculation variables
unsigned long injTime, spTime, ignTime, timeTDC;
unsigned long injTime0, injTime1, injTime2, injTime3;
unsigned long sparkTime0, sparkTime1, sparkTime2, sparkTime3;
unsigned long intervalCYL, startCYLTime, stopCYLTime;
unsigned long intervalTDC, startTDCTime, stopTDCTime;
unsigned long intervalCPS, startCPSTime, stopCPSTime;
//read usage variables
float airPressure, airTemperature;
float engMAP, engIAT, engOXY, engRPM, totalRPM;
void setup() {
// put your setup code here, to run once:
//set the pins
pinModeFast(inCPS, INPUT);
pinModeFast(inTDC, INPUT);
pinModeFast(inCYL, INPUT);
pinModeFast(fi[0], OUTPUT);
pinModeFast(fi[1], OUTPUT);
pinModeFast(fi[2], OUTPUT);
pinModeFast(fi[3], OUTPUT);
pinModeFast(sp[0], OUTPUT);
pinModeFast(sp[1], OUTPUT);
pinModeFast(sp[2], OUTPUT);
pinModeFast(sp[3], OUTPUT);
setEnable = false;
setFlowRateEnable = false;
digitalWriteFast(fi[0], LOW);
digitalWriteFast(fi[1], LOW);
digitalWriteFast(fi[2], LOW);
digitalWriteFast(fi[3], LOW);
digitalWriteFast(sp[0], LOW);
digitalWriteFast(sp[1], LOW);
digitalWriteFast(sp[2], LOW);
digitalWriteFast(sp[3], LOW);
Serial.begin(9600);
}
//get timers and settings for fuel injectors and ignition coils
void initial_calculations() {
//make the calculations
airTemperature = 300;//273 + C1 + engIAT * S1;
airPressure = 75;//C3 + engMAP * S3;
massAir = cylVolume * 0.0289 / 8.314; //mass air without P and T
massFuel = massAir / fuelAirRatio; //mass fuel without P and T
injectionTime = 1000 * massFuel / (rho * (flowRate / 60)); //in microseconds 00;
spTime = 2000; //spark coil charge time in microseconds
}
//initial setup for cold start
void startup_sequence() {
if (setFlowRateEnable == true)flowRate = 210;
else if (setFlowRateEnable == false)flowRate = 225;
}
void loop() {
// get the timing
initial_calculations();
startup_sequence();
injTime = 1000 * injectionTime * airPressure / airTemperature;
//read in the timing from the cam sensors
stateCYL = digitalReadFast(inCYL);
stateCPS = digitalReadFast(inCPS);
stateTDC = digitalReadFast(inTDC);
//main detection, timing, and writing to outputs
//CYL Counter
if (stateCYL != lastCYL) {
if (stateCYL == LOW) {
pulseCPS = 0;
pulseTDC = 0;
pulseCYL++;
startCYLTime = micros();
intervalCYL = startCYLTime - stopCYLTime;
//set the number of cam shaft revolutions to ignore
if (pulseCYL == 3)setEnable = true;
//set the number of initial cam shaft revolutions for extra fuel
if (pulseCYL == 2)setFlowRateEnable = true;
if (pulseCYL == 50)setFlowRateEnable = false;
}
lastCYL = stateCYL;
stopCYLTime = startCYLTime;
//if (intervalCYL >= 200000)ignTime = 1100;
//works but off
ignTime = 700 + (0.03 * intervalCYL);
//ignTime = 2000;
}
//TDC Counter
if (stateTDC != lastTDC) {
if (stateTDC == HIGH) {
pulseTDC++;
startTDCTime = micros();
//set injector zero times
if (pulseTDC == 3)injTime0 = micros();
if (pulseTDC == 2)injTime1 = micros();
if (pulseTDC == 4)injTime2 = micros();
if (pulseTDC == 1)injTime3 = micros();
//set zero times for spark plugs
if (pulseTDC == 1)sparkTime0 = micros(); //spark cylinder 1
if (pulseTDC == 4)sparkTime1 = micros(); //spark cylinder 2
if (pulseTDC == 2)sparkTime2 = micros(); //spark cylinder 3
if (pulseTDC == 3)sparkTime3 = micros(); //spark cylinder 4
intervalTDC = startTDCTime - stopTDCTime;
}
lastTDC = stateTDC;
stopTDCTime = startTDCTime;
}
//CPS Counter
if (stateCPS != lastCPS) {
if (stateCPS == HIGH) {
pulseCPS++; //increment the counter
//read sensors in between pulses
if (pulseCPS == 3) {
engMAP = analogRead(inMAP);//read manifold pressure
airPressure = C3 + (S3 * engMAP);
}
if (pulseCPS == 7) {
engIAT = analogRead(inIAT);//read intake temperature
airTemperature = C1 + (S1 * engIAT);
}
if (pulseCPS == 11) {
engOXY = analogRead(inOXY);//read AFR
}
}
lastCPS = stateCPS;
stopCPSTime = startCPSTime;
}
if (setEnable == true) {
//write to the spark plug outputs
timeTDC = intervalCYL / 4;
//cylinder 1
if (micros() >= sparkTime0 + timeTDC - (ignTime + spTime) &&
micros() <= sparkTime0 + timeTDC - (ignTime + spTime) + 1000) {
digitalWriteFast(sp[0], HIGH);
}
if (micros() >= sparkTime0 + timeTDC - ignTime)digitalWriteFast(sp[0], LOW);
//cylinder 2
if (micros() >= sparkTime1 + timeTDC - (ignTime + spTime) &&
micros() <= sparkTime1 + timeTDC - (ignTime + spTime) + 1000) {
digitalWriteFast(sp[1], HIGH);
}
if (micros() >= sparkTime1 + timeTDC - ignTime)digitalWriteFast(sp[1], LOW);
//cylinder 3
if (micros() >= sparkTime2 + timeTDC - (ignTime + spTime) &&
micros() <= sparkTime2 + timeTDC - (ignTime + spTime) + 1000) {
digitalWriteFast(sp[2], HIGH);
}
if (micros() >= sparkTime2 + timeTDC - ignTime)digitalWriteFast(sp[2], LOW);
//cylinder 4
if (micros() >= sparkTime3 + timeTDC - (ignTime + spTime) &&
micros() <= sparkTime3 + timeTDC - (ignTime + spTime) + 1000) {
digitalWriteFast(sp[3], HIGH);
}
if (micros() >= sparkTime3 + timeTDC - ignTime)digitalWriteFast(sp[3], LOW);
//write to the fuel injector outputs
//injector 1
if (micros() >= injTime0 + 25 && micros() <= injTime0 + 1000) {
digitalWriteFast(fi[0], HIGH);
}
if (micros() >= injTime0 + injTime) {
digitalWriteFast(fi[0], LOW);
}
//injector 2
if (micros() >= injTime1 + 25 && micros() <= injTime1 + 1000) {
digitalWriteFast(fi[1], HIGH);
}
if (micros() >= injTime1 + injTime) {
digitalWriteFast(fi[1], LOW);
}
//injector 3
if (micros() >= injTime2 + 25 && micros() <= injTime2 + 1000) {
digitalWriteFast(fi[2], HIGH);
}
if (micros() >= injTime2 + injTime) {
digitalWriteFast(fi[2], LOW);
}
//injector 4
if (micros() >= injTime3 + 25 && micros() <= injTime3 + 1000) {
digitalWriteFast(fi[3], HIGH);
}
if (micros() >= injTime3 + injTime) {
digitalWriteFast(fi[3], LOW);
}
}
}
No comments:
Post a Comment