Compare commits

11 Commits

Author SHA1 Message Date
5c9ef7e93b Fast ADC readings ok, to verify timing and settling time 2026-04-05 17:05:10 +02:00
a2d0afa0c9 adc read ok, very slow 2026-04-05 11:16:10 +02:00
1109681eb5 Merge branch 'debug' 2026-04-05 10:32:08 +02:00
c5d80052e5 Thans to copilot, microsecond resolution to wait for spark.
no missing firings detected
2026-04-04 22:12:53 +02:00
38c595fd7b revert on double task wait, normal and soft start working 2026-04-04 20:00:30 +02:00
b0842aadef Sync 12 and 34 working 2026-04-04 16:27:52 +02:00
0dc5d1ce79 Debug Config OK, ready to realtime debugging 2026-04-04 03:25:33 +02:00
Emanuele Trabattoni
941a2b4eaa debug testing commit 2026-04-04 03:11:44 +02:00
Emanuele Trabattoni
48df6a509d Test OK Channel A 2026-04-01 12:31:29 +02:00
Emanuele Trabattoni
ebff6281af Test Softs start working 2026-04-01 12:00:07 +02:00
Emanuele Trabattoni
d7e0990e36 Test working at 100Khz 2026-04-01 11:43:44 +02:00
18 changed files with 570 additions and 331 deletions

View File

@@ -1,7 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"Jason2866.esp-decoder",
"pioarduino.pioarduino-ide",
"platformio.platformio-ide"
],
"unwantedRecommendations": [

View File

@@ -11,8 +11,8 @@
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1",
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_CDC_ON_BOOT=0"
"-DARDUINO_USB_MODE=0",
"-DARDUINO_USB_CDC_ON_BOOT=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",

View File

@@ -8,9 +8,9 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32-s3-n16r8]
board = esp32-s3-n16r8
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
[env:esp32-s3-devkitc1-n16r8]
board = esp32-s3-devkitc1-n16r8
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
framework = arduino
lib_deps =
hideakitai/DebugLog@^0.8.4
@@ -18,51 +18,51 @@ lib_deps =
hideakitai/PCA95x5@^0.1.3
adafruit/Adafruit SSD1306@^2.5.16
garfius/Menu-UI@^1.2.0
board_build.partitions = partitions/default_16MB.csv
board_build.psram = enabled
monitor_speed = 115200
;Upload protocol configuration
upload_protocol = esptool
upload_port = /dev/ttyACM2
upload_speed = 921600
;Monitor configuration
monitor_port = /dev/ttyACM2
monitor_speed = 921600
; Build configuration
build_type = release
build_flags =
-DARDUINO_USB_CDC_ON_BOOT=0
-DARDUINO_USB_MODE=0
-fstack-protector-all
-DCONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=1
-DCONFIG_FREERTOS_USE_TRACE_FACILITY=1
[env:esp32-s3-n16r8-debug]
board = ${env:esp32-s3-n16r8.board}
platform = ${env:esp32-s3-n16r8.platform}
framework = ${env:esp32-s3-n16r8.framework}
lib_deps = ${env:esp32-s3-n16r8.lib_deps}
board_build.partitions = partitions/default_16MB.csv
board_build.psram = enabled
monitor_speed = 115200
[env:esp32-s3-devkitc1-n16r8-debug]
board = ${env:esp32-s3-devkitc1-n16r8.board}
platform = ${env:esp32-s3-devkitc1-n16r8.platform}
framework = ${env:esp32-s3-devkitc1-n16r8.framework}
lib_deps = ${env:esp32-s3-devkitc1-n16r8.lib_deps}
;Upload protocol configuration
upload_protocol = esptool
upload_port = /dev/ttyACM2
upload_speed = 921600
;Monitor configuration
monitor_port = /dev/ttyACM2
monitor_speed = 921600
; Debug configuration
debug_tool = esp-builtin
debug_speed = 15000
; Build configuration
build_type = debug
build_flags =
-O0
-g3
-ggdb
-fno-inline
-fno-ipa-sra
-fno-tree-sra
-fno-builtin
[env:esp32-devtest-debug]
board = esp32dev
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
framework = arduino
lib_deps =
hideakitai/DebugLog@^0.8.4
bblanchon/ArduinoJson@^7.4.2
hideakitai/PCA95x5@^0.1.3
adafruit/Adafruit SSD1306@^2.5.16
garfius/Menu-UI@^1.2.0
board_build.flash_size = 4MB
board_build.partitions = default.csv
monitor_speed = 115200
build_type = debug
build_flags =
-O0
-g3
-ggdb
-fno-inline
-fno-ipa-sra
-fno-tree-sra
-fno-builtin
-O0
-g3
-ggdb3
-DCORE_DEBUG_LEVEL=5
-DARDUINO_USB_CDC_ON_BOOT=0
-DARDUINO_USB_MODE=0
-fstack-protector-all

View File

@@ -120,14 +120,14 @@ void ADS1256::setDRATE(uint8_t drate) //Setting DRATE (sampling frequency)
{
writeRegister(DRATE_REG, drate);
_DRATE = drate;
delay(200);
delayMicroseconds(500);
}
void ADS1256::setMUX(uint8_t mux) //Setting MUX (input channel)
{
writeRegister(MUX_REG, mux);
_MUX = mux;
delay(200);
//delayMicroseconds(500);
}
void ADS1256::setPGA(uint8_t pga) //Setting PGA (input voltage range)
@@ -138,7 +138,7 @@ void ADS1256::setPGA(uint8_t pga) //Setting PGA (input voltage range)
_ADCON = (_ADCON & 0b11111000) | (_PGA & 0b00000111); // Clearing and then setting bits 2-0 based on pga
writeRegister(ADCON_REG, _ADCON);
delay(200);
delayMicroseconds(1000); //Delay to allow the PGA to settle after changing its value
updateConversionParameter(); //Update the multiplier according top the new PGA value
}
@@ -501,8 +501,6 @@ void ADS1256::writeRegister(uint8_t registerAddress, uint8_t registerValueToWrit
CS_HIGH();
_spi->endTransaction();
delay(100);
}
long ADS1256::readRegister(uint8_t registerAddress) //Reading a register
@@ -524,7 +522,7 @@ long ADS1256::readRegister(uint8_t registerAddress) //Reading a register
CS_HIGH();
_spi->endTransaction();
delay(100);
return regValue;
}

