Morning,
Having picked up my Arduino Uno a few days ago, I have tried to program it to be an EDIS controller, but as I am new to programming, I am not sure if I have done this the most effiecient way.
To give a bit of context:
EDIS was a system used by Ford in the 1990's to generate sparks without the use of a distributor. The EDIS module does the control of the sparks itself and has a default timing advance of 10 degrees, detected using a crankshaft position sensor.
The Arduino will recieve a 'PIP' signal (1 pulse per half revolution) from the EDIS module, and needs to return a SAW signal (variable length pulse between 64us and 1792us) approximately 10us after the PIP falling edge - It doesnt have to be exact.
Specifics:
The RPM of the engine, and manifold pressure (as measured by a 0 - 260kpa, 0-5VDC absolute pressure sensor) correspond to a value in the ignition 'map'
I have tried to implement a 2D array for this map, but I would like to be able to modify this without having to reload the program onto the arduino for tuning (updating values) whilst connected.
The final thing to mention is that for testing, I am not using the EDIS module (don't have one yet), so have simulated a pulsed output on pin 7 and linked this on the board to interupt pin 2.
The code seems to give the desired result, but probably isn't very efficient code
Any comments or suggestions greatly appreciated.
Oliver
//Global variables
volatile byte rpmcount;
unsigned long timeold;
int engine_rpm = 0;
// Global array for the ignition map, with values as microsecond duration of EDSIS SAW signal
// RPM values 0 to 1200 have 2048us added to the SAW duration to instigate MultiSpark from the EDIS unit.
// RPM values seperated into columns, Manifold Pressure (kpa) seperated into rows.
int ignition_map [17] [16] = {
//0 ,5 ,6 ,9 ,12 ,15 ,18 ,21 ,24 ,27 ,30 ,33 ,36 ,39 ,42,45 x100 RPM
{3123,3123,3021,2816,2714,618,570,512,435,369,307,246,184,123,64,64}, //20kpa
{3123,3123,3021,2816,2714,618,570,512,435,369,307,246,184,123,64,64}, //25kpa
{3123,3123,3021,2816,2714,618,570,512,435,369,307,246,184,123,64,64}, //30kpa
{3123,3123,3021,2816,2714,618,570,512,435,369,307,246,184,123,64,64}, //35kpa
{3123,3123,3021,2816,2714,618,570,512,435,369,307,246,184,123,64,64}, //40kpa
{3130,3130,3027,2822,2720,624,576,518,442,375,314,252,191,129,68,64}, //45kpa
{3136,3136,3034,2829,2726,630,582,525,448,381,320,259,197,136,74,64}, //50kpa
{3142,3142,3040,2835,2733,637,589,531,454,388,326,265,204,142,81,64}, //55kpa
{3149,3149,3046,2842,2739,643,595,538,461,394,333,271,210,148,87,64}, //60kpa
{3200,3200,3098,2893,2790,694,646,589,512,445,384,323,261,200,138,77}, //65kpa
{3251,3251,3149,2944,2842,746,698,640,563,497,435,374,312,251,189,128}, //70kpa
{3302,3302,3200,2995,2893,797,749,691,614,548,486,425,364,302,241,179}, //75kpa
{3354,3354,3251,3046,2944,848,800,742,666,599,538,476,415,353,292,230}, //80kpa
{3405,3405,3302,3098,2995,899,851,794,717,650,589,527,466,404,343,282}, //85kpa
{3430,3430,3328,3123,3021,925,877,819,742,676,614,553,492,430,369,307}, //90kpa
{3430,3430,3328,3123,3021,925,877,819,742,676,614,553,492,430,369,307}, //95kpa
{3430,3430,3328,3123,3021,925,877,819,742,676,614,553,492,430,369,307}, //100kpa
};
// Initialise Parameters
void setup(){
attachInterrupt(0, pip_interupt, FALLING); // initialise interupt to dectect the falling edge of the PIP signal coming in on digital pin 2
rpmcount = 0;
timeold = 0;
Serial.begin(115200);
pinMode(7, OUTPUT);
pinMode(13, OUTPUT);
}
// The loop routine runs over and over again forever: whilst device is powered
void loop(){
// Section of code to simulate the signal from EDIS. For this simulation, the pulse is output on digital pin 7
int delay_value = 500;
digitalWrite(7, HIGH);
delay(1);
digitalWrite(7, LOW);
delay(delay_value);
}
// PIP signal interupt - There are two PIP pulses per revolution, so the interrupt function is run twice per revolution
void pip_interupt() {
rpmcount++;
if (rpmcount >= 2) { // Update RPM every 2 pulses, increase this for better RPM resolution, decrease for a faster update
engine_rpm = 30000/(millis() - timeold)*rpmcount;
timeold = millis();
rpmcount = 0;
Serial.println("engine rpm");
Serial.println(engine_rpm,DEC);
}
int manifold_pressure = analogRead(A0) // Read value from pressure sensor. Returns values from 0 to 1023
int map_value = (rpm_pressure_to_spark(engine_rpm, manifold_pressure)); // Retrieve ignition map value
generate_SAW(map_value); // Call generate SAW function
}
// Function to map the engine rpm to an interger value for the array element int decode_rpm(int rpm) {
int max_rpm = 4500; // Maximum Engine RPM
int idle_rpm = 550; // Idle Speed
int increment = max_rpm / 15; // initialize increment to be the difference in rpm between each array element and the next
int map_rpm = 0;
if(rpm<idle_rpm){ // if rpm less than idle_rpm, use values from ignition map column [1]
map_rpm = 1;
} else if(rpm>max_rpm) { // if rpm more than the maximum engine RPM, use values from ignition map column [15]
map_rpm = 15;
}else{
while(map_rpm * increment < rpm) // otherwise find which array element corresponds the the rpm value
map_rpm++;
}
return map_rpm;
}
// Function to map the engine manifold absolute pressure to an interger value for the array element int decode_pressure(int pressure) {
int map_pressure_kpa = map(pressure,0,1023,0,260);
int map_pressure;
if(map_pressure_kpa < 20){
map_pressure = 0;
}else if (map_pressure_kpa > 100){
map_pressure = 16;
}else{
map_pressure = (((52 * map_pressure_kpa)/260)-4); //52 = 260/5 (max pressure / increment)
}
return map_pressure;
}
// Function to determine Ignition table value based on manifold pressure and engine rpm int rpm_pressure_to_spark(int rpm, float pressure){
int rpm_index = decode_rpm(rpm);
int pressure_index = decode_pressure(pressure);
return ignition_map [pressure_index] [rpm_index];
}
// Function to generate SAW signal to return to EDIS int generate_SAW(int SAW_length_us){
int map_value_us = SAW_length_us;
digitalWrite(13,HIGH);
delayMicroseconds(map_value_us);
digitalWrite(13,LOW);
Serial.println("SAW Length in microseconds");
Serial.println(map_value_us,DEC);
}