Coding my own open source 24x ECU [beta available]

Disassembly, Reassembly, Tools and devleopment. Going deep with Hardware and Software.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

For testing purposes.
...
What a mess.
You do not have the required permissions to view the files attached to this post.
Don't stress specific units.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

Alright, first test will be a 2 stroke, after I grab some some fuel line and my 'fuel rail' in the morning.
A Tecumseh HSK845 (150 cc), with a wing-it base tune.

Code: Select all

volatile unsigned long IATFuel[129] = {128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380,382,384};
//Comment above and uncomment below for no temp scaling, 256 = 100% or no change
//volatile unsigned long IATFuel[129] = {256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256};
//volatile unsigned long IATSpark [129] = {128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380,382,384};
//Comment above and uncomment below for no temp scaling, 256 = 100% or no change
volatile unsigned long IATSpark [129] = {256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256};

volatile unsigned long Limiter = 278 ; //Spark cut rev limiter, microseconds per 15 degrees. divide 2,500,000 by this number to get RPM. Limiter is set after rolling average and before being constrained for table access, can be set beyond table limits

volatile unsigned long EOIT [17] = {500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500};// these were test values, also in microseconds, change as needed
 //                                0 RPM ---------------------------------------------------------------------------9600 RPM same 600 spacing
 
volatile unsigned long Dstart [17] [17] = { //lower numbers = more advance, numbers are in microseconds
{2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333, 2954333},//"0" RPM
{94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611, 94611},// 600
{44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611, 44611},// 1200
{28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407, 28407},// 1800
{19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958, 19958},// 2400
{15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167, 15167},// 3000
{11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741, 11741},// 3600
{9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294, 9294},// 4200
{7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632, 7632},// 4800
{6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185, 6185},// 5400
{5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167, 5167},// 6000
{4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207, 4207},// 6600
{3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523, 3523},// 7200
{2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944, 2944},// 7800
{2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448, 2448},// 8400
{2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019},// 9000
{1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642} // 9600
};//low KPA --------------------------------------------------------------------------------- high KPA

volatile unsigned long Iend [17] [17] = { //injector on time, in microseconds
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},//"0" RPM
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 600
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 1200
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 1800
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 2400
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 3000
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 3600
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 4200
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 4800
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 5400
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 6000
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 6600
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 7200
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 7800
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 8400
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266},// 9000
{284, 284, 568, 853, 1137, 1422, 1706, 1991, 2275, 1560, 2844, 3129, 3413, 3697, 3982, 4266, 4266}// 9600
};//low KPA --------------------------------------------------------------------------------- high KPA

Code: Select all

#include "TuneArrays.h" 

const uint8_t pattern0 = 0b01111101;//0 degrees / TDC #1 and paired cylinder
const uint8_t pattern1 = 0b01110011;//90 degrees
const uint8_t pattern2 = 0b11000101;//180 degrees
const uint8_t pattern3 = 0b01000001;//270 degrees

