Re: Coding my own aftermarket ECU
Posted: Fri May 02, 2025 11:41 am
ChatGPT is like the worst customer support.
"Oh, this looks promising... oh, nevermind."
"Oh, this looks promising... oh, nevermind."
Electronic Fuel Injection - Developement & Tuning
https://pcmhacking.net/forums/
Code: Select all
#define CRANK_SENSOR_PIN 15 // Pin connected to the crankshaft sensor
volatile unsigned long lastTime = 0; // Last pulse time
volatile unsigned long pulseHighTime = 0; // Time of high phase
volatile unsigned long pulseLowTime = 0; // Time of low phase
void IRAM_ATTR handleCrankSignal() {
unsigned long currentTime = micros(); // Use micros() for high precision timing
// If it's the rising edge (start of a new pulse)
if (digitalRead(CRANK_SENSOR_PIN) == HIGH) {
pulseHighTime = currentTime - lastTime; // Time the high phase
} else {
pulseLowTime = currentTime - lastTime; // Time the low phase
// Classify the tooth as '1' or '0' based on the duration comparison
if (pulseHighTime > pulseLowTime) {
Serial.println(0); // Tooth is a '1' (high phase is longer)
} else {
Serial.println(1); // Tooth is a '0' (low phase is longer)
}
}
// Update last time for the next pulse
lastTime = currentTime;
}
void setup() {
Serial.begin(115200);
pinMode(CRANK_SENSOR_PIN, INPUT); // Set crank sensor pin as input
attachInterrupt(digitalPinToInterrupt(CRANK_SENSOR_PIN), handleCrankSignal, CHANGE); // Interrupt on change (rising or falling)
Serial.println("Crankshaft Sensor Decoder Initialized.");
}
void loop() {
// The loop is empty as we're handling everything in the interrupt function
}
Code: Select all
#define CRANK_SENSOR_PIN 15 // Pin connected to the crankshaft sensor
#define HISTORY_SIZE 8 // Number of recent results to store
volatile unsigned long lastTime = 0;
volatile unsigned long pulseHighTime = 0;
volatile unsigned long pulseLowTime = 0;
volatile int resultHistory[HISTORY_SIZE] = {0}; // Stores 1s and 0s
volatile int historyIndex = 0;
void IRAM_ATTR handleCrankSignal() {
unsigned long currentTime = micros();
if (digitalRead(CRANK_SENSOR_PIN) == HIGH) {
pulseHighTime = currentTime - lastTime;
} else {
pulseLowTime = currentTime - lastTime;
// Determine 1 or 0 based on high vs. low time
int result = (pulseHighTime > pulseLowTime) ? 0 : 1;
// Save result to history buffer
resultHistory[historyIndex] = result;
historyIndex = (historyIndex + 1) % HISTORY_SIZE;
// Print the current state of the buffer
Serial.print("Pattern: ");
for (int i = 0; i < HISTORY_SIZE; i++) {
Serial.print(resultHistory[(historyIndex + i) % HISTORY_SIZE]);
}
Serial.println();
}
lastTime = currentTime;
}
void setup() {
Serial.begin(115200);
pinMode(CRANK_SENSOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CRANK_SENSOR_PIN), handleCrankSignal, CHANGE);
Serial.println("Crankshaft Decoder with History Initialized.");
}
void loop() {
// Nothing here – all action is in the interrupt
}
Code: Select all
#define CRANK_SENSOR_PIN 0 // Pin connected to the crankshaft sensor
volatile unsigned long lastTime = 0; // Last pulse time
volatile unsigned long pulseHighTime = 0; // Duration of the high phase
volatile unsigned long pulseLowTime = 0; // Duration of the low phase
volatile uint8_t signalHistory = 0; // Last 8 results (bit pattern of 1s and 0s)
const uint8_t matchPattern = 0b00001111; // Replace with your desired pattern
void handleCrankSignal() {
unsigned long currentTime = micros();
if (digitalRead(CRANK_SENSOR_PIN) == HIGH) {
pulseHighTime = currentTime - lastTime;
} else {
pulseLowTime = currentTime - lastTime;
// Determine if this tooth is a '1' or '0'
uint8_t bit = (pulseHighTime > pulseLowTime) ? 0 : 1;
// Shift in the new bit (keep only last 8 bits)
signalHistory = ((signalHistory << 1) | bit) & 0xFF;
// Check if the pattern matches
if (signalHistory == matchPattern) {
digitalWrite(11, HIGH);
} else {
digitalWrite(11, LOW);
}
}
lastTime = currentTime;
}
void setup() {
pinMode(CRANK_SENSOR_PIN, INPUT);
pinMode(11, OUTPUT);
attachInterrupt(digitalPinToInterrupt(CRANK_SENSOR_PIN), handleCrankSignal, CHANGE);
}
void loop() {
// Nothing here – logic handled in interrupt
}
Code: Select all
// Read the captured values from the register
uint16_t high_duration = TC3->COUNT8.CC[0].reg; // Capture 1 (high duration)
uint16_t low_duration = TC3->COUNT8.CC[1].reg; // Capture 2 (low duration)
Code: Select all
TC3->COUNT32.CC[0].reg = YOUR_TOP_VALUE; // If using Match Compare
// OR
TC3->COUNT32.PER.reg = YOUR_TOP_VALUE; // If using waveform generation / periodic reset
Code: Select all
#define CRANK_SENSOR_PIN 2 // Pin connected to crankshaft sensor
volatile 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 = 4095 * 24; // Set this to the initial sum
volatile unsigned long lastTime = 0;
volatile unsigned long pulseHighTime = 0;
volatile unsigned long pulseLowTime = 0;
volatile uint8_t signalHistory = 0;
volatile bool newSample = false;
const uint8_t pattern0 = 0b00001111;
const uint8_t pattern1 = 0b01111101;
const uint8_t pattern2 = 0b11101110;
const uint8_t pattern3 = 0b01110011;
const uint8_t pattern4 = 0b10011000;
const uint8_t pattern5 = 0b11000101;
const uint8_t pattern6 = 0b00101000;
const uint8_t pattern7 = 0b01000001;
void handleCrankSignal() {
unsigned long currentTime = micros();
if (digitalRead(CRANK_SENSOR_PIN) == HIGH) {
pulseHighTime = currentTime - lastTime;
} else {
pulseLowTime = currentTime - lastTime;
uint8_t bit = (pulseHighTime > pulseLowTime) ? 0 : 1;
signalHistory = ((signalHistory << 1) | bit) & 0xFF;
newSample = true; // Signal to loop() to read ADC and update output
// Output patterns
digitalWrite(4, (signalHistory == pattern0) ? HIGH : LOW);
digitalWrite(5, (signalHistory == pattern1) ? HIGH : LOW);
digitalWrite(6, (signalHistory == pattern2) ? HIGH : LOW);
digitalWrite(7, (signalHistory == pattern3) ? HIGH : LOW);
digitalWrite(8, (signalHistory == pattern4) ? HIGH : LOW);
digitalWrite(9, (signalHistory == pattern5) ? HIGH : LOW);
digitalWrite(10, (signalHistory == pattern6) ? HIGH : LOW);
digitalWrite(11, (signalHistory == pattern7) ? HIGH : LOW);
}
lastTime = currentTime;
}
void setup() {
analogReadResolution(12);
// Serial.begin(115200);
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(A0, INPUT);
pinMode(CRANK_SENSOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CRANK_SENSOR_PIN), handleCrankSignal, CHANGE);
}
void loop() {
if (newSample) {
newSample = false;
// Rolling average: subtract old value, read new one, add it
total -= readings[bufIndex];
int newVal = analogRead(A0);
readings[bufIndex] = newVal;
total += newVal;
bufIndex = (bufIndex + 1) % 24;
int avg12bit = total / 24;
int avg8bit = avg12bit >> 4;
// Serial.println(avg8bit);
}
}