From 3294651ba2b28ea3a815a2245d61b4039eeb3672 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 11:57:55 -0400 Subject: [PATCH 01/55] GPIOs are labelled --- AutonomousDistroBoard/.mxproject | 2 +- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 11 ++++++++--- AutonomousDistroBoard/Core/Inc/main.h | 8 ++++++++ AutonomousDistroBoard/Core/Src/main.c | 14 +++++++------- README.md | 3 ++- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/AutonomousDistroBoard/.mxproject b/AutonomousDistroBoard/.mxproject index 5d4f1f4..1f3f62c 100644 --- a/AutonomousDistroBoard/.mxproject +++ b/AutonomousDistroBoard/.mxproject @@ -1,5 +1,5 @@ [PreviousLibFiles] -LibFiles=Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dmamux.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dmamux.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f407xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/tz_context.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_armv8mbl.h; +LibFiles=Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dmamux.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dmamux.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f407xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/tz_context.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_armv8mbl.h;Drivers/CMSIS/Include/core_sc000.h; [PreviousUsedCubeIDEFiles] SourceFiles=Core/Src/main.c;Core/Src/stm32f4xx_it.c;Core/Src/stm32f4xx_hal_msp.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Core/Src/system_stm32f4xx.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Core/Src/system_stm32f4xx.c;;; diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 7961d03..65ac4d7 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -83,6 +83,8 @@ PB5.Signal=CAN2_RX PB6.Locked=true PB6.Mode=CAN_Activate PB6.Signal=CAN2_TX +PB7.GPIOParameters=GPIO_Label +PB7.GPIO_Label=CAN_S PB7.Locked=true PB7.Signal=GPIO_Output PB9.Locked=true @@ -93,10 +95,16 @@ PC12.Signal=UART5_TX PD2.Locked=true PD2.Mode=Asynchronous PD2.Signal=UART5_RX +PE5.GPIOParameters=GPIO_Label +PE5.GPIO_Label=MAIN_COIL_EN PE5.Locked=true PE5.Signal=GPIO_Output +PE6.GPIOParameters=GPIO_Label +PE6.GPIO_Label=PRECHARGE_EN PE6.Locked=true PE6.Signal=GPIO_Output +PE8.GPIOParameters=GPIO_Label +PE8.GPIO_Label=LED_OUT PE8.Locked=true PE8.Signal=GPIO_Output PE9.Locked=true @@ -110,7 +118,6 @@ PH1-OSC_OUT.Signal=RCC_OSC_OUT PinOutPanel.RotationAngle=0 ProjectManager.AskForMigrate=true ProjectManager.BackupPrevious=false -ProjectManager.CompilerLinker=GCC ProjectManager.CompilerOptimize=6 ProjectManager.ComputerToolchain=false ProjectManager.CoupleFile=false @@ -136,8 +143,6 @@ ProjectManager.RegisterCallBack= ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=STM32CubeIDE ProjectManager.ToolChainLocation= -ProjectManager.UAScriptAfterPath= -ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=true ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_CAN2_Init-CAN2-false-HAL-true,4-MX_UART5_Init-UART5-false-HAL-true,5-MX_TIM1_Init-TIM1-false-HAL-true,6-MX_TIM11_Init-TIM11-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true,8-MX_USB_OTG_FS_PCD_Init-USB_OTG_FS-false-HAL-true RCC.48MHZClocksFreq_Value=48000000 diff --git a/AutonomousDistroBoard/Core/Inc/main.h b/AutonomousDistroBoard/Core/Inc/main.h index 6b80116..bdb3c58 100644 --- a/AutonomousDistroBoard/Core/Inc/main.h +++ b/AutonomousDistroBoard/Core/Inc/main.h @@ -59,6 +59,14 @@ void Error_Handler(void); /* USER CODE END EFP */ /* Private defines -----------------------------------------------------------*/ +#define MAIN_COIL_EN_Pin GPIO_PIN_5 +#define MAIN_COIL_EN_GPIO_Port GPIOE +#define PRECHARGE_EN_Pin GPIO_PIN_6 +#define PRECHARGE_EN_GPIO_Port GPIOE +#define LED_OUT_Pin GPIO_PIN_8 +#define LED_OUT_GPIO_Port GPIOE +#define CAN_S_Pin GPIO_PIN_7 +#define CAN_S_GPIO_Port GPIOB /* USER CODE BEGIN Private defines */ diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index fa69d31..4e1dcf9 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -435,24 +435,24 @@ static void MX_GPIO_Init(void) __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_8, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOE, MAIN_COIL_EN_Pin|PRECHARGE_EN_Pin|LED_OUT_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); + HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_RESET); - /*Configure GPIO pins : PE5 PE6 PE8 */ - GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_8; + /*Configure GPIO pins : MAIN_COIL_EN_Pin PRECHARGE_EN_Pin LED_OUT_Pin */ + GPIO_InitStruct.Pin = MAIN_COIL_EN_Pin|PRECHARGE_EN_Pin|LED_OUT_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - /*Configure GPIO pin : PB7 */ - GPIO_InitStruct.Pin = GPIO_PIN_7; + /*Configure GPIO pin : CAN_S_Pin */ + GPIO_InitStruct.Pin = CAN_S_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + HAL_GPIO_Init(CAN_S_GPIO_Port, &GPIO_InitStruct); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ diff --git a/README.md b/README.md index 46d4b2c..21a2273 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Autonomous Project electrical stack code -## Autonomous DistroBoard Pin Definitions +## Autonomous Control/Distro Board Pin Definitions - **CAN Bus (CAN2):** - RX: `PB5` @@ -30,6 +30,7 @@ Autonomous Project electrical stack code - TIM11 (CH1): `PB9` - **GPIOs:** + - CAN_S: `PB7` - Main Coil EN: `PE5` - Precharge EN: `PE6` - LED OUT: `PE8` From de89991dc3fb9e30c6fe6c4105e014a35b498d27 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 12:17:59 -0400 Subject: [PATCH 02/55] 8MHz HSE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PLLM = 8 PLLN = 240 PLLP = 2 PLLQ = 5 => VCO input = 8 / 8 = 1 MHz VCO output = 1 × 240 = 240 MHz SYSCLK = 240 / 2 = 120 MHz --- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 16 ++++++++-------- .../Core/Inc/stm32f4xx_hal_conf.h | 2 +- AutonomousDistroBoard/Core/Src/main.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 65ac4d7..514abf5 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -158,26 +158,26 @@ RCC.EthernetFreq_Value=120000000 RCC.FCLKCortexFreq_Value=120000000 RCC.FamilyName=M RCC.HCLKFreq_Value=120000000 -RCC.HSE_VALUE=25000000 +RCC.HSE_VALUE=8000000 RCC.HSI_VALUE=16000000 -RCC.I2SClocksFreq_Value=160000000 +RCC.I2SClocksFreq_Value=96000000 RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQ,PLLQCLKFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S RCC.LSE_VALUE=32768 RCC.LSI_VALUE=32000 RCC.MCO2PinFreq_Value=120000000 RCC.PLLCLKFreq_Value=120000000 -RCC.PLLM=15 -RCC.PLLN=144 +RCC.PLLM=8 +RCC.PLLN=240 RCC.PLLQ=5 RCC.PLLQCLKFreq_Value=48000000 RCC.RTCFreq_Value=32000 -RCC.RTCHSEDivFreq_Value=12500000 +RCC.RTCHSEDivFreq_Value=4000000 RCC.SYSCLKFreq_VALUE=120000000 RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK -RCC.VCOI2SOutputFreq_Value=320000000 -RCC.VCOInputFreq_Value=1666666.6666666667 +RCC.VCOI2SOutputFreq_Value=192000000 +RCC.VCOInputFreq_Value=1000000 RCC.VCOOutputFreq_Value=240000000 -RCC.VcooutputI2S=160000000 +RCC.VcooutputI2S=96000000 SH.S_TIM11_CH1.0=TIM11_CH1,PWM Generation1 CH1 SH.S_TIM11_CH1.ConfNb=1 SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1 diff --git a/AutonomousDistroBoard/Core/Inc/stm32f4xx_hal_conf.h b/AutonomousDistroBoard/Core/Inc/stm32f4xx_hal_conf.h index f5e58c1..d5a3ce5 100644 --- a/AutonomousDistroBoard/Core/Inc/stm32f4xx_hal_conf.h +++ b/AutonomousDistroBoard/Core/Inc/stm32f4xx_hal_conf.h @@ -96,7 +96,7 @@ * (when HSE is used as system clock source, directly or through the PLL). */ #if !defined (HSE_VALUE) - #define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 4e1dcf9..ee0d7d6 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -142,8 +142,8 @@ void SystemClock_Config(void) RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 15; - RCC_OscInitStruct.PLL.PLLN = 144; + RCC_OscInitStruct.PLL.PLLM = 8; + RCC_OscInitStruct.PLL.PLLN = 240; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 5; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) From 9ba1e0b5b567184db3343da398186b2845c9bf26 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 14:46:16 -0400 Subject: [PATCH 03/55] CAN2 tuning for 500k bus? BS1 = 12 TQ BS2 = 2 TQ Prescaler = 4 APB1 = 30 MHz --- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 13 +++++++------ AutonomousDistroBoard/Core/Src/main.c | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 514abf5..872edf6 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -2,12 +2,13 @@ CAD.formats= CAD.pinconfig= CAD.provider= -CAN2.BS1=CAN_BS1_1TQ -CAN2.BS2=CAN_BS2_1TQ -CAN2.CalculateBaudRate=625000 -CAN2.CalculateTimeBit=1600 -CAN2.CalculateTimeQuantum=533.3333333333334 -CAN2.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,BS1,BS2 +CAN2.BS1=CAN_BS1_12TQ +CAN2.BS2=CAN_BS2_2TQ +CAN2.CalculateBaudRate=499999 +CAN2.CalculateTimeBit=2000 +CAN2.CalculateTimeQuantum=133.33333333333334 +CAN2.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,BS1,BS2,Prescaler +CAN2.Prescaler=4 File.Version=6 KeepUserPlacement=false Mcu.CPN=STM32F407VGT6 diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index ee0d7d6..b35be37 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -182,11 +182,11 @@ static void MX_CAN2_Init(void) /* USER CODE END CAN2_Init 1 */ hcan2.Instance = CAN2; - hcan2.Init.Prescaler = 16; + hcan2.Init.Prescaler = 4; hcan2.Init.Mode = CAN_MODE_NORMAL; hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ; - hcan2.Init.TimeSeg1 = CAN_BS1_1TQ; - hcan2.Init.TimeSeg2 = CAN_BS2_1TQ; + hcan2.Init.TimeSeg1 = CAN_BS1_12TQ; + hcan2.Init.TimeSeg2 = CAN_BS2_2TQ; hcan2.Init.TimeTriggeredMode = DISABLE; hcan2.Init.AutoBusOff = DISABLE; hcan2.Init.AutoWakeUp = DISABLE; From 7ce11812d7b1f8438ffb67c5fc50738af06dd511 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 15:03:49 -0400 Subject: [PATCH 04/55] compiledb to generate a somewhat working compile_commands --- AutonomousDistroBoard/.gitignore | 1 + AutonomousDistroBoard/compile_commands.json | 960 ++++++++++++++++++++ 2 files changed, 961 insertions(+) create mode 100644 AutonomousDistroBoard/compile_commands.json diff --git a/AutonomousDistroBoard/.gitignore b/AutonomousDistroBoard/.gitignore index 9612dd8..c8384e3 100644 --- a/AutonomousDistroBoard/.gitignore +++ b/AutonomousDistroBoard/.gitignore @@ -1,5 +1,6 @@ Debug/ Release/ .settings/ +.cache/ .metadata/ .DS_Store \ No newline at end of file diff --git a/AutonomousDistroBoard/compile_commands.json b/AutonomousDistroBoard/compile_commands.json new file mode 100644 index 0000000..fce2998 --- /dev/null +++ b/AutonomousDistroBoard/compile_commands.json @@ -0,0 +1,960 @@ +[ + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.d", + "-MTDrivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.o" + ], + "file": "../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "-mcpu=cortex-m4", + "-g3", + "-DDEBUG", + "-c", + "-x", + "assembler-with-cpp", + "-MMD", + "-MP", + "-MFCore/Startup/startup_stm32f407vgtx.d", + "-MTCore/Startup/startup_stm32f407vgtx.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Startup/startup_stm32f407vgtx.o", + "../Core/Startup/startup_stm32f407vgtx.s" + ], + "file": "../Core/Startup/startup_stm32f407vgtx.s" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Core/Src/main.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFCore/Src/main.d", + "-MTCore/Src/main.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Src/main.o" + ], + "file": "../Core/Src/main.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Core/Src/stm32f4xx_hal_msp.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFCore/Src/stm32f4xx_hal_msp.d", + "-MTCore/Src/stm32f4xx_hal_msp.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Src/stm32f4xx_hal_msp.o" + ], + "file": "../Core/Src/stm32f4xx_hal_msp.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Core/Src/stm32f4xx_it.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFCore/Src/stm32f4xx_it.d", + "-MTCore/Src/stm32f4xx_it.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Src/stm32f4xx_it.o" + ], + "file": "../Core/Src/stm32f4xx_it.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Core/Src/syscalls.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFCore/Src/syscalls.d", + "-MTCore/Src/syscalls.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Src/syscalls.o" + ], + "file": "../Core/Src/syscalls.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Core/Src/sysmem.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFCore/Src/sysmem.d", + "-MTCore/Src/sysmem.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Src/sysmem.o" + ], + "file": "../Core/Src/sysmem.c" + }, + { + "directory": "/home/millankumar/Documents/EVC/AutonomousElectrical/AutonomousDistroBoard/Debug", + "arguments": [ + "arm-none-eabi-gcc", + "../Core/Src/system_stm32f4xx.c", + "-mcpu=cortex-m4", + "-std=gnu11", + "-g3", + "-DDEBUG", + "-DUSE_HAL_DRIVER", + "-DSTM32F407xx", + "-c", + "-I../Core/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc", + "-I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "-I../Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "-I../Drivers/CMSIS/Include", + "-O0", + "-ffunction-sections", + "-fdata-sections", + "-Wall", + "-fstack-usage", + + "-MMD", + "-MP", + "-MFCore/Src/system_stm32f4xx.d", + "-MTCore/Src/system_stm32f4xx.o", + "--specs=nano.specs", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-o", + "Core/Src/system_stm32f4xx.o" + ], + "file": "../Core/Src/system_stm32f4xx.c" + } +] From 0ce5c3ef5b233516ab63bdba936894bea4720bc2 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 15:20:12 -0400 Subject: [PATCH 05/55] TIM1 (steering) --- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 7 ++++++- AutonomousDistroBoard/Core/Src/main.c | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 872edf6..84ef147 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -10,6 +10,7 @@ CAN2.CalculateTimeQuantum=133.33333333333334 CAN2.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,BS1,BS2,Prescaler CAN2.Prescaler=4 File.Version=6 +GPIO.groupedBy=Group By Peripherals KeepUserPlacement=false Mcu.CPN=STM32F407VGT6 Mcu.Family=STM32F4 @@ -184,7 +185,11 @@ SH.S_TIM11_CH1.ConfNb=1 SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1 SH.S_TIM1_CH1.ConfNb=1 TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 -TIM1.IPParameters=Channel-PWM Generation1 CH1 +TIM1.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Period,Pulse-PWM Generation1 CH1,OCIdleState_1 +TIM1.OCIdleState_1=TIM_OCIDLESTATE_RESET +TIM1.Period=19999 +TIM1.Prescaler=89 +TIM1.Pulse-PWM\ Generation1\ CH1=1500 TIM11.Channel=TIM_CHANNEL_1 TIM11.IPParameters=Channel UART5.IPParameters=VirtualMode diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index b35be37..24f6ee3 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -223,9 +223,9 @@ static void MX_TIM1_Init(void) /* USER CODE END TIM1_Init 1 */ htim1.Instance = TIM1; - htim1.Init.Prescaler = 0; + htim1.Init.Prescaler = 89; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; - htim1.Init.Period = 65535; + htim1.Init.Period = 19999; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; @@ -240,7 +240,7 @@ static void MX_TIM1_Init(void) Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; + sConfigOC.Pulse = 1500; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; From d82636a4317435cfda42044e388d2b62b91e8e7c Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 15:20:24 -0400 Subject: [PATCH 06/55] TIM11 (throttle PWM) --- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 5 ++++- AutonomousDistroBoard/Core/Src/main.c | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 84ef147..4e93b4d 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -191,7 +191,10 @@ TIM1.Period=19999 TIM1.Prescaler=89 TIM1.Pulse-PWM\ Generation1\ CH1=1500 TIM11.Channel=TIM_CHANNEL_1 -TIM11.IPParameters=Channel +TIM11.IPParameters=Channel,Prescaler,Period,Pulse +TIM11.Period=19999 +TIM11.Prescaler=89 +TIM11.Pulse=1000 UART5.IPParameters=VirtualMode UART5.VirtualMode=Asynchronous USART3.IPParameters=VirtualMode diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 24f6ee3..09585bc 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -286,9 +286,9 @@ static void MX_TIM11_Init(void) /* USER CODE END TIM11_Init 1 */ htim11.Instance = TIM11; - htim11.Init.Prescaler = 0; + htim11.Init.Prescaler = 89; htim11.Init.CounterMode = TIM_COUNTERMODE_UP; - htim11.Init.Period = 65535; + htim11.Init.Period = 19999; htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim11) != HAL_OK) @@ -300,7 +300,7 @@ static void MX_TIM11_Init(void) Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; + sConfigOC.Pulse = 1000; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim11, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) From 3319f401369e929aea7e59944587b880fd55d16f Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 15:24:20 -0400 Subject: [PATCH 07/55] Fixing TIM1 and TIM11 prescaler? APB2TimFreq_Value=120000000 ?? --- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 4 ++-- AutonomousDistroBoard/Core/Src/main.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 4e93b4d..0f950ff 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -188,12 +188,12 @@ TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 TIM1.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Period,Pulse-PWM Generation1 CH1,OCIdleState_1 TIM1.OCIdleState_1=TIM_OCIDLESTATE_RESET TIM1.Period=19999 -TIM1.Prescaler=89 +TIM1.Prescaler=119 TIM1.Pulse-PWM\ Generation1\ CH1=1500 TIM11.Channel=TIM_CHANNEL_1 TIM11.IPParameters=Channel,Prescaler,Period,Pulse TIM11.Period=19999 -TIM11.Prescaler=89 +TIM11.Prescaler=119 TIM11.Pulse=1000 UART5.IPParameters=VirtualMode UART5.VirtualMode=Asynchronous diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 09585bc..210a709 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -223,7 +223,7 @@ static void MX_TIM1_Init(void) /* USER CODE END TIM1_Init 1 */ htim1.Instance = TIM1; - htim1.Init.Prescaler = 89; + htim1.Init.Prescaler = 119; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 19999; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; @@ -286,7 +286,7 @@ static void MX_TIM11_Init(void) /* USER CODE END TIM11_Init 1 */ htim11.Instance = TIM11; - htim11.Init.Prescaler = 89; + htim11.Init.Prescaler = 119; htim11.Init.CounterMode = TIM_COUNTERMODE_UP; htim11.Init.Period = 19999; htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; From 1eef814775172d7ded2c1af6fdb1ffae05465ee6 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 15:25:51 -0400 Subject: [PATCH 08/55] Starting TIM1/TIM11 --- AutonomousDistroBoard/Core/Src/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 210a709..aa171c1 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -107,6 +107,8 @@ int main(void) MX_USART3_UART_Init(); MX_USB_OTG_FS_PCD_Init(); /* USER CODE BEGIN 2 */ + HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); /* USER CODE END 2 */ From 9f491f18d106d6af6174145efdbe8c0c8415da04 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 15:50:14 -0400 Subject: [PATCH 09/55] USART3 (SBUS input) setup (circular DMA) --- .../AutonomousDistroBoard.ioc | 37 +++++++++++++------ AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h | 1 + AutonomousDistroBoard/Core/Src/main.c | 19 ++++++++++ .../Core/Src/stm32f4xx_hal_msp.c | 22 +++++++++++ AutonomousDistroBoard/Core/Src/stm32f4xx_it.c | 16 +++++++- 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index 0f950ff..dfeeef7 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -9,21 +9,34 @@ CAN2.CalculateTimeBit=2000 CAN2.CalculateTimeQuantum=133.33333333333334 CAN2.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,BS1,BS2,Prescaler CAN2.Prescaler=4 +Dma.Request0=USART3_RX +Dma.RequestsNb=1 +Dma.USART3_RX.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.USART3_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.USART3_RX.0.Instance=DMA1_Stream1 +Dma.USART3_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART3_RX.0.MemInc=DMA_MINC_ENABLE +Dma.USART3_RX.0.Mode=DMA_CIRCULAR +Dma.USART3_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART3_RX.0.PeriphInc=DMA_PINC_DISABLE +Dma.USART3_RX.0.Priority=DMA_PRIORITY_HIGH +Dma.USART3_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode File.Version=6 GPIO.groupedBy=Group By Peripherals KeepUserPlacement=false Mcu.CPN=STM32F407VGT6 Mcu.Family=STM32F4 Mcu.IP0=CAN2 -Mcu.IP1=NVIC -Mcu.IP2=RCC -Mcu.IP3=SYS -Mcu.IP4=TIM1 -Mcu.IP5=TIM11 -Mcu.IP6=UART5 -Mcu.IP7=USART3 -Mcu.IP8=USB_OTG_FS -Mcu.IPNb=9 +Mcu.IP1=DMA +Mcu.IP2=NVIC +Mcu.IP3=RCC +Mcu.IP4=SYS +Mcu.IP5=TIM1 +Mcu.IP6=TIM11 +Mcu.IP7=UART5 +Mcu.IP8=USART3 +Mcu.IP9=USB_OTG_FS +Mcu.IPNb=10 Mcu.Name=STM32F407V(E-G)Tx Mcu.Package=LQFP100 Mcu.Pin0=PE5 @@ -53,6 +66,7 @@ Mcu.UserName=STM32F407VGTx MxCube.Version=6.8.0 MxDb.Version=DB.6.0.80 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DMA1_Stream1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false @@ -146,7 +160,7 @@ ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=STM32CubeIDE ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_CAN2_Init-CAN2-false-HAL-true,4-MX_UART5_Init-UART5-false-HAL-true,5-MX_TIM1_Init-TIM1-false-HAL-true,6-MX_TIM11_Init-TIM11-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true,8-MX_USB_OTG_FS_PCD_Init-USB_OTG_FS-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_CAN2_Init-CAN2-false-HAL-true,5-MX_UART5_Init-UART5-false-HAL-true,6-MX_TIM1_Init-TIM1-false-HAL-true,7-MX_TIM11_Init-TIM11-false-HAL-true,8-MX_USART3_UART_Init-USART3-false-HAL-true,9-MX_USB_OTG_FS_PCD_Init-USB_OTG_FS-false-HAL-true RCC.48MHZClocksFreq_Value=48000000 RCC.AHBFreq_Value=120000000 RCC.APB1CLKDivider=RCC_HCLK_DIV4 @@ -197,7 +211,8 @@ TIM11.Prescaler=119 TIM11.Pulse=1000 UART5.IPParameters=VirtualMode UART5.VirtualMode=Asynchronous -USART3.IPParameters=VirtualMode +USART3.IPParameters=VirtualMode,Mode +USART3.Mode=MODE_TX_RX USART3.VirtualMode=VM_ASYNC USB_OTG_FS.IPParameters=VirtualMode USB_OTG_FS.VirtualMode=Device_Only diff --git a/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h b/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h index c513579..e71e301 100644 --- a/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h +++ b/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h @@ -55,6 +55,7 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void DMA1_Stream1_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index aa171c1..9bc0669 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -47,6 +47,7 @@ TIM_HandleTypeDef htim11; UART_HandleTypeDef huart5; UART_HandleTypeDef huart3; +DMA_HandleTypeDef hdma_usart3_rx; PCD_HandleTypeDef hpcd_USB_OTG_FS; @@ -57,6 +58,7 @@ PCD_HandleTypeDef hpcd_USB_OTG_FS; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); +static void MX_DMA_Init(void); static void MX_CAN2_Init(void); static void MX_UART5_Init(void); static void MX_TIM1_Init(void); @@ -100,6 +102,7 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_DMA_Init(); MX_CAN2_Init(); MX_UART5_Init(); MX_TIM1_Init(); @@ -417,6 +420,22 @@ static void MX_USB_OTG_FS_PCD_Init(void) } +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Stream1_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); + +} + /** * @brief GPIO Initialization Function * @param None diff --git a/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c b/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c index 2d18373..d4325d5 100644 --- a/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c +++ b/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c @@ -23,6 +23,7 @@ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ +extern DMA_HandleTypeDef hdma_usart3_rx; /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ @@ -340,6 +341,25 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + /* USART3 DMA Init */ + /* USART3_RX Init */ + hdma_usart3_rx.Instance = DMA1_Stream1; + hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4; + hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart3_rx.Init.Mode = DMA_CIRCULAR; + hdma_usart3_rx.Init.Priority = DMA_PRIORITY_HIGH; + hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx); + /* USER CODE BEGIN USART3_MspInit 1 */ /* USER CODE END USART3_MspInit 1 */ @@ -389,6 +409,8 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); + /* USART3 DMA DeInit */ + HAL_DMA_DeInit(huart->hdmarx); /* USER CODE BEGIN USART3_MspDeInit 1 */ /* USER CODE END USART3_MspDeInit 1 */ diff --git a/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c b/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c index fb58e2a..687819a 100644 --- a/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c +++ b/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c @@ -55,7 +55,7 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ - +extern DMA_HandleTypeDef hdma_usart3_rx; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -198,6 +198,20 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f4xx.s). */ /******************************************************************************/ +/** + * @brief This function handles DMA1 stream1 global interrupt. + */ +void DMA1_Stream1_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream1_IRQn 0 */ + + /* USER CODE END DMA1_Stream1_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_usart3_rx); + /* USER CODE BEGIN DMA1_Stream1_IRQn 1 */ + + /* USER CODE END DMA1_Stream1_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ From 8bc9966fd8e9ffe75f0633b7abc1219c2e682ea7 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:13:43 -0400 Subject: [PATCH 10/55] IBUS base logic: Single-byte feed (sync finder style) --- AutonomousDistroBoard/Core/Inc/ibus.h | 32 +++++++++++++++ AutonomousDistroBoard/Core/Src/ibus.c | 56 +++++++++++++++++++++++++++ AutonomousDistroBoard/Core/Src/main.c | 5 ++- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 AutonomousDistroBoard/Core/Inc/ibus.h create mode 100644 AutonomousDistroBoard/Core/Src/ibus.c diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h new file mode 100644 index 0000000..fd79a48 --- /dev/null +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -0,0 +1,32 @@ +#ifndef IBUS_H + +#include + +// #include "stm32f4xx_hal_dma.h" +#include "stm32f4xx_hal.h" + + +#define IBUS_CHANNEL_COUNT (14) +#define IBUS_FRAME_SIZE (32) +#define IBUS_DMA_BUFFER_SIZE (128) + + +extern uint8_t g_ibus_dma_buffer[IBUS_DMA_BUFFER_SIZE]; + +extern uint8_t g_ibus_frame[IBUS_FRAME_SIZE]; +extern uint8_t g_ibus_index; + + + +// Should be called in the main loop / 1kHz task to process incoming iBUS data +void ibus_process(UART_HandleTypeDef *sbus_huart); +// Single-byte feed (sync finder style), called by ibus_process +void ibus_parse_byte(uint8_t byte); + + + + + + + +#endif // IBUS_H \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c new file mode 100644 index 0000000..b0d2d66 --- /dev/null +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -0,0 +1,56 @@ +#include "ibus.h" +#include + + +volatile uint16_t g_dma_last_pos = 0; + +uint8_t g_ibus_frame[IBUS_FRAME_SIZE] = {0}; +uint8_t g_ibus_dma_buffer[IBUS_DMA_BUFFER_SIZE] = {0}; +uint8_t g_ibus_index = 0; +uint16_t g_ibus_channels[IBUS_CHANNEL_COUNT] = {0}; + + +void ibus_process(UART_HandleTypeDef *sbus_huart) { + uint16_t dma_pos = IBUS_DMA_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(sbus_huart->hdmarx); + + while (g_dma_last_pos != dma_pos) { + uint8_t byte = g_ibus_dma_buffer[g_dma_last_pos++]; + + if (g_dma_last_pos >= IBUS_DMA_BUFFER_SIZE) { + g_dma_last_pos = 0; + } + + ibus_parse_byte(byte); + } +} + + + +void ibus_parse_byte(uint8_t byte) { + // Byte 0: Length = 0x20 (32) + // Byte 1: Command = 0x40 + // Byte 2-29: 14 channels, little-endian uint16 + // Byte 30-31: checksum (little-endian) + + if (g_ibus_index == 0 && byte != 0x20) { + return; // wait for frame start + } + + g_ibus_frame[g_ibus_index++] = byte; + if (g_ibus_index == IBUS_FRAME_SIZE) { + g_ibus_index = 0; + if (g_ibus_frame[1] == 0x40) { + uint16_t checksum = 0xFFFF; + for (int i = 0; i < 30; i++) { + checksum -= g_ibus_frame[i]; + } + + uint16_t received = g_ibus_frame[30] | (g_ibus_frame[31] << 8); + if (checksum == received) { + for (int i = 0; i < IBUS_CHANNEL_COUNT; i++) { + g_ibus_channels[i] = g_ibus_frame[2 + i*2] | (g_ibus_frame[3 + i*2] << 8); + } + } + } + } +} \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 9bc0669..6d24adb 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -21,7 +21,7 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "ibus.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -110,9 +110,12 @@ int main(void) MX_USART3_UART_Init(); MX_USB_OTG_FS_PCD_Init(); /* USER CODE BEGIN 2 */ + HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); + HAL_UART_Receive_DMA(&huart3, g_ibus_dma_buffer, IBUS_DMA_BUFFER_SIZE); + /* USER CODE END 2 */ /* Infinite loop */ From 2a3c27d184ff6721e01810ade4c4a08ff88579f1 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:19:09 -0400 Subject: [PATCH 11/55] refactor iBUS --- AutonomousDistroBoard/Core/Inc/ibus.h | 18 +++++++---- AutonomousDistroBoard/Core/Src/ibus.c | 44 ++++++++++++++------------- AutonomousDistroBoard/Core/Src/main.c | 6 ++-- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index fd79a48..ced7cd4 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -1,8 +1,8 @@ #ifndef IBUS_H +#define IBUS_H #include -// #include "stm32f4xx_hal_dma.h" #include "stm32f4xx_hal.h" @@ -11,17 +11,23 @@ #define IBUS_DMA_BUFFER_SIZE (128) -extern uint8_t g_ibus_dma_buffer[IBUS_DMA_BUFFER_SIZE]; +// iBUS data structure +typedef struct { + uint8_t dma_buffer[IBUS_DMA_BUFFER_SIZE]; // DMA buffer for incoming UART data + uint8_t frame[IBUS_FRAME_SIZE]; // Buffer for assembling a single iBUS frame + uint8_t frame_index; // Current index in the frame buffer + uint16_t dma_last_pos; // Last processed position in the DMA buffer + uint16_t channels[IBUS_CHANNEL_COUNT]; // PWM values +} ibus_t; -extern uint8_t g_ibus_frame[IBUS_FRAME_SIZE]; -extern uint8_t g_ibus_index; +void ibus_init(ibus_t* ibus); // Should be called in the main loop / 1kHz task to process incoming iBUS data -void ibus_process(UART_HandleTypeDef *sbus_huart); +void ibus_process(ibus_t* ibus, UART_HandleTypeDef *sbus_huart); // Single-byte feed (sync finder style), called by ibus_process -void ibus_parse_byte(uint8_t byte); +void ibus_parse_byte(ibus_t* ibus, uint8_t byte); diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c index b0d2d66..03d38f3 100644 --- a/AutonomousDistroBoard/Core/Src/ibus.c +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -1,54 +1,56 @@ #include "ibus.h" + #include +#include + +ibus_t g_ibus = {0}; -volatile uint16_t g_dma_last_pos = 0; -uint8_t g_ibus_frame[IBUS_FRAME_SIZE] = {0}; -uint8_t g_ibus_dma_buffer[IBUS_DMA_BUFFER_SIZE] = {0}; -uint8_t g_ibus_index = 0; -uint16_t g_ibus_channels[IBUS_CHANNEL_COUNT] = {0}; +void ibus_init(ibus_t *ibus) { + memset(ibus, 0, sizeof(*ibus)); +} -void ibus_process(UART_HandleTypeDef *sbus_huart) { - uint16_t dma_pos = IBUS_DMA_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(sbus_huart->hdmarx); +void ibus_process(ibus_t* ibus, UART_HandleTypeDef* ibus_huart) { + uint16_t dma_pos = IBUS_DMA_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(ibus_huart->hdmarx); - while (g_dma_last_pos != dma_pos) { - uint8_t byte = g_ibus_dma_buffer[g_dma_last_pos++]; + while (ibus->dma_last_pos != dma_pos) { + uint8_t byte = ibus->dma_buffer[ibus->dma_last_pos++]; - if (g_dma_last_pos >= IBUS_DMA_BUFFER_SIZE) { - g_dma_last_pos = 0; + if (ibus->dma_last_pos >= IBUS_DMA_BUFFER_SIZE) { + ibus->dma_last_pos = 0; } - ibus_parse_byte(byte); + ibus_parse_byte(ibus, byte); } } -void ibus_parse_byte(uint8_t byte) { +void ibus_parse_byte(ibus_t *ibus, uint8_t byte) { // Byte 0: Length = 0x20 (32) // Byte 1: Command = 0x40 // Byte 2-29: 14 channels, little-endian uint16 // Byte 30-31: checksum (little-endian) - if (g_ibus_index == 0 && byte != 0x20) { + if (ibus->frame_index == 0 && byte != 0x20) { return; // wait for frame start } - g_ibus_frame[g_ibus_index++] = byte; - if (g_ibus_index == IBUS_FRAME_SIZE) { - g_ibus_index = 0; - if (g_ibus_frame[1] == 0x40) { + ibus->frame[ibus->frame_index++] = byte; + if (ibus->frame_index == IBUS_FRAME_SIZE) { + ibus->frame_index = 0; + if (ibus->frame[1] == 0x40) { uint16_t checksum = 0xFFFF; for (int i = 0; i < 30; i++) { - checksum -= g_ibus_frame[i]; + checksum -= ibus->frame[i]; } - uint16_t received = g_ibus_frame[30] | (g_ibus_frame[31] << 8); + uint16_t received = ibus->frame[30] | (ibus->frame[31] << 8); if (checksum == received) { for (int i = 0; i < IBUS_CHANNEL_COUNT; i++) { - g_ibus_channels[i] = g_ibus_frame[2 + i*2] | (g_ibus_frame[3 + i*2] << 8); + ibus->channels[i] = ibus->frame[2 + i*2] | (ibus->frame[3 + i*2] << 8); } } } diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 6d24adb..25c726e 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -52,7 +52,7 @@ DMA_HandleTypeDef hdma_usart3_rx; PCD_HandleTypeDef hpcd_USB_OTG_FS; /* USER CODE BEGIN PV */ - +ibus_t g_ibus = {0}; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -114,7 +114,8 @@ int main(void) HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); - HAL_UART_Receive_DMA(&huart3, g_ibus_dma_buffer, IBUS_DMA_BUFFER_SIZE); + ibus_init(&g_ibus); + HAL_UART_Receive_DMA(&huart3, g_ibus.dma_buffer, IBUS_DMA_BUFFER_SIZE); /* USER CODE END 2 */ @@ -125,6 +126,7 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ + ibus_process(&g_ibus, &huart3); } /* USER CODE END 3 */ } From c0b12959d8795efcf2160a40a8d5353d2f5385e4 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:24:46 -0400 Subject: [PATCH 12/55] logic setup --- AutonomousDistroBoard/Core/Inc/logic.h | 16 ++++++++++++++++ AutonomousDistroBoard/Core/Src/ibus.c | 3 --- AutonomousDistroBoard/Core/Src/logic.c | 7 +++++++ AutonomousDistroBoard/Core/Src/main.c | 3 ++- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 AutonomousDistroBoard/Core/Inc/logic.h create mode 100644 AutonomousDistroBoard/Core/Src/logic.c diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h new file mode 100644 index 0000000..ae9577f --- /dev/null +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -0,0 +1,16 @@ +#ifndef LOGIC_H +#define LOGIC_H + +#include "stm32f4xx_hal.h" + +#include "ibus.h" + + +// Called once in the main loop +void logic_run(ibus_t* ibus, UART_HandleTypeDef *sbus_huart); + + + + + +#endif // LOGIC_H \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c index 03d38f3..31672c6 100644 --- a/AutonomousDistroBoard/Core/Src/ibus.c +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -4,9 +4,6 @@ #include -ibus_t g_ibus = {0}; - - void ibus_init(ibus_t *ibus) { memset(ibus, 0, sizeof(*ibus)); } diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c new file mode 100644 index 0000000..d3f4555 --- /dev/null +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -0,0 +1,7 @@ +#include "logic.h" + + +void logic_run(ibus_t* ibus, UART_HandleTypeDef *sbus_huart) { + // Process iBUS data + ibus_process(ibus, sbus_huart); +} \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 25c726e..ceb3f89 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -22,6 +22,7 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "ibus.h" +#include "logic.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -126,7 +127,7 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - ibus_process(&g_ibus, &huart3); + logic_run(&g_ibus, &huart3); } /* USER CODE END 3 */ } From 5aa345b8464d14ef6a58e1be727b9baa0134003a Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:40:56 -0400 Subject: [PATCH 13/55] CAN message defs --- README.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 21a2273..5752f61 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ Autonomous Project electrical stack code -## Autonomous Control/Distro Board Pin Definitions +## Autonomous Control/Distro Board + +### Pin Definitions - **CAN Bus (CAN2):** - RX: `PB5` @@ -40,7 +42,25 @@ Autonomous Project electrical stack code - SWCLK: `PA14` - OSC_IN/OUT: `PH0` / `PH1` (8MHz HSE) -## Autonomous Nucelo Pin Definitions +### CAN messages + +- ID = `0x100` - **Control commands** (RX) + - Byte 0-1: throttle (uint16_t, little endian) + - Byte 2-3: steering (uint16_t, little endian) + - Byte 4-7: reserved / future use +- ID = `0x101` - **Status update** (TX) + - Byte 0: precharge + contactor + rc mode (bit flags) + - Bit0 = precharge + - Bit1 = contactor + - Bit2 = RC mode + - Bits3-7 = 0 + - Byte 1-2: throttle PWM (uint16_t, little endian) + - Byte 3-4: steering PWM (uint16_t, little endian) + - Byte 5-7: reserved / future use + +## Autonomous Nucelo + +### Pin Definitions - Rubik Pi 3 <-> nucleo-f446re: `SPI2` - SCK: `PB10` From b6a84a06f35d364e838cbb29cfee293b73cb7f76 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:41:20 -0400 Subject: [PATCH 14/55] CAN2 RX0 interupt --- AutonomousDistroBoard/AutonomousDistroBoard.ioc | 1 + AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h | 1 + .../Core/Src/stm32f4xx_hal_msp.c | 5 +++++ AutonomousDistroBoard/Core/Src/stm32f4xx_it.c | 15 +++++++++++++++ 4 files changed, 22 insertions(+) diff --git a/AutonomousDistroBoard/AutonomousDistroBoard.ioc b/AutonomousDistroBoard/AutonomousDistroBoard.ioc index dfeeef7..3e19a10 100644 --- a/AutonomousDistroBoard/AutonomousDistroBoard.ioc +++ b/AutonomousDistroBoard/AutonomousDistroBoard.ioc @@ -66,6 +66,7 @@ Mcu.UserName=STM32F407VGTx MxCube.Version=6.8.0 MxDb.Version=DB.6.0.80 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.CAN2_RX0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.DMA1_Stream1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true diff --git a/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h b/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h index e71e301..d2e1e25 100644 --- a/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h +++ b/AutonomousDistroBoard/Core/Inc/stm32f4xx_it.h @@ -56,6 +56,7 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void DMA1_Stream1_IRQHandler(void); +void CAN2_RX0_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c b/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c index d4325d5..1c32176 100644 --- a/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c +++ b/AutonomousDistroBoard/Core/Src/stm32f4xx_hal_msp.c @@ -109,6 +109,9 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) GPIO_InitStruct.Alternate = GPIO_AF9_CAN2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + /* CAN2 interrupt Init */ + HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn); /* USER CODE BEGIN CAN2_MspInit 1 */ /* USER CODE END CAN2_MspInit 1 */ @@ -139,6 +142,8 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5|GPIO_PIN_6); + /* CAN2 interrupt DeInit */ + HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn); /* USER CODE BEGIN CAN2_MspDeInit 1 */ /* USER CODE END CAN2_MspDeInit 1 */ diff --git a/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c b/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c index 687819a..dbd785b 100644 --- a/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c +++ b/AutonomousDistroBoard/Core/Src/stm32f4xx_it.c @@ -55,6 +55,7 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ +extern CAN_HandleTypeDef hcan2; extern DMA_HandleTypeDef hdma_usart3_rx; /* USER CODE BEGIN EV */ @@ -212,6 +213,20 @@ void DMA1_Stream1_IRQHandler(void) /* USER CODE END DMA1_Stream1_IRQn 1 */ } +/** + * @brief This function handles CAN2 RX0 interrupts. + */ +void CAN2_RX0_IRQHandler(void) +{ + /* USER CODE BEGIN CAN2_RX0_IRQn 0 */ + + /* USER CODE END CAN2_RX0_IRQn 0 */ + HAL_CAN_IRQHandler(&hcan2); + /* USER CODE BEGIN CAN2_RX0_IRQn 1 */ + + /* USER CODE END CAN2_RX0_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ From 12ffe24aa7666d873327a85733ccf6ad96dcdc34 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:53:41 -0400 Subject: [PATCH 15/55] Basic CAN system --- AutonomousDistroBoard/Core/Inc/can.h | 49 +++++++++++++++++++++++++ AutonomousDistroBoard/Core/Src/can.c | 54 ++++++++++++++++++++++++++++ README.md | 4 +-- 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 AutonomousDistroBoard/Core/Inc/can.h create mode 100644 AutonomousDistroBoard/Core/Src/can.c diff --git a/AutonomousDistroBoard/Core/Inc/can.h b/AutonomousDistroBoard/Core/Inc/can.h new file mode 100644 index 0000000..be410ca --- /dev/null +++ b/AutonomousDistroBoard/Core/Inc/can.h @@ -0,0 +1,49 @@ +#ifndef CAN_H +#define CAN_H + +#include +#include + +#include "stm32f4xx_hal.h" + + +#define CAN_BUS (CAN2) + +#define CAN_TX_PERIOD (10) // ms + +// - ID = `0x100` - **Control commands** (RX) +// - Byte 0-1: throttle (uint16_t, little endian), 0-1000, where 1000 = full throttle +// - Byte 2-3: steering (uint16_t, little endian), 0-1000, where 1000 = full right, 500 = center, 0 = full left +// - Byte 4-7: reserved / future use +#define CAN_ID_CONTROL (0x100) +typedef struct { + uint16_t throttle; // 0-1000 + uint16_t steering; // 0-1000 +} can_control_msg_t; + + +// - ID = `0x101` - **Status update** (TX) +// - Byte 0: precharge + contactor + rc mode (bit flags) +// - Bit0 = precharge +// - Bit1 = contactor +// - Bit2 = RC mode +// - Bits3-7 = 0 +// - Byte 1-2: throttle PWM (uint16_t, little endian) +// - Byte 3-4: steering PWM (uint16_t, little endian) +// - Byte 5-7: reserved / future use +#define CAN_ID_STATUS (0x101) +typedef struct { + bool precharge; + bool contactor; + bool rc_mode; + uint16_t throttle_pwm; + uint16_t steering_pwm; +} can_status_msg_t; + + +can_control_msg_t parse_can_control(const uint8_t* data); +void send_can_status(const can_status_msg_t* status, CAN_HandleTypeDef* hcan); + + + +#endif // CAN_H \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c new file mode 100644 index 0000000..f473689 --- /dev/null +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -0,0 +1,54 @@ +#include "can.h" + +#include "stm32f4xx_hal.h" + + +uint8_t rx_data[8]; + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + if (hcan->Instance == CAN_BUS) + { + CAN_RxHeaderTypeDef rx_header; + HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data); + + if (rx_header.StdId == CAN_ID_CONTROL) + { + can_control_msg_t cmd = parse_can_control(rx_data); + // logic_handle_control(&cmd); + } + } +} + + +can_control_msg_t parse_can_control(const uint8_t* data) { + can_control_msg_t msg; + msg.throttle = data[0] | (data[1] << 8); + msg.steering = data[2] | (data[3] << 8); + return msg; +} + +void send_can_status(const can_status_msg_t* status, CAN_HandleTypeDef* hcan) { + CAN_TxHeaderTypeDef tx_header; + uint8_t tx_data[8] = {0}; + + tx_header.StdId = CAN_ID_STATUS; + tx_header.ExtId = 0; + tx_header.RTR = CAN_RTR_DATA; + tx_header.IDE = CAN_ID_STD; + tx_header.DLC = 8; + + tx_data[0] = (status->precharge << 0) | (status->contactor << 1) | (status->rc_mode << 2); + tx_data[1] = status->throttle_pwm & 0xFF; + tx_data[2] = (status->throttle_pwm >> 8) & 0xFF; + tx_data[3] = status->steering_pwm & 0xFF; + tx_data[4] = (status->steering_pwm >> 8) & 0xFF; + tx_data[5] = 0; + tx_data[6] = 0; + tx_data[7] = 0; + + uint32_t tx_mailbox; + HAL_CAN_AddTxMessage(hcan, &tx_header, tx_data, &tx_mailbox); +} + + diff --git a/README.md b/README.md index 5752f61..eb2f8ea 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ Autonomous Project electrical stack code ### CAN messages - ID = `0x100` - **Control commands** (RX) - - Byte 0-1: throttle (uint16_t, little endian) - - Byte 2-3: steering (uint16_t, little endian) + - Byte 0-1: throttle (uint16_t, little endian), 0-1000, where 1000 = full throttle + - Byte 2-3: steering (uint16_t, little endian), 0-1000, where 500 = straight, 0 = full left, 1000 = full right - Byte 4-7: reserved / future use - ID = `0x101` - **Status update** (TX) - Byte 0: precharge + contactor + rc mode (bit flags) From 9420621309d9b31058ab87c4a8a2d26096869b82 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 16:59:22 -0400 Subject: [PATCH 16/55] logic has a struct struct --- AutonomousDistroBoard/Core/Inc/logic.h | 16 +++++++++++++++- AutonomousDistroBoard/Core/Src/logic.c | 12 ++++++++++-- AutonomousDistroBoard/Core/Src/main.c | 9 +++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index ae9577f..9d14cbd 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -1,13 +1,27 @@ #ifndef LOGIC_H #define LOGIC_H +#include +#include + #include "stm32f4xx_hal.h" #include "ibus.h" +typedef struct { + ibus_t ibus; + uint32_t last_can_tx_time; +} logic_state_t; + +void logic_init(logic_state_t* state); + // Called once in the main loop -void logic_run(ibus_t* ibus, UART_HandleTypeDef *sbus_huart); +void logic_run( + logic_state_t* state, + UART_HandleTypeDef *sbus_huart, + CAN_HandleTypeDef *hcan +); diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index d3f4555..94de8be 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -1,7 +1,15 @@ #include "logic.h" +void logic_init(logic_state_t* state) { + ibus_init(&state->ibus); + state->last_can_tx_time = 0; +} -void logic_run(ibus_t* ibus, UART_HandleTypeDef *sbus_huart) { +void logic_run( + logic_state_t* state, + UART_HandleTypeDef *sbus_huart, + CAN_HandleTypeDef *hcan +) { // Process iBUS data - ibus_process(ibus, sbus_huart); + ibus_process(&state->ibus, sbus_huart); } \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index ceb3f89..ab06add 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -53,7 +53,7 @@ DMA_HandleTypeDef hdma_usart3_rx; PCD_HandleTypeDef hpcd_USB_OTG_FS; /* USER CODE BEGIN PV */ -ibus_t g_ibus = {0}; +logic_state_t g_logic_state = {0}; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -111,12 +111,13 @@ int main(void) MX_USART3_UART_Init(); MX_USB_OTG_FS_PCD_Init(); /* USER CODE BEGIN 2 */ + logic_init(&g_logic_state); + HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); - ibus_init(&g_ibus); - HAL_UART_Receive_DMA(&huart3, g_ibus.dma_buffer, IBUS_DMA_BUFFER_SIZE); + HAL_UART_Receive_DMA(&huart3, g_logic_state.ibus.dma_buffer, IBUS_DMA_BUFFER_SIZE); /* USER CODE END 2 */ @@ -127,7 +128,7 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - logic_run(&g_ibus, &huart3); + logic_run(&g_logic_state, &huart3, &hcan2); } /* USER CODE END 3 */ } From 21efb947e084bba1bfa1d3ae3763f36bc7da7727 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 17:03:48 -0400 Subject: [PATCH 17/55] Simple callback system --- AutonomousDistroBoard/Core/Inc/logic.h | 6 ++++++ AutonomousDistroBoard/Core/Src/can.c | 5 +++-- AutonomousDistroBoard/Core/Src/logic.c | 11 +++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 9d14cbd..1060af9 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -7,6 +7,7 @@ #include "stm32f4xx_hal.h" #include "ibus.h" +#include "can.h" typedef struct { ibus_t ibus; @@ -23,6 +24,11 @@ void logic_run( CAN_HandleTypeDef *hcan ); +// Called from CAN RX callback when a control message is received +// Uses the global static pointer to the logic state, since the CAN callback +// doesn't have a way to pass user data +void logic_handle_control(const can_control_msg_t* cmd); + diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c index f473689..7f922ad 100644 --- a/AutonomousDistroBoard/Core/Src/can.c +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -2,20 +2,21 @@ #include "stm32f4xx_hal.h" +#include "logic.h" -uint8_t rx_data[8]; void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { if (hcan->Instance == CAN_BUS) { CAN_RxHeaderTypeDef rx_header; + uint8_t rx_data[8]; HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data); if (rx_header.StdId == CAN_ID_CONTROL) { can_control_msg_t cmd = parse_can_control(rx_data); - // logic_handle_control(&cmd); + logic_handle_control(&cmd); } } } diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 94de8be..c0d2cff 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -1,8 +1,19 @@ #include "logic.h" +static logic_state_t* g_logic_state_ptr = NULL; + + void logic_init(logic_state_t* state) { ibus_init(&state->ibus); state->last_can_tx_time = 0; + + g_logic_state_ptr = state; +} + +void logic_handle_control(const can_control_msg_t* cmd) { + if (g_logic_state_ptr == NULL) { + return; + } } void logic_run( From 0c234117521035ecb639aa4586d126c39c44bb70 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 17:09:05 -0400 Subject: [PATCH 18/55] logic loosely handles the RX-ed can message --- AutonomousDistroBoard/Core/Inc/can.h | 1 + AutonomousDistroBoard/Core/Inc/logic.h | 4 ++++ AutonomousDistroBoard/Core/Src/logic.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/AutonomousDistroBoard/Core/Inc/can.h b/AutonomousDistroBoard/Core/Inc/can.h index be410ca..14be4c4 100644 --- a/AutonomousDistroBoard/Core/Inc/can.h +++ b/AutonomousDistroBoard/Core/Inc/can.h @@ -10,6 +10,7 @@ #define CAN_BUS (CAN2) #define CAN_TX_PERIOD (10) // ms +#define CAN_RX_TIMEOUT (50) // ms // - ID = `0x100` - **Control commands** (RX) // - Byte 0-1: throttle (uint16_t, little endian), 0-1000, where 1000 = full throttle diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 1060af9..cf62082 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -12,6 +12,10 @@ typedef struct { ibus_t ibus; uint32_t last_can_tx_time; + + volatile uint16_t can_current_throttle; // 0-1000 + volatile uint16_t can_current_steering; // 0-1000 + volatile uint32_t last_control_timestamp; // HAL_GetTick() timestamp of last received control message } logic_state_t; void logic_init(logic_state_t* state); diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index c0d2cff..adc0db9 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -14,6 +14,10 @@ void logic_handle_control(const can_control_msg_t* cmd) { if (g_logic_state_ptr == NULL) { return; } + + g_logic_state_ptr->can_current_throttle = cmd->throttle; + g_logic_state_ptr->can_current_steering = cmd->steering; + g_logic_state_ptr->last_control_timestamp = HAL_GetTick(); } void logic_run( From 793910cfb0d31de81d0450b5e48eb462a06ebd3f Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 23:28:53 -0400 Subject: [PATCH 19/55] boot logic and contactor setting --- AutonomousDistroBoard/Core/Inc/logic.h | 17 +++++++++++ AutonomousDistroBoard/Core/Src/logic.c | 40 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index cf62082..3ce68db 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -9,10 +9,27 @@ #include "ibus.h" #include "can.h" + +#define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge +#define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor +#define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed + +typedef enum { + LOGIC_MODE_BOOTING = 0, + LOGIC_MODE_PRECHARGING, + LOGIC_MODE_CONTACTOR_CLOSING, + LOGIC_MODE_RUNNING, +} logic_mode_t; + + typedef struct { + logic_mode_t mode; + ibus_t ibus; uint32_t last_can_tx_time; + uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized + volatile uint16_t can_current_throttle; // 0-1000 volatile uint16_t can_current_steering; // 0-1000 volatile uint32_t last_control_timestamp; // HAL_GetTick() timestamp of last received control message diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index adc0db9..6d90f79 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -1,9 +1,17 @@ #include "logic.h" +#include + +#include "main.h" +#include "can.h" + + static logic_state_t* g_logic_state_ptr = NULL; void logic_init(logic_state_t* state) { + state->mode = LOGIC_MODE_BOOTING; + ibus_init(&state->ibus); state->last_can_tx_time = 0; @@ -27,4 +35,36 @@ void logic_run( ) { // Process iBUS data ibus_process(&state->ibus, sbus_huart); + + // Boot state machine logic + uint32_t now = HAL_GetTick(); + switch (state->mode) { + case LOGIC_MODE_BOOTING: + if (now >= state->boot_time + PRECHARGE_START_DELAY) { + state->mode = LOGIC_MODE_PRECHARGING; + // Start precharge: Precharge EN goes high + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); + } + break; + + case LOGIC_MODE_PRECHARGING: + if (now >= state->boot_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION) { + state->mode = LOGIC_MODE_CONTACTOR_CLOSING; + // Close contactor: Main Coil EN goes high + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); + } + break; + + case LOGIC_MODE_CONTACTOR_CLOSING: + if (now >= state->boot_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION + CONTACTOR_CLOSED_DELAY) { + state->mode = LOGIC_MODE_RUNNING; + // Contactor closed = precharge complete, Precharge EN can go low + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + } + break; + + case LOGIC_MODE_RUNNING: + // Normal operation, nothing to do here for now + break; + } } \ No newline at end of file From dbaf6397d95df975793c7c9fa072b8fa21734616 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 23:29:33 -0400 Subject: [PATCH 20/55] periodically sending CAN messages --- AutonomousDistroBoard/Core/Src/logic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 6d90f79..b041689 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -67,4 +67,17 @@ void logic_run( // Normal operation, nothing to do here for now break; } + + // Periodically send CAN status messages + if (now - state->last_can_tx_time >= CAN_TX_PERIOD) { + can_status_msg_t status = { + .precharge = (state->mode == LOGIC_MODE_PRECHARGING), + .contactor = (state->mode == LOGIC_MODE_RUNNING), + .rc_mode = 0, // TODO + .throttle_pwm = state->can_current_throttle * 20, // scale 0-1000 to 0-20000us + .steering_pwm = state->can_current_steering * 20, // scale 0-1000 to 0-20000us + }; + send_can_status(&status, hcan); + } + // REST OF LOGIC } \ No newline at end of file From 62e5fcb5de7ccef57393b4a7a6e875149f67e3e0 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 23:43:55 -0400 Subject: [PATCH 21/55] remote estop state machine logic if estop is thrown: - lift precharge and main coil - wait for estop to not be thrown - wait a bit more - restart precharge sequence --- AutonomousDistroBoard/Core/Inc/logic.h | 3 +++ AutonomousDistroBoard/Core/Src/logic.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 3ce68db..fcdcbce 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -13,12 +13,14 @@ #define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge #define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor #define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed +#define ESTOP_TRIGGERED_DELAY (3000) // ms, after remote estop is triggered, how long to wait before restarting the precharge sequence typedef enum { LOGIC_MODE_BOOTING = 0, LOGIC_MODE_PRECHARGING, LOGIC_MODE_CONTACTOR_CLOSING, LOGIC_MODE_RUNNING, + LOGIC_MODE_ESTOPPED, } logic_mode_t; @@ -29,6 +31,7 @@ typedef struct { uint32_t last_can_tx_time; uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized + uint32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or UINT32_MAX if not currently triggered volatile uint16_t can_current_throttle; // 0-1000 volatile uint16_t can_current_steering; // 0-1000 diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index b041689..6dc8a62 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -11,6 +11,8 @@ static logic_state_t* g_logic_state_ptr = NULL; void logic_init(logic_state_t* state) { state->mode = LOGIC_MODE_BOOTING; + state->boot_time = HAL_GetTick(); + state->estop_triggered_time = UINT32_MAX; // not currently triggered ibus_init(&state->ibus); state->last_can_tx_time = 0; @@ -36,6 +38,9 @@ void logic_run( // Process iBUS data ibus_process(&state->ibus, sbus_huart); + // TODO: Check for remote ESTOP trigger + // 500ms debounce!! + // Boot state machine logic uint32_t now = HAL_GetTick(); switch (state->mode) { @@ -66,6 +71,23 @@ void logic_run( case LOGIC_MODE_RUNNING: // Normal operation, nothing to do here for now break; + case LOGIC_MODE_ESTOPPED: + // For safety, force set main coil and precharge off + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + + if ((state->estop_triggered_time != UINT32_MAX) + && (now >= state->estop_triggered_time + ESTOP_TRIGGERED_DELAY)) { + // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence + state->mode = LOGIC_MODE_BOOTING; + state->estop_triggered_time = UINT32_MAX; // reset estop triggered time + + // Reset to booting state (both precharge and main coil off), + // then the logic will set precharge on in the next step of the state machine + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + } + break; } // Periodically send CAN status messages From 9ae32c368472632af4ffc6eaed33d8c75d0ee258 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 23:44:17 -0400 Subject: [PATCH 22/55] LOGIC_MODE_BOOTING -> LOGIC_MODE_STARTING --- AutonomousDistroBoard/Core/Inc/logic.h | 2 +- AutonomousDistroBoard/Core/Src/logic.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index fcdcbce..6b26b95 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -16,7 +16,7 @@ #define ESTOP_TRIGGERED_DELAY (3000) // ms, after remote estop is triggered, how long to wait before restarting the precharge sequence typedef enum { - LOGIC_MODE_BOOTING = 0, + LOGIC_MODE_STARTING = 0, LOGIC_MODE_PRECHARGING, LOGIC_MODE_CONTACTOR_CLOSING, LOGIC_MODE_RUNNING, diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 6dc8a62..51a6dc1 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -10,7 +10,7 @@ static logic_state_t* g_logic_state_ptr = NULL; void logic_init(logic_state_t* state) { - state->mode = LOGIC_MODE_BOOTING; + state->mode = LOGIC_MODE_STARTING; state->boot_time = HAL_GetTick(); state->estop_triggered_time = UINT32_MAX; // not currently triggered @@ -44,7 +44,7 @@ void logic_run( // Boot state machine logic uint32_t now = HAL_GetTick(); switch (state->mode) { - case LOGIC_MODE_BOOTING: + case LOGIC_MODE_STARTING: if (now >= state->boot_time + PRECHARGE_START_DELAY) { state->mode = LOGIC_MODE_PRECHARGING; // Start precharge: Precharge EN goes high @@ -79,7 +79,7 @@ void logic_run( if ((state->estop_triggered_time != UINT32_MAX) && (now >= state->estop_triggered_time + ESTOP_TRIGGERED_DELAY)) { // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence - state->mode = LOGIC_MODE_BOOTING; + state->mode = LOGIC_MODE_STARTING; state->estop_triggered_time = UINT32_MAX; // reset estop triggered time // Reset to booting state (both precharge and main coil off), From 9722cabd7a1307a948077986b00322a64edb43d0 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Mon, 23 Mar 2026 23:45:46 -0400 Subject: [PATCH 23/55] defines instead of magic numbers --- AutonomousDistroBoard/Core/Inc/ibus.h | 3 +++ AutonomousDistroBoard/Core/Src/ibus.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index ced7cd4..74821b7 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -10,6 +10,9 @@ #define IBUS_FRAME_SIZE (32) #define IBUS_DMA_BUFFER_SIZE (128) +#define IBUS_HEADER_DLC (0x20) +#define IBUS_HEADER_COMMAND (0x40) + // iBUS data structure typedef struct { diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c index 31672c6..f6378c8 100644 --- a/AutonomousDistroBoard/Core/Src/ibus.c +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -31,14 +31,14 @@ void ibus_parse_byte(ibus_t *ibus, uint8_t byte) { // Byte 2-29: 14 channels, little-endian uint16 // Byte 30-31: checksum (little-endian) - if (ibus->frame_index == 0 && byte != 0x20) { + if (ibus->frame_index == 0 && byte != IBUS_HEADER_DLC) { return; // wait for frame start } ibus->frame[ibus->frame_index++] = byte; if (ibus->frame_index == IBUS_FRAME_SIZE) { ibus->frame_index = 0; - if (ibus->frame[1] == 0x40) { + if (ibus->frame[1] == IBUS_HEADER_COMMAND) { uint16_t checksum = 0xFFFF; for (int i = 0; i < 30; i++) { checksum -= ibus->frame[i]; From 1d4aa88751a7d14fca36c396f8b00563c32204c1 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 00:59:24 -0400 Subject: [PATCH 24/55] remote ESTOP implementation --- AutonomousDistroBoard/Core/Inc/ibus.h | 3 +++ AutonomousDistroBoard/Core/Inc/logic.h | 7 +++++++ AutonomousDistroBoard/Core/Src/logic.c | 22 +++++++++++++++++++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index 74821b7..bb97a09 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -13,6 +13,9 @@ #define IBUS_HEADER_DLC (0x20) #define IBUS_HEADER_COMMAND (0x40) +#define IBUS_ESTOP_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered +#define IBUS_ESTOP_DEBOUNCE_TIME (500) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered + // iBUS data structure typedef struct { diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 6b26b95..4d546de 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -15,6 +15,12 @@ #define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed #define ESTOP_TRIGGERED_DELAY (3000) // ms, after remote estop is triggered, how long to wait before restarting the precharge sequence +#define IBUS_CHANNEL_THROTTLE (0) // 1000 = full stop, 2000 = full throttle forward +#define IBUS_CHANNEL_STEERING (1) // 1000 = full left, 1500 = center, 2000 = full right +#define IBUS_CHANNEL_MODE (2) // ~1000 = RC mode, ~2000 = autonomous mode +#define IBUS_CHANNEL_ESTOP (3) // ~1000 = not pressed, ~2000 = estop + + typedef enum { LOGIC_MODE_STARTING = 0, LOGIC_MODE_PRECHARGING, @@ -31,6 +37,7 @@ typedef struct { uint32_t last_can_tx_time; uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized + uint32_t estop_above_threshold_start_time; // HAL_GetTick() timestamp of when the ESTOP channel was first observed to go above the threshold, or UINT32_MAX if currently below the threshold uint32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or UINT32_MAX if not currently triggered volatile uint16_t can_current_throttle; // 0-1000 diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 51a6dc1..6415c8d 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -14,6 +14,8 @@ void logic_init(logic_state_t* state) { state->boot_time = HAL_GetTick(); state->estop_triggered_time = UINT32_MAX; // not currently triggered + state->estop_above_threshold_start_time = UINT32_MAX; // not currently above threshold + ibus_init(&state->ibus); state->last_can_tx_time = 0; @@ -38,11 +40,25 @@ void logic_run( // Process iBUS data ibus_process(&state->ibus, sbus_huart); - // TODO: Check for remote ESTOP trigger - // 500ms debounce!! + uint32_t now = HAL_GetTick(); + + // Check for remote ESTOP trigger + uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; + if (estop_channel_value >= IBUS_ESTOP_THRESHOLD) { + if (state->estop_above_threshold_start_time == UINT32_MAX) { + // Just observed ESTOP channel go above threshold, start debounce timer + state->estop_above_threshold_start_time = HAL_GetTick(); + } else if (now - state->estop_above_threshold_start_time >= IBUS_ESTOP_DEBOUNCE_TIME) { + // ESTOP channel has been above threshold for long enough, consider remote ESTOP triggered + state->estop_triggered_time = HAL_GetTick(); + state->mode = LOGIC_MODE_ESTOPPED; + } + } else { + // ESTOP channel is below threshold, reset debounce timer + state->estop_above_threshold_start_time = UINT32_MAX; + } // Boot state machine logic - uint32_t now = HAL_GetTick(); switch (state->mode) { case LOGIC_MODE_STARTING: if (now >= state->boot_time + PRECHARGE_START_DELAY) { From df9312ba7520be827800dc7970f24c26b6510a34 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 10:24:24 -0400 Subject: [PATCH 25/55] on state->mode = LOGIC_MODE_ESTOPPED unset precharge and main coil en --- AutonomousDistroBoard/Core/Src/logic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 6415c8d..2fbefd9 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -52,6 +52,9 @@ void logic_run( // ESTOP channel has been above threshold for long enough, consider remote ESTOP triggered state->estop_triggered_time = HAL_GetTick(); state->mode = LOGIC_MODE_ESTOPPED; + + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); } } else { // ESTOP channel is below threshold, reset debounce timer From 664d868ae438218926d5fc0f0af78b6e60cb1f59 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 12:15:56 -0400 Subject: [PATCH 26/55] Option type --- AutonomousDistroBoard/Core/Inc/util.h | 22 ++++++++++++++++++++ AutonomousDistroBoard/Core/Src/util.c | 29 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 AutonomousDistroBoard/Core/Inc/util.h create mode 100644 AutonomousDistroBoard/Core/Src/util.c diff --git a/AutonomousDistroBoard/Core/Inc/util.h b/AutonomousDistroBoard/Core/Inc/util.h new file mode 100644 index 0000000..22b8e68 --- /dev/null +++ b/AutonomousDistroBoard/Core/Inc/util.h @@ -0,0 +1,22 @@ +#ifndef UTIL_H +#define UTIL_H + +#include +#include + + +// Option type +typedef struct { + bool is_some; // true if the option contains a value, false if it is None + uint32_t value; +} option_u32_t; + +option_u32_t option_u32_some(uint32_t value); +option_u32_t option_u32_none(void); +bool option_u32_is_some(option_u32_t opt); +bool option_u32_is_none(option_u32_t opt); +uint32_t option_u32_unwrap(option_u32_t opt); // only call if opt is known to be Some!! + + + +#endif // UTIL_H \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/util.c b/AutonomousDistroBoard/Core/Src/util.c new file mode 100644 index 0000000..1fa78c6 --- /dev/null +++ b/AutonomousDistroBoard/Core/Src/util.c @@ -0,0 +1,29 @@ +#include "util.h" + +#include +#include + +option_u32_t option_u32_some(uint32_t value) { + option_u32_t opt = { + .is_some = true, + .value = value + }; + return opt; +} +option_u32_t option_u32_none(void) { + option_u32_t opt = { + .is_some = false, + .value = 0 // value is irrelevant when is_some is false + }; + return opt; +} +bool option_u32_is_some(option_u32_t opt) { + return opt.is_some; +} +bool option_u32_is_none(option_u32_t opt) { + return !opt.is_some; +} +uint32_t option_u32_unwrap(option_u32_t opt) { + // Only call this if opt is known to be Some, otherwise behavior is undefined + return opt.value; +} \ No newline at end of file From 1cb043993fa4bda35dd3f2f1d3436d0adb43a509 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 12:16:17 -0400 Subject: [PATCH 27/55] preparing for rising + falling debounce? --- AutonomousDistroBoard/Core/Inc/ibus.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index bb97a09..251c491 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -14,7 +14,8 @@ #define IBUS_HEADER_COMMAND (0x40) #define IBUS_ESTOP_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered -#define IBUS_ESTOP_DEBOUNCE_TIME (500) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered +#define IBUS_ESTOP_RISING_DEBOUNCE_TIME (500) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered +#define IBUS_ESTOP_FALLING_DEBOUNCE_TIME (50) // ms, when the rising estop is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer // iBUS data structure From f23302c8f6081cc5ed8d63b504300647bb6a87ca Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 12:20:54 -0400 Subject: [PATCH 28/55] use of option type instead of UINT32_MAX = none --- AutonomousDistroBoard/Core/Inc/logic.h | 5 +++-- AutonomousDistroBoard/Core/Src/logic.c | 23 ++++++++++++----------- AutonomousDistroBoard/Core/Src/main.c | 1 - 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 4d546de..808a223 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -8,6 +8,7 @@ #include "ibus.h" #include "can.h" +#include "util.h" #define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge @@ -37,8 +38,8 @@ typedef struct { uint32_t last_can_tx_time; uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized - uint32_t estop_above_threshold_start_time; // HAL_GetTick() timestamp of when the ESTOP channel was first observed to go above the threshold, or UINT32_MAX if currently below the threshold - uint32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or UINT32_MAX if not currently triggered + option_u32_t estop_above_threshold_start_time; // HAL_GetTick() timestamp of when the ESTOP channel was first observed to go above the threshold, or none if currently below the threshold + option_u32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or none if it is not currently triggered volatile uint16_t can_current_throttle; // 0-1000 volatile uint16_t can_current_steering; // 0-1000 diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 2fbefd9..d523813 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -2,8 +2,10 @@ #include +#include "ibus.h" #include "main.h" #include "can.h" +#include "util.h" static logic_state_t* g_logic_state_ptr = NULL; @@ -12,9 +14,9 @@ static logic_state_t* g_logic_state_ptr = NULL; void logic_init(logic_state_t* state) { state->mode = LOGIC_MODE_STARTING; state->boot_time = HAL_GetTick(); - state->estop_triggered_time = UINT32_MAX; // not currently triggered + state->estop_triggered_time = option_u32_none(); // not currently triggered - state->estop_above_threshold_start_time = UINT32_MAX; // not currently above threshold + state->estop_above_threshold_start_time = option_u32_none(); // not currently above threshold ibus_init(&state->ibus); state->last_can_tx_time = 0; @@ -45,12 +47,12 @@ void logic_run( // Check for remote ESTOP trigger uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; if (estop_channel_value >= IBUS_ESTOP_THRESHOLD) { - if (state->estop_above_threshold_start_time == UINT32_MAX) { + if (option_u32_is_none(state->estop_above_threshold_start_time)) { // Just observed ESTOP channel go above threshold, start debounce timer - state->estop_above_threshold_start_time = HAL_GetTick(); - } else if (now - state->estop_above_threshold_start_time >= IBUS_ESTOP_DEBOUNCE_TIME) { + state->estop_above_threshold_start_time = option_u32_some(now); + } else if (now - option_u32_unwrap(state->estop_above_threshold_start_time) >= IBUS_ESTOP_RISING_DEBOUNCE_TIME) { // ESTOP channel has been above threshold for long enough, consider remote ESTOP triggered - state->estop_triggered_time = HAL_GetTick(); + state->estop_triggered_time = option_u32_some(now); state->mode = LOGIC_MODE_ESTOPPED; HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); @@ -58,7 +60,7 @@ void logic_run( } } else { // ESTOP channel is below threshold, reset debounce timer - state->estop_above_threshold_start_time = UINT32_MAX; + state->estop_above_threshold_start_time = option_u32_none(); } // Boot state machine logic @@ -95,12 +97,11 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - if ((state->estop_triggered_time != UINT32_MAX) - && (now >= state->estop_triggered_time + ESTOP_TRIGGERED_DELAY)) { + if (option_u32_is_some(state->estop_triggered_time) + && (now >= option_u32_unwrap(state->estop_triggered_time) + ESTOP_TRIGGERED_DELAY)) { // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence state->mode = LOGIC_MODE_STARTING; - state->estop_triggered_time = UINT32_MAX; // reset estop triggered time - + state->estop_triggered_time = option_u32_none(); // reset estop triggered time // Reset to booting state (both precharge and main coil off), // then the logic will set precharge on in the next step of the state machine HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index ab06add..52dd065 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -21,7 +21,6 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ -#include "ibus.h" #include "logic.h" /* USER CODE END Includes */ From b7fabf7624e1d25a2da2a02c6a737f8a8e5ce1b7 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 12:21:20 -0400 Subject: [PATCH 29/55] Forgotten change: missing last_can_tx_time update --- AutonomousDistroBoard/Core/Src/logic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index d523813..7f5be5f 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -120,6 +120,7 @@ void logic_run( .steering_pwm = state->can_current_steering * 20, // scale 0-1000 to 0-20000us }; send_can_status(&status, hcan); + state->last_can_tx_time = now; } // REST OF LOGIC } \ No newline at end of file From b9c4e0b40944f314277f4a8d386beab0b1712781 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 15:31:10 -0400 Subject: [PATCH 30/55] proper debounce controller for remote estop rising debounce falling debounce accumulating debounce --- AutonomousDistroBoard/Core/Inc/ibus.h | 4 -- AutonomousDistroBoard/Core/Inc/logic.h | 7 ++- AutonomousDistroBoard/Core/Inc/util.h | 38 +++++++++++++- AutonomousDistroBoard/Core/Src/logic.c | 32 ++++++------ AutonomousDistroBoard/Core/Src/util.c | 69 ++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 23 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index 251c491..74821b7 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -13,10 +13,6 @@ #define IBUS_HEADER_DLC (0x20) #define IBUS_HEADER_COMMAND (0x40) -#define IBUS_ESTOP_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered -#define IBUS_ESTOP_RISING_DEBOUNCE_TIME (500) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered -#define IBUS_ESTOP_FALLING_DEBOUNCE_TIME (50) // ms, when the rising estop is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer - // iBUS data structure typedef struct { diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 808a223..e464150 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -21,6 +21,11 @@ #define IBUS_CHANNEL_MODE (2) // ~1000 = RC mode, ~2000 = autonomous mode #define IBUS_CHANNEL_ESTOP (3) // ~1000 = not pressed, ~2000 = estop +#define ESTOP_PWM_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered +#define ESTOP_RISING_DEBOUNCE (300) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered +#define ESTOP_ACCUMULATING_DEBOUNCE (30) // ms, when the rising estop is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer +#define ESTOP_FALLING_DEBOUNCE (50) // ms, require the ESTOP channel to be below the threshold for at least this long before considering the remote estop to be no longer triggered + typedef enum { LOGIC_MODE_STARTING = 0, @@ -38,7 +43,7 @@ typedef struct { uint32_t last_can_tx_time; uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized - option_u32_t estop_above_threshold_start_time; // HAL_GetTick() timestamp of when the ESTOP channel was first observed to go above the threshold, or none if currently below the threshold + debounce_controller_t estop_debounce; // debounce controller for the remote estop channel option_u32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or none if it is not currently triggered volatile uint16_t can_current_throttle; // 0-1000 diff --git a/AutonomousDistroBoard/Core/Inc/util.h b/AutonomousDistroBoard/Core/Inc/util.h index 22b8e68..c5cb2a7 100644 --- a/AutonomousDistroBoard/Core/Inc/util.h +++ b/AutonomousDistroBoard/Core/Inc/util.h @@ -5,7 +5,10 @@ #include -// Option type +bool has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms); + + +// Option type -----------------------------------------------------// typedef struct { bool is_some; // true if the option contains a value, false if it is None uint32_t value; @@ -16,7 +19,40 @@ option_u32_t option_u32_none(void); bool option_u32_is_some(option_u32_t opt); bool option_u32_is_none(option_u32_t opt); uint32_t option_u32_unwrap(option_u32_t opt); // only call if opt is known to be Some!! +//----------------------------------------------------------------------------// + + +// Debounce controller -------------------------------------------------------// +typedef struct { + bool stable_state; + option_u32_t transition_start_time; + option_u32_t interruption_start_time; + uint32_t rising_debounce_ms; + uint32_t falling_debounce_ms; + uint32_t accumulating_debounce_ms; +} debounce_controller_t; + +void debounce_controller_init( + debounce_controller_t* controller, + bool initial_state, + uint32_t rising_debounce_ms, + uint32_t falling_debounce_ms, + uint32_t accumulating_debounce_ms +); + +void debounce_controller_reset( + debounce_controller_t* controller, + bool state +); + +bool debounce_controller_update( + debounce_controller_t* controller, + bool raw_state, + uint32_t now +); +bool debounce_controller_get_state(const debounce_controller_t* controller); +//----------------------------------------------------------------------------// #endif // UTIL_H \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 7f5be5f..ab9b01b 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -15,8 +15,13 @@ void logic_init(logic_state_t* state) { state->mode = LOGIC_MODE_STARTING; state->boot_time = HAL_GetTick(); state->estop_triggered_time = option_u32_none(); // not currently triggered - - state->estop_above_threshold_start_time = option_u32_none(); // not currently above threshold + debounce_controller_init( + &state->estop_debounce, + false, + ESTOP_RISING_DEBOUNCE, + ESTOP_FALLING_DEBOUNCE, + ESTOP_ACCUMULATING_DEBOUNCE + ); ibus_init(&state->ibus); state->last_can_tx_time = 0; @@ -46,21 +51,14 @@ void logic_run( // Check for remote ESTOP trigger uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; - if (estop_channel_value >= IBUS_ESTOP_THRESHOLD) { - if (option_u32_is_none(state->estop_above_threshold_start_time)) { - // Just observed ESTOP channel go above threshold, start debounce timer - state->estop_above_threshold_start_time = option_u32_some(now); - } else if (now - option_u32_unwrap(state->estop_above_threshold_start_time) >= IBUS_ESTOP_RISING_DEBOUNCE_TIME) { - // ESTOP channel has been above threshold for long enough, consider remote ESTOP triggered - state->estop_triggered_time = option_u32_some(now); - state->mode = LOGIC_MODE_ESTOPPED; - - HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); - HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - } - } else { - // ESTOP channel is below threshold, reset debounce timer - state->estop_above_threshold_start_time = option_u32_none(); + bool estop_raw_high = estop_channel_value >= ESTOP_PWM_THRESHOLD; + bool estop_debounced_high = debounce_controller_update(&state->estop_debounce, estop_raw_high, now); + if (estop_debounced_high) { + state->estop_triggered_time = option_u32_some(now); + state->mode = LOGIC_MODE_ESTOPPED; + + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); } // Boot state machine logic diff --git a/AutonomousDistroBoard/Core/Src/util.c b/AutonomousDistroBoard/Core/Src/util.c index 1fa78c6..7a1a7b7 100644 --- a/AutonomousDistroBoard/Core/Src/util.c +++ b/AutonomousDistroBoard/Core/Src/util.c @@ -3,6 +3,10 @@ #include #include +bool has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms) { + return (uint32_t)(now - start) >= duration_ms; +} + option_u32_t option_u32_some(uint32_t value) { option_u32_t opt = { .is_some = true, @@ -26,4 +30,69 @@ bool option_u32_is_none(option_u32_t opt) { uint32_t option_u32_unwrap(option_u32_t opt) { // Only call this if opt is known to be Some, otherwise behavior is undefined return opt.value; +} + +void debounce_controller_init( + debounce_controller_t* controller, + bool initial_state, + uint32_t rising_debounce_ms, + uint32_t falling_debounce_ms, + uint32_t accumulating_debounce_ms +) { + controller->stable_state = initial_state; + controller->transition_start_time = option_u32_none(); + controller->interruption_start_time = option_u32_none(); + controller->rising_debounce_ms = rising_debounce_ms; + controller->falling_debounce_ms = falling_debounce_ms; + controller->accumulating_debounce_ms = accumulating_debounce_ms; +} + +void debounce_controller_reset( + debounce_controller_t* controller, + bool state +) { + controller->stable_state = state; + controller->transition_start_time = option_u32_none(); + controller->interruption_start_time = option_u32_none(); +} + +bool debounce_controller_update( + debounce_controller_t* controller, + bool raw_state, + uint32_t now +) { + if (raw_state == controller->stable_state) { + if (option_u32_is_some(controller->transition_start_time)) { + if (option_u32_is_none(controller->interruption_start_time)) { + controller->interruption_start_time = option_u32_some(now); + } else if (has_elapsed(now, option_u32_unwrap(controller->interruption_start_time), controller->accumulating_debounce_ms)) { + controller->transition_start_time = option_u32_none(); + controller->interruption_start_time = option_u32_none(); + } + } + + return controller->stable_state; + } + + if (option_u32_is_none(controller->transition_start_time)) { + controller->transition_start_time = option_u32_some(now); + } + + controller->interruption_start_time = option_u32_none(); + + uint32_t debounce_ms = raw_state + ? controller->rising_debounce_ms + : controller->falling_debounce_ms; + + if (has_elapsed(now, option_u32_unwrap(controller->transition_start_time), debounce_ms)) { + controller->stable_state = raw_state; + controller->transition_start_time = option_u32_none(); + controller->interruption_start_time = option_u32_none(); + } + + return controller->stable_state; +} + +bool debounce_controller_get_state(const debounce_controller_t* controller) { + return controller->stable_state; } \ No newline at end of file From fc99eded6364ed30090d4880578710740fa00d85 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 15:32:35 -0400 Subject: [PATCH 31/55] Aligning #defines --- AutonomousDistroBoard/Core/Inc/can.h | 2 -- AutonomousDistroBoard/Core/Inc/ibus.h | 6 +++--- AutonomousDistroBoard/Core/Inc/logic.h | 15 +++++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/can.h b/AutonomousDistroBoard/Core/Inc/can.h index 14be4c4..3eb0f09 100644 --- a/AutonomousDistroBoard/Core/Inc/can.h +++ b/AutonomousDistroBoard/Core/Inc/can.h @@ -9,8 +9,6 @@ #define CAN_BUS (CAN2) -#define CAN_TX_PERIOD (10) // ms -#define CAN_RX_TIMEOUT (50) // ms // - ID = `0x100` - **Control commands** (RX) // - Byte 0-1: throttle (uint16_t, little endian), 0-1000, where 1000 = full throttle diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index 74821b7..4ef52c0 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -6,11 +6,11 @@ #include "stm32f4xx_hal.h" -#define IBUS_CHANNEL_COUNT (14) -#define IBUS_FRAME_SIZE (32) +#define IBUS_CHANNEL_COUNT (14) +#define IBUS_FRAME_SIZE (32) #define IBUS_DMA_BUFFER_SIZE (128) -#define IBUS_HEADER_DLC (0x20) +#define IBUS_HEADER_DLC (0x20) #define IBUS_HEADER_COMMAND (0x40) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index e464150..3cf1db3 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -11,20 +11,23 @@ #include "util.h" -#define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge -#define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor +#define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge +#define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor #define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed -#define ESTOP_TRIGGERED_DELAY (3000) // ms, after remote estop is triggered, how long to wait before restarting the precharge sequence +#define ESTOP_TRIGGERED_DELAY (3000) // ms, after remote estop is triggered, how long to wait before restarting the precharge sequence #define IBUS_CHANNEL_THROTTLE (0) // 1000 = full stop, 2000 = full throttle forward #define IBUS_CHANNEL_STEERING (1) // 1000 = full left, 1500 = center, 2000 = full right #define IBUS_CHANNEL_MODE (2) // ~1000 = RC mode, ~2000 = autonomous mode #define IBUS_CHANNEL_ESTOP (3) // ~1000 = not pressed, ~2000 = estop -#define ESTOP_PWM_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered -#define ESTOP_RISING_DEBOUNCE (300) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered +#define ESTOP_PWM_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered +#define ESTOP_RISING_DEBOUNCE (300) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered #define ESTOP_ACCUMULATING_DEBOUNCE (30) // ms, when the rising estop is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer -#define ESTOP_FALLING_DEBOUNCE (50) // ms, require the ESTOP channel to be below the threshold for at least this long before considering the remote estop to be no longer triggered +#define ESTOP_FALLING_DEBOUNCE (50) // ms, require the ESTOP channel to be below the threshold for at least this long before considering the remote estop to be no longer triggered + +#define CAN_TX_PERIOD (10) // ms +// #define CAN_RX_TIMEOUT (50) // ms typedef enum { From 61e257048a663b8ebd53c7d9fb20def23da3b3b3 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 15:39:02 -0400 Subject: [PATCH 32/55] Update comments --- AutonomousDistroBoard/Core/Inc/util.h | 16 ++++++++++------ AutonomousDistroBoard/Core/Src/logic.c | 2 ++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/util.h b/AutonomousDistroBoard/Core/Inc/util.h index c5cb2a7..3a80713 100644 --- a/AutonomousDistroBoard/Core/Inc/util.h +++ b/AutonomousDistroBoard/Core/Inc/util.h @@ -23,13 +23,17 @@ uint32_t option_u32_unwrap(option_u32_t opt); // only call if opt is known to be // Debounce controller -------------------------------------------------------// +// Noise-tolerant debounce controller for boolean signals, with separate debounce +// times for rising and falling edges and an optional accumulating debounce feature +// to help filter out noise that causes multiple rapid transitions typedef struct { - bool stable_state; - option_u32_t transition_start_time; - option_u32_t interruption_start_time; - uint32_t rising_debounce_ms; - uint32_t falling_debounce_ms; - uint32_t accumulating_debounce_ms; + bool stable_state; // current accepted state + option_u32_t transition_start_time; // when a possible transition began + option_u32_t interruption_start_time; // when signal temporarily flipped back + uint32_t rising_debounce_ms; // configuration parameter: how long the signal needs to be continuously high before accepting a low->high transition + uint32_t falling_debounce_ms; // configuration parameter: how long the signal needs to be continuously low before accepting a high->low transition + uint32_t accumulating_debounce_ms; // configuration parameter: when a rising transition is in the debounce period, if the signal goes low again, + // require it to be continuously low for this long before resetting the debounce timer (helps filter out noise that causes multiple rapid transitions) } debounce_controller_t; void debounce_controller_init( diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index ab9b01b..50f7fc7 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -56,6 +56,8 @@ void logic_run( if (estop_debounced_high) { state->estop_triggered_time = option_u32_some(now); state->mode = LOGIC_MODE_ESTOPPED; + // Note: if it was high and remains high, we want to continue to update estop_triggered_time + // so the ESTOP_TRIGGERED_DELAY doesn't start until the remote estop goes low again HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); From 8456a2defcbddadf470413c5547a326aef2765ae Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 15:43:00 -0400 Subject: [PATCH 33/55] State machine always writes the state's state instead of only on transistions --- AutonomousDistroBoard/Core/Src/logic.c | 50 +++++++++++++++----------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 50f7fc7..4d65be3 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -59,57 +59,68 @@ void logic_run( // Note: if it was high and remains high, we want to continue to update estop_triggered_time // so the ESTOP_TRIGGERED_DELAY doesn't start until the remote estop goes low again + // These should be set when LOGIC_MODE_ESTOPPED, but just for safety, set them here... HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); } - // Boot state machine logic + // Precharge/contactor state machine logic switch (state->mode) { - case LOGIC_MODE_STARTING: + case LOGIC_MODE_STARTING: { + // Precharge and contactor low + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + if (now >= state->boot_time + PRECHARGE_START_DELAY) { state->mode = LOGIC_MODE_PRECHARGING; - // Start precharge: Precharge EN goes high - HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); } break; + } + case LOGIC_MODE_PRECHARGING: { + // Precharge on, contactor off + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - case LOGIC_MODE_PRECHARGING: if (now >= state->boot_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION) { state->mode = LOGIC_MODE_CONTACTOR_CLOSING; - // Close contactor: Main Coil EN goes high - HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); } break; + } + case LOGIC_MODE_CONTACTOR_CLOSING: { + // Precharge on, contactor on + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); - case LOGIC_MODE_CONTACTOR_CLOSING: if (now >= state->boot_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION + CONTACTOR_CLOSED_DELAY) { state->mode = LOGIC_MODE_RUNNING; - // Contactor closed = precharge complete, Precharge EN can go low - HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); } break; + } + case LOGIC_MODE_RUNNING: { + // Precharge off, contactor on + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); - case LOGIC_MODE_RUNNING: - // Normal operation, nothing to do here for now + // Normal operation! break; - case LOGIC_MODE_ESTOPPED: - // For safety, force set main coil and precharge off + } + case LOGIC_MODE_ESTOPPED: { + // STOP: precharge off, contactor off HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); if (option_u32_is_some(state->estop_triggered_time) && (now >= option_u32_unwrap(state->estop_triggered_time) + ESTOP_TRIGGERED_DELAY)) { // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence - state->mode = LOGIC_MODE_STARTING; state->estop_triggered_time = option_u32_none(); // reset estop triggered time - // Reset to booting state (both precharge and main coil off), - // then the logic will set precharge on in the next step of the state machine - HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); - HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + state->mode = LOGIC_MODE_STARTING; } break; + } } + // REST OF LOGIC + // Periodically send CAN status messages if (now - state->last_can_tx_time >= CAN_TX_PERIOD) { can_status_msg_t status = { @@ -122,5 +133,4 @@ void logic_run( send_can_status(&status, hcan); state->last_can_tx_time = now; } - // REST OF LOGIC } \ No newline at end of file From d564bc36a3b58f3ad6127be5c0f076c8043bdc53 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 15:58:48 -0400 Subject: [PATCH 34/55] RC disconnect system --- AutonomousDistroBoard/Core/Inc/ibus.h | 4 +++ AutonomousDistroBoard/Core/Inc/logic.h | 3 ++ AutonomousDistroBoard/Core/Inc/util.h | 2 +- AutonomousDistroBoard/Core/Src/ibus.c | 14 ++++++++-- AutonomousDistroBoard/Core/Src/logic.c | 38 ++++++++++++++++++-------- AutonomousDistroBoard/Core/Src/util.c | 6 ++-- 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/ibus.h b/AutonomousDistroBoard/Core/Inc/ibus.h index 4ef52c0..9b8d3f4 100644 --- a/AutonomousDistroBoard/Core/Inc/ibus.h +++ b/AutonomousDistroBoard/Core/Inc/ibus.h @@ -2,6 +2,7 @@ #define IBUS_H #include +#include #include "stm32f4xx_hal.h" @@ -16,6 +17,7 @@ // iBUS data structure typedef struct { + uint32_t last_frame_time; // HAL_GetTick() timestamp of when the last valid frame was received uint8_t dma_buffer[IBUS_DMA_BUFFER_SIZE]; // DMA buffer for incoming UART data uint8_t frame[IBUS_FRAME_SIZE]; // Buffer for assembling a single iBUS frame uint8_t frame_index; // Current index in the frame buffer @@ -26,6 +28,8 @@ typedef struct { void ibus_init(ibus_t* ibus); +bool ibus_is_connected(const ibus_t* ibus, uint32_t now, uint32_t timeout_ms); + // Should be called in the main loop / 1kHz task to process incoming iBUS data void ibus_process(ibus_t* ibus, UART_HandleTypeDef *sbus_huart); diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 3cf1db3..e6bf173 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -29,6 +29,8 @@ #define CAN_TX_PERIOD (10) // ms // #define CAN_RX_TIMEOUT (50) // ms +#define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost + typedef enum { LOGIC_MODE_STARTING = 0, @@ -36,6 +38,7 @@ typedef enum { LOGIC_MODE_CONTACTOR_CLOSING, LOGIC_MODE_RUNNING, LOGIC_MODE_ESTOPPED, + LOGIC_MODE_RC_DISCONNECTED } logic_mode_t; diff --git a/AutonomousDistroBoard/Core/Inc/util.h b/AutonomousDistroBoard/Core/Inc/util.h index 3a80713..0ac7bb9 100644 --- a/AutonomousDistroBoard/Core/Inc/util.h +++ b/AutonomousDistroBoard/Core/Inc/util.h @@ -5,7 +5,7 @@ #include -bool has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms); +bool util_has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms); // Option type -----------------------------------------------------// diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c index f6378c8..05fe197 100644 --- a/AutonomousDistroBoard/Core/Src/ibus.c +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -3,9 +3,15 @@ #include #include +#include "util.h" -void ibus_init(ibus_t *ibus) { - memset(ibus, 0, sizeof(*ibus)); + +void ibus_init(ibus_t* ibus) { + memset(ibus, 0, sizeof(ibus_t)); +} + +bool ibus_is_connected(const ibus_t* ibus, uint32_t now, uint32_t timeout_ms) { + return !util_has_elapsed(now, ibus->last_frame_time, timeout_ms); } @@ -25,7 +31,7 @@ void ibus_process(ibus_t* ibus, UART_HandleTypeDef* ibus_huart) { -void ibus_parse_byte(ibus_t *ibus, uint8_t byte) { +void ibus_parse_byte(ibus_t* ibus, uint8_t byte) { // Byte 0: Length = 0x20 (32) // Byte 1: Command = 0x40 // Byte 2-29: 14 channels, little-endian uint16 @@ -50,6 +56,8 @@ void ibus_parse_byte(ibus_t *ibus, uint8_t byte) { ibus->channels[i] = ibus->frame[2 + i*2] | (ibus->frame[3 + i*2] << 8); } } + + ibus->last_frame_time = HAL_GetTick(); } } } \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 4d65be3..a83ddb6 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -49,19 +49,22 @@ void logic_run( uint32_t now = HAL_GetTick(); + // Check for RC connection timeout + if (!ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { + state->mode = LOGIC_MODE_RC_DISCONNECTED; + } + // Check for remote ESTOP trigger - uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; - bool estop_raw_high = estop_channel_value >= ESTOP_PWM_THRESHOLD; - bool estop_debounced_high = debounce_controller_update(&state->estop_debounce, estop_raw_high, now); - if (estop_debounced_high) { - state->estop_triggered_time = option_u32_some(now); - state->mode = LOGIC_MODE_ESTOPPED; - // Note: if it was high and remains high, we want to continue to update estop_triggered_time - // so the ESTOP_TRIGGERED_DELAY doesn't start until the remote estop goes low again - - // These should be set when LOGIC_MODE_ESTOPPED, but just for safety, set them here... - HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); - HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { + uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; + bool estop_raw_high = estop_channel_value >= ESTOP_PWM_THRESHOLD; + bool estop_debounced_high = debounce_controller_update(&state->estop_debounce, estop_raw_high, now); + if (estop_debounced_high) { + state->estop_triggered_time = option_u32_some(now); + state->mode = LOGIC_MODE_ESTOPPED; + // Note: if it was high and remains high, we want to continue to update estop_triggered_time + // so the ESTOP_TRIGGERED_DELAY doesn't start until the remote estop goes low again + } } // Precharge/contactor state machine logic @@ -117,6 +120,17 @@ void logic_run( } break; } + case LOGIC_MODE_RC_DISCONNECTED: { + // STOP: precharge off, contactor off + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + + if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { + // If we receive a valid iBUS frame, consider the RC connection to be restored and restart precharge sequence + state->mode = LOGIC_MODE_STARTING; + } + break; + } } // REST OF LOGIC diff --git a/AutonomousDistroBoard/Core/Src/util.c b/AutonomousDistroBoard/Core/Src/util.c index 7a1a7b7..c1b729a 100644 --- a/AutonomousDistroBoard/Core/Src/util.c +++ b/AutonomousDistroBoard/Core/Src/util.c @@ -3,7 +3,7 @@ #include #include -bool has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms) { +bool util_has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms) { return (uint32_t)(now - start) >= duration_ms; } @@ -65,7 +65,7 @@ bool debounce_controller_update( if (option_u32_is_some(controller->transition_start_time)) { if (option_u32_is_none(controller->interruption_start_time)) { controller->interruption_start_time = option_u32_some(now); - } else if (has_elapsed(now, option_u32_unwrap(controller->interruption_start_time), controller->accumulating_debounce_ms)) { + } else if (util_has_elapsed(now, option_u32_unwrap(controller->interruption_start_time), controller->accumulating_debounce_ms)) { controller->transition_start_time = option_u32_none(); controller->interruption_start_time = option_u32_none(); } @@ -84,7 +84,7 @@ bool debounce_controller_update( ? controller->rising_debounce_ms : controller->falling_debounce_ms; - if (has_elapsed(now, option_u32_unwrap(controller->transition_start_time), debounce_ms)) { + if (util_has_elapsed(now, option_u32_unwrap(controller->transition_start_time), debounce_ms)) { controller->stable_state = raw_state; controller->transition_start_time = option_u32_none(); controller->interruption_start_time = option_u32_none(); From d89499be95c9b276ca92d20f2de7337469f20d6d Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 16:12:01 -0400 Subject: [PATCH 35/55] scaffold for autonomous_mode --- AutonomousDistroBoard/Core/Inc/logic.h | 10 ++++++++- AutonomousDistroBoard/Core/Src/logic.c | 28 ++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index e6bf173..8f8083e 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -23,9 +23,13 @@ #define ESTOP_PWM_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered #define ESTOP_RISING_DEBOUNCE (300) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered -#define ESTOP_ACCUMULATING_DEBOUNCE (30) // ms, when the rising estop is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer +#define ESTOP_ACCUMULATING_DEBOUNCE (30) // ms, when the rising ESTOP is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer #define ESTOP_FALLING_DEBOUNCE (50) // ms, require the ESTOP channel to be below the threshold for at least this long before considering the remote estop to be no longer triggered +#define MODE_PWM_THRESHOLD (1500) // if the MODE channel is above this value, consider it to be in autonomous mode, otherwise RC mode +#define MODE_DEBOUNCE_MS (500) // ms, require the MODE channel to be consistently above or below the threshold for at least this long before switching modes +#define MODE_ACCUMULATING_DEBOUNCE_MS (50) // ms, when the rising MODE is debouncing/accumulating, require the MODE channel to be below the threshold for at least this long before resetting the debounce timer + #define CAN_TX_PERIOD (10) // ms // #define CAN_RX_TIMEOUT (50) // ms @@ -48,10 +52,14 @@ typedef struct { ibus_t ibus; uint32_t last_can_tx_time; + // TODO: boot time should be start time and it needs to be reset when transition back to start state uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized + debounce_controller_t estop_debounce; // debounce controller for the remote estop channel option_u32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or none if it is not currently triggered + debounce_controller_t mode_debounce; // low = RC mode, high = autonomous mode + volatile uint16_t can_current_throttle; // 0-1000 volatile uint16_t can_current_steering; // 0-1000 volatile uint32_t last_control_timestamp; // HAL_GetTick() timestamp of last received control message diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index a83ddb6..adc46fb 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -15,6 +15,7 @@ void logic_init(logic_state_t* state) { state->mode = LOGIC_MODE_STARTING; state->boot_time = HAL_GetTick(); state->estop_triggered_time = option_u32_none(); // not currently triggered + debounce_controller_init( &state->estop_debounce, false, @@ -22,6 +23,13 @@ void logic_init(logic_state_t* state) { ESTOP_FALLING_DEBOUNCE, ESTOP_ACCUMULATING_DEBOUNCE ); + debounce_controller_init( + &state->mode_debounce, + false, + MODE_DEBOUNCE_MS, + MODE_DEBOUNCE_MS, + MODE_ACCUMULATING_DEBOUNCE_MS + ); ibus_init(&state->ibus); state->last_can_tx_time = 0; @@ -49,12 +57,12 @@ void logic_run( uint32_t now = HAL_GetTick(); - // Check for RC connection timeout + // All states: Check for RC connection timeout if (!ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { state->mode = LOGIC_MODE_RC_DISCONNECTED; } - // Check for remote ESTOP trigger + // All states: Check for remote ESTOP trigger if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; bool estop_raw_high = estop_channel_value >= ESTOP_PWM_THRESHOLD; @@ -67,6 +75,8 @@ void logic_run( } } + // TODO: output pwm for throttle and steering + // Precharge/contactor state machine logic switch (state->mode) { case LOGIC_MODE_STARTING: { @@ -99,14 +109,24 @@ void logic_run( } break; } - case LOGIC_MODE_RUNNING: { + case LOGIC_MODE_RUNNING: { //-------------------------------------------------// // Precharge off, contactor on HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); // Normal operation! + + // MODE switching logic + // Note: don't need to check for iBUS connection here because if we lost connection + // we would have already switched to RC_DISCONNECTED mode + uint16_t mode_channel_value = state->ibus.channels[IBUS_CHANNEL_MODE]; + bool mode_raw_high = mode_channel_value >= MODE_PWM_THRESHOLD; + debounce_controller_update(&state->mode_debounce, mode_raw_high, now); + + bool autonomous_mode = debounce_controller_get_state(&state->mode_debounce); + break; - } + } //--------------------------------------------------------------------------// case LOGIC_MODE_ESTOPPED: { // STOP: precharge off, contactor off HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); From a386fe9b5d0c98cf334958a3d2ca222684c8221c Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 16:45:26 -0400 Subject: [PATCH 36/55] fixing boot_time -> start_time the correct fix would be to to have the first state just set the start_time instead of needing to set it on every transition to STARTING but it's okay --- AutonomousDistroBoard/Core/Inc/logic.h | 3 +-- AutonomousDistroBoard/Core/Src/logic.c | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 8f8083e..ef6e7e0 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -52,8 +52,7 @@ typedef struct { ibus_t ibus; uint32_t last_can_tx_time; - // TODO: boot time should be start time and it needs to be reset when transition back to start state - uint32_t boot_time; // HAL_GetTick() timestamp of when the system initialized + uint32_t start_time; // HAL_GetTick() timestamp of when the precharge sequence started debounce_controller_t estop_debounce; // debounce controller for the remote estop channel option_u32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or none if it is not currently triggered diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index adc46fb..823dd8b 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -13,7 +13,7 @@ static logic_state_t* g_logic_state_ptr = NULL; void logic_init(logic_state_t* state) { state->mode = LOGIC_MODE_STARTING; - state->boot_time = HAL_GetTick(); + state->start_time = HAL_GetTick(); state->estop_triggered_time = option_u32_none(); // not currently triggered debounce_controller_init( @@ -84,7 +84,7 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - if (now >= state->boot_time + PRECHARGE_START_DELAY) { + if (now >= state->start_time + PRECHARGE_START_DELAY) { state->mode = LOGIC_MODE_PRECHARGING; } break; @@ -94,7 +94,7 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - if (now >= state->boot_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION) { + if (now >= state->start_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION) { state->mode = LOGIC_MODE_CONTACTOR_CLOSING; } break; @@ -104,7 +104,7 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); - if (now >= state->boot_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION + CONTACTOR_CLOSED_DELAY) { + if (now >= state->start_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION + CONTACTOR_CLOSED_DELAY) { state->mode = LOGIC_MODE_RUNNING; } break; @@ -137,6 +137,7 @@ void logic_run( // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence state->estop_triggered_time = option_u32_none(); // reset estop triggered time state->mode = LOGIC_MODE_STARTING; + state->start_time = now; } break; } @@ -148,6 +149,7 @@ void logic_run( if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { // If we receive a valid iBUS frame, consider the RC connection to be restored and restart precharge sequence state->mode = LOGIC_MODE_STARTING; + state->start_time = now; } break; } From 4d4cc75eb24242b6bd0a83b23f974c5276987154 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Tue, 24 Mar 2026 16:49:34 -0400 Subject: [PATCH 37/55] using util_has_elapsed and CAN TX-ing rc_mode --- AutonomousDistroBoard/Core/Src/logic.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 823dd8b..aabd6d5 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -84,7 +84,7 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - if (now >= state->start_time + PRECHARGE_START_DELAY) { + if (util_has_elapsed(now, state->start_time, PRECHARGE_START_DELAY)) { state->mode = LOGIC_MODE_PRECHARGING; } break; @@ -94,7 +94,8 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); - if (now >= state->start_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION) { + uint32_t total_delay = PRECHARGE_START_DELAY + PRECHARGE_DURATION; + if (util_has_elapsed(now, state->start_time, total_delay)) { state->mode = LOGIC_MODE_CONTACTOR_CLOSING; } break; @@ -104,7 +105,8 @@ void logic_run( HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_SET); - if (now >= state->start_time + PRECHARGE_START_DELAY + PRECHARGE_DURATION + CONTACTOR_CLOSED_DELAY) { + uint32_t total_delay = PRECHARGE_START_DELAY + PRECHARGE_DURATION + CONTACTOR_CLOSED_DELAY; + if (util_has_elapsed(now, state->start_time, total_delay)) { state->mode = LOGIC_MODE_RUNNING; } break; @@ -133,7 +135,7 @@ void logic_run( HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); if (option_u32_is_some(state->estop_triggered_time) - && (now >= option_u32_unwrap(state->estop_triggered_time) + ESTOP_TRIGGERED_DELAY)) { + && util_has_elapsed(now, option_u32_unwrap(state->estop_triggered_time), ESTOP_TRIGGERED_DELAY)) { // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence state->estop_triggered_time = option_u32_none(); // reset estop triggered time state->mode = LOGIC_MODE_STARTING; @@ -162,7 +164,7 @@ void logic_run( can_status_msg_t status = { .precharge = (state->mode == LOGIC_MODE_PRECHARGING), .contactor = (state->mode == LOGIC_MODE_RUNNING), - .rc_mode = 0, // TODO + .rc_mode = !debounce_controller_get_state(&state->mode_debounce), // if mode_debounce is low, we are in RC mode .throttle_pwm = state->can_current_throttle * 20, // scale 0-1000 to 0-20000us .steering_pwm = state->can_current_steering * 20, // scale 0-1000 to 0-20000us }; From 4ad64034ff085a1dca4177377127e6cbe9db6c68 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Wed, 25 Mar 2026 14:05:38 -0400 Subject: [PATCH 38/55] Primary PWM output logic --- AutonomousDistroBoard/Core/Inc/can.h | 4 +++ AutonomousDistroBoard/Core/Inc/logic.h | 14 ++++++-- AutonomousDistroBoard/Core/Inc/util.h | 2 ++ AutonomousDistroBoard/Core/Src/can.c | 7 ++++ AutonomousDistroBoard/Core/Src/logic.c | 45 +++++++++++++++++++++----- AutonomousDistroBoard/Core/Src/main.c | 2 +- AutonomousDistroBoard/Core/Src/util.c | 28 +++++++++++++++- 7 files changed, 89 insertions(+), 13 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/can.h b/AutonomousDistroBoard/Core/Inc/can.h index 3eb0f09..c9f49de 100644 --- a/AutonomousDistroBoard/Core/Inc/can.h +++ b/AutonomousDistroBoard/Core/Inc/can.h @@ -15,6 +15,8 @@ // - Byte 2-3: steering (uint16_t, little endian), 0-1000, where 1000 = full right, 500 = center, 0 = full left // - Byte 4-7: reserved / future use #define CAN_ID_CONTROL (0x100) +#define CAN_THROTTLE_MAX (1000) +#define CAN_STEERING_MAX (1000) typedef struct { uint16_t throttle; // 0-1000 uint16_t steering; // 0-1000 @@ -43,6 +45,8 @@ typedef struct { can_control_msg_t parse_can_control(const uint8_t* data); void send_can_status(const can_status_msg_t* status, CAN_HandleTypeDef* hcan); +uint16_t can_throttle_to_pwm(const can_control_msg_t* cmd); +uint16_t can_steering_to_pwm(const can_control_msg_t* cmd); #endif // CAN_H \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index ef6e7e0..76205ca 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -35,6 +35,12 @@ #define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost +#define THROTTLE_PWM_LOW (1000) +#define THROTTLE_PWM_HIGH (2000) +#define STEERING_PWM_LOW (1000) +#define STEERING_PWM_HIGH (2000) + +#define RC_MODE_THROTTLE_DIVISOR (3) // divide the iBUS throttle PWM by this much typedef enum { LOGIC_MODE_STARTING = 0, @@ -59,8 +65,8 @@ typedef struct { debounce_controller_t mode_debounce; // low = RC mode, high = autonomous mode - volatile uint16_t can_current_throttle; // 0-1000 - volatile uint16_t can_current_steering; // 0-1000 + volatile uint16_t can_current_throttle_pwm; // 1000-2000, updated by CAN RX callback + volatile uint16_t can_current_steering_pwm; // 1000-2000, updated by CAN RX callback volatile uint32_t last_control_timestamp; // HAL_GetTick() timestamp of last received control message } logic_state_t; @@ -71,7 +77,9 @@ void logic_init(logic_state_t* state); void logic_run( logic_state_t* state, UART_HandleTypeDef *sbus_huart, - CAN_HandleTypeDef *hcan + CAN_HandleTypeDef *hcan, + TIM_HandleTypeDef *throttle_htim, + TIM_HandleTypeDef *steering_htim ); // Called from CAN RX callback when a control message is received diff --git a/AutonomousDistroBoard/Core/Inc/util.h b/AutonomousDistroBoard/Core/Inc/util.h index 0ac7bb9..8fbe48f 100644 --- a/AutonomousDistroBoard/Core/Inc/util.h +++ b/AutonomousDistroBoard/Core/Inc/util.h @@ -6,6 +6,8 @@ bool util_has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms); +uint16_t clamp_u16(uint16_t value, uint16_t min, uint16_t max); +uint16_t map_u16(uint16_t value, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max); // Option type -----------------------------------------------------// diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c index 7f922ad..f2cd1e4 100644 --- a/AutonomousDistroBoard/Core/Src/can.c +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -3,6 +3,7 @@ #include "stm32f4xx_hal.h" #include "logic.h" +#include "util.h" void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) @@ -53,3 +54,9 @@ void send_can_status(const can_status_msg_t* status, CAN_HandleTypeDef* hcan) { } +uint16_t can_throttle_to_pwm(const can_control_msg_t* cmd) { + return map_u16(cmd->throttle, 0, CAN_THROTTLE_MAX, THROTTLE_PWM_LOW, THROTTLE_PWM_HIGH); +} +uint16_t can_steering_to_pwm(const can_control_msg_t* cmd) { + return map_u16(cmd->steering, 0, CAN_STEERING_MAX, STEERING_PWM_LOW, STEERING_PWM_HIGH); +} \ No newline at end of file diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index aabd6d5..4e04b2b 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -34,6 +34,10 @@ void logic_init(logic_state_t* state) { ibus_init(&state->ibus); state->last_can_tx_time = 0; + state->can_current_throttle_pwm = THROTTLE_PWM_LOW; + state->can_current_steering_pwm = (STEERING_PWM_LOW + STEERING_PWM_HIGH) / 2; + state->last_control_timestamp = 0; + g_logic_state_ptr = state; } @@ -42,15 +46,17 @@ void logic_handle_control(const can_control_msg_t* cmd) { return; } - g_logic_state_ptr->can_current_throttle = cmd->throttle; - g_logic_state_ptr->can_current_steering = cmd->steering; + g_logic_state_ptr->can_current_throttle_pwm = can_throttle_to_pwm(cmd); + g_logic_state_ptr->can_current_steering_pwm = can_steering_to_pwm(cmd); g_logic_state_ptr->last_control_timestamp = HAL_GetTick(); } void logic_run( logic_state_t* state, UART_HandleTypeDef *sbus_huart, - CAN_HandleTypeDef *hcan + CAN_HandleTypeDef *hcan, + TIM_HandleTypeDef *throttle_htim, + TIM_HandleTypeDef *steering_htim ) { // Process iBUS data ibus_process(&state->ibus, sbus_huart); @@ -75,7 +81,9 @@ void logic_run( } } - // TODO: output pwm for throttle and steering + uint16_t output_throttle_pwm = 0; + uint16_t output_steering_pwm = 0; + // TODO: handle for when not in running mode // Precharge/contactor state machine logic switch (state->mode) { @@ -127,6 +135,21 @@ void logic_run( bool autonomous_mode = debounce_controller_get_state(&state->mode_debounce); + // In autonomous mode, ignore iBUS throttle and steering and only use CAN commands + if (autonomous_mode) { + output_throttle_pwm = state->can_current_throttle_pwm; + output_steering_pwm = state->can_current_steering_pwm; + } + // In RC mode, ignore CAN commands and only use iBUS throttle and steering + else { + uint16_t ibus_throttle_pwm = state->ibus.channels[IBUS_CHANNEL_THROTTLE]; + uint16_t ibus_steering_pwm = state->ibus.channels[IBUS_CHANNEL_STEERING]; + + output_throttle_pwm = THROTTLE_PWM_LOW + (ibus_throttle_pwm - THROTTLE_PWM_LOW) / RC_MODE_THROTTLE_DIVISOR; + output_steering_pwm = ibus_steering_pwm; + } + + break; } //--------------------------------------------------------------------------// case LOGIC_MODE_ESTOPPED: { @@ -157,16 +180,22 @@ void logic_run( } } - // REST OF LOGIC + // Clamp the output PWM values to their valid ranges just in case + output_throttle_pwm = clamp_u16(output_throttle_pwm, THROTTLE_PWM_LOW, THROTTLE_PWM_HIGH); + output_steering_pwm = clamp_u16(output_steering_pwm, STEERING_PWM_LOW, STEERING_PWM_HIGH); + + // Output the PWM values + __HAL_TIM_SET_COMPARE(throttle_htim, TIM_CHANNEL_1, output_throttle_pwm); + __HAL_TIM_SET_COMPARE(steering_htim, TIM_CHANNEL_1, output_steering_pwm); // Periodically send CAN status messages - if (now - state->last_can_tx_time >= CAN_TX_PERIOD) { + if (util_has_elapsed(now, state->last_can_tx_time, CAN_TX_PERIOD)) { can_status_msg_t status = { .precharge = (state->mode == LOGIC_MODE_PRECHARGING), .contactor = (state->mode == LOGIC_MODE_RUNNING), .rc_mode = !debounce_controller_get_state(&state->mode_debounce), // if mode_debounce is low, we are in RC mode - .throttle_pwm = state->can_current_throttle * 20, // scale 0-1000 to 0-20000us - .steering_pwm = state->can_current_steering * 20, // scale 0-1000 to 0-20000us + .throttle_pwm = output_throttle_pwm, + .steering_pwm = output_steering_pwm }; send_can_status(&status, hcan); state->last_can_tx_time = now; diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 52dd065..6fbb294 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -127,7 +127,7 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - logic_run(&g_logic_state, &huart3, &hcan2); + logic_run(&g_logic_state, &huart3, &hcan2, &htim11, &htim1); } /* USER CODE END 3 */ } diff --git a/AutonomousDistroBoard/Core/Src/util.c b/AutonomousDistroBoard/Core/Src/util.c index c1b729a..7a3db49 100644 --- a/AutonomousDistroBoard/Core/Src/util.c +++ b/AutonomousDistroBoard/Core/Src/util.c @@ -3,10 +3,32 @@ #include #include +//----------------------------------------------------------------------------// bool util_has_elapsed(uint32_t now, uint32_t start, uint32_t duration_ms) { return (uint32_t)(now - start) >= duration_ms; } +uint16_t clamp_u16(uint16_t value, uint16_t min, uint16_t max) { + if (value < min) { + return min; + } else if (value > max) { + return max; + } else { + return value; + } +} + +uint16_t map_u16(uint16_t value, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max) { + if (in_max == in_min) { + // Avoid division by zero; return the midpoint of the output range + return (out_min + out_max) / 2; + } + uint32_t scaled = (uint32_t)(value - in_min) * (out_max - out_min); + return (uint16_t)(scaled / (in_max - in_min) + out_min); +} +//----------------------------------------------------------------------------// + +// option_u32_t --------------------------------------------------------------// option_u32_t option_u32_some(uint32_t value) { option_u32_t opt = { .is_some = true, @@ -31,7 +53,10 @@ uint32_t option_u32_unwrap(option_u32_t opt) { // Only call this if opt is known to be Some, otherwise behavior is undefined return opt.value; } +//----------------------------------------------------------------------------// + +// debounce_controller_t -----------------------------------------------------// void debounce_controller_init( debounce_controller_t* controller, bool initial_state, @@ -95,4 +120,5 @@ bool debounce_controller_update( bool debounce_controller_get_state(const debounce_controller_t* controller) { return controller->stable_state; -} \ No newline at end of file +} +//----------------------------------------------------------------------------// \ No newline at end of file From b0fc4287230638797642e5541cf5adfee27f96f3 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Wed, 25 Mar 2026 14:15:38 -0400 Subject: [PATCH 39/55] Improving CAN status output Now directly sends the mode + rc_mode matches the controller's polarity: - ID = `0x101` - **Status update** (TX) - Byte 0: state machine mode + rc mode - Bits0-3 = state machine mode (see logic.h::logic_mode_t) - Bit4 = RC mode (0 = rc mode, 1 = autonomous mode) - Bits5-7 = reserved - Byte 1-2: throttle PWM (uint16_t, little endian), the actual PWM value being sent to the ESC for throttle (1000-2000) - Byte 3-4: steering PWM (uint16_t, little endian), the actual PWM value being sent to the servo for steering (1000-2000) - Byte 5-7: reserved / future use --- AutonomousDistroBoard/Core/Inc/can.h | 22 ++++++++++------------ AutonomousDistroBoard/Core/Src/can.c | 3 ++- AutonomousDistroBoard/Core/Src/logic.c | 5 ++--- README.md | 13 ++++++------- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/can.h b/AutonomousDistroBoard/Core/Inc/can.h index c9f49de..0058133 100644 --- a/AutonomousDistroBoard/Core/Inc/can.h +++ b/AutonomousDistroBoard/Core/Inc/can.h @@ -24,21 +24,19 @@ typedef struct { // - ID = `0x101` - **Status update** (TX) -// - Byte 0: precharge + contactor + rc mode (bit flags) -// - Bit0 = precharge -// - Bit1 = contactor -// - Bit2 = RC mode -// - Bits3-7 = 0 -// - Byte 1-2: throttle PWM (uint16_t, little endian) -// - Byte 3-4: steering PWM (uint16_t, little endian) +// - Byte 0: state machine mode + rc mode +// - Bits0-3 = state machine mode (see logic.h::logic_mode_t) +// - Bit4 = RC mode (0 = rc mode, 1 = autonomous mode) +// - Bits5-7 = reserved +// - Byte 1-2: throttle PWM (uint16_t, little endian), the actual PWM value being sent to the ESC for throttle (1000-2000) +// - Byte 3-4: steering PWM (uint16_t, little endian), the actual PWM value being sent to the servo for steering (1000-2000) // - Byte 5-7: reserved / future use #define CAN_ID_STATUS (0x101) typedef struct { - bool precharge; - bool contactor; - bool rc_mode; - uint16_t throttle_pwm; - uint16_t steering_pwm; + uint8_t mode; // logic_mode_t + bool rc_mode; // false = rc mode, true = autonomous mode + uint16_t throttle_pwm; // actual PWM value being sent to the ESC for throttle (1000-2000) + uint16_t steering_pwm; // actual PWM value being sent to the servo for steering (1000-2000) } can_status_msg_t; diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c index f2cd1e4..fa0bd9d 100644 --- a/AutonomousDistroBoard/Core/Src/can.c +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -1,4 +1,5 @@ #include "can.h" +#include #include "stm32f4xx_hal.h" @@ -40,7 +41,7 @@ void send_can_status(const can_status_msg_t* status, CAN_HandleTypeDef* hcan) { tx_header.IDE = CAN_ID_STD; tx_header.DLC = 8; - tx_data[0] = (status->precharge << 0) | (status->contactor << 1) | (status->rc_mode << 2); + tx_data[0] = (status->mode & 0x0F) | ((uint8_t)status->rc_mode << 4); tx_data[1] = status->throttle_pwm & 0xFF; tx_data[2] = (status->throttle_pwm >> 8) & 0xFF; tx_data[3] = status->steering_pwm & 0xFF; diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 4e04b2b..791b4c4 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -191,9 +191,8 @@ void logic_run( // Periodically send CAN status messages if (util_has_elapsed(now, state->last_can_tx_time, CAN_TX_PERIOD)) { can_status_msg_t status = { - .precharge = (state->mode == LOGIC_MODE_PRECHARGING), - .contactor = (state->mode == LOGIC_MODE_RUNNING), - .rc_mode = !debounce_controller_get_state(&state->mode_debounce), // if mode_debounce is low, we are in RC mode + .mode = (uint8_t)state->mode, + .rc_mode = debounce_controller_get_state(&state->mode_debounce), // if mode_debounce is low, we are in RC mode .throttle_pwm = output_throttle_pwm, .steering_pwm = output_steering_pwm }; diff --git a/README.md b/README.md index eb2f8ea..c03960b 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,12 @@ Autonomous Project electrical stack code - Byte 2-3: steering (uint16_t, little endian), 0-1000, where 500 = straight, 0 = full left, 1000 = full right - Byte 4-7: reserved / future use - ID = `0x101` - **Status update** (TX) - - Byte 0: precharge + contactor + rc mode (bit flags) - - Bit0 = precharge - - Bit1 = contactor - - Bit2 = RC mode - - Bits3-7 = 0 - - Byte 1-2: throttle PWM (uint16_t, little endian) - - Byte 3-4: steering PWM (uint16_t, little endian) + - Byte 0: state machine mode + rc mode + - Bits0-3 = state machine mode (see logic.h::logic_mode_t) + - Bit4 = RC mode (0 = rc mode, 1 = autonomous mode) + - Bits5-7 = reserved + - Byte 1-2: throttle PWM (uint16_t, little endian), the actual PWM value being sent to the ESC for throttle (1000-2000) + - Byte 3-4: steering PWM (uint16_t, little endian), the actual PWM value being sent to the servo for steering (1000-2000) - Byte 5-7: reserved / future use ## Autonomous Nucelo From b1448901cd7e67820800656d67641fbfb4bd5cb6 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Wed, 25 Mar 2026 14:48:08 -0400 Subject: [PATCH 40/55] Trying to handle CAN disconnect --- AutonomousDistroBoard/Core/Inc/logic.h | 5 ++-- AutonomousDistroBoard/Core/Src/logic.c | 35 ++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 76205ca..43fb5f4 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -31,7 +31,7 @@ #define MODE_ACCUMULATING_DEBOUNCE_MS (50) // ms, when the rising MODE is debouncing/accumulating, require the MODE channel to be below the threshold for at least this long before resetting the debounce timer #define CAN_TX_PERIOD (10) // ms -// #define CAN_RX_TIMEOUT (50) // ms +#define CAN_RX_TIMEOUT (50) // ms #define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost @@ -48,7 +48,8 @@ typedef enum { LOGIC_MODE_CONTACTOR_CLOSING, LOGIC_MODE_RUNNING, LOGIC_MODE_ESTOPPED, - LOGIC_MODE_RC_DISCONNECTED + LOGIC_MODE_RC_DISCONNECTED, + LOGIC_MODE_CAN_DISCONNECTED } logic_mode_t; diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 791b4c4..1b18081 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -137,8 +137,17 @@ void logic_run( // In autonomous mode, ignore iBUS throttle and steering and only use CAN commands if (autonomous_mode) { - output_throttle_pwm = state->can_current_throttle_pwm; - output_steering_pwm = state->can_current_steering_pwm; + if (!util_has_elapsed(now, state->last_control_timestamp, CAN_RX_TIMEOUT)) { + // If we have received a control message recently, consider the CAN connection to be + // healthy and use CAN commands for throttle and steering + output_throttle_pwm = state->can_current_throttle_pwm; + output_steering_pwm = state->can_current_steering_pwm; + } else { + // If we have not received a control message recently, consider the CAN connection to + // be lost and switch to CAN_DISCONNECTED mode + state->mode = LOGIC_MODE_CAN_DISCONNECTED; + output_throttle_pwm = THROTTLE_PWM_LOW; // stop the car if CAN connection is lost + } } // In RC mode, ignore CAN commands and only use iBUS throttle and steering else { @@ -178,6 +187,28 @@ void logic_run( } break; } + case LOGIC_MODE_CAN_DISCONNECTED: { + // CAN disconnect in autonomous mode = stop the kart + // STOP: precharge off, contactor off + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + + uint16_t mode_channel_value = state->ibus.channels[IBUS_CHANNEL_MODE]; + bool mode_raw_high = mode_channel_value >= MODE_PWM_THRESHOLD; + debounce_controller_update(&state->mode_debounce, mode_raw_high, now); + + bool autonomous_mode = debounce_controller_get_state(&state->mode_debounce); + + if ((autonomous_mode && !util_has_elapsed(now, state->last_control_timestamp, CAN_RX_TIMEOUT)) + || (!autonomous_mode && ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT))) { + // If we are trying to be autonomous and receive a valid CAN control message, + // or if we are in RC mode and receive a valid iBUS frame, + // consider the connection to be restored and restart precharge sequence + state->mode = LOGIC_MODE_STARTING; + state->start_time = now; + } + break; + } } // Clamp the output PWM values to their valid ranges just in case From ba37c4fff6af88989248bf2194efd8af2768e07d Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Wed, 25 Mar 2026 14:57:09 -0400 Subject: [PATCH 41/55] Blink LED based on mode --- AutonomousDistroBoard/Core/Inc/logic.h | 11 ++++++++++ AutonomousDistroBoard/Core/Src/logic.c | 29 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 43fb5f4..a43a2fa 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -35,6 +35,15 @@ #define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost +#define LED_STARTING_PERIOD (20) // ms +#define LED_PRECHARGING_PERIOD (100) // ms +#define LED_CONTACTOR_CLOSING_PERIOD (20) // ms +#define LED_RUNNING_RC_PERIOD (1000) // ms +#define LED_RUNNING_AUTONOMOUS_PERIOD (500) // ms +#define LED_ESTOPPED_PERIOD (0) // solid on +#define LED_RC_DISCONNECTED_PERIOD (0) // solid on +#define LED_CAN_DISCONNECTED_PERIOD (0) // solid on + #define THROTTLE_PWM_LOW (1000) #define THROTTLE_PWM_HIGH (2000) #define STEERING_PWM_LOW (1000) @@ -69,6 +78,8 @@ typedef struct { volatile uint16_t can_current_throttle_pwm; // 1000-2000, updated by CAN RX callback volatile uint16_t can_current_steering_pwm; // 1000-2000, updated by CAN RX callback volatile uint32_t last_control_timestamp; // HAL_GetTick() timestamp of last received control message + + uint32_t led_blink_timestamp; // HAL_GetTick() timestamp of last LED toggle } logic_state_t; void logic_init(logic_state_t* state); diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 1b18081..6788b77 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -230,4 +230,33 @@ void logic_run( send_can_status(&status, hcan); state->last_can_tx_time = now; } + + // Blink LED + uint16_t led_period = 0; + switch (state->mode) { + case LOGIC_MODE_STARTING: led_period = LED_STARTING_PERIOD; break; + case LOGIC_MODE_PRECHARGING: led_period = LED_PRECHARGING_PERIOD; break; + case LOGIC_MODE_CONTACTOR_CLOSING: led_period = LED_CONTACTOR_CLOSING_PERIOD; break; + case LOGIC_MODE_RUNNING: { + bool autonomous_mode = debounce_controller_get_state(&state->mode_debounce); + if (autonomous_mode) { + led_period = LED_RUNNING_AUTONOMOUS_PERIOD; + } else { + led_period = LED_RUNNING_RC_PERIOD; + } + break; + } + case LOGIC_MODE_ESTOPPED: led_period = LED_ESTOPPED_PERIOD; break; + case LOGIC_MODE_RC_DISCONNECTED: led_period = LED_RC_DISCONNECTED_PERIOD; break; + case LOGIC_MODE_CAN_DISCONNECTED: led_period = LED_CAN_DISCONNECTED_PERIOD; break; + } + if (led_period == 0) { + // Solid on + HAL_GPIO_WritePin(LED_OUT_GPIO_Port, LED_OUT_Pin, GPIO_PIN_SET); + } else { + if (util_has_elapsed(now, state->led_blink_timestamp, led_period)) { + HAL_GPIO_TogglePin(LED_OUT_GPIO_Port, LED_OUT_Pin); + state->led_blink_timestamp = now; + } + } } \ No newline at end of file From 83c5e337b5b25410ff5040ecd4e1b63b35688ab9 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 21:06:35 -0400 Subject: [PATCH 42/55] Logic changes (Shriya/Jack feedback) - On contactor lifted modes: throttle pwm is disabled - On un-estopping, there is no delay - Better pre-state machine logic flow - Improved updating the RC mode debounce controller - Output PWMs live in state instead of in loop - Estop modes set steering straight --- AutonomousDistroBoard/Core/Inc/logic.h | 18 +++- AutonomousDistroBoard/Core/Src/logic.c | 129 ++++++++++++++++--------- 2 files changed, 102 insertions(+), 45 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index a43a2fa..d466e4e 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -48,6 +48,15 @@ #define THROTTLE_PWM_HIGH (2000) #define STEERING_PWM_LOW (1000) #define STEERING_PWM_HIGH (2000) +#define STEERING_PWM_CENTER ((STEERING_PWM_LOW + STEERING_PWM_HIGH) / 2) + +#define THROTTLE_PWM_GPIO_Port (GPIOB) +#define THROTTLE_PWM_Pin (GPIO_PIN_9) +#define THROTTLE_PWM_AF (GPIO_AF2_TIM4) + +#define STEERING_PWM_GPIO_Port (GPIOE) +#define STEERING_PWM_Pin (GPIO_PIN_9) +#define STEERING_PWM_AF (GPIO_AF3_TIM11) #define RC_MODE_THROTTLE_DIVISOR (3) // divide the iBUS throttle PWM by this much @@ -71,8 +80,6 @@ typedef struct { uint32_t start_time; // HAL_GetTick() timestamp of when the precharge sequence started debounce_controller_t estop_debounce; // debounce controller for the remote estop channel - option_u32_t estop_triggered_time; // HAL_GetTick() timestamp of when the remote estop was triggered or none if it is not currently triggered - debounce_controller_t mode_debounce; // low = RC mode, high = autonomous mode volatile uint16_t can_current_throttle_pwm; // 1000-2000, updated by CAN RX callback @@ -80,6 +87,10 @@ typedef struct { volatile uint32_t last_control_timestamp; // HAL_GetTick() timestamp of last received control message uint32_t led_blink_timestamp; // HAL_GetTick() timestamp of last LED toggle + + uint16_t output_throttle_pwm; // 1000-2000, the throttle PWM value that we will output (either from iBUS or CAN depending on mode) + uint16_t output_steering_pwm; // 1000-2000, the steering PWM value that we will output (either from iBUS or CAN depending on mode) + bool throttle_enabled; // whether the PWM channel for the throttle is enabled vs in input/high-impedance mode } logic_state_t; void logic_init(logic_state_t* state); @@ -99,6 +110,9 @@ void logic_run( // doesn't have a way to pass user data void logic_handle_control(const can_control_msg_t* cmd); +void pwm_disable(TIM_HandleTypeDef* htim, GPIO_TypeDef* gpio_port, uint32_t gpio_pin); +void pwm_enable(TIM_HandleTypeDef* htim, GPIO_TypeDef* gpio_port, uint32_t gpio_pin, uint32_t alternate_function); + diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 6788b77..ca3c25c 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -14,7 +14,6 @@ static logic_state_t* g_logic_state_ptr = NULL; void logic_init(logic_state_t* state) { state->mode = LOGIC_MODE_STARTING; state->start_time = HAL_GetTick(); - state->estop_triggered_time = option_u32_none(); // not currently triggered debounce_controller_init( &state->estop_debounce, @@ -38,6 +37,10 @@ void logic_init(logic_state_t* state) { state->can_current_steering_pwm = (STEERING_PWM_LOW + STEERING_PWM_HIGH) / 2; state->last_control_timestamp = 0; + state->output_throttle_pwm = THROTTLE_PWM_LOW; + state->output_steering_pwm = (STEERING_PWM_LOW + STEERING_PWM_HIGH) / 2; + state->throttle_enabled = true; // HAL init sets up the PWM + g_logic_state_ptr = state; } @@ -66,25 +69,25 @@ void logic_run( // All states: Check for RC connection timeout if (!ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { state->mode = LOGIC_MODE_RC_DISCONNECTED; - } - - // All states: Check for remote ESTOP trigger - if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { + } else { + // All states: update RC debounce controllers uint16_t estop_channel_value = state->ibus.channels[IBUS_CHANNEL_ESTOP]; bool estop_raw_high = estop_channel_value >= ESTOP_PWM_THRESHOLD; - bool estop_debounced_high = debounce_controller_update(&state->estop_debounce, estop_raw_high, now); + debounce_controller_update(&state->estop_debounce, estop_raw_high, now); + + uint16_t mode_channel_value = state->ibus.channels[IBUS_CHANNEL_MODE]; + bool mode_raw_high = mode_channel_value >= MODE_PWM_THRESHOLD; + debounce_controller_update(&state->mode_debounce, mode_raw_high, now); + + // All states: check remote estop + bool estop_debounced_high = debounce_controller_get_state(&state->estop_debounce); if (estop_debounced_high) { - state->estop_triggered_time = option_u32_some(now); state->mode = LOGIC_MODE_ESTOPPED; - // Note: if it was high and remains high, we want to continue to update estop_triggered_time - // so the ESTOP_TRIGGERED_DELAY doesn't start until the remote estop goes low again + // Note: if it was high and remains high, we want to continue to force + // state->mode = LOGIC_MODE_ESTOPPED just as a safety measure } } - uint16_t output_throttle_pwm = 0; - uint16_t output_steering_pwm = 0; - // TODO: handle for when not in running mode - // Precharge/contactor state machine logic switch (state->mode) { case LOGIC_MODE_STARTING: { @@ -126,13 +129,6 @@ void logic_run( // Normal operation! - // MODE switching logic - // Note: don't need to check for iBUS connection here because if we lost connection - // we would have already switched to RC_DISCONNECTED mode - uint16_t mode_channel_value = state->ibus.channels[IBUS_CHANNEL_MODE]; - bool mode_raw_high = mode_channel_value >= MODE_PWM_THRESHOLD; - debounce_controller_update(&state->mode_debounce, mode_raw_high, now); - bool autonomous_mode = debounce_controller_get_state(&state->mode_debounce); // In autonomous mode, ignore iBUS throttle and steering and only use CAN commands @@ -140,13 +136,13 @@ void logic_run( if (!util_has_elapsed(now, state->last_control_timestamp, CAN_RX_TIMEOUT)) { // If we have received a control message recently, consider the CAN connection to be // healthy and use CAN commands for throttle and steering - output_throttle_pwm = state->can_current_throttle_pwm; - output_steering_pwm = state->can_current_steering_pwm; + state->output_throttle_pwm = state->can_current_throttle_pwm; + state->output_steering_pwm = state->can_current_steering_pwm; } else { // If we have not received a control message recently, consider the CAN connection to // be lost and switch to CAN_DISCONNECTED mode state->mode = LOGIC_MODE_CAN_DISCONNECTED; - output_throttle_pwm = THROTTLE_PWM_LOW; // stop the car if CAN connection is lost + state->output_throttle_pwm = THROTTLE_PWM_LOW; // stop the car if CAN connection is lost } } // In RC mode, ignore CAN commands and only use iBUS throttle and steering @@ -154,31 +150,33 @@ void logic_run( uint16_t ibus_throttle_pwm = state->ibus.channels[IBUS_CHANNEL_THROTTLE]; uint16_t ibus_steering_pwm = state->ibus.channels[IBUS_CHANNEL_STEERING]; - output_throttle_pwm = THROTTLE_PWM_LOW + (ibus_throttle_pwm - THROTTLE_PWM_LOW) / RC_MODE_THROTTLE_DIVISOR; - output_steering_pwm = ibus_steering_pwm; + state->output_throttle_pwm = THROTTLE_PWM_LOW + (ibus_throttle_pwm - THROTTLE_PWM_LOW) / RC_MODE_THROTTLE_DIVISOR; + state->output_steering_pwm = ibus_steering_pwm; } break; } //--------------------------------------------------------------------------// case LOGIC_MODE_ESTOPPED: { - // STOP: precharge off, contactor off + // STOP: precharge off, contactor off, throttle low, steering straight HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + state->output_throttle_pwm = THROTTLE_PWM_LOW; + state->output_steering_pwm = STEERING_PWM_CENTER; - if (option_u32_is_some(state->estop_triggered_time) - && util_has_elapsed(now, option_u32_unwrap(state->estop_triggered_time), ESTOP_TRIGGERED_DELAY)) { - // After waiting for ESTOP_TRIGGERED_DELAY, restart precharge sequence - state->estop_triggered_time = option_u32_none(); // reset estop triggered time + bool estop_debounced_high = debounce_controller_get_state(&state->estop_debounce); + if (!estop_debounced_high) { state->mode = LOGIC_MODE_STARTING; state->start_time = now; } break; } case LOGIC_MODE_RC_DISCONNECTED: { - // STOP: precharge off, contactor off + // STOP: precharge off, contactor off, throttle low, steering straight HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + state->output_throttle_pwm = THROTTLE_PWM_LOW; + state->output_steering_pwm = STEERING_PWM_CENTER; if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { // If we receive a valid iBUS frame, consider the RC connection to be restored and restart precharge sequence @@ -189,21 +187,22 @@ void logic_run( } case LOGIC_MODE_CAN_DISCONNECTED: { // CAN disconnect in autonomous mode = stop the kart - // STOP: precharge off, contactor off + // STOP: precharge off, contactor off, throttle low, steering straigh HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + state->output_throttle_pwm = THROTTLE_PWM_LOW; + state->output_steering_pwm = STEERING_PWM_CENTER; uint16_t mode_channel_value = state->ibus.channels[IBUS_CHANNEL_MODE]; bool mode_raw_high = mode_channel_value >= MODE_PWM_THRESHOLD; debounce_controller_update(&state->mode_debounce, mode_raw_high, now); bool autonomous_mode = debounce_controller_get_state(&state->mode_debounce); + bool can_connection_ok = !util_has_elapsed(now, state->last_control_timestamp, CAN_RX_TIMEOUT); + bool ibus_connection_ok = ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT); - if ((autonomous_mode && !util_has_elapsed(now, state->last_control_timestamp, CAN_RX_TIMEOUT)) - || (!autonomous_mode && ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT))) { - // If we are trying to be autonomous and receive a valid CAN control message, - // or if we are in RC mode and receive a valid iBUS frame, - // consider the connection to be restored and restart precharge sequence + if ((autonomous_mode && can_connection_ok) + || (!autonomous_mode && ibus_connection_ok)) { state->mode = LOGIC_MODE_STARTING; state->start_time = now; } @@ -212,20 +211,35 @@ void logic_run( } // Clamp the output PWM values to their valid ranges just in case - output_throttle_pwm = clamp_u16(output_throttle_pwm, THROTTLE_PWM_LOW, THROTTLE_PWM_HIGH); - output_steering_pwm = clamp_u16(output_steering_pwm, STEERING_PWM_LOW, STEERING_PWM_HIGH); + state->output_throttle_pwm = clamp_u16(state->output_throttle_pwm, THROTTLE_PWM_LOW, THROTTLE_PWM_HIGH); + state->output_steering_pwm = clamp_u16(state->output_steering_pwm, STEERING_PWM_LOW, STEERING_PWM_HIGH); // Output the PWM values - __HAL_TIM_SET_COMPARE(throttle_htim, TIM_CHANNEL_1, output_throttle_pwm); - __HAL_TIM_SET_COMPARE(steering_htim, TIM_CHANNEL_1, output_steering_pwm); + bool should_throttle = state->mode == LOGIC_MODE_RUNNING; + if (should_throttle) { + if (!state->throttle_enabled) { + pwm_enable(throttle_htim, THROTTLE_PWM_GPIO_Port, THROTTLE_PWM_Pin, THROTTLE_PWM_AF); + state->throttle_enabled = true; + } + __HAL_TIM_SET_COMPARE(throttle_htim, TIM_CHANNEL_1, state->output_throttle_pwm); + } else { + if (state->throttle_enabled) { + __HAL_TIM_SET_COMPARE(throttle_htim, TIM_CHANNEL_1, state->output_throttle_pwm); + pwm_disable(throttle_htim, THROTTLE_PWM_GPIO_Port, THROTTLE_PWM_Pin); + state->throttle_enabled = false; + } + } + // All modes set the intended steering posistion + // And steering is powered from Distro/Control Board, not through contactor + __HAL_TIM_SET_COMPARE(steering_htim, TIM_CHANNEL_1, state->output_steering_pwm); // Periodically send CAN status messages if (util_has_elapsed(now, state->last_can_tx_time, CAN_TX_PERIOD)) { can_status_msg_t status = { .mode = (uint8_t)state->mode, .rc_mode = debounce_controller_get_state(&state->mode_debounce), // if mode_debounce is low, we are in RC mode - .throttle_pwm = output_throttle_pwm, - .steering_pwm = output_steering_pwm + .throttle_pwm = state->output_throttle_pwm, + .steering_pwm = state->output_steering_pwm }; send_can_status(&status, hcan); state->last_can_tx_time = now; @@ -259,4 +273,33 @@ void logic_run( state->led_blink_timestamp = now; } } +} + + +void pwm_disable(TIM_HandleTypeDef* htim, GPIO_TypeDef* gpio_port, uint32_t gpio_pin) { + // Stop PWM generation + HAL_TIM_PWM_Stop(htim, TIM_CHANNEL_1); + + // Put pin into Hi-Z (input mode) + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = gpio_pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + + HAL_GPIO_Init(gpio_port, &GPIO_InitStruct); +} + +void pwm_enable(TIM_HandleTypeDef* htim, GPIO_TypeDef* gpio_port, uint32_t gpio_pin, uint32_t alternate_function) { + // Put pin into alternate function mode for PWM output + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = gpio_pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = alternate_function; + + HAL_GPIO_Init(gpio_port, &GPIO_InitStruct); + + // Start PWM generation + HAL_TIM_PWM_Start(htim, TIM_CHANNEL_1); } \ No newline at end of file From 14defb7f01605f6c7296db2e01298beb2b45401d Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 21:23:06 -0400 Subject: [PATCH 43/55] First set of copilot fixes spelling, unused vars, estop duration, CAN min bytes --- AutonomousDistroBoard/Core/Inc/can.h | 1 + AutonomousDistroBoard/Core/Inc/logic.h | 3 +-- AutonomousDistroBoard/Core/Src/can.c | 9 +++------ AutonomousDistroBoard/Core/Src/logic.c | 4 ++-- README.md | 2 +- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/can.h b/AutonomousDistroBoard/Core/Inc/can.h index 0058133..4fc308c 100644 --- a/AutonomousDistroBoard/Core/Inc/can.h +++ b/AutonomousDistroBoard/Core/Inc/can.h @@ -15,6 +15,7 @@ // - Byte 2-3: steering (uint16_t, little endian), 0-1000, where 1000 = full right, 500 = center, 0 = full left // - Byte 4-7: reserved / future use #define CAN_ID_CONTROL (0x100) +#define CAN_CONTROL_MIN_BYTES (4) #define CAN_THROTTLE_MAX (1000) #define CAN_STEERING_MAX (1000) typedef struct { diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index d466e4e..6634e24 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -14,7 +14,6 @@ #define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge #define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor #define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed -#define ESTOP_TRIGGERED_DELAY (3000) // ms, after remote estop is triggered, how long to wait before restarting the precharge sequence #define IBUS_CHANNEL_THROTTLE (0) // 1000 = full stop, 2000 = full throttle forward #define IBUS_CHANNEL_STEERING (1) // 1000 = full left, 1500 = center, 2000 = full right @@ -24,7 +23,7 @@ #define ESTOP_PWM_THRESHOLD (1500) // if the ESTOP channel goes above this value, consider the remote estop to be triggered #define ESTOP_RISING_DEBOUNCE (300) // ms, require the ESTOP channel to be above the threshold for at least this long before considering the remote estop to be triggered #define ESTOP_ACCUMULATING_DEBOUNCE (30) // ms, when the rising ESTOP is debouncing/accumulating, require the ESTOP channel to be below the threshold for at least this long before resetting the debounce timer -#define ESTOP_FALLING_DEBOUNCE (50) // ms, require the ESTOP channel to be below the threshold for at least this long before considering the remote estop to be no longer triggered +#define ESTOP_FALLING_DEBOUNCE (300) // ms, require the ESTOP channel to be below the threshold for at least this long before considering the remote estop to be no longer triggered #define MODE_PWM_THRESHOLD (1500) // if the MODE channel is above this value, consider it to be in autonomous mode, otherwise RC mode #define MODE_DEBOUNCE_MS (500) // ms, require the MODE channel to be consistently above or below the threshold for at least this long before switching modes diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c index fa0bd9d..cb161c4 100644 --- a/AutonomousDistroBoard/Core/Src/can.c +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -7,16 +7,13 @@ #include "util.h" -void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) -{ - if (hcan->Instance == CAN_BUS) - { +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { + if (hcan->Instance == CAN_BUS) { CAN_RxHeaderTypeDef rx_header; uint8_t rx_data[8]; HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data); - if (rx_header.StdId == CAN_ID_CONTROL) - { + if ((rx_header.StdId == CAN_ID_CONTROL) && (rx_header.DLC >= CAN_CONTROL_MIN_BYTES)) { can_control_msg_t cmd = parse_can_control(rx_data); logic_handle_control(&cmd); } diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index ca3c25c..e45e062 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -187,7 +187,7 @@ void logic_run( } case LOGIC_MODE_CAN_DISCONNECTED: { // CAN disconnect in autonomous mode = stop the kart - // STOP: precharge off, contactor off, throttle low, steering straigh + // STOP: precharge off, contactor off, throttle low, steering straight HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); state->output_throttle_pwm = THROTTLE_PWM_LOW; @@ -229,7 +229,7 @@ void logic_run( state->throttle_enabled = false; } } - // All modes set the intended steering posistion + // All modes set the intended steering position // And steering is powered from Distro/Control Board, not through contactor __HAL_TIM_SET_COMPARE(steering_htim, TIM_CHANNEL_1, state->output_steering_pwm); diff --git a/README.md b/README.md index c03960b..b0df3ed 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Autonomous Project electrical stack code - Byte 3-4: steering PWM (uint16_t, little endian), the actual PWM value being sent to the servo for steering (1000-2000) - Byte 5-7: reserved / future use -## Autonomous Nucelo +## Autonomous Nucleo ### Pin Definitions From fc898f47cce965d483ef0ed54b04153f2d25df8c Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 21:23:51 -0400 Subject: [PATCH 44/55] increasing LED periods --- AutonomousDistroBoard/Core/Inc/logic.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index 6634e24..e140759 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -34,9 +34,10 @@ #define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost -#define LED_STARTING_PERIOD (20) // ms -#define LED_PRECHARGING_PERIOD (100) // ms -#define LED_CONTACTOR_CLOSING_PERIOD (20) // ms +// Really these are half periods b/c it is the rate at which the LED toggles +#define LED_STARTING_PERIOD (40) // ms +#define LED_PRECHARGING_PERIOD (200) // ms +#define LED_CONTACTOR_CLOSING_PERIOD (40) // ms #define LED_RUNNING_RC_PERIOD (1000) // ms #define LED_RUNNING_AUTONOMOUS_PERIOD (500) // ms #define LED_ESTOPPED_PERIOD (0) // solid on From ef86571e68e048ce0a9ac9a7bae93e53e11a6edc Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 21:33:54 -0400 Subject: [PATCH 45/55] fixing MA circular buffer --- AutonomousDistroBoard/Core/Src/ibus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c index 05fe197..a252b4c 100644 --- a/AutonomousDistroBoard/Core/Src/ibus.c +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -16,7 +16,8 @@ bool ibus_is_connected(const ibus_t* ibus, uint32_t now, uint32_t timeout_ms) { void ibus_process(ibus_t* ibus, UART_HandleTypeDef* ibus_huart) { - uint16_t dma_pos = IBUS_DMA_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(ibus_huart->hdmarx); + uint16_t dma_remaining = __HAL_DMA_GET_COUNTER(ibus_huart->hdmarx); + uint16_t dma_pos = (IBUS_DMA_BUFFER_SIZE - dma_remaining) % IBUS_DMA_BUFFER_SIZE; while (ibus->dma_last_pos != dma_pos) { uint8_t byte = ibus->dma_buffer[ibus->dma_last_pos++]; From 3fb648dc279825ff285140db2b1e9d63dde2d7df Mon Sep 17 00:00:00 2001 From: Millan Kumar <48894200+LelsersLasers@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:06:24 -0700 Subject: [PATCH 46/55] RC-mode throttle computation can underflow unflow fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- AutonomousDistroBoard/Core/Src/logic.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index e45e062..9d52557 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -150,7 +150,11 @@ void logic_run( uint16_t ibus_throttle_pwm = state->ibus.channels[IBUS_CHANNEL_THROTTLE]; uint16_t ibus_steering_pwm = state->ibus.channels[IBUS_CHANNEL_STEERING]; - state->output_throttle_pwm = THROTTLE_PWM_LOW + (ibus_throttle_pwm - THROTTLE_PWM_LOW) / RC_MODE_THROTTLE_DIVISOR; + int32_t throttle_delta = (int32_t)ibus_throttle_pwm - (int32_t)THROTTLE_PWM_LOW; + if (throttle_delta < 0) { + throttle_delta = 0; + } + state->output_throttle_pwm = THROTTLE_PWM_LOW + (uint16_t)(throttle_delta / RC_MODE_THROTTLE_DIVISOR); state->output_steering_pwm = ibus_steering_pwm; } From 441e27594e8a57fc0ca49defcc54c27fb96244ec Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 23:30:21 -0400 Subject: [PATCH 47/55] better CAN check --- AutonomousDistroBoard/Core/Src/can.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c index cb161c4..201b843 100644 --- a/AutonomousDistroBoard/Core/Src/can.c +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -13,7 +13,15 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { uint8_t rx_data[8]; HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data); - if ((rx_header.StdId == CAN_ID_CONTROL) && (rx_header.DLC >= CAN_CONTROL_MIN_BYTES)) { + if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) != HAL_OK) { + return; + } + if ((rx_header.IDE == CAN_ID_STD) && + (rx_header.RTR == CAN_RTR_DATA) && + (rx_header.StdId == CAN_ID_CONTROL) && + (rx_header.DLC >= CAN_CONTROL_MIN_BYTES)) + { + can_control_msg_t cmd = parse_can_control(rx_data); logic_handle_control(&cmd); } From 798f04bae0372da0ea7be62cd91f06b4deb0c03c Mon Sep 17 00:00:00 2001 From: Millan Kumar <48894200+LelsersLasers@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:32:19 -0700 Subject: [PATCH 48/55] map_u16 underflow fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- AutonomousDistroBoard/Core/Src/util.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/AutonomousDistroBoard/Core/Src/util.c b/AutonomousDistroBoard/Core/Src/util.c index 7a3db49..3421c51 100644 --- a/AutonomousDistroBoard/Core/Src/util.c +++ b/AutonomousDistroBoard/Core/Src/util.c @@ -22,8 +22,21 @@ uint16_t map_u16(uint16_t value, uint16_t in_min, uint16_t in_max, uint16_t out_ // Avoid division by zero; return the midpoint of the output range return (out_min + out_max) / 2; } - uint32_t scaled = (uint32_t)(value - in_min) * (out_max - out_min); - return (uint16_t)(scaled / (in_max - in_min) + out_min); + + // Saturate value to input range to avoid underflow/overflow in arithmetic + if (value <= in_min) { + return out_min; + } + if (value >= in_max) { + return out_max; + } + + uint32_t range_in = (uint32_t)in_max - (uint32_t)in_min; + uint32_t range_out = (uint32_t)out_max - (uint32_t)out_min; + uint32_t num = (uint32_t)value - (uint32_t)in_min; + uint32_t scaled = num * range_out; + + return (uint16_t)(scaled / range_in + out_min); } //----------------------------------------------------------------------------// From c17adeb4febee182e77340c7f1b7e6fb612ce4ba Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 23:38:49 -0400 Subject: [PATCH 49/55] last_frame_time only updated when checksum matches --- AutonomousDistroBoard/Core/Src/ibus.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AutonomousDistroBoard/Core/Src/ibus.c b/AutonomousDistroBoard/Core/Src/ibus.c index a252b4c..26e59e4 100644 --- a/AutonomousDistroBoard/Core/Src/ibus.c +++ b/AutonomousDistroBoard/Core/Src/ibus.c @@ -56,9 +56,8 @@ void ibus_parse_byte(ibus_t* ibus, uint8_t byte) { for (int i = 0; i < IBUS_CHANNEL_COUNT; i++) { ibus->channels[i] = ibus->frame[2 + i*2] | (ibus->frame[3 + i*2] << 8); } + ibus->last_frame_time = HAL_GetTick(); } - - ibus->last_frame_time = HAL_GetTick(); } } } \ No newline at end of file From f713372375de244d583035a1c7a97ba81ac65ac2 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Thu, 26 Mar 2026 23:40:55 -0400 Subject: [PATCH 50/55] steering straight on can disconnect --- AutonomousDistroBoard/Core/Src/logic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 9d52557..961af56 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -142,7 +142,8 @@ void logic_run( // If we have not received a control message recently, consider the CAN connection to // be lost and switch to CAN_DISCONNECTED mode state->mode = LOGIC_MODE_CAN_DISCONNECTED; - state->output_throttle_pwm = THROTTLE_PWM_LOW; // stop the car if CAN connection is lost + state->output_throttle_pwm = THROTTLE_PWM_LOW; + state->output_steering_pwm = STEERING_PWM_CENTER; } } // In RC mode, ignore CAN commands and only use iBUS throttle and steering From 7dc2798e65fa9a21b52e7ae44a36b5547d9a717c Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Fri, 27 Mar 2026 11:49:25 -0400 Subject: [PATCH 51/55] Accidentally called HAL_CAN_GetRxMessage twice --- AutonomousDistroBoard/Core/Src/can.c | 1 - 1 file changed, 1 deletion(-) diff --git a/AutonomousDistroBoard/Core/Src/can.c b/AutonomousDistroBoard/Core/Src/can.c index 201b843..21053cc 100644 --- a/AutonomousDistroBoard/Core/Src/can.c +++ b/AutonomousDistroBoard/Core/Src/can.c @@ -11,7 +11,6 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { if (hcan->Instance == CAN_BUS) { CAN_RxHeaderTypeDef rx_header; uint8_t rx_data[8]; - HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data); if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) != HAL_OK) { return; From db3c864808283baa5ce562022ef714a0979b81e8 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Fri, 27 Mar 2026 11:50:19 -0400 Subject: [PATCH 52/55] Actually starting the CAN peripheral Explicit CAN_S low Setting CAN filter (accept all) Starting CAN Starting FIFO0 interrupt message --- AutonomousDistroBoard/Core/Src/main.c | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/AutonomousDistroBoard/Core/Src/main.c b/AutonomousDistroBoard/Core/Src/main.c index 6fbb294..3ca4a32 100644 --- a/AutonomousDistroBoard/Core/Src/main.c +++ b/AutonomousDistroBoard/Core/Src/main.c @@ -110,12 +110,43 @@ int main(void) MX_USART3_UART_Init(); MX_USB_OTG_FS_PCD_Init(); /* USER CODE BEGIN 2 */ + // Initialize logic state logic_init(&g_logic_state); + + // CAN + // CAN_S must be low for CAN to operate + HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_RESET); + + // Filter + CAN_FilterTypeDef filter = {0}; + filter.FilterBank = 14; // CAN2 uses banks 14–27 on F4 + filter.FilterMode = CAN_FILTERMODE_IDMASK; + filter.FilterScale = CAN_FILTERSCALE_32BIT; + // Accept all IDs (for debugging) + filter.FilterIdHigh = 0x0000; + filter.FilterIdLow = 0x0000; + filter.FilterMaskIdHigh = 0x0000; + filter.FilterMaskIdLow = 0x0000; + filter.FilterFIFOAssignment = CAN_RX_FIFO0; + filter.FilterActivation = ENABLE; + filter.SlaveStartFilterBank = 14; + if (HAL_CAN_ConfigFilter(&hcan2, &filter) != HAL_OK) { + Error_Handler(); + } + // Start CAN peripheral + if (HAL_CAN_Start(&hcan2) != HAL_OK) { + Error_Handler(); + } + if (HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { + Error_Handler(); + } + // Start PWM outputs HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); + // Start iBUS circular DMA reception HAL_UART_Receive_DMA(&huart3, g_logic_state.ibus.dma_buffer, IBUS_DMA_BUFFER_SIZE); /* USER CODE END 2 */ From c7579e4631c022d8fbc8e16cc84c1ee334faffa9 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Fri, 27 Mar 2026 14:18:50 -0400 Subject: [PATCH 53/55] Recovery mode Shriya: i probably dont understand the state machine as much as i should, but is there a chance that precharge fires even if rc estop is pressed on recconnect? ex: rc disconnect -> rc estop pressed -> rc reconnect then 300 ms debounce window so rc estop is not considered pressed and then 200 ms for precharge start. Fix: *some state* -> error happens -> *error state* (estopped, rc dropped, etc) -> error fixed -> *recovering state* -> medium delay (2 sec?) -> *starting state* that way it will at worst bounce/return from recovering state and not precharging + LED blink times improved --- AutonomousDistroBoard/Core/Inc/logic.h | 21 ++++++++++++--------- AutonomousDistroBoard/Core/Src/logic.c | 20 +++++++++++++++++--- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index e140759..fa8ca94 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -14,6 +14,7 @@ #define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge #define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor #define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed +#define RECOVERING_DELAY (5000) // ms, how long to wait after transistioning after a fault (E-STOP, RC disconnect, CAN disconnect) before allowing to transition back to STARTING mode/precharge sequence #define IBUS_CHANNEL_THROTTLE (0) // 1000 = full stop, 2000 = full throttle forward #define IBUS_CHANNEL_STEERING (1) // 1000 = full left, 1500 = center, 2000 = full right @@ -35,14 +36,15 @@ #define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost // Really these are half periods b/c it is the rate at which the LED toggles -#define LED_STARTING_PERIOD (40) // ms -#define LED_PRECHARGING_PERIOD (200) // ms -#define LED_CONTACTOR_CLOSING_PERIOD (40) // ms -#define LED_RUNNING_RC_PERIOD (1000) // ms -#define LED_RUNNING_AUTONOMOUS_PERIOD (500) // ms -#define LED_ESTOPPED_PERIOD (0) // solid on -#define LED_RC_DISCONNECTED_PERIOD (0) // solid on -#define LED_CAN_DISCONNECTED_PERIOD (0) // solid on +#define LED_STARTING_PERIOD (100) // ms +#define LED_PRECHARGING_PERIOD (400) // ms +#define LED_CONTACTOR_CLOSING_PERIOD (50) // ms +#define LED_RUNNING_RC_PERIOD (1000) // ms +#define LED_RUNNING_AUTONOMOUS_PERIOD (250) // ms +#define LED_ESTOPPED_PERIOD (0) // solid on +#define LED_RC_DISCONNECTED_PERIOD (0) // solid on +#define LED_CAN_DISCONNECTED_PERIOD (0) // solid on +#define LED_RECOVERING_PERIOD (2000) // ms #define THROTTLE_PWM_LOW (1000) #define THROTTLE_PWM_HIGH (2000) @@ -67,7 +69,8 @@ typedef enum { LOGIC_MODE_RUNNING, LOGIC_MODE_ESTOPPED, LOGIC_MODE_RC_DISCONNECTED, - LOGIC_MODE_CAN_DISCONNECTED + LOGIC_MODE_CAN_DISCONNECTED, + LOGIC_MODE_RECOVERING, } logic_mode_t; diff --git a/AutonomousDistroBoard/Core/Src/logic.c b/AutonomousDistroBoard/Core/Src/logic.c index 961af56..aa4ce29 100644 --- a/AutonomousDistroBoard/Core/Src/logic.c +++ b/AutonomousDistroBoard/Core/Src/logic.c @@ -171,7 +171,7 @@ void logic_run( bool estop_debounced_high = debounce_controller_get_state(&state->estop_debounce); if (!estop_debounced_high) { - state->mode = LOGIC_MODE_STARTING; + state->mode = LOGIC_MODE_RECOVERING; state->start_time = now; } break; @@ -184,8 +184,7 @@ void logic_run( state->output_steering_pwm = STEERING_PWM_CENTER; if (ibus_is_connected(&state->ibus, now, RC_CONNECTION_TIMEOUT)) { - // If we receive a valid iBUS frame, consider the RC connection to be restored and restart precharge sequence - state->mode = LOGIC_MODE_STARTING; + state->mode = LOGIC_MODE_RECOVERING; state->start_time = now; } break; @@ -208,9 +207,23 @@ void logic_run( if ((autonomous_mode && can_connection_ok) || (!autonomous_mode && ibus_connection_ok)) { + state->mode = LOGIC_MODE_RECOVERING; + state->start_time = now; + } + break; + } + case LOGIC_MODE_RECOVERING: { + // Still stopped: precharge off, contactor off, throttle low, steering straight + HAL_GPIO_WritePin(PRECHARGE_EN_GPIO_Port, PRECHARGE_EN_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(MAIN_COIL_EN_GPIO_Port, MAIN_COIL_EN_Pin, GPIO_PIN_RESET); + state->output_throttle_pwm = THROTTLE_PWM_LOW; + state->output_steering_pwm = STEERING_PWM_CENTER; + + if (util_has_elapsed(now, state->start_time, RECOVERING_DELAY)) { state->mode = LOGIC_MODE_STARTING; state->start_time = now; } + break; } } @@ -268,6 +281,7 @@ void logic_run( case LOGIC_MODE_ESTOPPED: led_period = LED_ESTOPPED_PERIOD; break; case LOGIC_MODE_RC_DISCONNECTED: led_period = LED_RC_DISCONNECTED_PERIOD; break; case LOGIC_MODE_CAN_DISCONNECTED: led_period = LED_CAN_DISCONNECTED_PERIOD; break; + case LOGIC_MODE_RECOVERING: led_period = LED_RECOVERING_PERIOD; break; } if (led_period == 0) { // Solid on From 5120f1131d5892e8ebd51ea523f11bca347133d0 Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Fri, 27 Mar 2026 15:25:48 -0400 Subject: [PATCH 54/55] align --- AutonomousDistroBoard/Core/Inc/logic.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index fa8ca94..c8bc0df 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -36,14 +36,14 @@ #define RC_CONNECTION_TIMEOUT (100) // ms, if we did not get a valid iBUS frame within this time, consider the RC connection to be lost // Really these are half periods b/c it is the rate at which the LED toggles -#define LED_STARTING_PERIOD (100) // ms -#define LED_PRECHARGING_PERIOD (400) // ms -#define LED_CONTACTOR_CLOSING_PERIOD (50) // ms +#define LED_STARTING_PERIOD (100) // ms +#define LED_PRECHARGING_PERIOD (400) // ms +#define LED_CONTACTOR_CLOSING_PERIOD (50) // ms #define LED_RUNNING_RC_PERIOD (1000) // ms -#define LED_RUNNING_AUTONOMOUS_PERIOD (250) // ms -#define LED_ESTOPPED_PERIOD (0) // solid on -#define LED_RC_DISCONNECTED_PERIOD (0) // solid on -#define LED_CAN_DISCONNECTED_PERIOD (0) // solid on +#define LED_RUNNING_AUTONOMOUS_PERIOD (250) // ms +#define LED_ESTOPPED_PERIOD (0) // solid on +#define LED_RC_DISCONNECTED_PERIOD (0) // solid on +#define LED_CAN_DISCONNECTED_PERIOD (0) // solid on #define LED_RECOVERING_PERIOD (2000) // ms #define THROTTLE_PWM_LOW (1000) From 82d4dc48be3bc7eefc6de31a6f4403b311cf671a Mon Sep 17 00:00:00 2001 From: LelsersLasers Date: Fri, 27 Mar 2026 15:25:57 -0400 Subject: [PATCH 55/55] percharge duration bumped to 5s --- AutonomousDistroBoard/Core/Inc/logic.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AutonomousDistroBoard/Core/Inc/logic.h b/AutonomousDistroBoard/Core/Inc/logic.h index c8bc0df..28c80fb 100644 --- a/AutonomousDistroBoard/Core/Inc/logic.h +++ b/AutonomousDistroBoard/Core/Inc/logic.h @@ -2,7 +2,6 @@ #define LOGIC_H #include -#include #include "stm32f4xx_hal.h" @@ -12,7 +11,7 @@ #define PRECHARGE_START_DELAY (200) // ms, wait from boot before starting precharge -#define PRECHARGE_DURATION (3000) // ms, how long to run precharge before closing contactor +#define PRECHARGE_DURATION (5000) // ms, how long to run precharge before closing contactor #define CONTACTOR_CLOSED_DELAY (100) // ms, how long to wait after contactor is requested to be closed before considering it fully closed #define RECOVERING_DELAY (5000) // ms, how long to wait after transistioning after a fault (E-STOP, RC disconnect, CAN disconnect) before allowing to transition back to STARTING mode/precharge sequence