uint8_t RPMIndex = 0;
uint8_t adcIndex = 0;
unsigned long currentOnDelaySpark = 0;
unsigned long currentOffDelaySpark = 0;
unsigned long currentOnDelayFuel = 0;
unsigned long currentOffDelayFuel = 0;
bool pulseHighSpark0 = false;
bool pulseActiveSpark0 = false;
bool triggerPulseSpark0 = false;
unsigned long pulseStartTimeSpark0 = 0;
unsigned long pulseWidthSpark0 = 0;
bool pulseHighSpark1 = false;
bool pulseActiveSpark1 = false;
bool triggerPulseSpark1 = false;
unsigned long pulseStartTimeSpark1 = 0;
unsigned long pulseWidthSpark1 = 0;
bool pulseHighSpark2 = false;
bool pulseActiveSpark2 = false;
bool triggerPulseSpark2 = false;
unsigned long pulseStartTimeSpark2 = 0;
unsigned long pulseWidthSpark2 = 0;
bool pulseHighSpark3 = false;
bool pulseActiveSpark3 = false;
bool triggerPulseSpark3 = false;
unsigned long pulseStartTimeSpark3 = 0;
unsigned long pulseWidthSpark3 = 0;
bool pulseHighSpark4 = false;
bool pulseActiveSpark4 = false;
bool triggerPulseSpark4 = false;
unsigned long pulseStartTimeSpark4 = 0;
unsigned long pulseWidthSpark4 = 0;
bool pulseHighSpark5 = false;
bool pulseActiveSpark5 = false;
bool triggerPulseSpark5 = false;
unsigned long pulseStartTimeSpark5 = 0;
unsigned long pulseWidthSpark5 = 0;
bool pulseHighSpark6 = false;
bool pulseActiveSpark6 = false;
bool triggerPulseSpark6 = false;
unsigned long pulseStartTimeSpark6 = 0;
unsigned long pulseWidthSpark6 = 0;
bool pulseHighSpark7 = false;
bool pulseActiveSpark7 = false;
bool triggerPulseSpark7 = false;
unsigned long pulseStartTimeSpark7 = 0;
unsigned long pulseWidthSpark7 = 0;
bool pulseHighFuel0 = false;
bool pulseActiveFuel0 = false;
bool triggerPulseFuel0 = false;
unsigned long pulseStartTimeFuel0 = 0;
unsigned long pulseWidthFuel0 = 0;
bool pulseHighFuel1 = false;
bool pulseActiveFuel1 = false;
bool triggerPulseFuel1 = false;
unsigned long pulseStartTimeFuel1 = 0;
unsigned long pulseWidthFuel1 = 0;
bool pulseHighFuel2 = false;
bool pulseActiveFuel2 = false;
bool triggerPulseFuel2 = false;
unsigned long pulseStartTimeFuel2 = 0;
unsigned long pulseWidthFuel2 = 0;
bool pulseHighFuel3 = false;
bool pulseActiveFuel3 = false;
bool triggerPulseFuel3 = false;
unsigned long pulseStartTimeFuel3 = 0;
unsigned long pulseWidthFuel3 = 0;
bool pulseHighFuel4 = false;
bool pulseActiveFuel4 = false;
bool triggerPulseFuel4 = false;
unsigned long pulseStartTimeFuel4 = 0;
unsigned long pulseWidthFuel4 = 0;
bool pulseHighFuel5 = false;
bool pulseActiveFuel5 = false;
bool triggerPulseFuel5 = false;
unsigned long pulseStartTimeFuel5 = 0;
unsigned long pulseWidthFuel5 = 0;
bool pulseHighFuel6 = false;
bool pulseActiveFuel6 = false;
bool triggerPulseFuel6 = false;
unsigned long pulseStartTimeFuel6 = 0;
unsigned long pulseWidthFuel6 = 0;
bool pulseHighFuel7 = false;
bool pulseActiveFuel7 = false;
bool triggerPulseFuel7 = false;
unsigned long pulseStartTimeFuel7 = 0;
unsigned long pulseWidthFuel7 = 0;

int readings[24] {4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095};       // Circular buffer
int bufIndex = 0;       // Buffer index
long total = 4095L * 24;  // Set this to the initial sum

int readings2[24];       // Circular buffer
int bufIndex2 = 0;       // Buffer index
long total2 = 0L * 24;  // Set this to the initial sum

int readings3[24];       // Circular buffer
int bufIndex3 = 0;       // Buffer index
unsigned long total3 = 0UL * 24;  // Set this to the initial sum

unsigned long lastTime = 0;
unsigned long pulseHighTime = 0;
unsigned long pulseLowTime = 0;
uint8_t signalHistory = 0b00000000;
bool newSample = false;

void handleCrankSignal() {
  unsigned long currentTime = micros();
  if (digitalRead(22) == HIGH) {
    pulseLowTime = currentTime - lastTime;
  } else {
    pulseHighTime = currentTime - lastTime;
    uint8_t bit = (pulseHighTime > pulseLowTime) ? 1 : 0;
    signalHistory = ((signalHistory << 1) | bit) & 0xFF;

    newSample = true; // flag to loop()
  }
  lastTime = currentTime;
}

void handleSparkPulse(uint8_t pin, unsigned long startTime, bool &highFlag) {
  unsigned long now = micros();
  unsigned long elapsed = now - startTime;

  if (elapsed < currentOnDelaySpark) {
    digitalWrite(pin, LOW);
  } else {
    highFlag = true;
  }
}

