Updated pin definitions and trigger tasks from pickups

This commit is contained in:
Emanuele Trabattoni
2026-03-25 14:16:23 +01:00
parent b42474fff5
commit 8c5b7d4a1c
4 changed files with 294 additions and 98 deletions

View File

@@ -1,40 +1,106 @@
#include <Arduino.h>
#include "soc/gpio_struct.h"
#include "pins.h"
#define CORE_0 0
#define CORE_1 1
#define TASK_STACK 4096 // in words
#define TASK_PRIORITY 2 // priorità leggermente più alta
// =====================
// Event Flags (bitmask)
// =====================
#define PKDT_FLAG_AP (1 << 0)
#define PKDT_FLAG_AN (1 << 1)
#define PKDT_FLAG_BP (1 << 2)
#define PKDT_FLAG_BN (1 << 3)
#define TRIG_FLAG_A12P (1 << 0)
#define TRIG_FLAG_A12N (1 << 2)
#define TRIG_FLAG_A34P (1 << 1)
#define TRIG_FLAG_A34N (1 << 3)
#define TRIG_FLAG_B12P (1 << 4)
#define TRIG_FLAG_B12N (1 << 6)
#define TRIG_FLAG_B34P (1 << 5)
#define TRIG_FLAG_B34N (1 << 7)
// Task handle
TaskHandle_t pkdtTaskHandle = NULL;
TaskHandle_t trigA_TaskHandle = NULL;
TaskHandle_t trigB_TaskHandle = NULL;
// Task internal Status
struct taskStatus {
int64_t trig12_start;
int64_t trig34_start;
int64_t trig12_time;
int64_t trig34_time;
bool trig12_complete = false;
bool trig34_complete = false;
bool soft12 = false;
bool soft34 = false;
bool error12 = false;
bool error34 = false;
};
taskStatus ignA_status;
taskStatus ignB_status;
// Pin to flag Map
static const uint32_t int2flag[] = {
[TRIG_A12P] = TRIG_FLAG_A12P,
[TRIG_A12N] = TRIG_FLAG_A34P,
[TRIG_A34P] = TRIG_FLAG_A12N,
[TRIG_A34N] = TRIG_FLAG_A34N,
[TRIG_B12P] = TRIG_FLAG_B12P,
[TRIG_B12N] = TRIG_FLAG_B34P,
[TRIG_B34P] = TRIG_FLAG_B12N,
[TRIG_B34N] = TRIG_FLAG_B34N,
};
// =====================
// ISR (Pass return bitmask to ISR management function)
// one function for each wake up pin conncted to a trigger
// =====================
void IRAM_ATTR pkdt_isr_ap() {
void IRAM_ATTR trig_isr_a() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_AP, eSetBits, &xHigherPriorityTaskWoken);
auto startTime = esp_timer_get_time();
uint32_t status = GPIO.status;
uint32_t flags = 0;
while (status) {
uint32_t pin = __builtin_ctz(status); // trova primo bit attivo
status &= ~(1 << pin); // clear bit
flags |= int2flag[pin];
}
if (flags & (TRIG_FLAG_A12P | TRIG_FLAG_A12N))
ignA_status.trig12_start = startTime;
else
ignA_status.trig12_start = startTime;
if (trigA_TaskHandle) {
xTaskNotifyFromISR(trigA_TaskHandle, flags, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
void IRAM_ATTR pkdt_isr_an() {
void IRAM_ATTR trig_isr_b() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_AN, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void IRAM_ATTR pkdt_isr_bp() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_BP, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
uint32_t status = GPIO.status;
uint32_t flags = 0;
void IRAM_ATTR pkdt_isr_bn() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_BN, eSetBits, &xHigherPriorityTaskWoken);
while (status) {
uint32_t pin = __builtin_ctz(status); // trova primo bit attivo
status &= ~(1 << pin); // clear bit
flags |= int2flag[pin];
}
if (trigB_TaskHandle) {
xTaskNotifyFromISR(trigB_TaskHandle, flags, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}

View File

@@ -10,38 +10,21 @@
#include <isr.h>
#include <pins.h>
#include <channels.h>
#include <tasks.h>
// Device Libraries
#include <ADS1256.h>
#include <AD5292.h>
void pkdtTask(void *pvParameters) {
uint32_t notifiedValue;
while (true) {
// attende eventi
xTaskNotifyWait(
0x00, // non pulire all'ingresso
0xFFFFFFFF, // pulisci tutti i bit all'uscita
&notifiedValue, // valore ricevuto
portMAX_DELAY
);
// 🔥 QUI GIRA SU CORE 0
switch (notifiedValue)
case PKDT_FLAG_AP: {
handlePKDT(PKDT_AP);
break;
}
default:
LOG_ERROR("Invalid Interrupt: ", notifiedValue);
}
}
void setup() {
Serial.begin(9600);
delay(250);
Serial.begin(115200);
// Setup Logger
LOG_ATTACH_SERIAL(Serial);
LOG_SET_LEVEL(DebugLogLevel::LVL_INFO);
// Print Processor Info
LOG_INFO("ESP32 Chip:", ESP.getChipModel());
LOG_INFO("ESP32 PSram:", ESP.getPsramSize());
LOG_INFO("ESP32 Flash:", ESP.getFlashChipSize());
@@ -49,40 +32,72 @@ void setup() {
LOG_INFO("ESP32 Sketch:", ESP.getFreeSketchSpace());
// Initialize Interrupt pins on peak detectors
pinMode(PKDT_AP, INPUT_PULLDOWN);
pinMode(PKDT_AN, INPUT_PULLDOWN);
pinMode(PKDT_BP, INPUT_PULLDOWN);
pinMode(PKDT_BN, INPUT_PULLDOWN);
// interrupt
attachInterrupt(PKDT_AP, pkdt_isr_ap, RISING);
attachInterrupt(PKDT_AN, pkdt_isr_an, RISING);
attachInterrupt(PKDT_BP, pkdt_isr_bp, RISING);
attachInterrupt(PKDT_BN, pkdt_isr_bn, RISING);
pinMode(TRIG_A12P, INPUT_PULLDOWN);
pinMode(TRIG_A12N, INPUT_PULLDOWN);
pinMode(TRIG_A34P, INPUT_PULLDOWN);
pinMode(TRIG_A34N, INPUT_PULLDOWN);
pinMode(TRIG_B12P, INPUT_PULLDOWN);
pinMode(TRIG_B12N, INPUT_PULLDOWN);
pinMode(TRIG_B34P, INPUT_PULLDOWN);
pinMode(TRIG_B34N, INPUT_PULLDOWN);
// Ignition A Interrupts
attachInterrupt(TRIG_A12P, trig_isr_a, RISING);
attachInterrupt(TRIG_A34P, trig_isr_a, RISING);
attachInterrupt(TRIG_A12N, trig_isr_a, RISING);
attachInterrupt(TRIG_A34N, trig_isr_a, RISING);
// Ignition B Interrupts
attachInterrupt(TRIG_B12P, trig_isr_b, RISING);
attachInterrupt(TRIG_B34P, trig_isr_b, RISING);
attachInterrupt(TRIG_B12N, trig_isr_b, RISING);
attachInterrupt(TRIG_B34N, trig_isr_b, RISING);
// Init SPI interface
SPI.begin();
// Init ADC
auto adc = ADS1256(ADC_DRDY, ADC_RST, ADC_SYNC, ADC_CS, 0.0, SPI);
ADS1256.
}
void loop() {
// task su core 0
auto isrTask = xTaskCreatePinnedToCore(
pkdtTask,
"pkdtTask",
4096,
// global variables
bool running = true;
// Ignition A on Core 0
auto ignA_task_success = xTaskCreatePinnedToCore(
ignitionA_task,
"ignitionA_task",
TASK_STACK,
NULL,
2, // priorità leggermente più alta
&pkdtTaskHandle,
0
TASK_PRIORITY,
&trigA_TaskHandle,
CORE_0
);
if (isrTask != pdPASS){
// Ignition A on Core 1
auto ignB_task_success = xTaskCreatePinnedToCore(
ignitionB_task,
"ignitionB_task",
TASK_STACK,
NULL,
TASK_PRIORITY, // priorità leggermente più alta
&trigA_TaskHandle,
CORE_1
);
if ((ignA_task_success && ignB_task_success) != pdPASS){
LOG_ERROR("Unble to initialize ISR task");
}
LOG_INFO("Real Time Tasks A&B initialized");
////////////////////// MAIN LOOP //////////////////////
while (running) {
}
if (trigA_TaskHandle)
vTaskDelete(trigA_TaskHandle);
if (trigB_TaskHandle)
vTaskDelete(trigB_TaskHandle);
////////////////////// MAIN LOOP //////////////////////
}

View File

@@ -6,14 +6,15 @@
#define SPI_SCK 12
// =====================
// CHIP SELECT
// I2C BUS
// =====================
#define ADC_CS 10
#define POT_CS 9
#define SDA 8
#define SCL 9
// =====================
// ADC CONTROL
// =====================
#define ADC_CS 10
#define ADC_DRDY 4
#define ADC_RST 5
#define ADC_SYNC 6
@@ -21,47 +22,63 @@
// =====================
// DIGITAL POT
// =====================
#define POT_DRDY 7
#define POT_CS 7
#define POT_DRDY 18
// =====================
// RELAY
// RELAY OUT
// =====================
#define PICK_RELAY 8
#define PICK_RELAY 21
// =====================
// PEAK DETECTORS (DIGITAL INPUT)
// TRIGGER INPUT INTERRUPTS
// =====================
#define PKDT_AP 1
#define PKDT_AN 2
#define PKDT_BP 3
#define PKDT_BN 14
#define TRIG_A12P 1
#define TRIG_A12N 2
#define TRIG_A34P 3
#define TRIG_A34N 14
#define TRIG_B12P 15
#define TRIG_B12N 16
#define TRIG_B34P 17
#define TRIG_B34N 18
// =====================
// TRIGGER INPUTS
// PEAK DETECTOR RESET OUTPUTS
// =====================
#define TRIG_AP 15
#define TRIG_AN 16
#define TRIG_BP 17
#define TRIG_BN 18
#define RST_A12P 39
#define RST_A12N 40
#define RST_A34P 41
#define RST_A34N 42
#define RST_B12P 35
#define RST_B12N 36
#define RST_B34P 37
#define RST_B34N 38
// =====================
// SOFT START DETECT
// SPARK DETECT INPUTS
// =====================
#define SOFT_A 21
#define SOFT_B 47
#define SPARK_A12 45 // input only
#define SPARK_A34 46 // input only
#define SPARK_B12 47
#define SPARK_B34 48
// =====================
// STATUS OUTPUT
// STATUS & BUTTON su PCA9555 (I2C)
// =====================
#define STA_1 35
#define STA_2 36
#define STA_3 37
#define STA_4 38
#define STA_1 0
#define STA_2 1
#define STA_3 2
#define STA_4 3
#define STA_5 4
#define STA_6 5
#define STA_7 6
#define STA_8 7
// =====================
// BUTTON INPUT
// =====================
#define BTN_1 39
#define BTN_2 40
#define BTN_3 41
#define BTN_4 42
#define BTN_1 8
#define BTN_2 9
#define BTN_3 10
#define BTN_4 11
#define BTN_5 12
#define BTN_6 13
#define BTN_7 14
#define BTN_8 15

98
RotaxMonitor/src/tasks.h Normal file
View File

@@ -0,0 +1,98 @@
// Arduino Libraries
#include <Arduino.h>
#include <DebugLog.h>
// ISR
#include "isr.h"
const uint16_t spark_delay_us = 500;
void ignitionA_task(void *pvParameters) {
uint32_t notifiedValue;
while (true) {
// attende eventi
xTaskNotifyWait(
0x00, // non pulire all'ingresso
ULONG_MAX, // pulisci tutti i bit all'uscita
&notifiedValue, // valore ricevuto
portMAX_DELAY
);
uint64_t wait_time=0;
switch (notifiedValue) {
case TRIG_FLAG_A12P:
case TRIG_FLAG_A12N:
bool spark12_timeout = false;
if (ignA_status.trig12_complete) {
// read peak adc values from sample and hold
} else {
while(!digitalRead(SPARK_A12)) {
wait_time = ignA_status.trig12_start - esp_timer_get_time();
if (wait_time >= spark_delay_us) {
spark12_timeout = true;
break;
}
}
if (spark12_timeout) { // spark did not happen, timeout
ignA_status.trig12_complete = false;
} else { // spark did happen
ignA_status.trig12_complete = true;
ignA_status.trig12_time = wait_time;
}
}
break;
case TRIG_FLAG_A34P:
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;
default:
LOG_ERROR("Invalid A Interrupt: ", notifiedValue);
}
}
}
void ignitionB_task(void *pvParameters) {
uint32_t notifiedValue;
while (true) {
// attende eventi
xTaskNotifyWait(
0x00, // non pulire all'ingresso
0xFFFFFFFF, // pulisci tutti i bit all'uscita
&notifiedValue, // valore ricevuto
portMAX_DELAY
);
switch (notifiedValue) {
case TRIG_FLAG_B12P:
break;
case TRIG_FLAG_B34P:
break;
case TRIG_FLAG_B12N:
break;
case TRIG_FLAG_B34N:
break;
default:
LOG_ERROR("Invalid B Interrupt: ", notifiedValue);
}
}
}