View File

@@ -1,5 +1,8 @@
#pragma once
// Library defines
#define ADS1256_SPI_ALREADY_STARTED
// Device Libraries
#include <ADS1256.h>
#include <AD5292.h>

View File

@@ -11,49 +11,47 @@ void trig_isr(void *arg)
// exit if invalid args
if (!arg)
return;
// FOR TESTING ONLY
digitalWrite(POT_A_CS, HIGH);
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
isrParams *params = (isrParams *)arg;
ignitionBoxStatus *box = params->ign_stat;
TaskHandle_t task_handle = *params->rt_handle_ptr;
TaskHandle_t task_handle = params->rt_handle_ptr;
// exit if task not running
if (!task_handle)
return;
// reset spark flags, cannot be same time as trigger flags
box->coils12.spark_ok = false;
box->coils34.spark_ok = false;
switch (params->flag)
{
case TRIG_FLAG_12P:
case TRIG_FLAG_12N:
// only on first trigger to avoid multiple firing due to noise, to be fixed with hardware debounce
box->coils12.trig_time = time_us;
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
break;
case TRIG_FLAG_34P:
case TRIG_FLAG_34N:
// only on first trigger to avoid multiple firing due to noise, to be fixed with hardware debounce
box->coils34.trig_time = time_us;
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
break;
case SPARK_FLAG_12:
box->coils34.spark_ok = false;
box->coils12.spark_ok = true;
box->coils12.spark_time = time_us;
vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
// vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
break;
case SPARK_FLAG_34:
box->coils12.spark_ok = false;
box->coils34.spark_ok = true;
box->coils34.spark_time = time_us;
vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
// vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
break;
default:
break;
}
// FOR TESTING ONLY
digitalWrite(POT_A_CS, LOW);
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();

View File