void handleSparkPulse2(uint8_t pin, unsigned long startTime, bool &activeFlag, bool &highFlag, unsigned long &OnTime) {
  unsigned long now = micros();
  unsigned long elapsed = now - startTime;
  
  if (activeFlag){
    OnTime = currentOnDelaySpark + currentOffDelaySpark;
    activeFlag = false;
    digitalWrite(pin, HIGH);
  }
    if (elapsed > OnTime) {
    digitalWrite(pin, LOW);
    highFlag = false;
  }
}


void handleFuelPulse(uint8_t pin, unsigned long startTime, bool &highFlag) {
  unsigned long now = micros();
  unsigned long elapsed = now - startTime;

  if (elapsed < currentOnDelayFuel) {
    digitalWrite(pin, LOW);
  } else {
    highFlag = true;
  }
}

void handleFuelPulse2(uint8_t pin, unsigned long startTime, bool &activeFlag, bool &highFlag, unsigned long &OnTime) {
  unsigned long now = micros();
  unsigned long elapsed = now - startTime;
  
  if (activeFlag){
    OnTime = currentOnDelayFuel + currentOffDelayFuel;
    activeFlag = false;
    digitalWrite(pin, HIGH);
  }
    if (elapsed > OnTime) {
    digitalWrite(pin, LOW);
    highFlag = false;
  }
}





void setup() {
  analogReadResolution(12);
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(22, INPUT);
  pinMode(21, INPUT);
  attachInterrupt(digitalPinToInterrupt(22), handleCrankSignal, CHANGE);
}

