Corrected float free pulsewidth calc

This commit is contained in:
Josh Stewart 2013-07-10 10:26:16 +10:00
parent 3d1cdb6f4d
commit 7ea7c7afe5
4 changed files with 52 additions and 31 deletions

View File

@ -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;

View File

@ -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
};

View File

@ -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
View File

@ -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!