@@ -1,11 +1,12 @@
#pragma once
// Test device Flag
#define TEST
// #define TEST
// Arduino Libraries
#include <Arduino.h>
#include "soc/gpio_struct.h"
#include <map>
#ifndef TEST
#include "pins.h"
#else
@@ -20,14 +21,15 @@
// =====================
// Event Flags (bitmask)
// =====================
#define TRIG_FLAG_12P (1 << 0)
#define TRIG_FLAG_12N (1 << 2)
#define TRIG_FLAG_34P (1 << 1)
#define TRIG_FLAG_34N (1 << 3)
static const uint32_t TRIG_FLAG_12P = (1 << 0);
static const uint32_t TRIG_FLAG_12N = (1 << 1);
static const uint32_t TRIG_FLAG_34P = (1 << 2);
static const uint32_t TRIG_FLAG_34N = (1 << 3);
#define SPARK_FLAG_NIL (1 << 8)
#define SPARK_FLAG_12 (1 << 9)
#define SPARK_FLAG_34 (1 << 10)
static const uint32_t SPARK_FLAG_NIL = (1 << 8);
static const uint32_t SPARK_FLAG_12 = (1 << 9);
static const uint32_t SPARK_FLAG_34 = (1 << 10);
static const uint32_t SPARK_FLAG_TIMEOUT = (1 << 11);
// Spark Status
enum sparkStatus
@@ -45,41 +47,66 @@ enum sparkStatus
SPARK_SYNC_FAIL,
};
static const std::map<const sparkStatus, const char *> sparkStatusNames = {
{SPARK_POS_OK, "SPARK_POS_OK"},
{SPARK_NEG_OK, "SPARK_NEG_OK"},
{SPARK_POS_SKIP, "SPARK_POS_SKIP"},
{SPARK_NEG_SKIP, "SPARK_NEG_SKIP"},
{SPARK_POS_WAIT, "SPARK_POS_WAIT"},
{SPARK_NEG_WAIT, "SPARK_NEG_WAIT"},
{SPARK_POS_FAIL, "SPARK_POS_FAIL"},
{SPARK_NEG_FAIL, "SPARK_NEG_FAIL"},
{SPARK_POS_UNEXPECTED, "SPARK_POS_UNEXPECTED"},
{SPARK_NEG_UNEXPECTED, "SPARK_NEG_UNEXPECTED"},
{SPARK_SYNC_FAIL, "SPARK_SYNC_FAIL"},
};
enum softStartStatus
{
NORMAL,
SOFT_START
SOFT_START,
ERROR,
};
const std::map<const softStartStatus, const char *> softStartStatusNames = {
{NORMAL, "NORMAL"},
{SOFT_START, "SOFT_START"},
{ERROR, "ERROR"},
};
struct coilsStatus
{
int64_t trig_time;
int64_t spark_time;
int64_t spark_delay;
sparkStatus spark_status;
softStartStatus sstart_status;
float peak_p_in, peak_n_in;
float peak_p_out, peak_n_out;
float trigger_spark;
bool spark_ok;
int64_t trig_time = 0;
int64_t spark_time = 0;
int64_t spark_delay = 0; // in microseconds
sparkStatus spark_status = sparkStatus::SPARK_POS_OK;
softStartStatus sstart_status = softStartStatus::NORMAL;
float peak_p_in = 0.0, peak_n_in = 0.0;
float peak_p_out = 0.0, peak_n_out = 0.0;
float trigger_spark = 0.0;
bool spark_ok = false;
uint32_t n_events = 0;
};
// Task internal Status
struct ignitionBoxStatus
{
int64_t timestamp;
int64_t timestamp = 0;
// coils pairs for each ignition
coilsStatus coils12;
coilsStatus coils34;
// voltage from generator
float volts_gen = 0.0;
uint32_t n_queue_errors = 0;
uint32_t adc_read_time = 0;
};
struct isrParams {
struct isrParams
{
const uint32_t flag;
ignitionBoxStatus* ign_stat;
TaskHandle_t* rt_handle_ptr;
ignitionBoxStatus *ign_stat;
TaskHandle_t rt_handle_ptr;
};
void IRAM_ATTR trig_isr(void *arg);

View File

@@ -12,18 +12,29 @@
#include <devices.h>
#include <ui.h>
void printTaskList()
// FreeRTOS directives
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// #define CH_B_ENABLE
#define TEST
float freqToRPM(float freq)
{
return freq * 60.0f; // 1 pulse per revolution
}
void printTaskStats()
{
char buffer[1024];
Serial.println("Task Name\tState\tPrio\tStack\tNum");
vTaskList(buffer);
vTaskGetRunTimeStats(buffer);
Serial.println(buffer);
}
void setup()
{
Serial.begin(921600);
delay(250);
Serial.begin(115200);
// Setup Logger
LOG_ATTACH_SERIAL(Serial);
@@ -51,15 +62,15 @@ void loop()
{
// global variables
bool running = true;
Devices dev;
static Devices dev;
// Task handle
TaskHandle_t trigA_TaskHandle = NULL;
TaskHandle_t trigB_TaskHandle = NULL;
static TaskHandle_t trigA_TaskHandle = NULL;
static TaskHandle_t trigB_TaskHandle = NULL;
QueueHandle_t rt_taskA_queue = xQueueCreate(10, sizeof(ignitionBoxStatus));
QueueHandle_t rt_taskB_queue = xQueueCreate(10, sizeof(ignitionBoxStatus));
rtTaskParams taskA_params{
static QueueHandle_t rt_taskA_queue = xQueueCreate(10, sizeof(ignitionBoxStatus));
static QueueHandle_t rt_taskB_queue = xQueueCreate(10, sizeof(ignitionBoxStatus));
static rtTaskParams taskA_params{
.rt_running = true,
.dev = &dev,
.rt_handle_ptr = &trigA_TaskHandle,
@@ -75,13 +86,14 @@ void loop()
.rt_resets = rtTaskResets{.rst_io_12p = RST_EXT_A12P, .rst_io_12n = RST_EXT_A12N, .rst_io_34p = RST_EXT_A34P, .rst_io_34n = RST_EXT_A34N}};
LOG_INFO("Task Variables OK");
#ifndef TEST
#ifdef CH_B_ENABLE
QueueHandle_t rt_taskB_queue = xQueueCreate(10, sizeof(ignitionBoxStatus));
rtTaskParams taskB_params{
.rt_running = true,
.dev = &dev,
.rt_queue = rt_taskB_queue,
.rt_handle_ptr = &trigB_TaskHandle,
.rt_queue = rt_taskB_queue,
.rt_int = rtTaskInterrupts{
.isr_ptr = trig_isr,
.trig_pin_12p = TRIG_PIN_B12P,
@@ -95,13 +107,16 @@ void loop()
bool spiA_ok = true;
bool spiB_ok = true;
#ifndef TEST
// Init 2 SPI interfaces
SPIClass SPI_A(FSPI);
spiA_ok = SPI_A.begin(SPI_A_SCK, SPI_A_MISO, SPI_A_MOSI);
SPI_A.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1
#ifndef TEST
SPIClass SPI_B(HSPI);
spiB_ok = SPI_B.begin(SPI_B_SCK, SPI_B_MISO, SPI_B_MOSI);
#endif
SPI_B.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1
#endif
if (!spiA_ok || !spiB_ok)
{
LOG_ERROR("Unable to Initialize SPI Busses");
@@ -111,13 +126,13 @@ void loop()
}
LOG_INFO("Init SPI OK");
#ifndef TEST
// Init ADC_A
dev.adc_a = new ADS1256(ADC_A_DRDY, ADC_A_RST, ADC_A_SYNC, ADC_A_CS, 2.5, &SPI_A);
dev.adc_a = new ADS1256(ADC_A_DRDY, ADS1256::PIN_UNUSED, ADC_A_SYNC, ADC_A_CS, 2.5, &SPI_A);
dev.adc_a->InitializeADC();
dev.adc_a->setPGA(PGA_1);
dev.adc_a->setDRATE(DRATE_1000SPS);
dev.adc_a->setDRATE(DRATE_7500SPS);
#ifndef TEST
// Init ADC_B
dev.adc_a = new ADS1256(ADC_B_DRDY, ADC_B_RST, ADC_B_SYNC, ADC_B_CS, 2.5, &SPI_B);
dev.adc_a->InitializeADC();
@@ -140,7 +155,7 @@ void loop()
// Ignition B on Core 1
auto ignB_task_success = pdPASS;
#ifndef TEST
#ifdef CH_B_ENABLE
ignB_task_success = xTaskCreatePinnedToCore(
rtIgnitionTask,
"rtIgnitionTask_boxB",
@@ -162,49 +177,62 @@ void loop()
LOG_INFO("Real Time Tasks A & B initialized");
////////////////////// MAIN LOOP //////////////////////
uint32_t count(0);
clearScreen();
setCursor(0, 0);
ignitionBoxStatus ignA;
int64_t last = esp_timer_get_time();
uint32_t missed_firings12 = 0;
uint32_t missed_firings34 = 0;
uint32_t counter = 0;
while (running)
{
ignitionBoxStatus ignA;
if (xQueueReceive(rt_taskA_queue, &ignA, pdMS_TO_TICKS(100)) == pdTRUE)
if (xQueueReceive(rt_taskA_queue, &ignA, pdMS_TO_TICKS(1000)) == pdTRUE)
{
printField("++ Timestamp", (uint32_t)ignA.timestamp, 0, 0);
if (firstRun)
Serial.println("========== Coils 12 =============");
printField("Pickup Tim", (uint32_t)ignA.coils12.trig_time, 0, 1);
printField("Spark Tim", (uint32_t)ignA.coils12.spark_time, 0, 2);
printField("Spark Dly", (uint32_t)ignA.coils12.spark_delay, 0, 3);
printField("Spark Sts", (uint32_t)ignA.coils12.spark_status, 0, 4);
printField("Peak P_IN", ignA.coils12.peak_p_in, 0, 5);
printField("Peak P_OUT", ignA.coils12.peak_p_out, 0, 6);
printField("Peak N_IN", ignA.coils12.peak_n_in, 0, 7);
printField("Peak N_OUT", ignA.coils12.peak_n_out, 0, 8);
printField("SoftStart ", (uint32_t)ignA.coils12.sstart_status, 0, 9);
if (firstRun)
Serial.println("========== Coils 34 =============");
printField("Pickup Tim", (uint32_t)ignA.coils34.trig_time, 0, 11);
printField("Spark Tim", (uint32_t)ignA.coils34.spark_time, 0, 12);
printField("Spark Dly", (uint32_t)ignA.coils34.spark_delay, 0, 13);
printField("Spark Sts", (uint32_t)ignA.coils34.spark_delay, 0, 14);
printField("Peak P_IN", ignA.coils34.peak_p_in, 0, 15);
printField("Peak P_OUT", ignA.coils34.peak_p_out, 0, 16);
printField("Peak N_IN", ignA.coils34.peak_n_in, 0, 17);
printField("Peak N_OUT", ignA.coils34.peak_n_out, 0, 18);
printField("SoftStart ", (uint32_t)ignA.coils34.sstart_status, 0, 19);
if (firstRun)
Serial.println("========== END =============");
if (count++ % 10 == 0)
{
firstRun = true;
clearScreen();
setCursor(0, 0);
}
else
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();
firstRun = false;
if (ignA.coils12.spark_status == sparkStatus::SPARK_POS_FAIL || ignA.coils12.spark_status == sparkStatus::SPARK_NEG_FAIL)
missed_firings12++;
if (ignA.coils34.spark_status == sparkStatus::SPARK_POS_FAIL || ignA.coils34.spark_status == sparkStatus::SPARK_NEG_FAIL)
missed_firings34++;
clearScreen();
setCursor(0, 0);
printField("++ Timestamp", (uint32_t)ignA.timestamp);
Serial.println("========== Coils 12 =============");
printField("Events", (uint32_t)ignA.coils12.n_events);
printField("Missed Firing", missed_firings12);
printField("Spark Dly", (uint32_t)ignA.coils12.spark_delay);
printField("Spark Sts", sparkStatusNames.at(ignA.coils12.spark_status));
printField("Peak P_IN", ignA.coils12.peak_p_in);
printField("Peak N_IN", ignA.coils12.peak_n_in);
printField("Peak P_OUT", ignA.coils12.peak_p_out);
printField("Peak N_OUT", ignA.coils12.peak_n_out);
printField("Soft Start ", softStartStatusNames.at(ignA.coils12.sstart_status));
Serial.println("========== Coils 34 =============");
printField("Events", (uint32_t)ignA.coils34.n_events);
printField("Missed Firing", missed_firings34);
printField("Spark Dly", (uint32_t)ignA.coils34.spark_delay);
printField("Spark Sts", sparkStatusNames.at(ignA.coils34.spark_status));
printField("Peak P_IN", ignA.coils34.peak_p_in);
printField("Peak N_IN", ignA.coils34.peak_n_in);
printField("Peak P_OUT", ignA.coils34.peak_p_out);
printField("Peak N_OUT", ignA.coils34.peak_n_out);
printField("Soft Start ", softStartStatusNames.at(ignA.coils34.sstart_status));
Serial.println("========== END =============");
Serial.println();
printField("Engine RPM", freqToRPM(freq));
printField("ADC Read Time", (uint32_t)ignA.adc_read_time);
printField("Queue Errors", (uint32_t)ignA.n_queue_errors);
}
else
{
Serial.println("Waiting for data... ");
delay(500);
}
}

View File

@@ -48,27 +48,25 @@
// =====================
#define ADC_A_CS 4
#define ADC_A_DRDY 5
#define ADC_A_RST 6
#define ADC_A_SYNC 7
#define ADC_A_SYNC 6
#define ADC_B_CS 14
#define ADC_B_DRDY 15
#define ADC_B_RST 16
#define ADC_B_SYNC 17
#define ADC_B_SYNC 16
// =====================
// DIGITAL POT
// =====================
#define POT_A_CS 1
#define POT_B_CS 2
#define POT_A_CS 7
#define POT_B_CS 17
// =====================
// TRIGGER INPUT INTERRUPTS
// =====================
#define TRIG_PIN_A12P 18
#define TRIG_PIN_A12N 21
#define TRIG_PIN_A34P 33
#define TRIG_PIN_A34N 34
#define TRIG_PIN_A34P 1
#define TRIG_PIN_A34N 2
#define TRIG_PIN_B12P 38
#define TRIG_PIN_B12N 39
#define TRIG_PIN_B34P 40
@@ -78,8 +76,8 @@
// SPARK DETECT INPUTS
// =====================
#define SPARK_PIN_A12 42
#define SPARK_PIN_A34 45 // OK (strapping ma consentito)
#define SPARK_PIN_B12 46 // OK (strapping ma consentito)
#define SPARK_PIN_A34 45 // OK (strapping ma consentito) 45
#define SPARK_PIN_B12 46 // OK (strapping ma consentito) 46
#define SPARK_PIN_B34 47
// =====================

View File

@@ -1,4 +1,11 @@
#include "tasks.h"
#include <esp_timer.h>
// Timeout callback for microsecond precision
void spark_timeout_callback(void* arg) {
TaskHandle_t handle = (TaskHandle_t)arg;
xTaskNotify(handle, SPARK_FLAG_TIMEOUT, eSetValueWithOverwrite);
}
void rtIgnitionTask(void *pvParameters)
{
@@ -16,13 +23,14 @@ void rtIgnitionTask(void *pvParameters)
const rtTaskInterrupts rt_int = params->rt_int; // copy to avoid external override
const rtTaskResets rt_rst = params->rt_resets; // copy to avoid external override
QueueHandle_t rt_queue = params->rt_queue;
TaskHandle_t *rt_handle_ptr = params->rt_handle_ptr;
TaskHandle_t rt_handle_ptr = *params->rt_handle_ptr;
Devices *dev = params->dev;
ADS1256 *adc = dev->adc_a;
PCA9555 *io = dev->io;
ignitionBoxStatus ign_box_sts;
// Variables for ISR, static to be fixed in memory locations
static ignitionBoxStatus ign_box_sts; // common for all ISR calls
static isrParams isr_params_t12p{
.flag = TRIG_FLAG_12P,
.ign_stat = &ign_box_sts,
@@ -47,10 +55,18 @@ void rtIgnitionTask(void *pvParameters)
.flag = SPARK_FLAG_34,
.ign_stat = &ign_box_sts,
.rt_handle_ptr = rt_handle_ptr};
LOG_INFO("rtTask ISR Params OK");
pinMode(POT_A_CS, OUTPUT);
// Create esp_timer for microsecond precision timeout
esp_timer_handle_t timeout_timer;
esp_timer_create_args_t timer_args = {
.callback = spark_timeout_callback,
.arg = (void*)rt_handle_ptr,
.dispatch_method = ESP_TIMER_TASK,
.name = "spark_timeout"
};
esp_timer_create(&timer_args, &timeout_timer);
// Attach Pin Interrupts
attachInterruptArg(digitalPinToInterrupt(rt_int.trig_pin_12p), rt_int.isr_ptr, (void *)&isr_params_t12p, RISING);
@@ -70,8 +86,9 @@ void rtIgnitionTask(void *pvParameters)
LOG_WARN("rtTask Init Correct");
// Global rt_task_ptr variables
uint32_t it = 0;
uint32_t q_fail_count = 0;
bool first_cycle = true;
bool cycle12 = false;
bool cycle34 = false;
while (params->rt_running)
{
@@ -80,19 +97,25 @@ void rtIgnitionTask(void *pvParameters)
// WAIT FOR PICKUP SIGNAL
xTaskNotifyWait(
ULONG_MAX, // non pulire all'ingresso
0x00, // non pulire all'ingresso
ULONG_MAX, // pulisci i primi 8 bit
&pickup_flag, // valore ricevuto
portMAX_DELAY);
if (first_cycle && pickup_flag != TRIG_FLAG_12P) // skip first cycle because of possible initial noise on pickup signals at startu
{
continue;
}
#ifdef DEBUG
LOG_INFO("Iteration [", it++, "]");
Serial.print("\033[2J"); // clear screen
Serial.print("\033[H"); // cursor home
LOG_INFO("Pickup Flags: ", printBits(pickup_flag).c_str());
LOG_INFO("Iteration [", it++, "]");
if (!names.contains(pickup_flag))
{
LOG_ERROR("Wrong Pickup Flag");
LOG_ERROR("Pickup Flags: ", printBits(pickup_flag).c_str());
continue;
}
else
@@ -101,37 +124,50 @@ void rtIgnitionTask(void *pvParameters)
}
#endif
// WAIT FOR SPARK TO HAPPEN
auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(spark_timeout_max));
if (ign_box_sts.coils12.spark_ok || ign_box_sts.coils34.spark_ok) // otherwise timeout if none is set in the ISR
spark_flag = ign_box_sts.coils12.spark_ok ? SPARK_FLAG_12 : SPARK_FLAG_34;
else
spark_flag == SPARK_FLAG_NIL;
// Start microsecond precision timeout timer
esp_timer_stop(timeout_timer); // stop timer in case it was running from previous cycle
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
BaseType_t sp = pdFALSE;
sp = xTaskNotifyWait(
0x00, // non pulire all'ingresso
ULONG_MAX, // pulisci i primi 8 bit
&spark_flag, // valore ricevuto
portMAX_DELAY); // wait indefinitely, timeout handled by esp_timer
// Handle timeout or spark event
if (spark_flag == SPARK_FLAG_TIMEOUT) {
spark_flag = SPARK_FLAG_NIL;
} else {
// Spark occurred, stop the 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);
#ifdef DEBUG
LOG_INFO("Spark Flags: ", printBits(spark_flag).c_str());
if (!names.contains(spark_flag))
LOG_ERROR("No Spark");
else
LOG_INFO("Spark Trigger:", names.at(spark_flag));
#endif
// 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)
if ((pickup_flag == TRIG_FLAG_12P || pickup_flag == TRIG_FLAG_12N) && (spark_flag != SPARK_FLAG_12 && spark_flag != SPARK_FLAG_NIL))
{
ign_box_sts.coils12.spark_status = ign_box_sts.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL;
// Save error on circular buffer and skip to next cycle //
LOG_ERROR("Spark Mismatch");
continue;
}
// Select coil status reference based on pickup_flag
coilsStatus *coils;
switch (pickup_flag)
{
case TRIG_FLAG_12P:
first_cycle = false;
case TRIG_FLAG_12N:
coils = &ign_box_sts.coils12;
break;
@@ -141,7 +177,7 @@ void rtIgnitionTask(void *pvParameters)
break;
}
bool new_data = false;
// Select logic based on pickup and spark flags
switch (pickup_flag)
{
case TRIG_FLAG_12P:
@@ -154,8 +190,8 @@ void rtIgnitionTask(void *pvParameters)
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
#ifdef DEBUG
LOG_INFO("Trigger Spark POSITIVE");
LOG_INFO("Spark12 Delay Timer: ", (int)coils->spark_delay);
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
@@ -164,39 +200,42 @@ void rtIgnitionTask(void *pvParameters)
coils->spark_status = sparkStatus::SPARK_NEG_WAIT;
coils->sstart_status = softStartStatus::NORMAL;
}
new_data = true;
break; // Do nothing more on positive pulse
continue; // Do nothing more on positive pulse
}
// CASES for NEGATIVE cycle triggering of pickup and sparks 12 & 34
case TRIG_FLAG_12N:
case TRIG_FLAG_34N:
{
const bool expected_negative12 = 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
if (spark_flag != SPARK_FLAG_NIL && expected_negative12)
if (spark_flag != SPARK_FLAG_NIL && expected_negative)
{
coils->spark_delay = coils->spark_time - coils->trig_time;
coils->sstart_status = softStartStatus::SOFT_START;
coils->spark_status == sparkStatus::SPARK_NEG_OK;
coils->spark_status = sparkStatus::SPARK_NEG_OK;
#ifdef DEBUG
LOG_INFO("Trigger Spark NEGATIVE");
LOG_INFO("Spark12 Delay Timer: ", (int)ign_box_sts.coils12.spark_delay);
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
else if (spark_flag == SPARK_FLAG_NIL && expected_negative12)
else if (spark_flag == SPARK_FLAG_NIL && expected_negative)
{
coils->sstart_status = softStartStatus::NORMAL;
coils->sstart_status = softStartStatus::ERROR;
coils->spark_status = sparkStatus::SPARK_NEG_FAIL;
}
// Timeout not occouured, unexpected negative edge spark
else if (spark_flag != SPARK_FLAG_NIL && !expected_negative12)
else if (spark_flag != SPARK_FLAG_NIL && !expected_negative)
{
coils->sstart_status = softStartStatus::SOFT_START;
coils->spark_status = sparkStatus::SPARK_NEG_UNEXPECTED;
}
// Wait for finish of negative pulse to save data to buffer
new_data = true;
coils->n_events++;
if (pickup_flag == TRIG_FLAG_12N)
cycle12 = true;
else
cycle34 = true;
break;
}
default:
@@ -208,12 +247,14 @@ void rtIgnitionTask(void *pvParameters)
break;
}
if (new_data)
if (cycle12 && cycle34) // wait for both 12 and 34 cycles to complete before sending data to main loop and resetting peak detectors
{
vTaskDelay(pdMS_TO_TICKS(1)); // delay 1ms to allow peak detectors to charge for negative cycle
// read adc channels: pickup12, out12 [ pos + neg ]
cycle12 = false;
cycle34 = false;
// read adc channels: pickup12, out12 [ pos + neg ]
if (adc) // read only if adc initialized
{
uint32_t start_adc_read = esp_timer_get_time();
// from peak detector circuits
ign_box_sts.coils12.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_12P_IN);
ign_box_sts.coils12.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_12N_IN);
@@ -223,9 +264,10 @@ void rtIgnitionTask(void *pvParameters)
ign_box_sts.coils12.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_12N_OUT);
ign_box_sts.coils34.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_34P_OUT);
ign_box_sts.coils34.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_34N_OUT);
ign_box_sts.adc_read_time = (uint32_t)(esp_timer_get_time() - start_adc_read);
}
else // simulate adc read timig
vTaskDelay(pdMS_TO_TICKS(6));
vTaskDelay(pdMS_TO_TICKS(1));
// reset peak detectors + sample and hold
// outputs on io expander
@@ -237,18 +279,22 @@ void rtIgnitionTask(void *pvParameters)
io->write(iostat & ~rst_bitmask);
}
else
vTaskDelay(pdMS_TO_TICKS(2));
vTaskDelay(pdMS_TO_TICKS(1));
// send essage to main loop with ignition info, by copy so local static variable is ok
if (rt_queue)
ign_box_sts.timestamp = esp_timer_get_time(); // update data timestamp
if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, pdMS_TO_TICKS(1)) != pdPASS)
if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, 0) != pdPASS)
{
q_fail_count++;
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
esp_timer_delete(timeout_timer);
LOG_WARN("Ending realTime Task");
// Ignition A Interrupts DETACH
detachInterrupt(rt_int.trig_pin_12p);

View File

@@ -2,7 +2,7 @@
#define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG
// Serial debug flag
// #define DEBUG
//#define DEBUG
// Arduino Libraries
#include <Arduino.h>
@@ -16,7 +16,7 @@
#include "devices.h"
// Global Variables and Flags
const uint8_t spark_timeout_max = 2; // in milliseconds
const uint32_t spark_timeout_max = 500; // in microseconds
// Debug Variables
#ifdef DEBUG
@@ -27,6 +27,7 @@ static const std::map<const uint32_t, const char *> names = {
{TRIG_FLAG_34N, "TRIG_FLAG_34N"},
{SPARK_FLAG_12, "SPARK_FLAG_12"},
{SPARK_FLAG_34, "SPARK_FLAG_34"},
{SPARK_FLAG_TIMEOUT, "SPARK_FLAG_TIMEOUT"},
};
#endif

View File

@@ -2,47 +2,35 @@
#include <Arduino.h>
static bool firstRun = true;
void clearScreen(){
void clearScreen()
{
Serial.print("\033[2J"); // clear screen
Serial.print("\033[H"); // cursor home
Serial.flush();
}
void setCursor(const uint8_t x, const uint8_t y) {
Serial.printf("\033[%d;%d", y, x+1);
void setCursor(const uint8_t x, const uint8_t y)
{
Serial.printf("\033[%d;%d", y, x + 1);
Serial.flush();
}
void printField(const char name[], const uint32_t val, const uint8_t x, const uint8_t y) {
if (firstRun) {
setCursor(x,y);
Serial.printf("%15s: %06d\n", name, val);
return;
}
setCursor(x+16, y);
Serial.print(val);
void printField(const char name[], const uint32_t val)
{
Serial.printf("%15s: %06d\n", name, val);
}
void printField(const char name[], const int64_t val, const uint8_t x, const uint8_t y) {
if (firstRun) {
setCursor(x,y);
Serial.printf("%15s: %06u\n", name, (uint64_t)val);
return;
}
setCursor(x+16, y);
Serial.print((uint64_t)val);
Serial.flush();
void printField(const char name[], const int64_t val)
{
Serial.printf("%15s: %06u\n", name, (uint64_t)val);
}
void printField(const char name[], const float val, const uint8_t x, const uint8_t y) {
if (firstRun) {
setCursor(x,y);
Serial.printf("%15s: %4.2f\n", name, val);
return;
}
setCursor(x+16, y);
Serial.print(val);
Serial.flush();
void printField(const char name[], const float val)
{
Serial.printf("%15s: %4.2f\n", name, val);
}
void printField(const char name[], const char *val)
{
Serial.printf("%15s: %s\n", name, val);
}

View File

@@ -1,7 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"Jason2866.esp-decoder",
"pioarduino.pioarduino-ide",
"platformio.platformio-ide"
],
"unwantedRecommendations": [

View File

@@ -10,24 +10,24 @@
[env:esp32-devtest-release]
board = esp32dev
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
framework = arduino
lib_deps =
hideakitai/DebugLog@^0.8.4
board_build.flash_size = 4MB
board_build.partitions = default.csv
monitor_speed = 115200
monitor_speed = 921600
build_type = release
[env:esp32-devtest-debug]
board = esp32dev
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
framework = arduino
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
lib_deps =
hideakitai/DebugLog@^0.8.4
board_build.flash_size = 4MB
board_build.partitions = default.csv
monitor_speed = 115200
monitor_speed = 921600
build_type = debug
build_flags =
-O0

View File

@@ -7,8 +7,29 @@
static hw_timer_t *timerA = NULL;
static hw_timer_t *timerB = NULL;
TaskHandle_t main_t = NULL;
static uint32_t count = 0;
static const std::map<const uint32_t, const char*> pin2Name = {
#define FREQUENCY 100000 // 100 KHz
#define PERIOD_US 10
#define SPARK_DLY_MIN 10
#define SPARK_DLY_MAX 490
#define PAUSE_LONG_MIN 5000
#define PAUSE_LONG_MAX PAUSE_LONG_MIN*100
#define RPM_MIN 800
#define RPM_MAX 5500
void clearScreen(){
Serial.print("\033[2J"); // clear screen
Serial.print("\033[H"); // cursor home
Serial.flush();
}
static double filtered_rpm = 0;
static const std::map<const uint32_t, const char *> pin2Name = {
{PIN_TRIG_A12P, "HIGH_PIN_TRIG_A12P"},
{~PIN_TRIG_A12P, "LOW_PIN_TRIG_A12P"},
{PIN_TRIG_A12N, "HIGH_PIN_TRIG_A12N"},
@@ -20,13 +41,24 @@ static const std::map<const uint32_t, const char*> pin2Name = {
{SPARK_A12, "HIGH_SPARK_A12"},
{~SPARK_A12, "LOW_SPARK_A12"},
{SPARK_A34, "HIGH_SPARK_A34"},
{~SPARK_A34, "LOW_SPARK_A34"}
};
{~SPARK_A34, "LOW_SPARK_A34"},
{State::S_WAIT_10MS_END, "S_WAIT_10MS_END"},
{State::S_WAIT_10MS, "S_WAIT_10MS"}};
static timerStatus stsA = {
.clock_period_us = (uint32_t)PERIOD_US,
.pause_long_us = 10000,
.pause_short_us = 1000,
.coil_pulse_us = 1000,
.spark_pulse_us = 100,
.spark_delay_us = 50,
.main_task = NULL};
void setup()
{
Serial.begin(115200);
Serial.begin(921600);
delay(1000);
LOG_ATTACH_SERIAL(Serial);
pinMode(PIN_TRIG_A12P, OUTPUT);
@@ -43,25 +75,37 @@ void setup()
pinMode(SPARK_B12, OUTPUT);
pinMode(SPARK_B34, OUTPUT);
main_t = xTaskGetCurrentTaskHandleForCore(1);
pinMode(SPARK_DELAY_POT, ANALOG);
stsA.main_task = xTaskGetCurrentTaskHandleForCore(1);
// Timer: 80MHz / 80 = 1MHz → 1 tick = 1 µs
timerA = timerBegin(10000);
timerAttachInterruptArg(timerA, &onTimer, (void *)main_t);
timerAlarm(timerA, 10000, true, 0);
// Timer: 80MHz / 80 = 1MHz → 1 tick = 1 µs
// timerB = timerBegin(1);
// timerAttachInterrupt(timerB, &onTimer);
// timerStart(timerB);
timerA = timerBegin(FREQUENCY);
timerAttachInterruptArg(timerA, &onTimer, (void *)&stsA);
timerAlarm(timerA, 1, true, 0);
LOG_INFO("Setup Complete");
}
void loop()
{
uint32_t value = 0;
if (xTaskNotifyWait(0x00, ULONG_MAX, &value, 0))
Serial.println(pin2Name.at(value));
delay(10);
LOG_INFO("Loop: ", count++);
uint32_t spark_delay = (uint32_t)(map(analogRead(SPARK_DELAY_POT), 0, 4096, SPARK_DLY_MIN, SPARK_DLY_MAX) / PERIOD_US);
stsA.spark_delay_us = spark_delay * PERIOD_US;
if (stsA.spark_delay_us > (SPARK_DLY_MIN + SPARK_DLY_MAX) / 2) {
stsA.soft_start = true;
stsA.spark_delay_us -= (SPARK_DLY_MIN + SPARK_DLY_MAX) / 2;
} else {
stsA.soft_start = false;
}
double new_rpm = (double)(map(analogRead(FREQ_POT), 0, 4096, RPM_MIN, RPM_MAX));
filtered_rpm = filtered_rpm + 0.1 * (new_rpm - filtered_rpm);
stsA.pause_long_us = (uint32_t)(60000000.0f / filtered_rpm / 2.0f);
LOG_INFO("Spark Delay uS: ", stsA.spark_delay_us, "\tSoft Start: ", stsA.soft_start ? "TRUE" : "FALSE");
LOG_INFO("Engine Rpm: ", (uint32_t)(filtered_rpm));
LOG_INFO("Coil Pulse: ", stsA.coil_pulse_us, "us");
LOG_INFO("Spark Pulse: ", stsA.spark_pulse_us, "us");
delay(100);
clearScreen();
}

View File

@@ -17,3 +17,7 @@
#define SPARK_B12 4
#define SPARK_B34 5
// Pot
#define SPARK_DELAY_POT 13
#define FREQ_POT 14

View File

@@ -1,119 +1,192 @@
#include "timer.h"
#define TIME_CONST 1
enum State {
S_12P,
S_12N_DELAY,
S_12N,
S_WAIT_10MS,
S_34P,
S_34N_DELAY,
S_34N,
S_WAIT_1MS,
S_WAIT_10MS_END
};
volatile State state = S_12P;
volatile uint32_t state_time = 0;
void onTimer(void* arg) {
volatile static bool wait_sent = false;
void onTimer(void *arg)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
TaskHandle_t task = (TaskHandle_t)(arg);
state_time += 1;
timerStatus *params = (timerStatus *)(arg);
TaskHandle_t task = params->main_task;
switch (state) {
// increment state time
params->state_time += params->clock_period_us;
digitalWrite(PIN_TRIG_B12P, HIGH);
switch (params->state)
{
case S_12P:
digitalWrite(PIN_TRIG_A12P, HIGH);
xTaskNotifyFromISR(task, PIN_TRIG_A12P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
if (state_time == 2*TIME_CONST){
xTaskNotifyFromISR(task, SPARK_A12, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A12, HIGH);
if (params->state_time == params->clock_period_us && !params->coil12p_high)
{
// xTaskNotifyFromISR(task, PIN_TRIG_A12P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A12P, HIGH);
params->coil12p_high = true;
wait_sent = false;
}
if (state_time == 7*TIME_CONST) {
xTaskNotifyFromISR(task, ~SPARK_A12, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A12, LOW);
if (!params->soft_start)
{
if (params->state_time == params->spark_delay_us)
{
// xTaskNotifyFromISR(task, SPARK_A12, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A12, HIGH);
}
if (params->state_time == (params->spark_delay_us + params->spark_pulse_us))
{
// xTaskNotifyFromISR(task, ~SPARK_A12, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A12, LOW);
}
}
if (state_time >= 5*TIME_CONST) {
xTaskNotifyFromISR(task, ~PIN_TRIG_A12P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
if (params->state_time >= params->coil_pulse_us && params->coil12p_high)
{
// xTaskNotifyFromISR(task, ~PIN_TRIG_A12P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A12P, LOW);
params->coil12p_high = false;
}
if (state_time >= 10*TIME_CONST) {
state = S_12N;
state_time = 0;
if (params->state_time >= params->pause_short_us)
{
params->state = S_12N;
params->state_time = 0;
}
break;
case S_12N:
xTaskNotifyFromISR(task, PIN_TRIG_A12N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A12N, HIGH);
if (state_time >= 5*TIME_CONST) {
xTaskNotifyFromISR(task, ~PIN_TRIG_A12N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
case S_12N:
if (params->state_time == params->clock_period_us && !params->coil12n_high)
{
// xTaskNotifyFromISR(task, PIN_TRIG_A12N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A12N, HIGH);
params->coil12n_high = true;
}
if (params->soft_start)
{
if (params->state_time == params->spark_delay_us)
{
// xTaskNotifyFromISR(task, SPARK_A12, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A12, HIGH);
}
if (params->state_time == (params->spark_delay_us + params->spark_pulse_us))
{
// xTaskNotifyFromISR(task, ~SPARK_A12, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A12, LOW);
}
}
if (params->state_time >= params->coil_pulse_us && params->coil12n_high)
{
// xTaskNotifyFromISR(task, ~PIN_TRIG_A12N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A12N, LOW);
state = S_WAIT_10MS;
state_time = 0;
params->coil12n_high = false;
params->state = S_WAIT_10MS;
params->state_time = 0;
}
break;
case S_WAIT_10MS:
if (state_time >= 10*TIME_CONST) {
state = S_34P;
state_time = 0;
if (!wait_sent)
{
// xTaskNotifyFromISR(task, S_WAIT_10MS, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
wait_sent = true;
}
if (params->state_time >= params->pause_long_us)
{
params->state = S_34P;
params->state_time = 0;
}
break;
case S_34P:
xTaskNotifyFromISR(task, PIN_TRIG_A34P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A34P, HIGH);
if (state_time == 2*TIME_CONST){
xTaskNotifyFromISR(task, SPARK_A34, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A34, HIGH);
}
if (state_time == 7*TIME_CONST) {
xTaskNotifyFromISR(task, ~SPARK_A34, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A34, LOW);
if (params->state_time == params->clock_period_us && !params->coil34p_high)
{
// xTaskNotifyFromISR(task, PIN_TRIG_A34P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A34P, HIGH);
params->coil34p_high = true;;
wait_sent = false;
}
if (state_time >= 5*TIME_CONST) {
xTaskNotifyFromISR(task, ~PIN_TRIG_A34P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
if (!params->soft_start)
{
if (params->state_time == params->spark_delay_us)
{
// xTaskNotifyFromISR(task, SPARK_A34, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A34, HIGH);
}
if (params->state_time == params->spark_delay_us + params->spark_pulse_us)
{
// xTaskNotifyFromISR(task, ~SPARK_A34, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A34, LOW);
}
}
if (params->state_time >= params->coil_pulse_us && params->coil34p_high)
{
// xTaskNotifyFromISR(task, ~PIN_TRIG_A34P, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A34P, LOW);
params->coil34p_high = false;
}
if (state_time >= 10*TIME_CONST) {
state = S_34N;
state_time = 0;
if (params->state_time >= params->pause_short_us)
{
params->state = S_34N;
params->state_time = 0;
}
break;
case S_34N:
xTaskNotifyFromISR(task, PIN_TRIG_A34N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A34N, HIGH);
if (params->state_time == params->clock_period_us && !params->coil34n_high)
{
// xTaskNotifyFromISR(task, PIN_TRIG_A34N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A34N, HIGH);
params->coil34n_high = true;
}
if (state_time >= 5*TIME_CONST) {
xTaskNotifyFromISR(task, ~PIN_TRIG_A34N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
if (params->soft_start)
{
if (params->state_time == params->spark_delay_us)
{
// xTaskNotifyFromISR(task, SPARK_A34, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A34, HIGH);
}
if (params->state_time == params->spark_delay_us + params->spark_pulse_us)
{
// xTaskNotifyFromISR(task, ~SPARK_A34, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(SPARK_A34, LOW);
}
}
if (params->state_time >= params->coil_pulse_us && params->coil34n_high)
{
// xTaskNotifyFromISR(task, ~PIN_TRIG_A34N, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
digitalWrite(PIN_TRIG_A34N, LOW);
state = S_WAIT_10MS_END;
state_time = 0;
params->coil34n_high = false;
params->state = S_WAIT_10MS_END;
params->state_time = 0;
}
break;
case S_WAIT_10MS_END:
if (state_time >= 10*TIME_CONST) {
state = S_12P;
state_time = 0;
if (!wait_sent)
{
// xTaskNotifyFromISR(task, S_WAIT_10MS_END, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
wait_sent = true;
}
if (params->state_time >= params->pause_long_us)
{
params->state = S_12P;
params->state_time = 0;
}
break;
}
digitalWrite(PIN_TRIG_B12P, LOW);
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}

View File

@@ -6,4 +6,35 @@
#include "driver/gpio.h"
void IRAM_ATTR onTimer(void* arg);
enum State
{
S_12P,
S_12N_DELAY,
S_12N,
S_WAIT_10MS,
S_34P,
S_34N_DELAY,
S_34N,
S_WAIT_1MS,
S_WAIT_10MS_END
};
struct timerStatus
{
State state = State::S_12P;
uint32_t state_time = 0;
uint32_t clock_period_us;
uint32_t pause_long_us;
uint32_t pause_short_us;
uint32_t coil_pulse_us;
uint32_t spark_pulse_us;
uint32_t spark_delay_us;
bool soft_start = false;
bool coil12p_high = false;
bool coil34p_high = false;
bool coil12n_high = false;
bool coil34n_high = false;
TaskHandle_t main_task;
};
void IRAM_ATTR onTimer(void *arg);