Загрузка...

What is the problem of ESC calibration? (STM32)

Thread in C/C++ created by Krafit Aug 14, 2025. 315 views

  1. Krafit
    Krafit Topic starter Aug 14, 2025 0 May 3, 2025
    Когда я включаю питание к esc он издает один пик и молчание. Никаких других звуков. Если отключаю или отсоеденяю стм он начинает пикать что ждет калибровку. Почему мой код не калибрует корректно,все нейросети обошел и полный ноль



    Code
    #define USE_FULL_LL_DRIVER

    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "stm32h7xx_ll_rcc.h"
    #include "stm32h7xx_ll_bus.h"
    #include "stm32h7xx_ll_system.h"
    #include "stm32h7xx_ll_exti.h"
    #include "stm32h7xx_ll_cortex.h"
    #include "stm32h7xx_ll_utils.h"
    #include "stm32h7xx_ll_pwr.h"
    #include "stm32h7xx_ll_tim.h"
    #include "stm32h7xx_ll_gpio.h"

    /* Private typedef -----------------------------------------------------------*/
    typedef struct {
    uint16_t min_pulse;
    uint16_t max_pulse;
    uint16_t neutral_pulse;
    } ESC_CalibrationParams;

    typedef enum {
    CALIBRATION_IDLE,
    CALIBRATION_MIN,
    CALIBRATION_MAX,
    CALIBRATION_NEUTRAL,
    CALIBRATION_COMPLETE
    } CalibrationState;

    /* Private define ------------------------------------------------------------*/
    #define ESC_MIN_PULSE 1000 // мкс
    #define ESC_MAX_PULSE 2000 // мкс
    #define ESC_NEUTRAL_PULSE 1500 // мкс
    #define PWM_FREQUENCY 50 // Гц

    /* Private variables ---------------------------------------------------------*/
    ESC_CalibrationParams esc_calibration = {
    .min_pulse = ESC_MIN_PULSE,
    .max_pulse = ESC_MAX_PULSE,
    .neutral_pulse = ESC_NEUTRAL_PULSE
    };

    CalibrationState current_state = CALIBRATION_IDLE;
    uint32_t calibration_timestamp = 0;

    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    void GPIO_Init(void);
    void TIM1_PWM_Init(void);
    void ESC_Calibration_Process(void);
    void ESC_Set_Pulse_Width(uint16_t pulse_width);
    void Delay_Ms(uint32_t ms);

    int main(void)
    {
    HAL_Init();
    SystemClock_Config();
    GPIO_Init();
    TIM1_PWM_Init();
    ESC_Calibration_Process();

    while (1) {
    ESC_Set_Pulse_Width(1100); // Очень медленное вращение
    Delay_Ms(100); // Небольшая задержка в цикле
    }
    }

    void SystemClock_Config(void)
    {
    LL_RCC_HSI_Enable();
    while(LL_RCC_HSI_IsReady() != 1) {}

    LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
    LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_1);
    LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
    LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
    LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_1);
    LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_1);

    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
    while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {}

    SystemCoreClockUpdate();
    }

    void GPIO_Init(void)
    {
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);

    LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
    LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_9, LL_GPIO_AF_1);

    LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);
    LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_PUSHPULL);
    LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_9, LL_GPIO_PULL_NO);
    }

    void TIM1_PWM_Init(void)
    {
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);

    // Для 50 Гц нужно: 64MHz / (prescaler * ARR) = 50 Hz
    // 64000000 / (64 * 20000) = 50 Hz
    LL_TIM_SetPrescaler(TIM1, 63); // Делитель 64 (63+1)
    LL_TIM_SetAutoReload(TIM1, 19999); // Период 20000 тиков = 20мс

    /* Настройка канала CH1 */
    LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_PWM1);
    LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCPOLARITY_HIGH);
    LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1);
    LL_TIM_OC_SetCompareCH1(TIM1, 1500); // Начальное значение 1.5мс


    LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1);


    LL_TIM_SetBreakInputSourcePolarity(TIM1, LL_TIM_BREAK_INPUT_BKIN,
    LL_TIM_BKIN_SOURCE_BKIN, LL_TIM_BKIN_POLARITY_LOW);
    LL_TIM_DisableBRK(TIM1);
    LL_TIM_EnableAllOutputs(TIM1);
    LL_TIM_GenerateEvent_UPDATE(TIM1);
    LL_TIM_EnableCounter(TIM1);
    }


    void ESC_Calibration_Process() {
    ESC_Set_Pulse_Width(esc_calibration.min_pulse);
    Delay_Ms(3000); // Дождаться звуковых сигналов ESC
    ESC_Set_Pulse_Width(esc_calibration.max_pulse);
    Delay_Ms(3000);
    }
    void ESC_Set_Pulse_Width(uint16_t pulse_width_us) {
    if (pulse_width_us < 1000) pulse_width_us = 1000;
    if (pulse_width_us > 2000) pulse_width_us = 2000;

    LL_TIM_OC_SetCompareCH1(TIM1, pulse_width_us);
    }

    void Delay_Ms(uint32_t ms) {
    uint32_t tickstart = HAL_GetTick();
    uint32_t wait = ms;

    /* Ожидание пока не пройдет заданное время */
    while((HAL_GetTick() - tickstart) < wait) {
    // Можно добавить __NOP() для оптимизации
    }
    }



    void Error_Handler(void)
    {
    __disable_irq();
    while (1)
    {
    }
    }

    #ifdef USE_FULL_ASSERT
    void assert_failed(uint8_t *file, uint32_t line)
    {
    /* USER can add his own implementation to report the file name and line number */
    }
    #endif
     
Loading...