Coding my own aftermarket ECU
Re: Coding my own aftermarket ECU
Looking at this, it might be more accurate to say the range of interpolation "noise" is Frac = 0 to Frac = what the code calculation says it should be.
https://www.youtube.com/watch?v=A4_zRVw8nag
https://www.youtube.com/watch?v=A4_zRVw8nag
Don't stress specific units.
Re: Coding my own aftermarket ECU
My best guess is, code throws the math at floating point unit, which takes multiple clock cycles to complete the math, but after just one clock cycle, grabs the value before the multiple cycle float math finishes... a race condition. Something like that. Not trying to fix that today. I'll test it later with a short delay (a few microseconds) after lines with float math. See if it get's more consistent. Go for optimizing after that.
EDIT: Didn't work.
EDIT: Didn't work.
Don't stress specific units.
Re: Coding my own aftermarket ECU
Blindly stabbing at it by replacing variables with constants make it seem like its signal generator instability... but I only see a measurable 5 RPM variation.
Don't stress specific units.
Re: Coding my own aftermarket ECU
It's not the interpolation code itself.
Code: Select all
// --- Calculate RPM timing (µs per event) ---
unsigned long RPMTime = pulseHighTime + pulseLowTime;
RPMTime = constrain(RPMTime, 134, 125000); // 18600 RPM to 20 RPM
IndexFull = (2500000/(RPMTime*600));
IndexWhole = (int)IndexFull;
IndexPlusOne = IndexWhole + 1;
IndexPlusOne = constrain(IndexPlusOne, 0, 31);
TerpA = Iend[9][adcIndex];//
TerpB = Iend[10][adcIndex];//
Diff = TerpB - TerpA;
Frac = .5; //IndexFull - IndexWhole;
TerpC = Diff * Frac;
TerpD = TerpA + TerpC;
Last edited by AngelMarc on Sat Jun 14, 2025 9:34 pm, edited 1 time in total.
Don't stress specific units.
Re: Coding my own aftermarket ECU
No interpolation, just involving a truncated float. Horrible results
https://www.youtube.com/watch?v=Z99Jf7TEtJo
Replacing
with
Get's rid of the weird double spikes... somehow.
Code: Select all
unsigned long RPMTime = pulseHighTime + pulseLowTime;
RPMTime = constrain(RPMTime, 134, 125000); // 18600 RPM to 20 RPM
IndexFull = (2500000/(RPMTime*600));
IndexWhole = (int)IndexFull;
//IndexPlusOne = IndexWhole + 1;
//IndexPlusOne = constrain(IndexPlusOne, 0, 31);
//TerpA = Iend[IndexWhole][adcIndex];//
//TerpB = Iend[IndexPlusOne][adcIndex];//
//Diff = TerpB - TerpA;
//Frac = .5; //IndexFull - IndexWhole;
//TerpC = Diff * Frac;
//TerpD = TerpA + TerpC;
// --- Update delay values from tables ---
currentOnDelay11 = Dstart[IndexWhole][adcIndex];
currentOffDelay11 = Dend[IndexWhole][adcIndex];
currentOnDelay4 = Istart[IndexWhole][adcIndex];
currentOnDelay4 = Iend[IndexWhole][adcIndex];
//currentOffDelay4 = TerpD;
Replacing
Code: Select all
IndexFull = (2500000/(RPMTime*600));
IndexWhole = (int)IndexFull;
Code: Select all
IndexWhole = (int)(2500000/(RPMTime*600));
Don't stress specific units.
- antus
- Site Admin
- Posts: 8996
- Joined: Sat Feb 28, 2009 8:34 pm
- cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B - Contact:
Re: Coding my own aftermarket ECU
It can only be a race condition if you have things running in parallel, eg one in the main thread on the main CPU and code in an interrupt handler that can interrupt the main loop and run something else. Or an MCU with 2 cores and you have code running in both. Since its bare metal there is no operating system to provide threads in software that could create a race condition.
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
Re: Coding my own aftermarket ECU
ChatGPT suggested fixed point code that works better, but still seems awefuly sloppy.
I sweep the analog input and see a range that looks just as bad as float.
Code: Select all
unsigned long RPMTime = pulseHighTime + pulseLowTime;
RPMTime = constrain(RPMTime, 134, 125000); // Clamp RPMTime for your RPM range
// Calculate IndexFull in fixed-point 16.16 format
uint32_t IndexFull_fixed = (uint32_t)((2500000ULL << 16) / (RPMTime * 600UL)); // <<16 for fractional bits
uint16_t Frac_fixed = IndexFull_fixed & 0xFFFF; // Fractional part (0 to 65535)
uint8_t IndexWhole = (IndexFull_fixed >> 16); // Whole part
IndexWhole = constrain(IndexWhole, 0, 31);
uint8_t IndexPlusOne = constrain(IndexWhole + 1, 0, 31);
// Get lookup values from your table
uint16_t TerpA = Iend[IndexWhole][adcIndex];
uint16_t TerpB = Iend[IndexPlusOne][adcIndex];
// Integer linear interpolation: TerpD = TerpA + ( (TerpB - TerpA) * Frac_fixed ) >> 16;
int16_t Diff = (int16_t)TerpB - (int16_t)TerpA;
uint16_t TerpD = TerpA + ((int32_t)Diff * Frac_fixed >> 16);
// TerpD is your interpolated result, integer, .00 precision (whole number)
I sweep the analog input and see a range that looks just as bad as float.
Last edited by AngelMarc on Thu Jun 12, 2025 6:48 pm, edited 1 time in total.
Don't stress specific units.
Re: Coding my own aftermarket ECU
It's my understanding Arduino uses MBed OS as firmware for ARM.antus wrote: ↑Thu Jun 12, 2025 6:15 pm It can only be a race condition if you have things running in parallel, eg one in the main thread on the main CPU and code in an interrupt handler that can interrupt the main loop and run something else. Or an MCU with 2 cores and you have code running in both. Since its bare metal there is no operating system to provide threads in software that could create a race condition.
Don't stress specific units.
- antus
- Site Admin
- Posts: 8996
- Joined: Sat Feb 28, 2009 8:34 pm
- cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B - Contact:
Re: Coding my own aftermarket ECU
Hmm thats interesting. I thought arduino was all C on bare metal. A quick google found me this https://forum.arduino.cc/t/is-it-possib ... d/1162356/ and also a few notes that say mbed goes end of life mid 2026. So I think you may have 3 opions. mbed, arduino core or bare metal. Ill have to read some more.
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
Re: Coding my own aftermarket ECU
I'm not crazy about the abstraction layers, but I'm certainly not ready to do this in assembly. Extra windows with "live" updates of some of the compilation steps would be cool. Arduino specific library interporated away, then idk plain C, then assembly. Not sure how much it would help me right now; but I'm sure it'd be wonderful for some. Something like Ghidra's function graph, scroll one and it shows you where it is in the other.
Last edited by AngelMarc on Thu Jun 12, 2025 7:44 pm, edited 1 time in total.
Don't stress specific units.