Coding my own open source 24x ECU [beta available]
-
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 aftermarket ECU
Found this bit of info that leads me to believe, as long as you're fine with a 4,000+ year run time limit, your cylinder count limit is 48, only assuming standard paired cylinder/even fire engines.
You do not have the required permissions to view the files attached to this post.
Last edited by AngelMarc on Fri Jun 06, 2025 12:56 am, edited 1 time in total.
Don't stress specific units.
-
antus
- Site Admin
- Posts: 10013
- Joined: Sat Feb 28, 2009 10:34 am
- cars: TX Gemini 2L Twincam 8psi
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Subaru WRX 2007
Re: Coding my own aftermarket ECU
Im not sure how your planning to use the timer but you may only need to time between one event at the next and that'll fire an irq and in that irq handler you can read a cylinder counter, fire a spark or injection event, increment the counter and exit the irq handler. That way you dont have a practicle limit on number of cylinders. If your looking to do sequential injection you might set the second of those 4 timers to start another delay to time the injection to fire straight through an open valve. And then you'd need something to check and re-sync if trigger timing measured does something crazy like difference between pulses is too large meaning an event might have been missed or not enough crank pulses between cam pulses meaning the same.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
-
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 aftermarket ECU
I'm past that. Read my most recent code paste. It's continuously checking sync, always.
Arduinos default for timer reference, apparently the 64 bit value is compared to my array numbers; meaning 4,000 years of continuous running before a timer overflow can cause a problem. I prefer indefinite with timer resets, but I'll take the simplicity that comes with a 4,000 year overflow.
End of injection is a tunable parameter. 1 array for how long after specific sync pulse pattern to start injection, one for how long it stays on.
Same for spark, that gives you dwell and timing.
It's as simple as I laid out... other than adding IAT.
Convenient tuning is just more involved than I have so far. And no ECU code needs changed for convenient tuning. External software can convert conventional "tuner guy" numbers (like degrees and VE) into the format I'm using for this ECU. Then just write entire with Arduino IDE.
Part of that process would be converting microseconds to degrees at each of the 32 RPMs. The patterns are max advance plus microseconds (microseconds being converted to degrees for more advance added to the familiar tuner's max advance). Some of the same for "Dstart" and "Dend" arrays to to get consistent dwell at different timing and different RPM. Same for fuel except pulse width "Iend" is suppose to vary greatly in degrees. You work backwards from there and use "Istart" to get end of injection where you want it.
ECUs can't advance, they can only delay from a starting point. There are no exceptions to that; so this code approaches from the start of that process.
Side note, even modern CPU cahce prefetchers don't do things in advance, they just parallelize part of the process for less delay.
Arduinos default
Code: Select all
micros()End of injection is a tunable parameter. 1 array for how long after specific sync pulse pattern to start injection, one for how long it stays on.
Same for spark, that gives you dwell and timing.
It's as simple as I laid out... other than adding IAT.
Convenient tuning is just more involved than I have so far. And no ECU code needs changed for convenient tuning. External software can convert conventional "tuner guy" numbers (like degrees and VE) into the format I'm using for this ECU. Then just write entire with Arduino IDE.
Part of that process would be converting microseconds to degrees at each of the 32 RPMs. The patterns are max advance plus microseconds (microseconds being converted to degrees for more advance added to the familiar tuner's max advance). Some of the same for "Dstart" and "Dend" arrays to to get consistent dwell at different timing and different RPM. Same for fuel except pulse width "Iend" is suppose to vary greatly in degrees. You work backwards from there and use "Istart" to get end of injection where you want it.
ECUs can't advance, they can only delay from a starting point. There are no exceptions to that; so this code approaches from the start of that process.
Side note, even modern CPU cahce prefetchers don't do things in advance, they just parallelize part of the process for less delay.
Last edited by AngelMarc on Fri Jun 06, 2025 4:39 am, edited 5 times in total.
Don't stress specific units.
-
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 aftermarket ECU
Copy paste in more variations of these lines if you're impatient.
in global variables
In void handleCrankSignal() interrupt routine
in void setup()
in void loop()
That'd get you more channels than you can use.
Later on I plan to remove the arrays and replace them with setup code that pulls the arrays from an SD card and puts them in SRAM for the rest of the code to use, same as it does now. No change to loop or interrupt.
in global variables
Code: Select all
const uint8_t pattern0 = 0b00001111;
const uint8_t pattern1 = 0b01111101;
// Pin 11 (pattern1)
bool pulseActive11 = false;
bool triggerPulse11 = false;
unsigned long pulseStartTime11 = 0;
unsigned long currentOnDelay11 = 1000;
unsigned long currentOffDelay11 = 1000;
// Pin 4 (pattern0)
bool pulseActive4 = false;
bool triggerPulse4 = false;
unsigned long pulseStartTime4 = 0;
unsigned long currentOnDelay4 = 1000;
unsigned long currentOffDelay4 = 1000;
Code: Select all
if (signalHistory == pattern1) triggerPulse11 = true;
if (signalHistory == pattern0) triggerPulse4 = true;
Code: Select all
pinMode(4, OUTPUT);
pinMode(11, OUTPUT);
in void loop()
Code: Select all
if (triggerPulse11) {
triggerPulse11 = false;
pulseStartTime11 = micros();
pulseActive11 = true;
}
if (triggerPulse4) {
triggerPulse4 = false;
pulseStartTime4 = micros();
pulseActive4 = true;
}
// --- Pulse timing for pin 11 (pattern1) ---
if (pulseActive11) {
unsigned long now = micros();
unsigned long elapsed = now - pulseStartTime11;
if (elapsed < currentOnDelay11) {
digitalWrite(11, LOW);
} else if (elapsed < currentOnDelay11 + currentOffDelay11) {
digitalWrite(11, HIGH);
} else {
digitalWrite(11, LOW);
pulseActive11 = false;
}
}
// --- Pulse timing for pin 4 (pattern0) ---
if (pulseActive4) {
unsigned long now = micros();
unsigned long elapsed = now - pulseStartTime4;
if (elapsed < currentOnDelay4) {
digitalWrite(4, LOW);
} else if (elapsed < currentOnDelay4 + currentOffDelay4) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
pulseActive4 = false;
}
}
}
Later on I plan to remove the arrays and replace them with setup code that pulls the arrays from an SD card and puts them in SRAM for the rest of the code to use, same as it does now. No change to loop or interrupt.
Don't stress specific units.
-
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 aftermarket ECU
This part was suppose to be easy. I get this, and a Teensy 4.0 that acts like it's on it's way to the trash bin.
You do not have the required permissions to view the files attached to this post.
Last edited by AngelMarc on Tue Jul 01, 2025 9:57 am, edited 2 times in total.
Don't stress specific units.
-
antus
- Site Admin
- Posts: 10013
- Joined: Sat Feb 28, 2009 10:34 am
- cars: TX Gemini 2L Twincam 8psi
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Subaru WRX 2007
Re: Coding my own aftermarket ECU
Those teensy 4.0 are a decent mcu. If you wanna bin it, fine, but you might want to list it for sale. Someone else might want it.
If you want to solve those problems I'd suggest looking at the pinouts for the MCU. Check which pins you are using and check if they are multi purpose with any other hardware that is getting in the way. You might need to move on different pins. Also check for compatible voltages between the main board and your SDCard interface. You might need a different voltage option, or level shift hardware.
If you want to solve those problems I'd suggest looking at the pinouts for the MCU. Check which pins you are using and check if they are multi purpose with any other hardware that is getting in the way. You might need to move on different pins. Also check for compatible voltages between the main board and your SDCard interface. You might need a different voltage option, or level shift hardware.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
-
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 aftermarket ECU
Already did. And anything mentioning voltage says 3.3 volt.
You do not have the required permissions to view the files attached to this post.
Don't stress specific units.
-
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 aftermarket ECU
I don't sell fried electronics.antus wrote: Mon Jun 09, 2025 1:26 am Those teensy 4.0 are a decent mcu. If you wanna bin it, fine, but you might want to list it for sale. Someone else might want it.
EDIT: Filled a chewing tobacco container with carb cleaner, put the Teensy 4.0 in that, jiggled it around a bit over a couple hours of soaking, heat gunned it dry... seems to cooperate now.
Last edited by AngelMarc on Tue Jul 01, 2025 9:58 am, edited 2 times in total.
Don't stress specific units.
-
antus
- Site Admin
- Posts: 10013
- Joined: Sat Feb 28, 2009 10:34 am
- cars: TX Gemini 2L Twincam 8psi
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Subaru WRX 2007
Re: Coding my own aftermarket ECU
Ahh its toast. I see. Looks like sclk is shared with CAN and an onboard led. That looks optional between 23 and 13 with default on 23 thus out the way but if its cooked its cooked.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
-
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 aftermarket ECU
Not the first time I've missed a shared pin with an LED. Last time was a Teensy 2.0.
All these extra pins not used on the full size 4.1, and they do this.
I desoldered it. If that was the reason, it's too late. It connects just long enough to here the windows sound.
Still fails to initialize on other boards though.
All these extra pins not used on the full size 4.1, and they do this.
I desoldered it. If that was the reason, it's too late. It connects just long enough to here the windows sound.
Still fails to initialize on other boards though.
Don't stress specific units.