Fixed pin mappings and task logic

This commit is contained in:
Emanuele Trabattoni
2026-03-25 17:19:53 +01:00
parent 8c5b7d4a1c
commit bece80ad6c
4 changed files with 179 additions and 78 deletions

View File

@@ -1,13 +1,16 @@
#pragma once
#include <Arduino.h> #include <Arduino.h>
#include "soc/gpio_struct.h" #include "soc/gpio_struct.h"
#include "pins.h" #include "pins.h"
#define CORE_0 0 #define CORE_0 0
#define CORE_1 1 #define CORE_1 1
#define TASK_STACK 4096 // in words #define TASK_STACK 4096 // in words
#define TASK_PRIORITY 2 // priorità leggermente più alta #define TASK_PRIORITY 2 // priorità leggermente più alta
#define IGN_BUF_SIZE 128
// ===================== // =====================
// Event Flags (bitmask) // Event Flags (bitmask)
// ===================== // =====================
@@ -20,41 +23,82 @@
#define TRIG_FLAG_B34P (1 << 5) #define TRIG_FLAG_B34P (1 << 5)
#define TRIG_FLAG_B34N (1 << 7) #define TRIG_FLAG_B34N (1 << 7)
#define SPARK_FLAG_A12 (1 << 0)
#define SPARK_FLAG_A34 (1 << 2)
#define SPARK_FLAG_B12 (1 << 1)
#define SPARK_FLAG_B34 (1 << 3)
// Task handle // Task handle
TaskHandle_t trigA_TaskHandle = NULL; TaskHandle_t trigA_TaskHandle = NULL;
TaskHandle_t trigB_TaskHandle = NULL; TaskHandle_t trigB_TaskHandle = NULL;
// Task internal Status // Spark Status
struct taskStatus { enum sparkStatus {
int64_t trig12_start; SPARK_POS_OK,
int64_t trig34_start; SPARK_NEG_OK,
SPARK_POS_SKIP,
int64_t trig12_time; SPARK_NEG_SKIP,
int64_t trig34_time; SPARK_POS_WAIT,
SPARK_NEG_WAIT,
bool trig12_complete = false; SPARK_POS_FAIL,
bool trig34_complete = false; SPARK_NEG_FAIL,
SPARK_POS_UNEXPECTED,
bool soft12 = false; SPARK_NEG_UNEXPECTED,
bool soft34 = false; SPARK_SYNC_FAIL,
bool error12 = false;
bool error34 = false;
}; };
taskStatus ignA_status; // Task internal Status
taskStatus ignB_status; struct ignitionBoxStatus {
// start time from ISR
int64_t trig12_start;
int64_t trig34_start;
// time at which spark occours
int64_t trig12_end;
int64_t trig34_end;
// computed delay from pickup to spark
int64_t spark12_delay;
int64_t spark34_delay;
// spark status
sparkStatus spark12_status = sparkStatus::SPARK_POS_OK;
sparkStatus spark34_status = sparkStatus::SPARK_POS_OK;
// soft start status for circuits 12 and 34
bool soft12_engaged = false;
bool soft34_engaged = false;
// peak voltage from circuits 12 and 34
float volts12_pickup;
float volts34_pickup;
// peak voltage from conditioned output 12 and 34
float volts12_out;
float volts34_out;
// voltage from generator
float volts_gen;
};
ignitionBoxStatus ignA_status;
ignitionBoxStatus ignB_status;
ignitionBoxStatus ingA_statusBuffer[IGN_BUF_SIZE];
ignitionBoxStatus ingB_statusBuffer[IGN_BUF_SIZE];
// Pin to flag Map // Pin to flag Map
static const uint32_t int2flag[] = { static uint32_t pin2trig[49];
[TRIG_A12P] = TRIG_FLAG_A12P, void initTriggerPinMapping() {
[TRIG_A12N] = TRIG_FLAG_A34P, pin2trig[TRIG_A12P] = TRIG_FLAG_A12P;
[TRIG_A34P] = TRIG_FLAG_A12N, pin2trig[TRIG_A12N] = TRIG_FLAG_A12N;
[TRIG_A34N] = TRIG_FLAG_A34N, pin2trig[TRIG_A34P] = TRIG_FLAG_A34P;
[TRIG_B12P] = TRIG_FLAG_B12P, pin2trig[TRIG_A34N] = TRIG_FLAG_A34N;
[TRIG_B12N] = TRIG_FLAG_B34P, pin2trig[TRIG_B12P] = TRIG_FLAG_B12P;
[TRIG_B34P] = TRIG_FLAG_B12N, pin2trig[TRIG_B12N] = TRIG_FLAG_B12N;
[TRIG_B34N] = TRIG_FLAG_B34N, pin2trig[TRIG_B34P] = TRIG_FLAG_B34P;
pin2trig[TRIG_B34N] = TRIG_FLAG_B34N;
};
static uint32_t pin2spark[49];
void initSparkPinMapping() {
pin2spark[SPARK_A12] = SPARK_FLAG_A12;
pin2spark[SPARK_A34] = SPARK_FLAG_A34;
pin2spark[SPARK_B12] = SPARK_FLAG_B12;
pin2spark[SPARK_B34] = SPARK_FLAG_B34;
}; };
// ===================== // =====================
@@ -72,7 +116,7 @@ void IRAM_ATTR trig_isr_a() {
uint32_t pin = __builtin_ctz(status); // trova primo bit attivo uint32_t pin = __builtin_ctz(status); // trova primo bit attivo
status &= ~(1 << pin); // clear bit status &= ~(1 << pin); // clear bit
flags |= int2flag[pin]; flags |= pin2trig[pin];
} }
if (flags & (TRIG_FLAG_A12P | TRIG_FLAG_A12N)) if (flags & (TRIG_FLAG_A12P | TRIG_FLAG_A12N))
@@ -86,17 +130,26 @@ void IRAM_ATTR trig_isr_a() {
} }
} }
void IRAM_ATTR spark_a() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t spark_flag = GPIO.status1.val & SPARK_A12 ? SPARK_FLAG_A12 : SPARK_FLAG_A34 ;
if (trigA_TaskHandle) {
xTaskNotifyFromISR(trigA_TaskHandle, spark_flag, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
void IRAM_ATTR trig_isr_b() { void IRAM_ATTR trig_isr_b() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t status = GPIO.status; uint32_t status = GPIO.status1.val;
uint32_t flags = 0; uint32_t flags = 0;
while (status) { while (status) {
uint32_t pin = __builtin_ctz(status); // trova primo bit attivo uint32_t pin = __builtin_ctz(status); // trova primo bit attivo
status &= ~(1 << pin); // clear bit status &= ~(1 << pin); // clear bit
flags |= int2flag[pin]; flags |= pin2trig[pin];
} }
if (trigB_TaskHandle) { if (trigB_TaskHandle) {
@@ -104,3 +157,12 @@ void IRAM_ATTR trig_isr_b() {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} }
} }
void IRAM_ATTR spark_b() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t spark_flag = GPIO.status1.val & SPARK_B12 ? SPARK_FLAG_B12 : SPARK_FLAG_B34 ;
if (trigB_TaskHandle) {
xTaskNotifyFromISR(trigB_TaskHandle, spark_flag, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}

View File

@@ -7,7 +7,6 @@
#include <SPI.h> #include <SPI.h>
// Definitions // Definitions
#include <isr.h>
#include <pins.h> #include <pins.h>
#include <channels.h> #include <channels.h>
#include <tasks.h> #include <tasks.h>
@@ -31,7 +30,7 @@ void setup() {
LOG_INFO("ESP32 Heap:", ESP.getHeapSize()); LOG_INFO("ESP32 Heap:", ESP.getHeapSize());
LOG_INFO("ESP32 Sketch:", ESP.getFreeSketchSpace()); LOG_INFO("ESP32 Sketch:", ESP.getFreeSketchSpace());
// Initialize Interrupt pins on peak detectors // Initialize Interrupt pins on coil detectors
pinMode(TRIG_A12P, INPUT_PULLDOWN); pinMode(TRIG_A12P, INPUT_PULLDOWN);
pinMode(TRIG_A12N, INPUT_PULLDOWN); pinMode(TRIG_A12N, INPUT_PULLDOWN);
pinMode(TRIG_A34P, INPUT_PULLDOWN); pinMode(TRIG_A34P, INPUT_PULLDOWN);
@@ -40,17 +39,29 @@ void setup() {
pinMode(TRIG_B12N, INPUT_PULLDOWN); pinMode(TRIG_B12N, INPUT_PULLDOWN);
pinMode(TRIG_B34P, INPUT_PULLDOWN); pinMode(TRIG_B34P, INPUT_PULLDOWN);
pinMode(TRIG_B34N, INPUT_PULLDOWN); pinMode(TRIG_B34N, INPUT_PULLDOWN);
initTriggerPinMapping();
// Initialize Interrupt pins on spark detectors
pinMode(SPARK_A12, INPUT_PULLDOWN);
pinMode(SPARK_A34, INPUT_PULLDOWN);
pinMode(SPARK_B12, INPUT_PULLDOWN);
pinMode(SPARK_B34, INPUT_PULLDOWN);
initSparkPinMapping();
// Ignition A Interrupts // Ignition A Interrupts
attachInterrupt(TRIG_A12P, trig_isr_a, RISING); attachInterrupt(TRIG_A12P, trig_isr_a, RISING);
attachInterrupt(TRIG_A34P, trig_isr_a, RISING); attachInterrupt(TRIG_A34P, trig_isr_a, RISING);
attachInterrupt(TRIG_A12N, trig_isr_a, RISING); attachInterrupt(TRIG_A12N, trig_isr_a, RISING);
attachInterrupt(TRIG_A34N, trig_isr_a, RISING); attachInterrupt(TRIG_A34N, trig_isr_a, RISING);
attachInterrupt(SPARK_A12, spark_a, RISING);
attachInterrupt(SPARK_A34, spark_a, RISING);
// Ignition B Interrupts // Ignition B Interrupts
attachInterrupt(TRIG_B12P, trig_isr_b, RISING); attachInterrupt(TRIG_B12P, trig_isr_b, RISING);
attachInterrupt(TRIG_B34P, trig_isr_b, RISING); attachInterrupt(TRIG_B34P, trig_isr_b, RISING);
attachInterrupt(TRIG_B12N, trig_isr_b, RISING); attachInterrupt(TRIG_B12N, trig_isr_b, RISING);
attachInterrupt(TRIG_B34N, trig_isr_b, RISING); attachInterrupt(TRIG_B34N, trig_isr_b, RISING);
attachInterrupt(SPARK_B12, spark_b, RISING);
attachInterrupt(SPARK_B34, spark_b, RISING);
// Init SPI interface // Init SPI interface
SPI.begin(); SPI.begin();

View File

@@ -1,3 +1,5 @@
#pragma once
// ===================== // =====================
// SPI BUS // SPI BUS
// ===================== // =====================

View File

@@ -1,3 +1,5 @@
#pragma once
// Arduino Libraries // Arduino Libraries
#include <Arduino.h> #include <Arduino.h>
#include <DebugLog.h> #include <DebugLog.h>
@@ -5,67 +7,91 @@
// ISR // ISR
#include "isr.h" #include "isr.h"
const uint16_t spark_delay_us = 500; const auto spark_timeout_max = 1;
void ignitionA_task(void *pvParameters) { void ignitionA_task(void *pvParameters) {
uint32_t notifiedValue; uint32_t pickup_flag;
uint32_t spark_flag;
while (true) { while (true) {
// attende eventi // WAIT FOR PICKUP SIGNAL
xTaskNotifyWait( xTaskNotifyWait(
0x00, // non pulire all'ingresso 0x00, // non pulire all'ingresso
ULONG_MAX, // pulisci tutti i bit all'uscita ULONG_MAX, // pulisci tutti i bit all'uscita
&notifiedValue, // valore ricevuto &pickup_flag, // valore ricevuto
portMAX_DELAY portMAX_DELAY
); );
// WAIT FOR SPARK TO HAPPEN
uint64_t wait_time=0; auto spark_timeout = xTaskNotifyWait(
switch (notifiedValue) { 0x00, // non pulire all'ingresso
case TRIG_FLAG_A12P: ULONG_MAX, // pulisci tutti i bit all'uscita
case TRIG_FLAG_A12N: &spark_flag, // valore ricevuto
bool spark12_timeout = false; spark_timeout_max
if (ignA_status.trig12_complete) { );
// read peak adc values from sample and hold // Save current time to compute delay from pickup to spark
} else { auto curr_time = esp_timer_get_time();
while(!digitalRead(SPARK_A12)) {
wait_time = ignA_status.trig12_start - esp_timer_get_time(); // A trigger from pickup 12 is followed by a spark event on 34 or vice versa pickup 34 triggers spark on 12
if (wait_time >= spark_delay_us) { if ((pickup_flag == TRIG_FLAG_A12P || pickup_flag == TRIG_FLAG_A12N) && spark_flag != SPARK_A12) {
spark12_timeout = true; ignA_status.trig12_start = ignA_status.trig34_start = -1;
break; ignA_status.trig12_end = ignA_status.trig34_end = -1;
} ignA_status.spark12_delay = ignA_status.spark34_delay = -1;
} ignA_status.soft12_engaged = ignA_status.soft34_engaged = false;
if (spark12_timeout) { // spark did not happen, timeout ignA_status.spark12_status = ignA_status.spark12_status = sparkStatus::SPARK_SYNC_FAIL;
ignA_status.trig12_complete = false; // Save error on circular buffer and skip to next cycle //
} else { // spark did happen // [TODO]
ignA_status.trig12_complete = true; continue;
ignA_status.trig12_time = wait_time; }
}
switch (pickup_flag) {
case TRIG_FLAG_A12P: {
// Timeout not occourred, expected POSITIVE edge spark OCCOURRED
if (spark_timeout == pdPASS) {
ignA_status.trig12_end = curr_time;
ignA_status.spark12_delay = ignA_status.trig12_end - ignA_status.trig12_end;
ignA_status.soft12_engaged = false; // because spark on positive edge
ignA_status.spark12_status = sparkStatus::SPARK_POS_OK; // do not wait for spark on negative edge
}
// Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED
else if (spark_timeout == pdFAIL) {
ignA_status.spark12_status = sparkStatus::SPARK_NEG_WAIT;
ignA_status.soft12_engaged = false;
} }
// Do nothing more on positive pulse
break; break;
}
case TRIG_FLAG_A12N: {
bool expected_negative12 = ignA_status.spark12_status == sparkStatus::SPARK_NEG_WAIT;
// Timeout not occourred, expected NEGATIVE edge spark OCCOURRED
if (spark_timeout == pdPASS && expected_negative12) {
ignA_status.trig12_end = curr_time;
ignA_status.spark12_delay = ignA_status.trig12_end - ignA_status.trig12_end;
ignA_status.soft12_engaged = true;
ignA_status.spark12_status == sparkStatus::SPARK_NEG_OK;
}
// Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED
else if (spark_timeout == pdFAIL && expected_negative12) {
ignA_status.trig12_start = 0;
ignA_status.trig12_end = 0;
ignA_status.soft12_engaged = false;
ignA_status.spark12_status = sparkStatus::SPARK_NEG_FAIL;
}
// Timeout not occouured, unexpected negative edge spark
else if (spark_timeout == pdPASS && !expected_negative12) {
ignA_status.soft12_engaged = true;
ignA_status.spark12_status = sparkStatus::SPARK_NEG_UNEXPECTED;
}
// Save status on circular buffer
break;
}
case TRIG_FLAG_A34P: case TRIG_FLAG_A34P:
case TRIG_FLAG_A34N: case TRIG_FLAG_A34N:
bool spark34_timeout = false;
if (ignA_status.trig12_complete) {
// read peak adc values from sample and hold
} else {
while(!digitalRead(SPARK_A34)) {
wait_time = ignA_status.trig34_start - esp_timer_get_time();
if (wait_time >= spark_delay_us) {
spark12_timeout = true;
break;
}
}
if (spark34_timeout) { // spark did not happen, timeout
ignA_status.trig34_complete = false;
} else { // spark did happen
ignA_status.trig34_complete = true;
ignA_status.trig34_time = wait_time;
}
}
break; break;
default: default:
LOG_ERROR("Invalid A Interrupt: ", notifiedValue); LOG_ERROR("Invalid A Interrupt");
} }
} }