Improved task code

This commit is contained in:
Emanuele Trabattoni
2026-04-07 10:51:53 +02:00
parent dc44decd64
commit f36cb96f21
4 changed files with 46 additions and 84 deletions

View File

@@ -36,18 +36,13 @@ void trig_isr(void *arg)
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
break; break;
case SPARK_FLAG_12: case SPARK_FLAG_12:
box->coils34.spark_ok = false;
box->coils12.spark_ok = true;
box->coils12.spark_time = time_us; box->coils12.spark_time = time_us;
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
// vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
break; break;
case SPARK_FLAG_34: case SPARK_FLAG_34:
box->coils12.spark_ok = false;
box->coils34.spark_ok = true;
box->coils34.spark_time = time_us; box->coils34.spark_time = time_us;
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
// vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
break; break;
default: default:
break; break;

View File

@@ -26,10 +26,9 @@ static const uint32_t TRIG_FLAG_12N = (1 << 1);
static const uint32_t TRIG_FLAG_34P = (1 << 2); static const uint32_t TRIG_FLAG_34P = (1 << 2);
static const uint32_t TRIG_FLAG_34N = (1 << 3); static const uint32_t TRIG_FLAG_34N = (1 << 3);
static const uint32_t SPARK_FLAG_NIL = (1 << 8); static const uint32_t SPARK_FLAG_TIMEOUT = (1 << 8);
static const uint32_t SPARK_FLAG_12 = (1 << 9); static const uint32_t SPARK_FLAG_12 = (1 << 9);
static const uint32_t SPARK_FLAG_34 = (1 << 10); static const uint32_t SPARK_FLAG_34 = (1 << 10);
static const uint32_t SPARK_FLAG_TIMEOUT = (1 << 11);
// Spark Status // Spark Status
enum sparkStatus enum sparkStatus
@@ -78,15 +77,15 @@ struct coilsStatus
{ {
int64_t trig_time = 0; int64_t trig_time = 0;
int64_t spark_time = 0; int64_t spark_time = 0;
int64_t spark_delay = 0; // in microseconds uint32_t spark_delay = 0; // in microseconds
sparkStatus spark_status = sparkStatus::SPARK_POS_OK; sparkStatus spark_status = sparkStatus::SPARK_POS_OK;
softStartStatus sstart_status = softStartStatus::NORMAL; softStartStatus sstart_status = softStartStatus::NORMAL;
float peak_p_in = 0.0, peak_n_in = 0.0; float peak_p_in = 0.0;
float peak_p_out = 0.0, peak_n_out = 0.0; float peak_n_in = 0.0;
float trigger_spark = 0.0; float peak_p_out = 0.0;
bool spark_ok = false; float peak_n_out = 0.0;
float level_spark = 0.0;
uint32_t n_events = 0; uint32_t n_events = 0;
}; };
// Task internal Status // Task internal Status
@@ -98,6 +97,9 @@ struct ignitionBoxStatus
coilsStatus coils34; coilsStatus coils34;
// voltage from generator // voltage from generator
float volts_gen = 0.0; float volts_gen = 0.0;
// enine rpm
uint32_t eng_rpm = 0;
// debug values
uint32_t n_queue_errors = 0; uint32_t n_queue_errors = 0;
uint32_t adc_read_time = 0; uint32_t adc_read_time = 0;
}; };

View File

