/****Simple reliable Electronic wasted spark Ignition System for 4-cylinder, 4-stroke engines.
***** Anders Stenhammar. 2016, Sweden **********/
// Arduino UNO and Nano compatible.
// Set the tachometer for 2 ECU pulses per rev.
// Please send feedback to anders.stenhammar84@gmail.com
// http://www.andersstenhammar.com
//________________________________________________________________________________________________
// To be able to manipulate the AVR processor timers:
#include
#include
//Pin definitions:
const byte HallPin = 3; // (PORTD,3) to Hall sensor Vcc
const byte IgnOffPin = 11; // Ignition switch
const byte BattOKpin =10; // Drives the warning lamp for low battery voltage.
const byte TachoPin =9; // (PORTB,1)
const byte Ign1Pin = 5; // (PORTD,5)
const byte Ign2Pin = 2; // (PORTD,2)
const int VoltRefPin =A0; // Analog pin for voltage measuring.
volatile unsigned long ProcessTime; // Time it takes for the ignition code to execute.
volatile unsigned long startProcessTime; // Starting time for the ignintion code.
volatile unsigned long ProcessEnd; // Endtime for the ignition code.
volatile unsigned long ignDelay; // Time from 3 degrees to where the spark should happen.
volatile unsigned long microseconds; // The microsecondcounter value.
volatile unsigned long half_revolution_time; // The time it takes for the crank to turn 1/2 revolution.
volatile int crankingDwell; // The time the coil should charge during cranking
volatile int runningDwell; // The time the coil should charge during running
volatile int dwellTime; // The time the coil should charge.
volatile byte IgnSystem; // Definition for active ign system.
volatile boolean IgnOff; // Status on ignition switch
volatile boolean HallStatus; // Status Hall sensor (Hall high = north magnet)
int VoltValue; // variable to store the value coming from the VoltRefPin A7.
int BatteryVolt;
boolean LedState;
long interval;
unsigned long previousMillis;
unsigned long currentMillis;
/***********************************************************************/
void setup() {
pinMode(Ign1Pin, OUTPUT); // Initialize the Ignition 1 pin as an output.
pinMode(Ign2Pin, OUTPUT); // -“-
pinMode(TachoPin, OUTPUT); // -“-
pinMode(BattOKpin, OUTPUT);
pinMode(HallPin, INPUT); //
pinMode(IgnOffPin, INPUT); //
digitalWrite(TachoPin, LOW); // Turn the rpm signal off in case it’s on
digitalWrite(BattOKpin, LOW); // Turn the warning signal off in case it’s on
digitalWrite(Ign1Pin, HIGH); //Turn the ignition off in case it’s on (inverted)
digitalWrite(Ign2Pin, HIGH); // -“-
runningDwell = 3000; //in uS (VAG:3000uS)
crankingDwell = 4000; //in uS (VAG:3000uS)
half_revolution_time = 0; // The time it takes for one half revolution.
IgnSystem = 0; // No ignition system is active (cranking mode).
IgnOff=HIGH; // Set ignition ON or OFF, depending on your switch setup
ProcessTime=0; // The compensation time for the slow arduino.
/********** Setup timer2*************/
noInterrupts();
TCCR2A = 0; // Turn off Control register for waveform generation
TCCR2B = 0; // Turn off noise cancelling, turn off edge select, waveform gen mode 0,
TCCR2A |= (1 << WGM21); // Turn on CTC mode (so it will start again) automatically TIMSK2 |= (1 << OCIE2A); // Set interrupt on compare match. OCR2A = 8; // Prescaler of 64 gives 4uS per tick, 4uS * 8 = 32uS (32uS = 1 degree at ~5100rpm). TCNT2 = 0; // Reset timer counter to 0 microseconds = 0; // Preset the us counter variable. interrupts(); /*Delay the ignition at power up and blink the warning lamp */ delay(5000); digitalWrite(BattOKpin, HIGH); delay(5000); digitalWrite(BattOKpin, LOW); delay(5000); digitalWrite(BattOKpin, HIGH); delay(5000); digitalWrite(BattOKpin, LOW); //Activate Hall sensor Interrupt pin attachInterrupt(digitalPinToInterrupt(HallPin),SensorChange, CHANGE); } //======================================================================== /* The interrupt action: The Timer starts to count up 32 uS at a time.*/ //(Check to see if needed to make some overlap from cranking mode to running mode!) void SensorChange () { // startProcessTime = micros(); //Beginning of ignition code to measure ignition process time HallStatus = digitalRead(HallPin); // Check the crank position. half_revolution_time = microseconds; // For crank speed measurement TCNT2 = 0; // Reset the timer count to 0 microseconds = 0;//ProcessTime; // Preset the uS counter variable to compensate for code processing time. TCCR2B |= (1 << CS22); // Load 64 prescaler, and this starts the timer2! // While cranking (rpm < 300) if ((half_revolution_time > 100000)||(half_revolution_time==0)) {
dwellTime = crankingDwell; //Setting the dwelltime for cranking.
ignDelay = crankingDwell; //Setting the ignDelay to 0 for immediate coil charging. (CHECK TO SEE IF THIS FUNCTION CAN BE REMOVED! IT IS ALSO IN THE LOOP!)
if (IgnOff == LOW){ // If the ignition switch is open and If Rev Limit is not reached: IgnOn is HIGH
if (HallStatus==HIGH){
IgnSystem = 2;
bitClear(PORTD,2); //digitalWrite(Ign2Pin, LOW); // (Turn on coil 2 charging immediately.) // spark off
}
if (HallStatus==LOW){
IgnSystem = 1;
bitClear(PORTD,5); //digitalWrite(Ign1Pin, LOW); // (Turn on coil 1 charging immediately,)
}
// While running (rpm >= 300), coil nr 2 will be used at next ignition.
if ((half_revolution_time<=100000)&&(half_revolution_time>0)){
dwellTime = runningDwell; //setting the dwelltime for running
if (HallStatus==HIGH){
IgnSystem = 1; //start using coil nr1 instead.
}
if (HallStatus==LOW){
IgnSystem = 2;
}
}
}
}
}
/*=============================================================================
The Interrupt Service Routine for Timer2 that will be executed each time the
timer reach the compare match register (32uS)*/
ISR(TIMER2_COMPA_vect) {
microseconds=microseconds+32; // Increases the variable “microseconds” by 32 every time the ISR is executed).
/************ coil charging*****************************/
if ((microseconds >= (ignDelay-dwellTime)) && (microseconds < (ignDelay))) { bitClear(PORTB,1); // digitalWrite(TachoPin, LOW)//Tachometer ECU PWM signal on if (IgnSystem == 1) { // If ignitionsystem 1 is selected, then: bitClear(PORTD,5); // (Turn on coil 1 charging.) //digitalWrite(Ign1Pin, LOW); } if (IgnSystem == 2) { // If ignitionsystem 2 is selected, then: bitClear(PORTD,2); // (Turn on coil 2 charging.) //digitalWrite(Ign2Pin, LOW); } } /***********Discharge coilspark*******************************************/ // When the microseconds has reached the ignDelay, then: if (microseconds >= ignDelay) {
bitSet(PORTD,5); // digitalWriteFast(Ign1Pin, LOW); // Stop charging coil 1. (Gives spark)
bitSet(PORTD,2); // digitalWriteFast(Ign2Pin, LOW); // Stop charging coil 2. (Gives spark)
bitSet(PORTB,1); // digitalWriteFast(TachoPin, HIGH) // Tachometer ECU PWM signal off
//Last part of ignition code to measure process time
//ProcessEnd = micros();
//ProcessTime = ProcessEnd – startProcessTime;
/***********************************************************/
if (microseconds > 100000) { // If the engine has stopped or is still cranking, stop and reset the timer:
TCCR2B &= ~(1 << CS22); // Clear the prescaler, and this stops the timer2! TCCR2B = 0; microseconds = 0; half_revolution_time = 0; // ProcessTime = 0; //Still under testing } } } void loop() { HallStatus = digitalRead(HallPin); // Check the crank position. digitalWrite(BattOKpin, LedState); // Iluminate the battery indicator led. /*****REV LIMITATION & ignition switch control*****************************************************/ if ((half_revolution_time<7000)&&(half_revolution_time!=0)){ IgnOff = HIGH; } else{ IgnOff = digitalRead(IgnOffPin); // Check the Ignition switch position. } //_______________________________________________________________________________ /*****IGNITION TIMING CURVE************************************************/ //Following numbers are based on an excell sheet with the advance curve attached. if ((half_revolution_time<= 8333)&&(half_revolution_time>0)){ ///Advance 29-0 @ 3600-4000 rpm (soft rev limitation)
ignDelay = (( -1593 / 100) * (half_revolution_time/10) + 20126 );
}
else
if ((half_revolution_time<= 9091)&&(half_revolution_time>0)){ ///Advance 28 @ 3300-3600 rpm
ignDelay = (( 1125 / 100) * (half_revolution_time/10) + -2702 );
}
else
if ((half_revolution_time<=10714 )&&(half_revolution_time>0)){ ///Advance 27 @ 2800-3300 rpm
ignDelay = (( 1157 / 100) * (half_revolution_time/10) + -3466 );
}
else
if ((half_revolution_time<= 12500)&&(half_revolution_time>0)){ ///Advance 24 @ 2400-2800 rpm
ignDelay = (( 1053 / 100) * (half_revolution_time/10) + -2533 );
}
else
if ((half_revolution_time<= 25000)&&(half_revolution_time>0)){ //Advance 10-24 @ 1200-2400 rpm
ignDelay = (( 994 / 100) * (half_revolution_time/10) + -1667 );
}
else
if ((half_revolution_time<= 50000)&&(half_revolution_time>0)){ //Advance 7-10 @ 600-1200 rpm
ignDelay = (( 1040 / 100) * (half_revolution_time/10) + -4801 );
}
else
if ((half_revolution_time<= 75000)&&(half_revolution_time>0)){ //Advance 9-7 @ 400-600 rpm
ignDelay = (( 1098 / 100) * (half_revolution_time/10) + -12317 );
}
else
if ((half_revolution_time<= 100000)&&(half_revolution_time>0)){ //Advance -3-9 @ 300-400 rpm
ignDelay = (( 833 / 100) * (half_revolution_time/10) + 16667 );
}
//_____________________________________________________________________________________
//
///*****************DWELL/VOLTAGE KOMPENSATION************************/
//
//byte CoilOn = digitalRead(Ign1Pin); // Check the status of the ignition coil 1
//
//if (byte CoilOn=LOW){ //Check the voltage and adjust dwell time only one time each revolution.
//
// VoltValue = analogRead(VoltRefPin); // read the value from the VoltRefPin:
// BatteryVolt = map(VoltValue, 0, 1023, 0, 18); // VoltValue 0 to 1032 = 0-18Volt
//
////Dwell times: 8,0V – 5,0msec, 10,0V = 4,0msec, 14,0V = 2,9msec, and 16,0V = 2,5msec.
//if (BatteryVolt<=8){ // runningDwell = 5000; //} //else //if (BatteryVolt<=10){ // runningDwell = map(BatteryVolt, 8, 10, 5000, 4000); //} //else //if (BatteryVolt<=12){ // runningDwell = map(BatteryVolt, 10, 12, 4000, 3450); //} //else //if (BatteryVolt<=14){ // runningDwell = map(BatteryVolt, 12, 14, 3450, 2900); //} //else //if (BatteryVolt<=16){ // runningDwell = map(BatteryVolt, 14, 16, 2900, 2500); //} //else //if (BatteryVolt<=18){ // runningDwell = 2500; // } // // crankingDwell = (runningDwell+1000); // Set the dwell time for cranking. //} ////________________________________________________________________________________ // ///*****************BATTERY VOLTAGE WARNING CODE************************/ // //if (BatteryVolt > 12){ // If voltage is over 12V: Steady green light indicating battery is OK
// LedState = HIGH; // ledState used to set the LED
//}
//else{
///**********IF voltage is under 12V, start warning by blinking with different intervalls****/
//if (BatteryVolt <= 9){ // interval = 500; // interval at which to blink (milliseconds) //} //else //if (BatteryVolt<=10){ // interval = 1500; // interval at which to blink (milliseconds) //} //if (BatteryVolt <= 11){ // interval = 3000; // interval at which to blink (milliseconds) //} //previousMillis = 0; // will store last time LED was updated //currentMillis = millis(); // //if (currentMillis – previousMillis >= interval) {
// previousMillis = currentMillis; // save the last time you blinked the LED
//
// if (LedState == LOW) {
// LedState = HIGH;
// } else {
// LedState = LOW;
// }
// // set the LED with the ledState of the variable:
// digitalWrite(BattOKpin, LedState);
// }
// }
////_____________________________________________________________________________________
}
ไม่มีความคิดเห็น:
แสดงความคิดเห็น