Hey,
I found a code for a 180° engine but i want to tweek it to get it more accurate/ adaptable.
The code calculates the array with the delays (linear) but u want to make the array myself.
The following code only uses 2 hall sensors and the spark time for the second cilinder is calculated (the time for 180 °). I think this is not good because when the engine is ac/deccellerating very fast this will not be correct anymore.
Here you see the code with the text in witch i believe it works.
const int MIN_RPM = 800;
const int MAX_INDEX = 200;
const int DWELL = 1500;
const int COIL1 = 4;
const int COIL2 = 7;
const int SENSOR1 = 2; //idle sensor
const int SENSOR2 = 3; //cam sensor
bool triggered = false;
long lastDuration = 0;
unsigned short currentIndex = 0;
unsigned int RPMS[MAX_INDEX];
unsigned int HALVES[MAX_INDEX];
unsigned int DELAYS[MAX_INDEX];
///Build all of the values in the arrays based on our starting RPM and initial and final advance
///Redline is (MAX_INDEX-1) * 50 + MIN_RPM
void calculateArrayValues()
{
double startRPM = MIN_RPM; //use a double for increased precision in the calculations
int startAdvance = 18; //18 degrees of advance coming on at 800 rpm
int endAdvance = 38; //total advance of 38 degrees
int endRPM = 4000; //total advance to be achived at 4000 rpm
int hallAdvance = 180; //assume sensor is 180 degrees advanced from TDC
double slope = abs(endAdvance - startAdvance)/abs(endRPM - startRPM); //function to calculate linear advance is y = mx+b where m = (y1-y2)/(x1-x2) // hier word m berekend (tg van de alpha)
int intercept = startAdvance - (startRPM * slope); //intercept is b from above formula // hier word de b berekend van boven de formule
//build the arrays, 50 rpm at a time
for(int i = 0; i < MAX_INDEX; i++)
{
double usPerDegree = 1000000 / (startRPM / 60) / 360;
double advance = startRPM * slope + intercept; //use our function to calculate the advance
int advanceDelay;
if(startRPM >= endRPM) //if our current RPM is >= the to ending RPM, just use 38 degrees
{
advance = 38;
}
advanceDelay = ((hallAdvance - advance) * usPerDegree) - DWELL; //calculate the time we wait before picking up the sensor and starting the spark process on the coil(s)
DELAYS[i] = advanceDelay;
HALVES[i] = usPerDegree * 180; //we're on a 180 twin, so calculate the delay between the first coil (left) and second coil (right) firing. This way, we only need one pickup.
startRPM += 50; //increment the RPMs for the next iteration
}
}
///Fires a coil by grounding the selected pin, waiting the dwell period, then ungrounding it
void dwellAndFire(int pin)
{
digitalWrite(pin, HIGH); //ground the coil
delayMicroseconds(DWELL);
digitalWrite(pin, LOW); //trigger the coil
}
///Fires both coils with the currently mapped delay values
void fireWithDelays()
{
delayMicroseconds(DELAYS[currentIndex]);
dwellAndFire(COIL1);
delayMicroseconds(HALVES[currentIndex]);
dwellAndFire(COIL2);
}
///Interrupt for the idle sensor. At RPMs less than RPMS[0], use this sensor to immediately trigger the coil(s) with no delay.
///This sensor will be located around 6 to 10 degrees BTDC
void idleSensor()
{
if(lastDuration > RPMS[0])
{
int coil2Delay = (lastDuration / 4); //engine spinning slower than our map, calculate delay for second coil (divide by four is 90 degrees of rotation)
dwellAndFire(COIL1); //fire left coil
delayMicroseconds(coil2Delay); //wait 180 degrees
dwellAndFire(COIL2); //fire right coil
}
}
///Interrupt for the "running" sensor
void camSensor()
{
triggered = true;
}
///Set the pins appropriately, calculate the values we'll be using, and then attach the interrupts
void setup()
{
pinMode(COIL1, OUTPUT);
pinMode(COIL2, OUTPUT);
pinMode(SENSOR1, INPUT);
pinMode(SENSOR2, INPUT);
calculateArrayValues();
attachInterrupt(1, camSensor, RISING); //cam sensor interrupt, als de camsensor een interupt geeft word de void camsensor uitgevoerd.
attachInterrupt(0, idleSensor, RISING); //idle sensor interrupt, als de motor te traag draait < dan x aantal toeren word void idle uitgevoerd., MAAR de motor moet altijd eerst camsensor interupt passeren (deze staat vroeger)
//dus deze volgende word sowieso altijd ook uitgevoed
// moet trouwens daar in de camsensor interupt de durations / toerntal bepaald word !!!
}
///If we pickup a trigger from the running sensor, adjust the timing map and then fire the coils
void loop()
{
if(triggered)
{
noInterrupts(); //turn off interrupts
triggered = false;
lastDuration = (micros() - lastDuration); //number of microseconds since last rotation
if(lastDuration > RPMS[MAX_INDEX]) //not past redline, OK to fire spark
{
if(lastDuration < RPMS[0]) //cam sensor (not idle sensor) handling spark check index
{
if(lastDuration < RPMS[currentIndex]) //engine speed increasing
{
currentIndex++; //jump to the next value in the array
}
else if (lastDuration > RPMS[currentIndex]) //engine speed decreasing
{
currentIndex--; //drop to the previous value in the array
}
fireWithDelays();
}
}
interrupts(); //turn interrupts back on
}
}
First we declare de min rpm and the maximum index for the array (the higher the more preciese).
Then the dwell time. Here 1,5 ms.
Set pin 4 to control coil one and pin 7 to control coil 2.
Set the inputs for the coils sensor 1 (advance sensor) pin 2 (interupt) sensor 2 (idle) pin 3 (interupt)
declare a state 'triggered' = false
set the duration on '0'
set the index (from the arrays) at 0
Declare the arrays
RPMS (used to store the engine speed )
HALVES (used to store the delay time between 1st en 2nd cilinder )
at the 'void calculatearrayvalues' we want to, as the name says, calculate the arrays one time.
This is math :p. Simple below 800 the advance is 18° between 800 and 4000 => lineair rising line
calculated, above 4000 fixed to 38°.
So the arrays get filled up from 0 (800rpm) to 200 (10 000) (max index) by delays and halvedelays.
Then we have a void dwell and fire.
this is the function where the cils just have to spark. Just wait the dwell time and fire. Called by another section of the program.
The next is void fire with delays
This is the function where we are above 800 rpm.
Wait the delay 'call' the dwell and fire funcion. wait a half rotation and do the same for the second cilinder.
Next is the void idel sensor.
Here the engine is >800rpm. calculate the delay for coil 2, Just dwell and fire coil 1, wait calculated delay and fire coil 2 (determined by the void dwell and fire section).
Next is the camsensor (180BTDC). Makes the 'triggered state' true.
Then we have the setup. (speeks for itselves.)
Maybe only a little bit info for the interupt. The camsensor always comes before the idle sensor, it is mechanically determined.
The last is the void loop.
=> if the state triggered is true (camsensor detection)
switch of interrups, make it false again for the second round.
Look if the motor is not running to fast. (do nothing motor protection, advance will be as at idle => way to late)
Look if it is running below 800 rpm (do nothing go to idle, dwell and fire)
Look if higher then 800 => advance from table dwell and fire.
I know the explanation is not as good on paper explained as i would like to tell it. But if you can't follow my well written in perfect English tekst => ASK, i will be as happy to help as i can.