From 42e64b673c8e0cb2c8a89f5d91a2b5ca48f38411 Mon Sep 17 00:00:00 2001 From: Hector van der Aa Date: Wed, 3 Jun 2026 10:56:28 +0200 Subject: [PATCH] Initial sync implementation Implemented system sync with crank and cam state and simple error handling --- STM32/CM7/Core/Inc/global_state.h | 34 ++++++++++-------- STM32/CM7/Core/Inc/macros.h | 13 +++++++ STM32/CM7/Core/Src/main.c | 7 ++-- STM32/CM7/Core/Src/tasks/cam.c | 33 ++++++++++++----- STM32/CM7/Core/Src/tasks/crank.c | 59 ++++++++++++++++++++++++++----- STM32/STM32.ioc | 4 ++- 6 files changed, 115 insertions(+), 35 deletions(-) create mode 100644 STM32/CM7/Core/Inc/macros.h diff --git a/STM32/CM7/Core/Inc/global_state.h b/STM32/CM7/Core/Inc/global_state.h index cc444c6..d26ba16 100644 --- a/STM32/CM7/Core/Inc/global_state.h +++ b/STM32/CM7/Core/Inc/global_state.h @@ -3,21 +3,27 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include +#include + +#define MAX_CAM_MISS 2 + +typedef enum { SYNC_OK = 0, SYNC_PENDING = 1, SYNC_NOT_OK = 2 } sync_state_t; + typedef enum { - SYNC_OK = 0, - SYNC_PENDING = 1, - SYNC_NOT_OK = 2 -} sync_state; -typedef enum { - CYCLE_EXHAUST = 0, - CYCLE_INTAKE = 1, - CYCLE_COMPRESSION = 2, - CYCLE_COMBUSTION = 3, + CYCLE_COMBUSTION = 0, + CYCLE_EXHAUST = 1, + CYCLE_INTAKE = 2, + CYCLE_COMPRESSION = 3, CYCLE_UNKNOWN = 4 -} crank_state; +} crank_state_t; + +typedef enum { CAM_IDLE = 0, CAM_TRIGD = 1 } cam_state_t; + typedef struct { - crank_state cycle; - sync_state sync; - ring_buffer_t crank_RB; - ring_buffer_t cam_RB; + crank_state_t crank_state; + cam_state_t cam_state; + uint8_t cam_miss_ctr; + sync_state_t sync_state; + ring_buffer_t crank_RB; + ring_buffer_t cam_RB; } global_state_t; diff --git a/STM32/CM7/Core/Inc/macros.h b/STM32/CM7/Core/Inc/macros.h new file mode 100644 index 0000000..fabbbbb --- /dev/null +++ b/STM32/CM7/Core/Inc/macros.h @@ -0,0 +1,13 @@ +// Copyright (C) 2026 Hector van der Aa +// Copyright (C) 2026 Pierre Barbier +// Copyright (C) 2026 Association Exergie +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifdef DEBUG +#include "SEGGER_RTT.h" +#define DEBUG_LOG(fmt, ...) SEGGER_RTT_printf(0, fmt "\n", ##__VA_ARGS__) +#else +#define DEBUG_LOG(fmt, ...) \ + do { \ + } while (0) +#endif diff --git a/STM32/CM7/Core/Src/main.c b/STM32/CM7/Core/Src/main.c index d6cebad..b8be124 100644 --- a/STM32/CM7/Core/Src/main.c +++ b/STM32/CM7/Core/Src/main.c @@ -160,7 +160,10 @@ int main(void) HAL_Init(); /* USER CODE BEGIN Init */ - state_g.sync = SYNC_NOT_OK; + state_g.sync_state = SYNC_NOT_OK; + state_g.crank_state = CYCLE_UNKNOWN; + state_g.cam_state = CAM_IDLE; + state_g.cam_miss_ctr = 0; /* USER CODE END Init */ /* Configure the system clock */ @@ -359,7 +362,7 @@ static void MX_TIM2_Init(void) sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; - sConfigIC.ICFilter = 0; + sConfigIC.ICFilter = 10; if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); diff --git a/STM32/CM7/Core/Src/tasks/cam.c b/STM32/CM7/Core/Src/tasks/cam.c index ab5a39a..2a8b552 100644 --- a/STM32/CM7/Core/Src/tasks/cam.c +++ b/STM32/CM7/Core/Src/tasks/cam.c @@ -4,22 +4,37 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "cmsis_os2.h" +#include "macros.h" #include "main.h" #include "ring_buffer.h" #include "tasks.h" -#ifdef DEBUG -#include "SEGGER_RTT.h" -#endif void camHandler(void *argument) { for (;;) { osThreadFlagsWait(0x01, osFlagsWaitAny, osWaitForever); -#ifdef DEBUG - SEGGER_RTT_printf(0, "Cam pulse detected at: %lu\n\r", - ringBufferRead(&state_g.cam_RB, 0)); -#endif /* ifdef DEBUG */ - if (state_g.sync == SYNC_OK) { - // TODO complete algorithm for scheduling spark + + DEBUG_LOG("Cam pulse detected at: %lu\n\r", + ringBufferRead(&state_g.cam_RB, 0)); + + // FILTERS + + state_g.cam_state = CAM_TRIGD; + state_g.cam_miss_ctr = 0; + switch (state_g.sync_state) { + case SYNC_NOT_OK: { + state_g.sync_state = SYNC_PENDING; + DEBUG_LOG("Sync state updated to pending\n\r"); + break; + } + case SYNC_PENDING: { + if (state_g.crank_state == CYCLE_COMPRESSION) { + state_g.sync_state = SYNC_OK; + DEBUG_LOG("Sync state updated to OK\n\r"); + } + break; + } + default: + break; } } } diff --git a/STM32/CM7/Core/Src/tasks/crank.c b/STM32/CM7/Core/Src/tasks/crank.c index 9664726..d2eecd4 100644 --- a/STM32/CM7/Core/Src/tasks/crank.c +++ b/STM32/CM7/Core/Src/tasks/crank.c @@ -4,22 +4,63 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "cmsis_os2.h" +#include "macros.h" #include "main.h" #include "ring_buffer.h" #include "tasks.h" -#ifdef DEBUG -#include "SEGGER_RTT.h" -#endif void crankHandler(void *argument) { for (;;) { osThreadFlagsWait(0x01, osFlagsWaitAny, osWaitForever); -#ifdef DEBUG - SEGGER_RTT_printf(0, "Crank pulse detected at: %lu\n\r", - ringBufferRead(&state_g.crank_RB, 0)); -#endif /* ifdef DEBUG */ - if (state_g.sync == SYNC_OK) { - // TODO complete algorithm for scheduling spark + DEBUG_LOG("Crank pulse detected at: %lu\n\r", + ringBufferRead(&state_g.crank_RB, 0)); + // FILTER + + // INCREMENT SWITCH + switch (state_g.crank_state) { + case CYCLE_COMPRESSION: { + if (state_g.cam_state != CAM_TRIGD) { + DEBUG_LOG("Cam miss detected, sync dynamite incoming\n\r"); + state_g.cam_miss_ctr++; + if (state_g.cam_miss_ctr > MAX_CAM_MISS) { + state_g.sync_state = SYNC_NOT_OK; + state_g.crank_state = CYCLE_UNKNOWN; + break; + } + } + state_g.crank_state = CYCLE_COMBUSTION; + DEBUG_LOG("Crank state incremented\n\r"); + state_g.cam_state = CAM_IDLE; + break; + } + case CYCLE_COMBUSTION: + case CYCLE_EXHAUST: + case CYCLE_INTAKE: { + if (state_g.cam_state == CAM_TRIGD) { + state_g.sync_state = SYNC_NOT_OK; + state_g.crank_state = CYCLE_UNKNOWN; + state_g.cam_state = CAM_IDLE; + break; + } + state_g.crank_state++; + DEBUG_LOG("Crank state incremented\n\r"); + break; + } + case CYCLE_UNKNOWN: { + if (state_g.sync_state == SYNC_PENDING && + state_g.cam_state == CAM_TRIGD) { + state_g.crank_state = CYCLE_COMBUSTION; + state_g.cam_state = CAM_IDLE; + } + break; + } + } + + // SPARK SCHEDULE + if (state_g.crank_state == CYCLE_COMPRESSION && + state_g.sync_state == SYNC_OK) { + DEBUG_LOG("Spark schedule reached, congrats\n\r"); + // TODO: schedule spark } } } diff --git a/STM32/STM32.ioc b/STM32/STM32.ioc index d1bd666..23b034e 100644 --- a/STM32/STM32.ioc +++ b/STM32/STM32.ioc @@ -249,8 +249,10 @@ SYS.userName=SYS_M7 TIM2.Channel-Input_Capture1_from_TI1=TIM_CHANNEL_1 TIM2.Channel-Input_Capture2_from_TI2=TIM_CHANNEL_2 TIM2.ClockDivision=TIM_CLOCKDIVISION_DIV4 +TIM2.ICFilter_CH1=10 +TIM2.ICFilter_CH2=10 TIM2.ICPolarity_CH1=TIM_INPUTCHANNELPOLARITY_FALLING -TIM2.IPParameters=ClockDivision,Prescaler,Channel-Input_Capture1_from_TI1,ICPolarity_CH1,Channel-Input_Capture2_from_TI2 +TIM2.IPParameters=ClockDivision,Prescaler,Channel-Input_Capture1_from_TI1,ICPolarity_CH1,Channel-Input_Capture2_from_TI2,ICFilter_CH2,ICFilter_CH1 TIM2.Prescaler=0 VP_FREERTOS_M7_VS_CMSIS_V2.Mode=CMSIS_V2 VP_FREERTOS_M7_VS_CMSIS_V2.Signal=FREERTOS_M7_VS_CMSIS_V2