void loop() {
  if (newSample) {
    newSample = false;

        //if (digitalRead(21) == HIGH){
    // Spark patterns
    if (signalHistory == pattern0) {triggerPulseSpark0 = true; triggerPulseFuel0 = true;}
    if (signalHistory == pattern1) {triggerPulseSpark2 = true; triggerPulseFuel2 = true;}
    if (signalHistory == pattern2) {triggerPulseSpark4 = true; triggerPulseFuel4 = true;}
    if (signalHistory == pattern3) {triggerPulseSpark6 = true; triggerPulseFuel6 = true;}
    //} 
        //if (digitalRead(21) == LOW) {
    if (signalHistory == pattern0) {triggerPulseSpark1 = true; triggerPulseFuel1 = true;}
    if (signalHistory == pattern1) {triggerPulseSpark3 = true; triggerPulseFuel3 = true;}
    if (signalHistory == pattern2) {triggerPulseSpark5 = true; triggerPulseFuel5 = true;}
    if (signalHistory == pattern3) {triggerPulseSpark7 = true; triggerPulseFuel7 = true;}
    //}


    unsigned long RPMTime = pulseHighTime + pulseLowTime;//Calculate RPMtime (µs per 15 degrees)
    total2 -= readings2[bufIndex2];
    unsigned long newVal2 = RPMTime;
    readings2[bufIndex2] = newVal2;
    total2 += newVal2;
    bufIndex2 = (bufIndex2 + 1) % 24;
    unsigned long RPMTimeavg = total2 / 24UL;
    uint Predicted360Time = RPMTimeavg * 24;//48 for full sequential, 720 degrees. 24 for waste spark, 360 degrees.

    // FIXED: Rev limiter + low-RPM cutoff
    unsigned long Dwell = 4000UL;
    if (RPMTimeavg < Limiter) {
      Dwell = 0UL;  // spark cut when RPM too high
    } else if (RPMTimeavg > 125000UL) {
     Dwell = 0UL;  // below 20 RPM, also cut spark
    }
    
    RPMTimeavg = constrain(RPMTimeavg, 278UL, 3000000UL);  // 9600 RPM to 0 RPM. Always round the decimal up, even if it's 0.0001. Not overflowing arrays is important
    // --- ADC rolling average (12-bit to 7-bit scale) ---
    total -= readings[bufIndex];
    int newVal = analogRead(A0);
    readings[bufIndex] = newVal;
    total += newVal;
    bufIndex = (bufIndex + 1) % 24;
    int avg12bit = total / 24;
    adcIndex = avg12bit >> 8; //Discarding LSBs to match array resolution
    uint32_t IndexFull = ((uint64_t)2500000 << 8) / ((uint32_t)RPMTimeavg * 600);
    
    uint16_t IndexWhole = IndexFull >> 8;
    uint8_t Frac = IndexFull & 0xFF;
    int Frac2 = avg12bit & 0x1F;

    int TerpA = Dstart[IndexWhole][adcIndex]; 
    int TerpB = Dstart[IndexWhole +1][adcIndex];                                   
    int TerpD = TerpA + (((TerpB - TerpA) * Frac) >> 8);
    int TerpA2 = Dstart[IndexWhole][adcIndex +1];                                           
    int TerpB2 = Dstart[IndexWhole +1][adcIndex +1];
    int TerpD2 = TerpA2 + (((TerpB2 - TerpA2) * Frac) >> 8);
    int TerpD5 = TerpD + (((TerpD2 - TerpD) * Frac2) >> 8);  

    int TerpA3 = Iend[IndexWhole][adcIndex+1];                                           
    int TerpB3 = Iend[IndexWhole +1][adcIndex +1];
    int TerpD3 = TerpA3 + (((TerpB3 - TerpA3) * Frac) >> 8);
    int TerpA4 = Iend[IndexWhole][adcIndex];
    int TerpB4 = Iend[IndexWhole +1][adcIndex];
    int TerpD4 = TerpA4 + (((TerpB4 - TerpA4) * Frac) >> 8);
    int TerpD6 = TerpD4 + (((TerpD3 - TerpD4) * Frac2) >> 8); 

    total3 -= readings3[bufIndex3];
    int newVal3 = analogRead(A1);
    readings3[bufIndex3] = newVal3;
    total3 += newVal3;
    bufIndex3 = (bufIndex3 + 1) % 24;
    int IATavg = total3 / 24;
    int IAT7bit = IATavg >> 5;

    int Temp = IATSpark [IAT7bit];
    int Scaled = ((TerpD5 * Temp) >>8);
    int TrimA = EOIT [IndexWhole];
    int TrimB = EOIT [IndexWhole +1];
    int TrimTerp = TrimA + (((TrimB - TrimA) * Frac) >> 8);

    int Temp2 = IATFuel [IAT7bit];
    int Scaled3 = ((TerpD6 * Temp2) >>8);
    int ScaledOffset = Predicted360Time - (Scaled3 + TrimTerp);
    if (ScaledOffset < 0) ScaledOffset = 0;

    if (RPMTimeavg > 125000UL){  //if RPM below minimum = 20RPM
      Scaled3 = 0UL;             //Fuel off 
      signalHistory = 0b00000000;//Sync reset
    }



    // --- Update delay values from tables ---
    currentOnDelaySpark = Scaled;
    currentOffDelaySpark = Dwell;

    currentOnDelayFuel = ScaledOffset;
    currentOffDelayFuel = Scaled3;
  }
  // --- Check for new pulse triggers from crank handler ---
   // --- Spark pulse triggers ---
  if (triggerPulseSpark0) { triggerPulseSpark0 = false; pulseStartTimeSpark0 = micros(); pulseActiveSpark0 = true; }
  if (triggerPulseSpark1) { triggerPulseSpark1 = false; pulseStartTimeSpark1 = micros(); pulseActiveSpark1 = true; }
  if (triggerPulseSpark2) { triggerPulseSpark2 = false; pulseStartTimeSpark2 = micros(); pulseActiveSpark2 = true; }
  if (triggerPulseSpark3) { triggerPulseSpark3 = false; pulseStartTimeSpark3 = micros(); pulseActiveSpark3 = true; }
  if (triggerPulseSpark4) { triggerPulseSpark4 = false; pulseStartTimeSpark4 = micros(); pulseActiveSpark4 = true; }
  if (triggerPulseSpark5) { triggerPulseSpark5 = false; pulseStartTimeSpark5 = micros(); pulseActiveSpark5 = true; }
  if (triggerPulseSpark6) { triggerPulseSpark6 = false; pulseStartTimeSpark6 = micros(); pulseActiveSpark6 = true; }
  if (triggerPulseSpark7) { triggerPulseSpark7 = false; pulseStartTimeSpark7 = micros(); pulseActiveSpark7 = true; }

  // --- Fuel pulse triggers ---
  if (triggerPulseFuel0) { triggerPulseFuel0 = false; pulseStartTimeFuel0 = micros(); pulseActiveFuel0 = true; }
  if (triggerPulseFuel1) { triggerPulseFuel1 = false; pulseStartTimeFuel1 = micros(); pulseActiveFuel1 = true; }
  if (triggerPulseFuel2) { triggerPulseFuel2 = false; pulseStartTimeFuel2 = micros(); pulseActiveFuel2 = true; }
  if (triggerPulseFuel3) { triggerPulseFuel3 = false; pulseStartTimeFuel3 = micros(); pulseActiveFuel3 = true; }
  if (triggerPulseFuel4) { triggerPulseFuel4 = false; pulseStartTimeFuel4 = micros(); pulseActiveFuel4 = true; }
  if (triggerPulseFuel5) { triggerPulseFuel5 = false; pulseStartTimeFuel5 = micros(); pulseActiveFuel5 = true; }
  if (triggerPulseFuel6) { triggerPulseFuel6 = false; pulseStartTimeFuel6 = micros(); pulseActiveFuel6 = true; }
  if (triggerPulseFuel7) { triggerPulseFuel7 = false; pulseStartTimeFuel7 = micros(); pulseActiveFuel7 = true; }

  // --- Spark pulse timing (Pins 0 to 7) ---
  if (pulseHighSpark0) handleSparkPulse2(0, pulseStartTimeSpark0, pulseActiveSpark0, pulseHighSpark0, pulseWidthSpark0);
  if (pulseHighSpark1) handleSparkPulse2(1, pulseStartTimeSpark1, pulseActiveSpark1, pulseHighSpark1, pulseWidthSpark1);
  if (pulseHighSpark2) handleSparkPulse2(2, pulseStartTimeSpark2, pulseActiveSpark2, pulseHighSpark2, pulseWidthSpark2);
  if (pulseHighSpark3) handleSparkPulse2(3, pulseStartTimeSpark3, pulseActiveSpark3, pulseHighSpark3, pulseWidthSpark3);
  if (pulseHighSpark4) handleSparkPulse2(4, pulseStartTimeSpark4, pulseActiveSpark4, pulseHighSpark4, pulseWidthSpark4);
  if (pulseHighSpark5) handleSparkPulse2(5, pulseStartTimeSpark5, pulseActiveSpark5, pulseHighSpark5, pulseWidthSpark5);
  if (pulseHighSpark6) handleSparkPulse2(6, pulseStartTimeSpark6, pulseActiveSpark6, pulseHighSpark6, pulseWidthSpark6);
  if (pulseHighSpark7) handleSparkPulse2(7, pulseStartTimeSpark7, pulseActiveSpark7, pulseHighSpark7, pulseWidthSpark7);

  if (pulseActiveSpark0) handleSparkPulse(0, pulseStartTimeSpark0, pulseHighSpark0);
  if (pulseActiveSpark1) handleSparkPulse(1, pulseStartTimeSpark1, pulseHighSpark1);
  if (pulseActiveSpark2) handleSparkPulse(2, pulseStartTimeSpark2, pulseHighSpark2);
  if (pulseActiveSpark3) handleSparkPulse(3, pulseStartTimeSpark3, pulseHighSpark3);
  if (pulseActiveSpark4) handleSparkPulse(4, pulseStartTimeSpark4, pulseHighSpark4);
  if (pulseActiveSpark5) handleSparkPulse(5, pulseStartTimeSpark5, pulseHighSpark5);
  if (pulseActiveSpark6) handleSparkPulse(6, pulseStartTimeSpark6, pulseHighSpark6);
  if (pulseActiveSpark7) handleSparkPulse(7, pulseStartTimeSpark7, pulseHighSpark7);

  // --- Fuel pulse timing (Pins 8 to 15) ---
  if (pulseHighFuel0) handleFuelPulse2(8, pulseStartTimeFuel0, pulseActiveFuel0, pulseHighFuel0, pulseWidthFuel0);
  if (pulseHighFuel1) handleFuelPulse2(9, pulseStartTimeFuel1, pulseActiveFuel1, pulseHighFuel1, pulseWidthFuel1);
  if (pulseHighFuel2) handleFuelPulse2(10, pulseStartTimeFuel2, pulseActiveFuel2, pulseHighFuel2, pulseWidthFuel2);
  if (pulseHighFuel3) handleFuelPulse2(11, pulseStartTimeFuel3, pulseActiveFuel3, pulseHighFuel3, pulseWidthFuel3);
  if (pulseHighFuel4) handleFuelPulse2(12, pulseStartTimeFuel4, pulseActiveFuel4, pulseHighFuel4, pulseWidthFuel4);
  if (pulseHighFuel5) handleFuelPulse2(13, pulseStartTimeFuel5, pulseActiveFuel5, pulseHighFuel5, pulseWidthFuel5);
  if (pulseHighFuel6) handleFuelPulse2(14, pulseStartTimeFuel6, pulseActiveFuel6, pulseHighFuel6, pulseWidthFuel6);
  if (pulseHighFuel7) handleFuelPulse2(15, pulseStartTimeFuel7, pulseActiveFuel7, pulseHighFuel7, pulseWidthFuel7);

  if (pulseActiveFuel0) handleFuelPulse(8, pulseStartTimeFuel0, pulseHighFuel0);
  if (pulseActiveFuel1) handleFuelPulse(9, pulseStartTimeFuel1, pulseHighFuel1);
  if (pulseActiveFuel2) handleFuelPulse(10, pulseStartTimeFuel2, pulseHighFuel2);
  if (pulseActiveFuel3) handleFuelPulse(11, pulseStartTimeFuel3, pulseHighFuel3);
  if (pulseActiveFuel4) handleFuelPulse(12, pulseStartTimeFuel4, pulseHighFuel4);
  if (pulseActiveFuel5) handleFuelPulse(13, pulseStartTimeFuel5, pulseHighFuel5);
  if (pulseActiveFuel6) handleFuelPulse(14, pulseStartTimeFuel6, pulseHighFuel6);
  if (pulseActiveFuel7) handleFuelPulse(15, pulseStartTimeFuel7, pulseHighFuel7);
}

