Corrected float free pulsewidth calc
This commit is contained in:
parent
3d1cdb6f4d
commit
7ea7c7afe5
12
comms.ino
12
comms.ino
|
@ -73,9 +73,9 @@ void sendValues(int length)
|
|||
boolean b = 0; //inj_port2.status;
|
||||
response[1] = ((a & 0x01) << 0) | ((a & 0x02) << 1) | ((a & 0x04) << 1) | ((b & 0x01) << 1) | ((b & 0x02) << 3) | ((b & 0x04) << 3); //squirt
|
||||
|
||||
response[2] = 0; // Engine Status
|
||||
response[2] = (byte)128; // Engine Status
|
||||
response[3] = 0x00; //baro
|
||||
response[4] = 0x00; //map
|
||||
response[4] = currentStatus.MAP; //map
|
||||
response[5] = 0x00; //mat
|
||||
response[6] = 0x00; //Coolant
|
||||
response[7] = 0x00; //TPS
|
||||
|
@ -84,12 +84,12 @@ void sendValues(int length)
|
|||
response[10] = 0x00; //Exhaust gas correction (%)
|
||||
response[11] = 0x00; //Air Correction (%)
|
||||
response[12] = 0x00; //Warmup enrichment (%)
|
||||
response[13] = (rpm / 100); //rpm / 100
|
||||
response[14] = 0x00; //Pulsewidth 1 divided by 10 (in ms)
|
||||
response[13] = (currentStatus.RPM / 100); //rpm / 100
|
||||
response[14] = currentStatus.PW / 100; //Pulsewidth 1 divided by 10 (in ms)
|
||||
response[15] = 0x00; //acceleration enrichment (ms)
|
||||
response[16] = 0x00; //Barometer correction (%)
|
||||
response[17] = 0x00; //Total GammaE (%)
|
||||
response[18] = 0x00; //Current VE 1 (%)
|
||||
response[18] = currentStatus.VE; //Current VE 1 (%)
|
||||
response[19] = 0x00; //Pulsewidth 2 divided by 10 (in ms)
|
||||
response[20] = 0x00; //mCurrent VE 2 (%)
|
||||
response[21] = 0x00; //Idle
|
||||
|
@ -142,7 +142,7 @@ void sendPage()
|
|||
response[99] = 0;
|
||||
for(byte x=100;x<108;x++) { response[x] = fuelTable.axisX[(x-100)] / 100; }
|
||||
for(byte y=108;y<116;y++) { response[y] = fuelTable.axisY[7-(y-108)]; }
|
||||
response[116] = 0;
|
||||
response[116] = ((engineCylinders-1) * 16) + (1 * 8) + ((engineStrokes / 4) * 4) + 2; // (engineCylinders * 16) + (1 * 8) + ((engineStrokes / 4) * 4) + 4
|
||||
response[117] = 0;
|
||||
response[118] = 0;
|
||||
response[119] = 0;
|
||||
|
|
11
globals.h
11
globals.h
|
@ -1,3 +1,14 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
byte ms_version = 20;
|
||||
|
||||
//The status struct contains the current values for all 'live' variables
|
||||
struct statuses {
|
||||
volatile boolean hasSync;
|
||||
unsigned int RPM;
|
||||
byte MAP;
|
||||
byte TPS;
|
||||
byte VE;
|
||||
unsigned long PW; //In uS
|
||||
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ Need to calculate the req_fuel figure here, preferably in pre-processor macro
|
|||
#define pinCoil 7 //Pin for the coil (AS above, 1 cyl only)
|
||||
#define pinTPS 8 //TPS input pin
|
||||
#define pinTrigger 2 //The CAS pin
|
||||
#define pinMAP 0 //MAP sensor pin
|
||||
//**************************************************************************************************
|
||||
|
||||
#include "utils.h"
|
||||
|
@ -43,12 +44,10 @@ int req_fuel_uS = req_fuel * 1000; //Convert to uS and, importantly, an int. Thi
|
|||
int triggerActualTeeth = triggerTeeth - triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt
|
||||
int triggerToothAngle = 360 / triggerTeeth; //The number of degrees that passes from tooth to tooth
|
||||
|
||||
volatile boolean hasSync = false;
|
||||
volatile int toothCurrentCount = 0; //The current number of teeth (Onec sync has been achieved, this can never actually be 0
|
||||
volatile unsigned long toothLastToothTime = 0; //The time (micros()) that the last tooth was registered
|
||||
volatile unsigned long toothLastMinusOneToothTime = 0; //The time (micros()) that the tooth before the last tooth was registered
|
||||
|
||||
int rpm = 0; //Stores the last recorded RPM value
|
||||
struct table fuelTable;
|
||||
struct table ignitionTable;
|
||||
|
||||
|
@ -59,12 +58,16 @@ unsigned long counter;
|
|||
unsigned long scheduleStart;
|
||||
unsigned long scheduleEnd;
|
||||
|
||||
struct statuses currentStatus;
|
||||
|
||||
void setup() {
|
||||
|
||||
//Begin the main crank trigger interrupt pin setup
|
||||
//The interrupt numbering is a bit odd - See here for reference: http://arduino.cc/en/Reference/AttachInterrupt
|
||||
//These assignments are based on the Arduino Mega AND VARY BETWEEN BOARDS. Please confirm the board you are using and update acordingly.
|
||||
int triggerInterrupt = 0; // By default, use the first interrupt. The user should always have set things up (Or even better, use the recommended pinouts)
|
||||
currentStatus.RPM = 0;
|
||||
currentStatus.hasSync = false;
|
||||
switch (pinTrigger) {
|
||||
|
||||
//Arduino Mega 2560 mapping (Uncomment to use)
|
||||
|
@ -129,29 +132,27 @@ void loop()
|
|||
//delay(2500);
|
||||
//Always check for sync
|
||||
//Main loop runs within this clause
|
||||
if (hasSync)
|
||||
if (currentStatus.hasSync)
|
||||
{
|
||||
|
||||
//Calculate the RPM based on the time between the last 2 teeth. I have no idea whether this will be accurate AT ALL, but it's fairly efficient and means there doesn't need to be another variable placed into the trigger interrupt
|
||||
if (toothCurrentCount != 1) //We can't perform the RPM calculation if we're at the first tooth as the timing would be double (Well, we can, but it would need a different calculation and I don't think it's worth it, just use the last RPM value)
|
||||
{
|
||||
long revolutionTime = (triggerTeeth * (toothLastToothTime - toothLastMinusOneToothTime)); //The time in uS that one revolution would take at current speed
|
||||
rpm = US_IN_MINUTE / revolutionTime;
|
||||
currentStatus.RPM = US_IN_MINUTE / revolutionTime;
|
||||
}
|
||||
//Serial.print("RPM: "); Serial.println(rpm);
|
||||
//rpm = 1000;
|
||||
//Get the current MAP value
|
||||
int MAP = 20; //Placeholder
|
||||
int TPS = 20; //Placeholder
|
||||
//currentStatus.MAP = 100; //Placeholder
|
||||
currentStatus.MAP = map(analogRead(pinMAP), 0, 1023, 0, 100);
|
||||
currentStatus.TPS = 20; //Placeholder
|
||||
|
||||
//Begin the fuel calculation
|
||||
//Perform lookup into fuel map for RPM vs MAP value
|
||||
int VE = getTableValue(fuelTable, MAP, rpm);
|
||||
currentStatus.VE = getTableValue(fuelTable, currentStatus.MAP, currentStatus.RPM);
|
||||
//Calculate an injector pulsewidth form the VE
|
||||
unsigned long pulseWidth = PW(req_fuel_uS, VE, MAP, 100, engineInjectorDeadTime); //The 100 here is just a placeholder for any enrichment factors (Cold start, acceleration etc). To add 10% extra fuel, this would be 110
|
||||
|
||||
currentStatus.PW = PW(req_fuel_uS, currentStatus.VE, currentStatus.MAP, 100, engineInjectorDeadTime); //The 100 here is just a placeholder for any enrichment factors (Cold start, acceleration etc). To add 10% extra fuel, this would be 110
|
||||
//Perform a lookup to get the desired ignition advance
|
||||
int ignitionAdvance = getTableValue(ignitionTable, MAP, rpm);
|
||||
int ignitionAdvance = getTableValue(ignitionTable, currentStatus.MAP, currentStatus.RPM);
|
||||
|
||||
//Determine the current crank angle
|
||||
int crankAngle = (toothCurrentCount - 1) * triggerToothAngle + triggerAngle; //Number of teeth that have passed since tooth 1, multiplied by the angle each tooth represents, plus the angle that tooth 1 is from TDC
|
||||
|
@ -163,7 +164,7 @@ void loop()
|
|||
unsigned long timePerDegree = (toothLastToothTime - toothLastMinusOneToothTime) / triggerToothAngle; //The time (uS) it is currently taking to move 1 degree
|
||||
|
||||
//Determine next firing angles
|
||||
int injectorStartAngle = 355 - (pulseWidth / timePerDegree); //This is a bit rough, but is based on the idea that all fuel needs to be delivered before the inlet valve opens. I am using 355 as the point at which the injector MUST be closed by. See http://www.extraefi.co.uk/sequential_fuel.html for more detail
|
||||
int injectorStartAngle = 355 - (currentStatus.PW / timePerDegree); //This is a bit rough, but is based on the idea that all fuel needs to be delivered before the inlet valve opens. I am using 355 as the point at which the injector MUST be closed by. See http://www.extraefi.co.uk/sequential_fuel.html for more detail
|
||||
int ignitionStartAngle = 360 - ignitionAdvance; //Simple
|
||||
|
||||
//Serial.print("Injector start angle: "); Serial.println(injectorStartAngle);
|
||||
|
@ -176,7 +177,7 @@ void loop()
|
|||
{
|
||||
setSchedule1(openInjector,
|
||||
(injectorStartAngle - crankAngle) * timePerDegree,
|
||||
pulseWidth,
|
||||
currentStatus.PW,
|
||||
closeInjector
|
||||
);
|
||||
}
|
||||
|
@ -191,9 +192,13 @@ void loop()
|
|||
}
|
||||
|
||||
//Check for any requets from serial
|
||||
if (Serial.available() > 0)
|
||||
//Serial.println(toothCurrentCount);
|
||||
if (toothCurrentCount == 1) //Only check the serial buffer (And hence process serial commands) once per revolution
|
||||
{
|
||||
command();
|
||||
if (Serial.available() > 0)
|
||||
{
|
||||
command();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,7 +228,7 @@ void loop()
|
|||
}
|
||||
*/
|
||||
trigger();
|
||||
|
||||
delay(1);
|
||||
}
|
||||
else
|
||||
{ getSync(); }
|
||||
|
@ -254,7 +259,7 @@ void getSync()
|
|||
delay(1); //A 1000us delay should make for about a 5000rpm test speed with a 12 tooth wheel(60000000us / (1000us * triggerTeeth)
|
||||
toothLastToothTime = micros();
|
||||
|
||||
hasSync = true;
|
||||
currentStatus.hasSync = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,7 +284,7 @@ void trigger()
|
|||
//If the time between the current tooth and the last is greater than 1.5x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after the gap
|
||||
//if ( (curTime - toothLastToothTime) > (1.5 * (toothLastToothTime - toothLastMinusOneToothTime))) { toothCurrentCount = 1; }
|
||||
if ( (curTime - toothLastToothTime) > ((3 * (toothLastToothTime - toothLastMinusOneToothTime))>>1)) { toothCurrentCount = 1; } //Same as above, but uses bitshift instead of multiplying by 1.5
|
||||
//if (toothCurrentCount > triggerActualTeeth) { toothCurrentCount = 1; } //For testing ONLY
|
||||
if (toothCurrentCount > triggerActualTeeth) { toothCurrentCount = 1; } //For testing ONLY
|
||||
|
||||
// Update the last few tooth times
|
||||
toothLastMinusOneToothTime = toothLastToothTime;
|
||||
|
|
17
utils.h
17
utils.h
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
These are some utility functions and variables used through the main code
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#define MS_IN_MINUTE 60000
|
||||
#define US_IN_MINUTE 60000000
|
||||
|
||||
|
@ -22,17 +22,22 @@ MAP: In KPa, read from the sensor
|
|||
GammaE: Sum of Enrichment factors (Cold start, acceleration). This is a multiplication factor (Eg to add 10%, this should be 110)
|
||||
injOpen: Injector open time. The time the injector take to open in uS
|
||||
*/
|
||||
int PW(int REQ_FUEL, int VE, int MAP, int GammaE, int injOpen)
|
||||
int PW(int REQ_FUEL, byte VE, byte MAP, int GammaE, int injOpen)
|
||||
{
|
||||
//Standard float version of the calculation
|
||||
//return (REQ_FUEL * (float)(VE/100.0) * (float)(MAP/100.0) * (float)(GammaE/100.0) + injOpen);
|
||||
|
||||
//100% float free version, does sacrifice a little bit of accuracy. Accuracy loss is in the order of 0.1ms (100uS)
|
||||
int iVE = (VE << 7) / 100;
|
||||
int iMAP = (MAP << 7) / 100;
|
||||
|
||||
int iVE = ((int)VE << 7) / 100;
|
||||
int iMAP = ((int)MAP << 7) / 100;
|
||||
int iGammaE = (GammaE << 7) / 100;
|
||||
int pulsewidth = (REQ_FUEL * iVE * iMAP * iGammaE) >> 21;
|
||||
return (pulsewidth + injOpen);
|
||||
|
||||
unsigned long intermediate = ((long)REQ_FUEL * (long)iVE) >>7; //Need to use an intermediate value to avoid overflowing the long
|
||||
intermediate = (intermediate * iMAP) >> 7;
|
||||
intermediate = (intermediate * iGammaE) >> 7;
|
||||
return (int)intermediate + injOpen;
|
||||
|
||||
}
|
||||
|
||||
/* Determine the Gamma Enrichment number. Forumla borrowed from MS2 manual... may be skipped/simplified for arduino!
|
||||
|
|
Loading…
Reference in New Issue