2020-10-20 03:40:04 -07:00
/**********************************************************************
__________ ______ ____ _ __ ____ __ __ ________
/ ____ / __ \ / _ / / / __ \ / | / / / __ \ / / / / / / ____ /
/ / / / / // // / / / / / |/ / / /_/ / / / / / / / __
/ / ___ / / _ / // // /___ / /_/ / /| / / ____/ /___/ /_/ / /_/ /
\ ____ / \ ____ / ___ / _____ / \ ____ / _ / | _ / / _ / / _____ / \ ____ / \ ____ /
2023-02-05 20:31:43 -08:00
COIL ON PLUG Script V1 .3 for Atmega328P made by Bouletmarc ( BMDevs )
2020-10-20 03:40:04 -07:00
This Coil On Plug script are intended to be used on Honda / Acura 4 cylinders cars running on a distributor normally . ( Mostly Serie B - D - F - H Engines )
2023-02-05 20:31:43 -08:00
This application samples require two signals , ( ICM & FC1 Pin3 )
It syncs the firing sequence to the specific Cylinder from the FC1 Pin3 signal and then control the firing sequence to the coils with the ICM signal .
It activate 4 x Digital ouputs pins ( used to trigger each coils ) depending on which cylinder should fire .
Connection wiring :
On the ECU , at the FC1 header location , connect the pin1 to 5 V on the arduino
On the ECU , at the FC1 header location , connect the pin3 to D2 on the arduino
On the ECU , at the FC1 header location , connect the pin12 to GND on the arduino
On the ECU , at the big connectors outputs , on the big connector A , CUT the ICM wire going to the body / engine bay and connect the wire coming from the ECU connector to D3 on the arduino
On the Arduino , connect D8 with the ICM wire previously cut going to your body ( to power the tachometer )
On the Arduino , connect D4 with the Coil1 5 v signal
On the Arduino , connect D5 with the Coil2 5 v signal
On the Arduino , connect D6 with the Coil3 5 v signal
On the Arduino , connect D7 with the Coil4 5 v signal
RPM / SYNC Informations :
- The ICM signal become High state first
- The FC1 signal will trigger 6 times High - Low state
- The ICM signal become Low then rapididly High state again
- The FC1 signal will trigger 12 times High - Low state
- The ICM signal become Low then rapididly High state again
- The FC1 signal will trigger 4 times High - Low state
- - The ICM signal become Low then rapididly High state again - - > but this time it ' s to fire the first coil ! !
- The FC1 signal will trigger 5 - 6 times High - Low state ( depending on ignition timing ) between each coils firing
- The FC1 signal doesn ' t loose timing while under ignition cut circonstances
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ICM Signal : ____ - - - - - - - - - - - - - - - _ - - - - - - - - - - - - - - - - - - - - - - - _ - - - - - - - _ - - - - - - - - - - - _ - - - - - - - - - - - _ - - - - - - - - - - - _ - - - - - - - - - - - _ - - - - - - - - - - - _ - - - - - - - - - - - _
FC1 Signal : ________ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _ - _
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2020-10-20 03:40:04 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <digitalWriteFast.h>
// MODIFIABLE PARAMETERS VARS
2023-02-05 20:31:43 -08:00
const bool WastedSpark = false ; //wasted spark fire each cylinders on 2x of the 4x stroke rather than only 1x stroke
const bool InternalDWellTime = false ; //set this to true to spark the coils with the internal DWell times or to false to use the 'external' DWell time incoming from the ICM interrupt
const int DWELL_INTERNAL = 2500 ; // DWell in Microseconds (Sparking time for coils), this value enter in count only if using the Internal DWell Time
const byte fireOrder [ ] = { 1 , 3 , 4 , 2 } ; //Basicly the firing order 1-3-4-2 can it be offseted! ##### {4, 2, 1, 3} ##### {3, 4, 2, 1} ##### {2, 1, 3, 4}
2020-10-20 03:40:04 -07:00
// MODIFIABLE OUTPUT PINS (just make sure you aren't using a pins listed in the Inputs Pins bellow
2023-02-05 20:31:43 -08:00
const byte CoilP1 = 4 ; //Atmega328P=4 ATTiny44=3
const byte CoilP2 = 5 ; //Atmega328P=5 ATTiny44=4
const byte CoilP3 = 6 ; //Atmega328P=6 ATTiny44=5
const byte CoilP4 = 7 ; //Atmega328P=7 ATTiny44=6
const byte RPMOut = 8 ; //Atmega328P=8 ATTiny44=6
2020-12-03 07:32:57 -08:00
//const byte Status = 10; //Atmega328P=10 ATTiny44=8
2020-10-20 03:40:04 -07:00
//#############################################################################################################
// INPUT PINS (DO NOT MODIFY, INPUT PINS ARE SPECIFIC FOR THE INTERRUPTS AND OTHER IMPORTANT FUNCTIONS)
2023-02-05 20:31:43 -08:00
//#############################################################################################################
const byte FC1_Pin3 = 2 ; //Atmega328P=2 ATTiny44=1
const byte ICM_Pin = 3 ; //Atmega328P=3 ATTiny44=2
2020-10-20 03:40:04 -07:00
// VARS (DO NOT MODIFY)
uint8_t CYLINDER = 0 ;
bool desynced = true ;
int SyncCount = 0 ;
2023-02-05 20:31:43 -08:00
int SyncCountICM = 0 ;
int LastSyncCount = 0 ;
int DesyncCount = 0 ;
const int MaxDesyncTime = 500 ; //max desync timer in milliseconds
2020-10-20 03:40:04 -07:00
2023-02-05 20:31:43 -08:00
// VARS FOR RPM SERIAL LOGGING
//uint8_t SPARKS = 0;
//uint16_t RPM = 0;
//unsigned long LASTMILLIS = 0;
2020-10-20 03:40:04 -07:00
2023-02-05 20:31:43 -08:00
//#############################################################################################################
// SETUP/STARTING CODES
2020-10-20 03:40:04 -07:00
//#############################################################################################################
void setup ( ) {
CYLINDER = 0 ;
//Set Outputs
Ignite_Off ( ) ; //Turn Off all Coils before enabling Outputs
pinModeFast ( CoilP1 , OUTPUT ) ;
pinModeFast ( CoilP2 , OUTPUT ) ;
pinModeFast ( CoilP3 , OUTPUT ) ;
pinModeFast ( CoilP4 , OUTPUT ) ;
2023-02-05 20:31:43 -08:00
pinModeFast ( RPMOut , OUTPUT ) ;
2020-12-03 07:32:57 -08:00
//pinModeFast(Status, OUTPUT);
2020-10-20 03:40:04 -07:00
//Set Inputs
2023-02-05 20:31:43 -08:00
pinMode ( FC1_Pin3 , INPUT ) ;
pinMode ( ICM_Pin , INPUT ) ;
2020-10-20 03:40:04 -07:00
//Attach Interrupts
2023-02-05 20:31:43 -08:00
attachInterrupt ( digitalPinToInterrupt ( FC1_Pin3 ) , ISR_FC1_Pin3 , RISING ) ;
attachInterrupt ( digitalPinToInterrupt ( ICM_Pin ) , ISR_ICM_Pin , FALLING ) ;
2020-10-20 03:40:04 -07:00
2023-02-05 20:31:43 -08:00
//Set RPM Serial logging Timer
//SetTimer();
//Serial.begin(115200);
2020-10-20 03:40:04 -07:00
}
//###############################################################
2023-02-05 20:31:43 -08:00
// MAIN RUNNING CODES
//###############################################################
void loop ( ) {
delay ( 1 ) ;
CalculateIsSynced ( ) ;
2020-10-20 03:40:04 -07:00
2023-02-05 20:31:43 -08:00
//Calucalute average DWell time with Engine RPM
//DWELL_INTERNAL = map(RPM, 0, 11000, MAXDWELL, MINDWELL);
2020-10-20 03:40:04 -07:00
}
2023-02-05 20:31:43 -08:00
void CalculateIsSynced ( ) {
2020-10-20 03:40:04 -07:00
if ( ! desynced ) {
2023-02-05 20:31:43 -08:00
if ( LastSyncCount = = SyncCount ) {
DesyncCount + + ;
2020-10-20 03:40:04 -07:00
}
2023-02-05 20:31:43 -08:00
if ( DesyncCount > = MaxDesyncTime ) {
SetDecynced ( ) ;
2020-10-20 03:40:04 -07:00
}
2023-02-05 20:31:43 -08:00
LastSyncCount = SyncCount ;
2020-10-20 03:40:04 -07:00
}
}
void SetDecynced ( ) {
desynced = true ;
Ignite_Off ( ) ;
CYLINDER = 0 ;
SyncCount = 0 ;
2023-02-05 20:31:43 -08:00
SyncCountICM = 0 ;
DesyncCount = 0 ;
LastSyncCount = 0 ;
2020-10-20 03:40:04 -07:00
}
//###############################################################
2023-02-05 20:31:43 -08:00
// COILS FIRING FUNCTIONS
2020-10-20 03:40:04 -07:00
//###############################################################
void FIRE_COIL1 ( ) {
digitalWriteFast ( CoilP1 , HIGH ) ;
2023-02-05 20:31:43 -08:00
if ( WastedSpark ) {
2020-10-20 03:40:04 -07:00
digitalWriteFast ( CoilP4 , HIGH ) ;
2023-02-05 20:31:43 -08:00
}
2020-10-20 03:40:04 -07:00
}
void FIRE_COIL2 ( ) {
digitalWriteFast ( CoilP2 , HIGH ) ;
2023-02-05 20:31:43 -08:00
if ( WastedSpark ) {
2020-10-20 03:40:04 -07:00
digitalWriteFast ( CoilP3 , HIGH ) ;
2023-02-05 20:31:43 -08:00
}
2020-10-20 03:40:04 -07:00
}
void FIRE_COIL3 ( ) {
digitalWriteFast ( CoilP3 , HIGH ) ;
2023-02-05 20:31:43 -08:00
if ( WastedSpark ) {
2020-10-20 03:40:04 -07:00
digitalWriteFast ( CoilP2 , HIGH ) ;
2023-02-05 20:31:43 -08:00
}
2020-10-20 03:40:04 -07:00
}
void FIRE_COIL4 ( ) {
digitalWriteFast ( CoilP4 , HIGH ) ;
2023-02-05 20:31:43 -08:00
if ( WastedSpark ) {
2020-10-20 03:40:04 -07:00
digitalWriteFast ( CoilP1 , HIGH ) ;
2023-02-05 20:31:43 -08:00
}
2020-10-20 03:40:04 -07:00
}
void Ignite_ON ( ) {
//Get the specified cylinder to fire with the firing order
if ( CYLINDER > 0 ) {
//fire the desired cylinder
if ( fireOrder [ CYLINDER - 1 ] = = 1 ) {
FIRE_COIL1 ( ) ;
}
if ( fireOrder [ CYLINDER - 1 ] = = 2 ) {
FIRE_COIL2 ( ) ;
}
if ( fireOrder [ CYLINDER - 1 ] = = 3 ) {
FIRE_COIL3 ( ) ;
}
if ( fireOrder [ CYLINDER - 1 ] = = 4 ) {
FIRE_COIL4 ( ) ;
}
2023-02-05 20:31:43 -08:00
//Fire ICM Out for Tachometer
digitalWriteFast ( RPMOut , LOW ) ;
2020-10-20 03:40:04 -07:00
}
}
void Ignite_Off ( ) {
//Turn off All Coils
digitalWriteFast ( CoilP1 , LOW ) ;
digitalWriteFast ( CoilP2 , LOW ) ;
digitalWriteFast ( CoilP3 , LOW ) ;
digitalWriteFast ( CoilP4 , LOW ) ;
2023-02-05 20:31:43 -08:00
digitalWriteFast ( RPMOut , HIGH ) ;
2020-10-20 03:40:04 -07:00
}
//###############################################################
2023-02-05 20:31:43 -08:00
// INTERRUPTS FC1 AND ICM INPUTS
//###############################################################
void ISR_FC1_Pin3 ( ) {
if ( desynced ) {
CYLINDER = 0 ;
SyncCount + + ;
}
else
{
SyncCount + + ;
//Increase Cylinder firing on the 5th FC1 pulse, prepare it for when the next ICM pulse will fire.
//If the ignition degree are negative, the ICM will pulse slightly before the 6th FC1 pulse, better prepare it in advance on the 5th pulse!
if ( SyncCount = = 5 )
{
CYLINDER + + ;
if ( CYLINDER > 4 ) {
2020-10-20 03:40:04 -07:00
CYLINDER = 1 ;
2023-02-05 20:31:43 -08:00
}
SyncCount = 0 ;
}
2020-10-20 03:40:04 -07:00
2023-02-05 20:31:43 -08:00
//Reset Sync Counting every 6x FC1 pulses
if ( SyncCount = = 6 ) {
SyncCount = 0 ;
}
2020-10-20 03:40:04 -07:00
}
}
2023-02-05 20:31:43 -08:00
void ISR_ICM_Pin ( ) {
//START SYNC SEQUENCE
if ( desynced )
{
//AFTER 5-6x FC1 PULSE
if ( SyncCountICM = = 0 & & ( SyncCount = = 5 | | SyncCount = = 6 ) )
{
SyncCountICM + + ;
SyncCount = 0 ;
}
//AFTER 11-12x FC1 PULSE
if ( SyncCountICM = = 1 & & ( SyncCount = = 11 | | SyncCount = = 12 ) )
{
SyncCountICM + + ;
SyncCount = 0 ;
}
//AFTER 3-4x FC1 PULSE
if ( SyncCountICM = = 2 & & ( SyncCount = = 3 | | SyncCount = = 4 ) )
{
SyncCountICM + + ;
SyncCount = 0 ;
CYLINDER = 1 ;
desynced = false ;
2020-10-20 03:40:04 -07:00
}
2023-02-05 20:31:43 -08:00
}
if ( ! desynced & & CYLINDER > 0 ) {
//Fire the specific Cylinder Coil
Ignite_ON ( ) ;
2020-10-20 03:40:04 -07:00
//Wait for DWell Time
if ( InternalDWellTime ) {
2023-02-05 20:31:43 -08:00
delayMicroseconds ( DWELL_INTERNAL ) ;
2020-10-20 03:40:04 -07:00
}
else {
2023-02-05 20:31:43 -08:00
while ( digitalRead ( ICM_Pin ) = = LOW ) { } ;
2020-10-20 03:40:04 -07:00
}
2023-02-05 20:31:43 -08:00
//Unfire the Coils
2020-10-20 03:40:04 -07:00
Ignite_Off ( ) ;
}
}
2023-02-05 20:31:43 -08:00
//#############################################################################################################
//#############################################################################################################
//#############################################################################################################
//#############################################################################################################
//#############################################################################################################
// RPM SERIAL LOGGING CODES
//#############################################################################################################
/*void SetTimer() {
cli ( ) ; //stop interrupts
//set timer1 interrupt at 5Hz
TCCR1A = 0 ; // set entire TCCR1A register to 0
TCCR1B = 0 ; // same for TCCR1B
TCNT1 = 0 ; //initialize counter value to 0
//################################################
// set compare match register for 1hz increments
//Formula : ((Clock) / (Prescalar * desired interrupt frequency))
// ((16,000,000) / (1 * (XXX Frequency))
// ((16*10^6)) / (1*1024) - 1 (must be <65536)
//################################################
uint16_t FreqHZ = 5 ; //frequency in Hz
OCR1A = ( ( 16000000 ) / ( 1 * ( FreqHZ * 1024 ) ) ) - 1 ;
// turn on CTC mode
TCCR1B | = ( 1 < < WGM12 ) ;
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B | = ( 1 < < CS12 ) | ( 1 < < CS10 ) ;
// enable timer compare interrupt
TIMSK1 | = ( 1 < < OCIE1A ) ;
sei ( ) ; //allow interrupts
}
//###############################################################
ISR ( TIMER1_COMPA_vect ) {
//Turn off interrupts since we use Serial commands, this also ensure we calculate the RPM when nothing trigger the interrupts (interrupts turned off)
noInterrupts ( ) ;
GetRPM ( ) ;
Serial . println ( " RPM: " + String ( RPM ) + " rpm " ) ;
//Attach again the interrupts since we finished calculating RPM and possibly sending Serial datas
attachInterrupt ( digitalPinToInterrupt ( FC1_Pin3 ) , ISR_FC1_Pin3 , FALLING ) ;
attachInterrupt ( digitalPinToInterrupt ( ICM_Pin ) , ISR_ICM_Pin , RISING ) ;
}
void GetRPM ( ) {
//Calculate engine RPM
uint16_t Thistime = millis ( ) - LASTMILLIS ;
RPM = ( ( 30 * 1000 ) / ( Thistime ) * SPARKS ) / 1.666 ;
LASTMILLIS = millis ( ) ;
SPARKS = 0 ;
} */