@@ -18,11 +18,6 @@
// #define CH_B_ENABLE // #define CH_B_ENABLE
#define TEST #define TEST
float freqToRPM(float freq)
{
return freq * 60.0f; // 1 pulse per revolution
}
void printTaskStats() void printTaskStats()
{ {
char buffer[1024]; char buffer[1024];
@@ -188,10 +183,6 @@ void loop()
{ {
if (xQueueReceive(rt_taskA_queue, &ignA, pdMS_TO_TICKS(1000)) == pdTRUE) if (xQueueReceive(rt_taskA_queue, &ignA, pdMS_TO_TICKS(1000)) == pdTRUE)
{ {
float freq = (esp_timer_get_time() - last) / 1000000.0f; // in seconds
freq = freq > 0 ? 1.0f / freq : 0; // Calculate frequency (Hz)
last = esp_timer_get_time();
if (ignA.coils12.spark_status == sparkStatus::SPARK_POS_FAIL || ignA.coils12.spark_status == sparkStatus::SPARK_NEG_FAIL) if (ignA.coils12.spark_status == sparkStatus::SPARK_POS_FAIL || ignA.coils12.spark_status == sparkStatus::SPARK_NEG_FAIL)
missed_firings12++; missed_firings12++;
if (ignA.coils34.spark_status == sparkStatus::SPARK_POS_FAIL || ignA.coils34.spark_status == sparkStatus::SPARK_NEG_FAIL) if (ignA.coils34.spark_status == sparkStatus::SPARK_POS_FAIL || ignA.coils34.spark_status == sparkStatus::SPARK_NEG_FAIL)
@@ -201,7 +192,7 @@ void loop()
setCursor(0, 0); setCursor(0, 0);
printField("++ Timestamp", (uint32_t)ignA.timestamp); printField("++ Timestamp", (uint32_t)ignA.timestamp);
Serial.println("========== Coils 12 ============="); Serial.println("========== Coils 12 =============");
printField("Events", (uint32_t)ignA.coils12.n_events); printField("Events", ignA.coils12.n_events);
printField("Missed Firing", missed_firings12); printField("Missed Firing", missed_firings12);
printField("Spark Dly", (uint32_t)ignA.coils12.spark_delay); printField("Spark Dly", (uint32_t)ignA.coils12.spark_delay);
printField("Spark Sts", sparkStatusNames.at(ignA.coils12.spark_status)); printField("Spark Sts", sparkStatusNames.at(ignA.coils12.spark_status));
@@ -212,7 +203,7 @@ void loop()
printField("Soft Start ", softStartStatusNames.at(ignA.coils12.sstart_status)); printField("Soft Start ", softStartStatusNames.at(ignA.coils12.sstart_status));
Serial.println("========== Coils 34 ============="); Serial.println("========== Coils 34 =============");
printField("Events", (uint32_t)ignA.coils34.n_events); printField("Events", ignA.coils34.n_events);
printField("Missed Firing", missed_firings34); printField("Missed Firing", missed_firings34);
printField("Spark Dly", (uint32_t)ignA.coils34.spark_delay); printField("Spark Dly", (uint32_t)ignA.coils34.spark_delay);
printField("Spark Sts", sparkStatusNames.at(ignA.coils34.spark_status)); printField("Spark Sts", sparkStatusNames.at(ignA.coils34.spark_status));
@@ -224,9 +215,9 @@ void loop()
Serial.println("========== END ============="); Serial.println("========== END =============");
Serial.println(); Serial.println();
printField("Engine RPM", freqToRPM(freq)); printField("Engine RPM", ignA.eng_rpm);
printField("ADC Read Time", (uint32_t)ignA.adc_read_time); printField("ADC Read Time", ignA.adc_read_time);
printField("Queue Errors", (uint32_t)ignA.n_queue_errors); printField("Queue Errors", ignA.n_queue_errors);
} }
else else
{ {

View File

@@ -2,7 +2,8 @@
#include <esp_timer.h> #include <esp_timer.h>
// Timeout callback for microsecond precision // Timeout callback for microsecond precision
void spark_timeout_callback(void* arg) { void spark_timeout_callback(void *arg)
{
TaskHandle_t handle = (TaskHandle_t)arg; TaskHandle_t handle = (TaskHandle_t)arg;
xTaskNotify(handle, SPARK_FLAG_TIMEOUT, eSetValueWithOverwrite); xTaskNotify(handle, SPARK_FLAG_TIMEOUT, eSetValueWithOverwrite);
} }
@@ -64,8 +65,7 @@ void rtIgnitionTask(void *pvParameters)
.callback = spark_timeout_callback, .callback = spark_timeout_callback,
.arg = (void *)rt_handle_ptr, .arg = (void *)rt_handle_ptr,
.dispatch_method = ESP_TIMER_TASK, .dispatch_method = ESP_TIMER_TASK,
.name = "spark_timeout" .name = "spark_timeout"};
};
esp_timer_create(&timer_args, &timeout_timer); esp_timer_create(&timer_args, &timeout_timer);
// Attach Pin Interrupts // Attach Pin Interrupts
@@ -89,6 +89,8 @@ void rtIgnitionTask(void *pvParameters)
bool first_cycle = true; bool first_cycle = true;
bool cycle12 = false; bool cycle12 = false;
bool cycle34 = false; bool cycle34 = false;
int64_t last_cycle_time = 0;
uint32_t n_errors = 0;
while (params->rt_running) while (params->rt_running)
{ {
@@ -103,9 +105,7 @@ void rtIgnitionTask(void *pvParameters)
portMAX_DELAY); portMAX_DELAY);
if (first_cycle && pickup_flag != TRIG_FLAG_12P) // skip first cycle because of possible initial noise on pickup signals at startu if (first_cycle && pickup_flag != TRIG_FLAG_12P) // skip first cycle because of possible initial noise on pickup signals at startu
{
continue; continue;
}
#ifdef DEBUG #ifdef DEBUG
Serial.print("\033[2J"); // clear screen Serial.print("\033[2J"); // clear screen
@@ -128,35 +128,19 @@ void rtIgnitionTask(void *pvParameters)
esp_timer_stop(timeout_timer); // stop timer in case it was running from previous cycle esp_timer_stop(timeout_timer); // stop timer in case it was running from previous cycle
esp_timer_start_once(timeout_timer, spark_timeout_max); esp_timer_start_once(timeout_timer, spark_timeout_max);
spark_flag = SPARK_FLAG_NIL; // default value in case of timeout, to be set by ISR if spark event occours
// WAIT FOR SPARK TO HAPPEN OR TIMEOUT // WAIT FOR SPARK TO HAPPEN OR TIMEOUT
BaseType_t sp = pdFALSE; xTaskNotifyWait(
sp = xTaskNotifyWait(
0x00, // non pulire all'ingresso 0x00, // non pulire all'ingresso
ULONG_MAX, // pulisci i primi 8 bit ULONG_MAX, // pulisci i primi 8 bit
&spark_flag, // valore ricevuto &spark_flag, // valore ricevuto
portMAX_DELAY); // wait indefinitely, timeout handled by esp_timer portMAX_DELAY); // wait indefinitely, timeout handled by esp_timer
// Handle timeout or spark event // Handle timeout or spark event
if (spark_flag == SPARK_FLAG_TIMEOUT) { if (spark_flag != SPARK_FLAG_TIMEOUT)
spark_flag = SPARK_FLAG_NIL;
} else {
// Spark occurred, stop the timer
esp_timer_stop(timeout_timer); esp_timer_stop(timeout_timer);
}
#ifdef DEBUG
// LOG_INFO("Spark Flags: ", printBits(spark_flag).c_str());
LOG_INFO("Spark12:", ign_box_sts.coils12.spark_ok ? "TRUE" : "FALSE");
LOG_INFO("Spark34:", ign_box_sts.coils34.spark_ok ? "TRUE" : "FALSE");
if (names.contains(spark_flag))
LOG_INFO("Spark Trigger:", names.at(spark_flag));
#endif
xTaskNotifyStateClear(NULL);
ulTaskNotifyValueClear(NULL, 0xFFFFFFFF);
// A trigger from pickup 12 is followed by a spark event on 34 or vice versa pickup 34 triggers spark on 12 // A trigger from pickup 12 is followed by a spark event on 34 or vice versa pickup 34 triggers spark on 12
if ((pickup_flag == TRIG_FLAG_12P || pickup_flag == TRIG_FLAG_12N) && (spark_flag != SPARK_FLAG_12 && spark_flag != SPARK_FLAG_NIL)) if ((pickup_flag == TRIG_FLAG_12P || pickup_flag == TRIG_FLAG_12N) && (spark_flag != SPARK_FLAG_12 && spark_flag != SPARK_FLAG_TIMEOUT))
{ {
ign_box_sts.coils12.spark_status = ign_box_sts.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL; ign_box_sts.coils12.spark_status = ign_box_sts.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL;
continue; continue;
@@ -167,7 +151,14 @@ void rtIgnitionTask(void *pvParameters)
switch (pickup_flag) switch (pickup_flag)
{ {
case TRIG_FLAG_12P: case TRIG_FLAG_12P:
{
first_cycle = false; first_cycle = false;
// compute engine rpm from cycle time
auto current_time = esp_timer_get_time();
auto cycle_time = current_time - last_cycle_time;
last_cycle_time = current_time;
ign_box_sts.eng_rpm = (uint32_t)(60.0f / (cycle_time / 1000000.0f));
}
case TRIG_FLAG_12N: case TRIG_FLAG_12N:
coils = &ign_box_sts.coils12; coils = &ign_box_sts.coils12;
break; break;
@@ -184,18 +175,14 @@ void rtIgnitionTask(void *pvParameters)
case TRIG_FLAG_34P: case TRIG_FLAG_34P:
{ {
// Timeout not occourred, expected POSITIVE edge spark OCCOURRED // Timeout not occourred, expected POSITIVE edge spark OCCOURRED
if (spark_flag != SPARK_FLAG_NIL) if (spark_flag != SPARK_FLAG_TIMEOUT)
{ {
coils->spark_delay = coils->spark_time - coils->trig_time; coils->spark_delay = (uint32_t)(coils->spark_time - coils->trig_time);
coils->sstart_status = softStartStatus::NORMAL; // because spark on positive edge coils->sstart_status = softStartStatus::NORMAL; // because spark on positive edge
coils->spark_status = sparkStatus::SPARK_POS_OK; // do not wait for spark on negative edge coils->spark_status = sparkStatus::SPARK_POS_OK; // do not wait for spark on negative edge
#ifdef DEBUG
LOG_INFO("Spark on POSITIVE pulse");
LOG_INFO("Spark Delay Time: ", (int32_t)coils->spark_delay);
#endif
} }
// Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED
else if (spark_flag == SPARK_FLAG_NIL) else if (spark_flag == SPARK_FLAG_TIMEOUT)
{ {
coils->spark_status = sparkStatus::SPARK_NEG_WAIT; coils->spark_status = sparkStatus::SPARK_NEG_WAIT;
coils->sstart_status = softStartStatus::NORMAL; coils->sstart_status = softStartStatus::NORMAL;
@@ -208,24 +195,20 @@ void rtIgnitionTask(void *pvParameters)
{ {
const bool expected_negative = coils->spark_status == sparkStatus::SPARK_NEG_WAIT; const bool expected_negative = coils->spark_status == sparkStatus::SPARK_NEG_WAIT;
// Timeout not occourred, expected NEGATIVE edge spark OCCOURRED // Timeout not occourred, expected NEGATIVE edge spark OCCOURRED
if (spark_flag != SPARK_FLAG_NIL && expected_negative) if (spark_flag != SPARK_FLAG_TIMEOUT && expected_negative)
{ {
coils->spark_delay = coils->spark_time - coils->trig_time; coils->spark_delay = (uint32_t)(coils->spark_time - coils->trig_time);
coils->sstart_status = softStartStatus::SOFT_START; coils->sstart_status = softStartStatus::SOFT_START;
coils->spark_status = sparkStatus::SPARK_NEG_OK; coils->spark_status = sparkStatus::SPARK_NEG_OK;
#ifdef DEBUG
LOG_INFO("Spark on NEGATIVE pulse");
LOG_INFO("Spark Delay Time: ", (int32_t)coils->spark_delay);
#endif
} }
// Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED
else if (spark_flag == SPARK_FLAG_NIL && expected_negative) else if (spark_flag == SPARK_FLAG_TIMEOUT && expected_negative)
{ {
coils->sstart_status = softStartStatus::ERROR; coils->sstart_status = softStartStatus::ERROR;
coils->spark_status = sparkStatus::SPARK_NEG_FAIL; coils->spark_status = sparkStatus::SPARK_NEG_FAIL;
} }
// Timeout not occouured, unexpected negative edge spark // Timeout not occouured, unexpected negative edge spark
else if (spark_flag != SPARK_FLAG_NIL && !expected_negative) else if (spark_flag != SPARK_FLAG_TIMEOUT && !expected_negative)
{ {
coils->sstart_status = softStartStatus::SOFT_START; coils->sstart_status = softStartStatus::SOFT_START;
coils->spark_status = sparkStatus::SPARK_NEG_UNEXPECTED; coils->spark_status = sparkStatus::SPARK_NEG_UNEXPECTED;
@@ -239,11 +222,6 @@ void rtIgnitionTask(void *pvParameters)
break; break;
} }
default: default:
#ifdef DEUG
LOG_ERROR("Invalid Interrupt");
LOG_ERROR("Pickup Flags: ", printBits(pickup_flag).c_str());
LOG_ERROR("Spark Flags: ", printBits(spark_flag).c_str());
#endif
break; break;
} }
@@ -251,6 +229,7 @@ void rtIgnitionTask(void *pvParameters)
{ {
cycle12 = false; cycle12 = false;
cycle34 = false; cycle34 = false;
// read adc channels: pickup12, out12 [ pos + neg ] // read adc channels: pickup12, out12 [ pos + neg ]
if (adc) // read only if adc initialized if (adc) // read only if adc initialized
{ {
@@ -285,12 +264,7 @@ void rtIgnitionTask(void *pvParameters)
if (rt_queue) if (rt_queue)
ign_box_sts.timestamp = esp_timer_get_time(); // update data timestamp ign_box_sts.timestamp = esp_timer_get_time(); // update data timestamp
if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, 0) != pdPASS) if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, 0) != pdPASS)
{ ign_box_sts.n_queue_errors = ++n_errors;
static uint32_t n_errors = 0;
n_errors++;
ign_box_sts.n_queue_errors = n_errors;
LOG_ERROR("Failed to send to rt_queue");
}
} }
} }
// Delete the timeout timer // Delete the timeout timer