Last edited by AngelMarc on Mon Sep 22, 2025 6:37 am, edited 3 times in total.
Don't stress specific units.
MPC001
Posts: 174
Joined: Sat May 05, 2018 11:41 am

Re: Coding my own open source 24x ECU [beta available]

Post by MPC001 »

:thumbup: 😎
User avatar
Gareth
Posts: 2678
Joined: Fri Mar 14, 2014 10:37 am
Location: Bacchus Marsh, Vic

Re: Coding my own open source 24x ECU [beta available]

Post by Gareth »

Can't wait to see a video of this running!! :thumbup:
According to chemistry, alcohol is a solution...
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

Figured I'd at least do a hardware electrical test. Well, sent a pico 10 volts and fried it. Forgot which voltage regulator I had, and didn't adjust it down before plugging it in.
Good thing I had 2. Hook other one up... I can't get shit out of it. Test it and output board on bench with signal gen and eventually... https://www.youtube.com/watch?v=ozLFKbWECEk
Put a resistor plug in, didn't complain anymore; haven't seen dropped pulses since.
Last edited by AngelMarc on Tue Sep 23, 2025 12:39 am, edited 3 times in total.
Don't stress specific units.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

... as far as I can tell, my crank sensor is dead. Pulls voltage low whether metal is present or not. Another damn delay and expense.
Last edited by AngelMarc on Mon Sep 22, 2025 11:45 pm, edited 1 time in total.
Don't stress specific units.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

And in the process of troubleshooting crank sensor, I sent 5 volts to GPIO of the other one, so it probably died too. I'll find out for sure another day. All the crank sensor wires are black, easy to mix up, and then re-mix up when you think you're sorting them out, especially with that spaghetti mess.
Don't stress specific units.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

Thought I'd get back to it today.
You do not have the required permissions to view the files attached to this post.
Don't stress specific units.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

Try again a week from now when yet another sensor shows up. Or I use my $12 generic gen 3 LS sensor that works fine and make the appropriate circuit to use it...
Don't stress specific units.
User avatar
AngelMarc
Posts: 612
Joined: Sat Apr 08, 2023 11:23 am
cars: A CB450 running to 8,000RPM with a P59.

Re: Coding my own open source 24x ECU [beta available]

Post by AngelMarc »

Got the new generic 12595966 sensor. Bench tested fine. Getting closer... again.
Don't stress specific units.