diff --git a/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c b/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c index 4ace5cb..546224f 100644 --- a/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c +++ b/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c @@ -16,6 +16,7 @@ MCU_CortexMemoryTypeDef MCU_CORTEX_MEM; // MCU PERIPH INIT void Initialize_Periph_Sim(void) { + uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000); Init_TIM_SIM(); Init_ADC_SIM(); } diff --git a/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json b/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json index b1970f0..489a2f4 100644 --- a/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json +++ b/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json @@ -15,7 +15,6 @@ "Initialize_Periph_Sim()" ], "PeriphSimulation": [ - "uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000)", "Simulate_Periph_Sim()" ], "PeriphDeinit": [ diff --git a/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h b/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h index 8f592c0..ab4f3d5 100644 --- a/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h +++ b/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h @@ -55,7 +55,7 @@ // INPUT/OUTPUTS PARAMS START #define IN_PORT_NUMB 2 #define ADC_PORT_1_WIDTH 6 -#define IN_PORT_2_WIDTH 1 +#define IN_PORT_2_WIDTH 16 #define OUT_PORT_NUMB 3 #define THYR_PORT_1_WIDTH 6 diff --git a/MATLAB/app_wrapper/app_init.c b/MATLAB/app_wrapper/app_init.c index 705b1e2..c399266 100644 --- a/MATLAB/app_wrapper/app_init.c +++ b/MATLAB/app_wrapper/app_init.c @@ -24,6 +24,7 @@ void app_init(void) { MX_TIM8_Init(); MX_TIM5_Init(); MX_ADC3_Init(); + UPP_SetDefault(1, 1); UPP_Init(); UPP_PreWhile(); diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index 6a06c4e..97e301b 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -8,7 +8,7 @@ float dbg[16]; -#define PIN_READ(_verbname_) (_verbname_##_GPIO_Port->ODR & (_verbname_##_Pin)) ? 0 : 1 +#define PIN_READ(_verbname_) (_verbname_##_GPIO_Port->ODR & (_verbname_##_Pin)) ? 1 : 0 void Write_Thyristors(real_T* Buffer, int ind_port) { @@ -66,6 +66,7 @@ void app_readInputs(const real_T* Buffer) { ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5)); alpha_dbg = ReadInputArray(1, 0); + upp.call->go = ReadInputArray(1, 1); // USER APP INPUT END } @@ -83,19 +84,19 @@ void app_writeOutputBuffer(real_T* Buffer) { int nn = 0; //WriteOutputArray(upp.hangle.htim->Instance->CNT, 2, nn++); - //WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++); - //WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++); - //WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++); + WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++); + WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++); + WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++); //WriteOutputArray(dbg[0], 2, nn++); //WriteOutputArray(dbg[1], 2, nn++); //WriteOutputArray(dbg[2], 2, nn++); - //WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++); - //WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++); - //WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++); - //WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++); - //WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++); - //WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++); + WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++); + WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++); + WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++); + WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++); + WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++); + WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++); // USER APP OUTPUT END } \ No newline at end of file diff --git a/MATLAB/app_wrapper/app_wrapper.c b/MATLAB/app_wrapper/app_wrapper.c index 78882d0..3941387 100644 --- a/MATLAB/app_wrapper/app_wrapper.c +++ b/MATLAB/app_wrapper/app_wrapper.c @@ -9,7 +9,15 @@ void app_step(void) { // USER APP STEP START + UPP_While(); + + static uint32_t uwTickPrev = 0; + if (uwTickPrev != uwTick) + { + uwTickPrev = uwTick; + UPP_Tick(); + } // USER APP STEP END } diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index 2f48cc2..1685338 100644 Binary files a/MATLAB/upp_r2023.slx and b/MATLAB/upp_r2023.slx differ diff --git a/UPP/AllLibs/Modbus b/UPP/AllLibs/Modbus index 3aa2797..e0ce0e6 160000 --- a/UPP/AllLibs/Modbus +++ b/UPP/AllLibs/Modbus @@ -1 +1 @@ -Subproject commit 3aa279736d9383a06613f72d7b7462f0f23d7d4d +Subproject commit e0ce0e6dbf35d035175d30971442bc8d99f3bdd7 diff --git a/UPP/AllLibs/PeriphGeneral b/UPP/AllLibs/PeriphGeneral index 1cc886a..272642b 160000 --- a/UPP/AllLibs/PeriphGeneral +++ b/UPP/AllLibs/PeriphGeneral @@ -1 +1 @@ -Subproject commit 1cc886aa8dc5c2fcfdad93a21207793b2cd85fab +Subproject commit 272642b310043355b0af95e0410afbbcb74d17b7 diff --git a/UPP/Core/Configs/memspi_config.h b/UPP/Core/Configs/memspi_config.h index 54ed13b..aa1cde8 100644 --- a/UPP/Core/Configs/memspi_config.h +++ b/UPP/Core/Configs/memspi_config.h @@ -16,7 +16,7 @@ ******************************************************************************/ #ifndef __SPI_MEMORY_CONFIG_H_ #define __SPI_MEMORY_CONFIG_H_ -#include "upp_config.h" +#include "upp_defs.h" /////////////////////////---USER SETTINGS---///////////////////////// diff --git a/UPP/Core/Configs/modbus_config.h b/UPP/Core/Configs/modbus_config.h index dcae48e..0851d68 100644 --- a/UPP/Core/Configs/modbus_config.h +++ b/UPP/Core/Configs/modbus_config.h @@ -19,7 +19,7 @@ ******************************************************************************/ #ifndef _MODBUS_CONFIG_H_ #define _MODBUS_CONFIG_H_ -#include "upp_config.h" +#include "upp_defs.h" // Общие параметры #define MODBUS_DEVICE_ID 1 ///< Адрес устройства в сети Modbus diff --git a/UPP/Core/Configs/modbus_data.c b/UPP/Core/Configs/modbus_data.c index 1626ce8..b1cb836 100644 --- a/UPP/Core/Configs/modbus_data.c +++ b/UPP/Core/Configs/modbus_data.c @@ -22,6 +22,9 @@ #include "modbus_inputregs.h" #include "modbus_devid.h" +/* DEFINE DATA FOR MODBUS */ +MB_DataStructureTypeDef MB_DATA = {0};; ///< Coils & Registers +MB_DataInternalTypeDef MB_INTERNAL; /** * @brief Check is address valid for certain array. @@ -78,6 +81,10 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u { *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр } + else if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_PRVT_PARAMS_ADR, R_HOLDING_PRVT_PARAMS_QNT) == ET_NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_INTERNAL, Addr - R_HOLDING_PRVT_PARAMS_ADR); // указатель на выбранный по Addr регистр + } // if address doesnt match any array - return illegal data address response else { diff --git a/UPP/Core/Configs/modbus_data.h b/UPP/Core/Configs/modbus_data.h index 848006b..985af13 100644 --- a/UPP/Core/Configs/modbus_data.h +++ b/UPP/Core/Configs/modbus_data.h @@ -50,20 +50,24 @@ #ifndef _MODBUS_DATA_H_ #define _MODBUS_DATA_H_ - + +#include "upp_defs.h" +#include "upp_control.h" #include "stdint.h" //--------------SIZES OF DATA--------------- +#define R_HOLDING_PRVT_PARAMS_ADR 555 +#define R_HOLDING_PRVT_PARAMS_QNT (sizeof(UPP_PrvtParams_t)/sizeof(uint16_t)) // DEFINES FOR INPUT REGISTERS ARRAYS #define R_INPUT_ADDR 0 ///< Начальный адрес входных регистров -#define R_INPUT_QNT 16 ///< Количество входных регистров +#define R_INPUT_QNT (sizeof(UPP_PUI_Values_t)/sizeof(uint16_t)) ///< Количество входных регистров // DEFINES FOR HOLDING REGISTERS ARRAYS #define R_HOLDING_ADDR 0 ///< Начальный адрес регистров хранения -#define R_HOLDING_QNT 16 ///< Количество регистров хранения +#define R_HOLDING_QNT (sizeof(UPP_PUI_Params_t)/sizeof(uint16_t)) ///< Количество регистров хранения // DEFINES FOR COIL ARRAYS #define C_COILS_ADDR 0 ///< Начальный адрес коилов @@ -89,7 +93,7 @@ */ typedef struct //MB_DataInRegsTypeDef { - uint16_t in[16]; + UPP_PUI_Values_t pui; }MB_DataInRegsTypeDef; @@ -98,7 +102,7 @@ typedef struct //MB_DataInRegsTypeDef */ typedef struct //MB_DataInRegsTypeDef { - uint16_t out[16]; + UPP_PUI_Params_t pui_params; }MB_DataHoldRegsTypeDef; @@ -153,6 +157,13 @@ typedef struct // tester modbus data extern MB_DataStructureTypeDef MB_DATA; +typedef struct +{ + UPP_FuncCalls_t FuncCalls; + UPP_PrvtParams_t param; +}MB_DataInternalTypeDef; +extern MB_DataInternalTypeDef MB_INTERNAL; + #endif //_MODBUS_DATA_H_ ///////////////////////////////////////////////////////////// diff --git a/UPP/Core/Configs/mylibs_config.h b/UPP/Core/Configs/mylibs_config.h index 89c6755..a9dbd71 100644 --- a/UPP/Core/Configs/mylibs_config.h +++ b/UPP/Core/Configs/mylibs_config.h @@ -10,7 +10,7 @@ *************************************************************************/ #ifndef __MYLIBS_CONFIG_H_ #define __MYLIBS_CONFIG_H_ -#include "upp_config.h" +#include "upp_defs.h" // user includes /** diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h index 1208474..706225f 100644 --- a/UPP/Core/Configs/upp_config.h +++ b/UPP/Core/Configs/upp_config.h @@ -27,39 +27,58 @@ #define TEMP_1 0 #define TEMP_2 1 -/* Дефайны для базовых величин */ -#define PM_U_BASE 1216.0 -#define PM_I_BASE 53.0 -/* Дефайны для настройки мониторинга питания */ -#define PM_ADC_PERIOD_MKS 10 -#define PM_ZERO_CROSS_HYSTERESIS_V 10 -#define PM_ZERO_CROSS_DEBOUNCE_10US 2.5*100 // (2.5 * 100 = 2.5 мс) - - - - -/* Рассчитанные дефайны */ -#define PM_ADC_PERIOD (180*PM_ADC_PERIOD_MKS)-1 - -/* Общие для всего проекта структуры*/ /** - * @brief Состояния полуволны + * @addtogroup UPP_DEFAULT_PARAMS Default params for external flash + * @ingroup UPP_CONFIG + * @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке + * @{ */ -typedef enum { - UPP_WAVE_UNKNOWED = 0, - UPP_WAVE_POSITIVE, - UPP_WAVE_NEGATIVE -} UPP_HalfWave_t; - +/* Параметры ПУИ */ +#define PUI_Iref_PERCENT_DEFAULT 150 +#define PUI_Tnt_MS_DEFAULT 300 +#define PUI_Umin_PERCENT_DEFAULT 80 +#define PUI_Umax_PERCENT_DEFAULT 120 +#define PUI_Imax_PERCENT_DEFAULT 99 +#define PUI_Imin_PERCENT_DEFAULT 7 +#define PUI_TiMax_US_DEFAULT 5000 +#define PUI_Tdelay_SECONDS_DEFAULT 30 +#define PUI_Interlace_EN_DEFAULT 5000 + +/* Параметры АЦП */ +#define ADC_U_MAX_V_DEFAULT 1216.0 +#define ADC_I_MAX_A_DEFAULT 53.0 +#define ADC_U_ZERO_DEFAULT 2048 +#define ADC_I_ZERO_DEFAULT 2048 + +/* Параметры определения перехода через ноль */ +#define ZERO_CROSS_HYSTERESIS_V_DEFAULT 10.0 +#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2.5*100 // (2.5 * 100 = 2.5 мс) + +/* Параметры ШИМ для тиристоров */ +#define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000 +#define PWM_THYR_PULSE_NUMBER_DEFAULT 20 + +/** //UPP_DEFAULT_PARAMS + * @} + */ + + /** - * @brief Названия Фаз + * @addtogroup UPP_COMPILED_PARAMS Fixed params + * @ingroup UPP_CONFIG + * @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять + * @{ */ -typedef enum { - UPP_PHASE_A = 0, - UPP_PHASE_B = 1, - UPP_PHASE_C = 2, - UPP_PHASE_UNKNOWN = 3 -} UPP_Phase_t; +#define PM_U_NOM_V 690 +#define PM_I_NOM_V 5 +#define PM_F_NOM_HZ 50 + +#define PM_ADC_PERIOD_MKS 10 ///< Период опроса АЦП в мкс +/* Частоты таймеров в МГц*/ +#define ADC_TIM8_FREQ_MZH 180 ///< Частота тиков таймера АЦП +#define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы) +#define PWM_TIM3_FREQ_MHZ 90 ///< Частота тиков таймера ШИМ (5-6 каналы) +#define ANGLE_TIM2_FREQ_MHZ 90 ///< Частота тиков таймера отсчета угла открытия тиристоров #endif //_UPP_CONFIG_H_ diff --git a/UPP/Core/Configs/upp_defs.h b/UPP/Core/Configs/upp_defs.h new file mode 100644 index 0000000..5d9ae19 --- /dev/null +++ b/UPP/Core/Configs/upp_defs.h @@ -0,0 +1,178 @@ +/** +****************************************************************************** +* @file upp_defs.h +* @brief Общие дефайны УПП +****************************************************************************** +@addtogroup UPP_DEFS UPP defines +@ingroup UPP_MAIN +@brief Общие дефайны для всего проекта УПП +@{ +****************************************************************************** +* @details +******************************************************************************/ +#ifndef _UPP_DEFS_H_ +#define _UPP_DEFS_H_ +#include "upp_config.h" + +/** + * @addtogroup UPP_HIGHLEVEL Defines for high-level + * @ingroup UPP_DEFS + * @brief Дефайны УПП которые определяют коды ошибок и параметры для общения с верхним уровнем + * @{ + */ + + +/** + * @brief Список аварий УПП + */ +typedef enum { + WM_Not_Init = 0, ///< УПП не инициализирован + WM_Ready = 1, ///< УПП в готовности + WM_Running = 2, ///< УПП в работе, управляет тиристорами + WM_Error = 3, ///< УПП в аварии +} UPP_WorkModeType_t; + +/** + * @brief Список аварий УПП + */ +typedef enum { + Err_None = 0, ///< Неисправность отсутствует + + /* Програмные ошибки */ + Err_Internal_1 = 1, ///< Внутренняя неисправность УПП 1 + Err_Internal_2 = 2, ///< Внутренняя неисправность УПП 2 + Err_Internal_3 = 3, ///< Внутренняя неисправность УПП 3 + Err_Internal_4 = 4, ///< Внутренняя неисправность УПП 4 + Err_Internal_5 = 5, ///< Внутренняя неисправность УПП 5 + Err_Internal_6 = 6, ///< Внутренняя неисправность УПП 6 + + /* Ошибки по питанию */ + Err_Power_Digit_5V = 7, ///< Неисправность цифрового источника питания (5 В) + Err_Power_24V = 8, ///< Неисправность источника питания 24 В + Err_Power_Analog_5V = 9, ///< Неисправность аналогового источника питания микроконтроллера (± 5 В) + Err_Power_SCI_5V = 10, ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В) + Err_Power_DIO_24V = 11, ///< Неисправность источника питания дискретных входов/выходов (24 В) + + /* Ошибки по допустимым пределам Наряжений/Токов/Температуры */ + Err_OverCurrent = 12, ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t) + Err_OverVoltage = 13, ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t) + Err_OverTemperature = 14, ///< Температура выше допустимой (плюс 85 °C) + Err_UnderVoltage = 15, ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t) + + /* Ошибки по обрывам фаз */ + Err_LossPhaseAll = 16, ///< Обрыв трёх фаз (см. Imin в @ref UPP_PUI_Params_t) + Err_LossPhaseA = 17, ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t) + Err_LossPhaseB = 18, ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t) + Err_LossPhaseC = 19, ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t) + + /* Другие ошибки */ + Err_LongStart = 20, ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t) + Err_Interlace = 21, ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t) + Err_OverFrequency = 22, ///< Частота сети выше допустимой + Err_UnderFrequency = 23, ///< Частота сети ниже допустимой +} UPP_ErrorType_t; + + +/** + * @brief Структура данных от УПП передаваемых в ПУИ + */ +typedef struct { + uint16_t Error; /** @brief Текущая авария + @details В случае срабатывания защиты */ + + uint16_t WorkMode; /** @brief Режим работы + @details «Готовность» или «Работа» */ + + uint16_t Voltage; /** @brief Напряжение на входе УПП, Вольты */ + + uint16_t Current; /** @brief Ток на входе УПП, Амперы */ + + uint16_t Frequency; /** @brief Частота напряжения на входе УПП */ + + uint16_t Temperature; /** @brief Температура радиатора тиристоров, Градусы Цельсия */ +} UPP_PUI_Values_t; + +/** + * @brief Структура параметров УПП от ПУИ + * @details Параметры по умолчанию приведены в @ref UPP_DEFAULT_PARAMS + * @note Защиты №X приведены в @ref UPP_ErrorType_t + */ +typedef struct { + uint16_t Iref; /** @brief Уставка ограничения тока УПП + @details В диапазоне от 100 % до 500 % от Iн = 5 А + По умолчанию – @ref PUI_Iref_PERCENT_DEFAULT */ + + uint16_t Tnt; /** @brief Уставка времени нарастания заданного тока + @details В диапазоне от 50 до 5000 мс. + По умолчанию – @ref PUI_Tnt_MS_DEFAULT */ + + uint16_t Umin; /** @brief Уставка защиты №15 от понижения напряжения входной сети + @details В диапазоне от 5% до 99 % от Uн = 690 В. + По умолчанию – @ref PUI_Umin_PERCENT_DEFAULT */ + + uint16_t Umax; /** @brief Уставка защиты №13 от повышения напряжения входной сети + @details В диапазоне от 100% до 120 % от Uн = 690 В. + По умолчанию – @ref PUI_Umax_PERCENT_DEFAULT */ + + uint16_t Imax; /** @brief Уставка защиты №12 по току + @details В диапазоне от 5 % до 99 % от 50 А. + По умолчанию – @ref PUI_Imax_PERCENT_DEFAULT */ + + uint16_t Imin; /** @brief Уставка защит № 16 – №19 от обрыва фаз(ы) + @details В диапазоне от 0 % до 40 % от Iн = 5 А. При задании нуля эти защиты отключаются. + По умолчанию – @ref PUI_Imin_PERCENT_DEFAULT */ + + uint16_t TiMax; /** @brief Выдержка времени на срабатывание защиты № 12 по току + @details В диапазоне от 500 до 10000 мкс. + По умолчанию – @ref PUI_TiMax_US_DEFAULT */ + + uint16_t Tdelay; /** @brief Выдержка времени защиты № 20 от затянутого пуска + @details В диапазоне от 5 до 60 с. + По умолчанию – @ref PUI_Tdelay_SECONDS_DEFAULT */ + + uint16_t Interlace; /** @brief Разрешение защиты № 21 от обратного порядка чередования фаз; + @details 0 – нет защиты, 1 – есть защита. + По умолчанию – @ref PUI_Interlace_EN_DEFAULT */ +} UPP_PUI_Params_t; + + +/** //UPP_HIGHLEVEL + * @} + */ + + +/** + * @addtogroup UPP_INTERNAL_DEFS Defines for internal use + * @ingroup UPP_DEFS + * @brief Дефайны УПП которые используютяс исключительно внутри программы + * @{ + */ +#define ANGLE_PERIOD_MS (((float)1/(PM_F_NOM_HZ*2))*1000) +/** + * @brief Состояния полуволны + */ +typedef enum { + UPP_WAVE_UNKNOWED = 0, + UPP_WAVE_POSITIVE, + UPP_WAVE_NEGATIVE +} UPP_HalfWave_t; + +/** + * @brief Названия Фаз + */ +typedef enum { + UPP_PHASE_A = 0, + UPP_PHASE_B = 1, + UPP_PHASE_C = 2, + UPP_PHASE_UNKNOWN = 3 +} UPP_Phase_t; + +/** //UPP_INTERNAL_DEFS + * @} + */ +#endif //_UPP_DEFS_H_ + + +/** //UPP_DEFS + * @} + */ diff --git a/UPP/Core/Inc/main.h b/UPP/Core/Inc/main.h index 704767c..ad65e1f 100644 --- a/UPP/Core/Inc/main.h +++ b/UPP/Core/Inc/main.h @@ -31,11 +31,10 @@ extern "C" { /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ -#include "upp_config.h" +#include "upp_defs.h" +#include "upp_errors.h" #include "mylibs_include.h" -#ifndef MATLAB #include "modbus.h" -#endif /* USER CODE END Includes */ /* Exported types ------------------------------------------------------------*/ @@ -56,7 +55,7 @@ extern "C" { void Error_Handler(void); /* USER CODE BEGIN EFP */ -extern __IO uint32_t micros; + /* USER CODE END EFP */ /* Private defines -----------------------------------------------------------*/ diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c index 5129c70..2a8b7eb 100644 --- a/UPP/Core/PowerMonitor/adc_tools.c +++ b/UPP/Core/PowerMonitor/adc_tools.c @@ -7,32 +7,6 @@ ******************************************************************************/ #include "adc_tools.h" -//Полосовой фильтр 45-55 Гц -static float coefs_biquad_U[5] = { - 0.000010f, // b0 - 0.000020f, // b1 - 0.000010f, // b2 - -1.900000f, // a1 - 0.950000f // a2 -}; - -// ФНЧ 100 Гц -static float coefs_biquad_I[5] = { - 0.000010f, // b0 - 0.000020f, // b1 - 0.000010f, // b2 - -1.900000f, // a1 - 0.950000f // a2 -}; -// ФНЧ 10 Гц -static float coefs_biquad_T[5] = { - 0.0002f, // b0 - 0.0004f, // b1 - 0.0002f, // b2 - -1.98f, // a1 - 0.980f // a2 -}; - static void ADC_EnableAllFilters(ADC_Periodic_t *adc) { for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) @@ -106,6 +80,8 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le adc->Coefs[ChNumb].lMax = levelMax; adc->Coefs[ChNumb].vMax = valueMax; adc->Coefs[ChNumb].lZero = levelZero; + + ADC_ResetStatistics(adc, ChNumb); return HAL_OK; } @@ -116,16 +92,16 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le * @return HAL Status. * @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim. */ -HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period) +HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs) { HAL_StatusTypeDef res; if(assert_upp(adc)) return HAL_ERROR; - if(Period == 0) + if(PeriodUs == 0) return HAL_ERROR; // Запускаем таймер который будет запускать опрос АЦП с заданным периодом - __HAL_TIM_SET_AUTORELOAD(adc->htim, Period); + __HAL_TIM_SET_AUTORELOAD(adc->htim, TIM_MicrosToTick(PeriodUs, ADC_TIM8_FREQ_MZH)); res = HAL_TIM_Base_Start(adc->htim); if(res != HAL_OK) { diff --git a/UPP/Core/PowerMonitor/adc_tools.h b/UPP/Core/PowerMonitor/adc_tools.h index e61e16b..7a47e57 100644 --- a/UPP/Core/PowerMonitor/adc_tools.h +++ b/UPP/Core/PowerMonitor/adc_tools.h @@ -123,7 +123,7 @@ HAL_StatusTypeDef ADC_Init(ADC_Periodic_t *adc, TIM_HandleTypeDef *htim, ADC_Han /* Конфигуарция канала АЦП. */ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax); /* Запуск АЦП. */ -HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period); +HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs); /* Остановка АЦП. */ HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc); diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c index f4dcf07..ff8c982 100644 --- a/UPP/Core/PowerMonitor/power_monitor.c +++ b/UPP/Core/PowerMonitor/power_monitor.c @@ -15,17 +15,32 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK) return HAL_ERROR; - if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, 2048, PM_U_BASE, 4095) != HAL_OK) - return HAL_ERROR; - if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC, 2048, PM_U_BASE, 4095) != HAL_OK) - return HAL_ERROR; - if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC, 2048, PM_I_BASE, 4095) != HAL_OK) + if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA], + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA], + 4095) != HAL_OK) return HAL_ERROR; - if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA, 2048, PM_I_BASE, 4095) != HAL_OK) + + if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC, + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC], + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC], + 4095) != HAL_OK) + return HAL_ERROR; + + if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC, + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC], + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC], + 4095) != HAL_OK) + return HAL_ERROR; + + if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA, + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA], + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA], + 4095) != HAL_OK) return HAL_ERROR; - if(ZC_Init(&hpm->zc, 3, PM_ZERO_CROSS_HYSTERESIS_V, PM_ZERO_CROSS_DEBOUNCE_10US) != HAL_OK) + if(ZC_Init(&hpm->zc, 3, (float)MB_INTERNAL.param.zc.Hysteresis/100, MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK) return HAL_ERROR; if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK) @@ -41,7 +56,7 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) { - if(ADC_Start(&hpm->adc, PM_ADC_PERIOD) != HAL_OK) + if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_MKS) != HAL_OK) return HAL_ERROR; return HAL_OK; @@ -51,6 +66,7 @@ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) void PowerMonitor_Handle(PowerMonitor_t *hpm) { + /* Считываем АЦП */ static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0}; ADC_Handle(&hpm->adc); diff --git a/UPP/Core/PowerMonitor/zero_cross.c b/UPP/Core/PowerMonitor/zero_cross.c index d587251..621f08e 100644 --- a/UPP/Core/PowerMonitor/zero_cross.c +++ b/UPP/Core/PowerMonitor/zero_cross.c @@ -28,9 +28,9 @@ HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels, memset(zc, 0, sizeof(ZeroCross_Handle_t)); // Установка параметров хендла - zc->NumChannels = num_channels; - zc->Hysteresis = hysteresis; - zc->DebounceSamples = debounce_samples; + zc->Config.NumChannels = num_channels; + zc->Config.Hysteresis = hysteresis; + zc->Config.DebounceSamples = debounce_samples; // Инициализация каналов for (int i = 0; i < num_channels; i++) { @@ -63,7 +63,7 @@ HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel, if (assert_upp(zc)){ return HAL_ERROR; } - if (channel >= zc->NumChannels) { + if (channel >= zc->Config.NumChannels) { return HAL_ERROR; } @@ -94,7 +94,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin if (!zc->f.Monitoring) { return; } - if (channel >= zc->NumChannels) { + if (channel >= zc->Config.NumChannels) { return; } int zc_detected = 0; @@ -111,16 +111,16 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin } // Детектирование rising edge (отрицательное -> положительное) - if ((zc_ch->LastValue <= -zc->Hysteresis) && - (value >= zc->Hysteresis)) + if ((zc_ch->LastValue <= -zc->Config.Hysteresis) && + (value >= zc->Config.Hysteresis)) { if (zc_ch->EdgeType == ZC_RISING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) { - if(zc->DebounceSamples) + if(zc->Config.DebounceSamples) { if(zc_ch->DebounceCounter == 0) { - zc_ch->DebounceCounter = zc->DebounceSamples; + zc_ch->DebounceCounter = zc->Config.DebounceSamples; } } @@ -128,16 +128,16 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin } } // Детектирование falling edge (положительное -> отрицательное) - else if ((zc_ch->LastValue >= zc->Hysteresis) && - (value <= -zc->Hysteresis)) + else if ((zc_ch->LastValue >= zc->Config.Hysteresis) && + (value <= -zc->Config.Hysteresis)) { if (zc_ch->EdgeType == ZC_FALLING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) { - if(zc->DebounceSamples) + if(zc->Config.DebounceSamples) { if(zc_ch->DebounceCounter == 0) { - zc_ch->DebounceCounter = zc->DebounceSamples; + zc_ch->DebounceCounter = zc->Config.DebounceSamples; } } @@ -149,7 +149,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin { zc_ch->HalfWave = zc_detected == 1 ? UPP_WAVE_POSITIVE : UPP_WAVE_NEGATIVE; zc_ch->Occurred = 1; - uint32_t RealTimeShift = 0;//zc->DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции + uint32_t RealTimeShift = 0;//zc->Config.DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции // Переход подтвержден сразу uint32_t RealTimestamp = timestamp-RealTimeShift; @@ -166,7 +166,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin } // Сохраняем текущее значение для следующей итерации в случае если оно не в мертвой зоне - if((value > zc->Hysteresis) || (value < -zc->Hysteresis)) + if((value > zc->Config.Hysteresis) || (value < -zc->Config.Hysteresis)) { zc_ch->LastValue = value; } @@ -188,7 +188,7 @@ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t times return; } - for (int ch = 0; ch < zc->NumChannels; ch++) { + for (int ch = 0; ch < zc->Config.NumChannels; ch++) { ZC_ProcessChannel(zc, ch, values[ch], timestamp); } @@ -238,7 +238,7 @@ float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel) if (assert_upp(zc)){ return 0.0f; } - if (channel >= zc->NumChannels) { + if (channel >= zc->Config.NumChannels) { return 0.0f; } @@ -273,7 +273,7 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel) return; } - if (channel < zc->NumChannels) { + if (channel < zc->Config.NumChannels) { zc->Channel[channel].LastValue = 0.0f; zc->Channel[channel].CurrentValue = 0.0f; zc->Channel[channel].DebounceCounter = 0; @@ -284,7 +284,7 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel) } else { // Сброс всех каналов - for (int i = 0; i < zc->NumChannels; i++) { + for (int i = 0; i < zc->Config.NumChannels; i++) { zc->Channel[i].LastValue = 0.0f; zc->Channel[i].CurrentValue = 0.0f; zc->Channel[i].DebounceCounter = 0; diff --git a/UPP/Core/PowerMonitor/zero_cross.h b/UPP/Core/PowerMonitor/zero_cross.h index ba22f79..cb75130 100644 --- a/UPP/Core/PowerMonitor/zero_cross.h +++ b/UPP/Core/PowerMonitor/zero_cross.h @@ -100,15 +100,22 @@ typedef struct { ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода } ZC_Channel_t; + +/** + * @brief Параметры перехода через ноль + */ +typedef struct { + uint8_t NumChannels; ///< Количество используемых каналов для этого хендла + float Hysteresis; ///< Гистерезис для избежания дребезга + uint16_t DebounceSamples; ///< Количество samples для антидребезга +} ZC_Config_t; + /** * @brief Хендл детектора нуля */ typedef struct { - ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t - uint8_t NumChannels; ///< Количество используемых каналов для этого хендла - float Hysteresis; ///< Гистерезис для избежания дребезга - uint16_t DebounceSamples; ///< Количество samples для антидребезга - + ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t + ZC_Config_t Config; struct { unsigned Initialized:1; ///< Флаг инициализации unsigned Monitoring:1; ///< Флаг активности мониторинга diff --git a/UPP/Core/Src/main.c b/UPP/Core/Src/main.c index 9096b23..076b2e2 100644 --- a/UPP/Core/Src/main.c +++ b/UPP/Core/Src/main.c @@ -34,7 +34,7 @@ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ -__IO uint32_t micros; + /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ diff --git a/UPP/Core/Src/stm32f4xx_it.c b/UPP/Core/Src/stm32f4xx_it.c index f151479..cf5eee0 100644 --- a/UPP/Core/Src/stm32f4xx_it.c +++ b/UPP/Core/Src/stm32f4xx_it.c @@ -246,6 +246,7 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void) HAL_TIM_IRQHandler(&htim14); /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */ #endif + UPP_Tick(); /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */ } diff --git a/UPP/Core/UPP/angle_control.c b/UPP/Core/UPP/angle_control.c index 767edaf..781a050 100644 --- a/UPP/Core/UPP/angle_control.c +++ b/UPP/Core/UPP/angle_control.c @@ -1,7 +1,7 @@ /** ****************************************************************************** -* @file pwm_thyristors.c -* @brief Модуль для управления тиристорами +* @file angle_control.c +* @brief Модуль для формирования и отсчитывания угла открытия ****************************************************************************** * @details ******************************************************************************/ @@ -10,22 +10,16 @@ /** - * @brief Инициализация ШИМ тиристоров. + * @brief Инициализация таймера для расчета угла открытия. * @param hangle Указатель на таймер * @return HAL Status. */ -HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax) +HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle) { if(hangle == NULL) return HAL_ERROR; - if(AngleMax < 0 || AngleMax > 1) - return HAL_ERROR; - if(AngleMin < 0 || AngleMin > 1) - return HAL_ERROR; hangle->htim = &angletim; - hangle->AngleMax = AngleMax; - hangle->AngleMin = AngleMin; HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_1); @@ -36,9 +30,65 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float Angle Angle_Reset(hangle, UPP_PHASE_B); Angle_Reset(hangle, UPP_PHASE_C); + hangle->f.Initialized = 1; return HAL_OK; } +/** + * @brief Инициализация углов открытия. + * @param hangle Указатель на таймер + * @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ + * @param AngleMin Минимально возможный угол открытия + * @param AngleMax Максимально возможный угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax) +{ + if(assert_upp(hangle)) + return HAL_ERROR; + if(hangle->f.Running) + return HAL_BUSY; + if(AngleMax < 0 || AngleMax > 1) + return HAL_ERROR; + if(AngleMin < 0 || AngleMin > 1) + return HAL_ERROR; + + if(AngleMax > hangle->Config.AngleLimit) + AngleMax = hangle->Config.AngleLimit; + if(AngleMin > hangle->Config.AngleLimit) + AngleMin = hangle->Config.AngleLimit; + + if(AngleMin >= AngleMax) + return HAL_ERROR; + + hangle->Config.AngleMax = AngleMax; + hangle->Config.AngleMin = AngleMin; + + return HAL_OK; +} + +/** + * @brief Инициализация предельного угла открытия. + * @param hangle Указатель на таймер + * @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ + * @param AngleMin Минимально возможный угол открытия + * @param AngleMax Максимально возможный угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit) +{ + if(assert_upp(hangle)) + return HAL_ERROR; + if(hangle->f.Running) + return HAL_BUSY; + + if(AngleLimit < 0 || AngleLimit > 1) + return HAL_ERROR; + + hangle->Config.AngleLimit = AngleLimit; + + return HAL_OK; +} /** * @brief Хендл таймера для рассчета угла открытия. * @param hangle Указатель на таймер @@ -46,7 +96,7 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float Angle */ UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) { - if(hangle == NULL) + if(assert_upp(hangle)) return UPP_PHASE_UNKNOWN; @@ -79,9 +129,9 @@ UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) * @param Phase Для какой фазы надо установить угол открытия * @return HAL Status. */ -HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq) +HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs) { - if(hangle == NULL) + if(assert_upp(hangle)) return HAL_ERROR; // Если канал дурацкий - возвращаем ошибку @@ -89,16 +139,16 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A { return HAL_ERROR; } - if(Angle > hangle->AngleMax) + if(Angle > hangle->Config.AngleMax) { - Angle = hangle->AngleMax; + Angle = hangle->Config.AngleMax; } - if(Angle < hangle->AngleMin) + if(Angle < hangle->Config.AngleMin) { - Angle = hangle->AngleMin; + Angle = hangle->Config.AngleMin; } - uint32_t timer_ticks = TIM_FreqToTick(Freq/Angle, ANGLE_TIM2_FREQ_MHZ); + uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*Angle, ANGLE_TIM2_FREQ_MHZ); uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks; switch(Phase) @@ -106,16 +156,19 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A case UPP_PHASE_A: __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_1, ccr_ticks); __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC1); + hangle->f.Running++; break; case UPP_PHASE_B: __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_2, ccr_ticks); __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC2); + hangle->f.Running++; break; case UPP_PHASE_C: __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_3, ccr_ticks); __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC3); + hangle->f.Running++; break; case UPP_PHASE_UNKNOWN: @@ -136,7 +189,7 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A */ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase) { - if(hangle == NULL) + if(assert_upp(hangle)) return HAL_ERROR; // Если канал дурацкий - возвращаем ошибку @@ -149,14 +202,20 @@ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase) { case UPP_PHASE_A: __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC1); + if(hangle->f.Running) + hangle->f.Running--; break; case UPP_PHASE_B: __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC2); + if(hangle->f.Running) + hangle->f.Running--; break; case UPP_PHASE_C: __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC3); + if(hangle->f.Running) + hangle->f.Running--; break; case UPP_PHASE_UNKNOWN: diff --git a/UPP/Core/UPP/angle_control.h b/UPP/Core/UPP/angle_control.h index 4da20e1..2b62a01 100644 --- a/UPP/Core/UPP/angle_control.h +++ b/UPP/Core/UPP/angle_control.h @@ -1,27 +1,39 @@ /** ****************************************************************************** -* @file pwm_thyristors.h -* @brief Модуль для управления тиристорами (объединённый 6-канальный) +* @file angle_control.h +* @brief Модуль для формирования и отсчитывания угла открытия ****************************************************************************** */ #ifndef _ANGLE_CONTROL_H_ #define _ANGLE_CONTROL_H_ #include "main.h" -#define ANGLE_TIM2_FREQ_MHZ 90 +typedef struct +{ + float AngleLimit; ///< Лимит AngleMax, рассчитывается от параметров ШИМ + float AngleMin; ///< Минимально возможный угол открытия + float AngleMax; ///< Максимально возможный угол открытия +}Angle_Config_t; typedef struct { TIM_HandleTypeDef *htim; + Angle_Config_t Config; - float AngleMin; - float AngleMax; + struct { + unsigned Initialized : 1; + unsigned Running : 3; ///< Сколько каналов запущено сейчас + } f; }Angle_Handle_t; /* Инициализация Таймера для рассчета угла открытия. */ -HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax); +HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle); +/* Инициализация углов открытия. */ +HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax); +/* Инициализация предельного угла открытия. */ +HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit); /* Установка угла открытия в таймер. */ -HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq); +HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs); /* Сброс угла открытия у таймера. */ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase); diff --git a/UPP/Core/UPP/pwm_thyristors.c b/UPP/Core/UPP/pwm_thyristors.c index 20455c8..2d6daba 100644 --- a/UPP/Core/UPP/pwm_thyristors.c +++ b/UPP/Core/UPP/pwm_thyristors.c @@ -56,7 +56,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED); PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED); - PWM_SetFrequency(hpwm, hpwm->Config.Frequency); + PWM_SetConfig(hpwm, MB_INTERNAL.param.pwm.PhaseMask, MB_INTERNAL.param.pwm.Frequency, MB_INTERNAL.param.pwm.PulseNumber); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2); @@ -115,7 +115,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) * @param Phase На какой фазе надо остановить ШИМ * @return HAL Status. */ -HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop) +HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all) { if(assert_upp(hpwm)) return HAL_ERROR; @@ -129,10 +129,18 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_ hpwm->Phase[Phase]->State = PWM_THYR_DISABLED; - if(force_stop) + // Если не force_stop_all - сбрасываем только текущий канал + if (!force_stop_all) { __PWM_SetOutputState(hpwm->Phase[Phase], PWM_DISABLE); } + // Если force_stop_all - сбрасываем ВСЕ КАНАЛЫ + else { + for(int ch = 0; ch < 6; ch++) + { + __PWM_SetOutputState(&hpwm->AllPhases[ch], PWM_DISABLE); + } + } return HAL_OK; } @@ -169,6 +177,7 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) __PWM_SetOutputState(hPhase, PWM_ENABLE); hPhase->PulseCnt = hpwm->Config.PulseNumber; hPhase->State = PWM_THYR_TIM_ACTIVE; + hpwm->f.Running++; break; case PWM_THYR_TIM_ACTIVE: @@ -182,6 +191,8 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) case PWM_THYR_TIM_DONE: hPhase->State = PWM_THYR_TIM_WAIT; + if(hpwm->f.Running) + hpwm->f.Running--; break; default: @@ -192,6 +203,37 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) return HAL_OK; } +/** + * @brief Установка частоты ШИМ. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @param Frequency Частота в ГЦ + * @return HAL Status. + */ +HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber) +{ + if(assert_upp(hpwm)) + return HAL_ERROR; + if(hpwm->f.Running) + return HAL_BUSY; + + HAL_TIM_Base_Stop(&hpwm1); + + hpwm->Config.PhaseMask.all = PhaseMask; + hpwm->Config.PulseNumber = PulseNumber; + hpwm->Config.Frequency = Frequency; + __HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(Frequency, PWM_TIM1_FREQ_MHZ)); + __HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(Frequency, PWM_TIM3_FREQ_MHZ)); + __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); + __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); + __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); + __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); + __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); + __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); + + return HAL_TIM_Base_Start_IT(&hpwm1); +} + + /** * @brief Установка полуволны для слежения. * @param hpwm Указатель на хендл ШИМ тиристоров @@ -206,7 +248,7 @@ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_Hal // Сбрасываем текущий канал - PWM_Stop(hpwm, Phase, 1); + PWM_Stop(hpwm, Phase, 0); // Если канал дурацкий - выставляем заглушку if(Phase >= 3) diff --git a/UPP/Core/UPP/pwm_thyristors.h b/UPP/Core/UPP/pwm_thyristors.h index fa56447..5908225 100644 --- a/UPP/Core/UPP/pwm_thyristors.h +++ b/UPP/Core/UPP/pwm_thyristors.h @@ -1,7 +1,7 @@ /** ****************************************************************************** * @file pwm_thyristors.h -* @brief Модуль для управления тиристорами (объединённый 6-канальный) +* @brief Модуль для управления тиристорами ****************************************************************************** */ #ifndef _PWM_THYRISTORS_H @@ -12,23 +12,11 @@ -#define PWM_TIM1_FREQ_MHZ 180 -#define PWM_TIM3_FREQ_MHZ 90 -#define PWM_ENABLE TIM_OCMODE_PWM1 -#define PWM_DISABLE TIM_OCMODE_FORCED_ACTIVE +#define PWM_ENABLE TIM_OCMODE_PWM2 +#define PWM_DISABLE TIM_OCMODE_FORCED_INACTIVE -#define PWM_SetFrequency(_hpwm_, _freq_) \ -do { _hpwm_->Config.Frequency = _freq_; \ - __HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(_freq_, PWM_TIM1_FREQ_MHZ)); \ - __HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(_freq_, PWM_TIM3_FREQ_MHZ)); \ - __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \ - __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \ - __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \ - __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \ - __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); \ - __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); }while(0); // Индексы для структур каналов @ref PWM_Handle_t @@ -67,7 +55,7 @@ typedef struct { } PWM_Channel_t; /** - * @brief Канал PWM (один тиристор) + * @brief Параметры ШИМ */ typedef struct { union @@ -81,7 +69,7 @@ typedef struct { }; }PhaseMask; ///< Какими каналами управлять uint8_t PulseNumber; ///< Сколько импульсов отправить в пакете для открытия тиристоров - uint32_t Frequency; ///< Частота импульсов + uint16_t Frequency; ///< Частота импульсов } PWM_ThyrConfig_t; /** @@ -93,7 +81,7 @@ typedef struct { struct { unsigned Initialized : 1; - unsigned Running : 1; ///< true если оба таймера запущены + unsigned Running : 3; ///< Сколько каналов запущено сейчас } f; } PWM_Handle_t; @@ -103,7 +91,9 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm); /* Запуск ШИМ. */ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase); /* Остановить ШИМ. */ -HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop); +HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all); +/* Установка частоты ШИМ. */ +HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber); /* Установка полуволны для слежения. */ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave); /* Установка полуволны для слежения. */ diff --git a/UPP/Core/UPP/upp_control.c b/UPP/Core/UPP/upp_control.c new file mode 100644 index 0000000..dec4727 --- /dev/null +++ b/UPP/Core/UPP/upp_control.c @@ -0,0 +1,267 @@ +/** +****************************************************************************** +* @file upp_control.c +* @brief Модуль определябщий поведение УПП +****************************************************************************** +* @details +******************************************************************************/ +#include "upp_main.h" // всё остальное по работе с УПП + + +static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef); +static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef); +static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc); +static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef); +static int __AngleSetLimit(void); + +/** + * @brief Контроль внутренних параметров УПП. + * @return HAL Status. + */ +void UPP_Control_InternalParams(void) +{ + if(upp.call->go) // при запущеном УПП ничего не меняем + return; + + // флаги обновились ли конфиги + static int adc_channel_update[ADC_NUMB_OF_REGULAR_CHANNELS] = {0}; + static int zc_update = 0; + static int pwm_update = 0; + + // временная переменная для параметров каналов АЦП + float adc_channel_max[ADC_NUMB_OF_REGULAR_CHANNELS] = {0}; + uint16_t adc_channel_zero[ADC_NUMB_OF_REGULAR_CHANNELS] = {0}; + // временная переменная для параметров перехода через ноль + float zc_hysteresis = upp.pm.zc.Config.Hysteresis; + uint16_t zc_debounce = upp.pm.zc.Config.DebounceSamples; + // временная переменная для параметров ШИМ + uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all; + uint16_t pwm_freq = upp.hpwm.Config.Frequency; + uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber; + + + for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) + { + adc_channel_max[i] = upp.pm.adc.Coefs[i].vMax; + adc_channel_zero[i] = upp.pm.adc.Coefs[i].lZero; + + // Максимальное измеряемое напряжение + if(__CheckSimpleParamF(&adc_channel_max[i], MB_INTERNAL.param.adc.ADC_Max[i], 10)) + { + adc_channel_update[i] = 1; + } + // Значение АЦП при нулевом входе + if(__CheckSimpleParamU16(&adc_channel_zero[i], MB_INTERNAL.param.adc.ADC_Zero[i])) + { + adc_channel_update[i] = 1; + } + } + + // Параметры алгоритма перехода через ноль + if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 100)) + { + zc_update = 1; + } + if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.Hysteresis)) + { + zc_update = 1; + } + + // Параметры ШИМ токов + if(__CheckSimpleParamU8(&pwm_phase_mask, MB_INTERNAL.param.pwm.PhaseMask, 1)) + { + pwm_update = 1; + } + if(__CheckSimpleParamU16(&pwm_freq, MB_INTERNAL.param.pwm.Frequency)) + { + pwm_update = 1; + } + if(__CheckSimpleParamU8(&pwm_pulse_num, MB_INTERNAL.param.pwm.PulseNumber, 1)) + { + pwm_update = 1; + } + + + // Обновление АЦП конфигов + for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) + { + if(adc_channel_update[i]) + { + if(ADC_ConfigChannel(&upp.pm.adc, i, adc_channel_zero[i], adc_channel_max[i], 4095) == HAL_OK) + adc_channel_update[i] = 0; + else + errors.prvt.cnt.adc_reinit_err++; + } + } + // Обновление Zero-Cross конфигов + if(zc_update) + { + if(ZC_Init(&upp.pm.zc, upp.pm.zc.Config.NumChannels, zc_hysteresis, zc_debounce) == HAL_OK) + zc_update = 0; + else + errors.prvt.cnt.zc_reinit_err++; + } + // Обновление ШИМ конфигов + if(pwm_update) + { + if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_pulse_num) == HAL_OK) + { + pwm_update = 0; + __AngleSetLimit(); + } + else + errors.prvt.cnt.pwm_reinit_err++; + } + if (upp.hangle.Config.AngleLimit == 0) + { + __AngleSetLimit(); + } +} + + +/** + * @brief Установка параметров на дефолтные значения @ref UPP_DEFAULT_PARAMS. + * @param pui_default Сбросить параметры ПУИ + * @param internal_default Сбросить внутренние параметры + * @return HAL Status. + */ +void UPP_SetDefault(int pui_default, int internal_default) +{ + if(pui_default) + { + MB_DATA.HoldRegs.pui_params.Iref = PUI_Iref_PERCENT_DEFAULT; + MB_DATA.HoldRegs.pui_params.Tnt = PUI_Tnt_MS_DEFAULT; + MB_DATA.HoldRegs.pui_params.Umin = PUI_Umin_PERCENT_DEFAULT; + MB_DATA.HoldRegs.pui_params.Umax = PUI_Umax_PERCENT_DEFAULT; + MB_DATA.HoldRegs.pui_params.Imax = PUI_Imax_PERCENT_DEFAULT; + MB_DATA.HoldRegs.pui_params.Imin = PUI_Imin_PERCENT_DEFAULT; + MB_DATA.HoldRegs.pui_params.TiMax = PUI_TiMax_US_DEFAULT; + MB_DATA.HoldRegs.pui_params.Tdelay = PUI_Tdelay_SECONDS_DEFAULT; + MB_DATA.HoldRegs.pui_params.Interlace = PUI_Interlace_EN_DEFAULT; + } + + if(internal_default) + { + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10; + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10; + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10; + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA] = ADC_I_MAX_A_DEFAULT*10; + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA] = ADC_U_ZERO_DEFAULT; + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_DEFAULT; + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT; + MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA] = ADC_I_ZERO_DEFAULT; + + MB_INTERNAL.param.pwm.PhaseMask = 0x7; // (все три фазы) + MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT; + MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT; + + MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_V_DEFAULT*100; + MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT; + //__AngleSetLimit(); + } +} + + + +static int __AngleSetLimit(void) +{ + // Перерасчет максимально допустимого угла + float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS; + float angle_limit = 1 - pulses_percent_of_period; + Angle_SetLimit(&upp.hangle, angle_limit); +} + + + +/** + * @brief Сверить и обновить float параметр из uint16_t. + * @param paramDist Указатель на float параметр + * @param paramSrc Значение для сравнения с float параметром + * @param Coef Коэффициент для приведения float к uint16_t: uint16_t = float*coef, float = uint16_t/coef + * @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc. + */ +static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef) +{ + if(paramDist == NULL) + return 0; + + uint16_t expected_mb_param = *paramDist*Coef; + if(expected_mb_param != paramSrc) + { + *paramDist = (float)paramSrc/Coef; + return 1; + } + else + { + return 0; + } +} +/** + * @brief Сверить и обновить uint32_t параметр из uint16_t. + * @param paramDist Указатель на uint32_t параметр + * @param paramSrc Значение для сравнения с uint32_t параметром + * @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint32_t*coef, uint32_t = uint16_t/coef + * @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc. + */ +static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef) +{ + if(paramDist == NULL) + return 0; + + uint16_t expected_mb_param = *paramDist*Coef; + if(expected_mb_param != paramSrc) + { + *paramDist = (uint32_t)paramSrc/Coef; + return 1; + } + else + { + return 0; + } +} +/** + * @brief Сверить и обновить uint16_t параметр из uint16_t. + * @param paramDist Указатель на uint16_t параметр + * @param paramSrc Значение для сравнения с uint16_t параметром + * @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc. + */ +static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc) +{ + if(paramDist == NULL) + return 0; + + uint16_t expected_mb_param = *paramDist; + if(expected_mb_param != paramSrc) + { + *paramDist = (uint16_t)paramSrc; + return 1; + } + else + { + return 0; + } +} + +/** + * @brief Сверить и обновить uint8_t параметр из uint16_t. + * @param paramDist Указатель на uint8_t параметр + * @param paramSrc Значение для сравнения с uint32_t параметром + * @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint8_t*coef, uint8_t = uint16_t/coef + * @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc. + */ +static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef) +{ + if(paramDist == NULL) + return 0; + + uint16_t expected_mb_param = *paramDist*Coef; + if(expected_mb_param != paramSrc) + { + *paramDist = (uint8_t)paramSrc/Coef; + return 1; + } + else + { + return 0; + } +} \ No newline at end of file diff --git a/UPP/Core/UPP/upp_control.h b/UPP/Core/UPP/upp_control.h new file mode 100644 index 0000000..6404411 --- /dev/null +++ b/UPP/Core/UPP/upp_control.h @@ -0,0 +1,67 @@ +/** +****************************************************************************** +* @file upp_control.h +* @brief Модуль определябщий поведение УПП +****************************************************************************** +* @details +******************************************************************************/ + +#ifndef _UPP_CONTROL_H +#define _UPP_CONTROL_H +#include "upp_defs.h" + +typedef struct +{ + unsigned set_default_pui:1; + unsigned set_default_internal:1; + unsigned go:1; + unsigned stop:1; + + + unsigned reserved:11; + unsigned reset_mcu:1; +}UPP_FuncCalls_t; + + +typedef struct +{ + /* Параметры АЦП */ + struct + { + uint16_t ADC_Max[4]; + uint16_t ADC_Zero[4]; + }adc; + + /* Параметры ШИМ */ + struct + { + uint16_t PhaseMask; + uint16_t Frequency; + uint16_t PulseNumber; + }pwm; + + /* Параметры Угла */ + struct + { + uint16_t Hysteresis; + uint16_t DebouneCouner; + }zc; + + /* Параметры Угла */ + struct + { + uint16_t Angle_Max; + uint16_t Angle_Min; + }angle; + + + +}UPP_PrvtParams_t; + + +/* Контроль внутренних параметров УПП. */ +void UPP_Control_InternalParams(void); +/* Установка параметров на дефолтные значения */ +void UPP_SetDefault(int pui_default, int internal_default); + +#endif //_UPP_CONTROL_H \ No newline at end of file diff --git a/UPP/Core/UPP/upp_errors.c b/UPP/Core/UPP/upp_errors.c new file mode 100644 index 0000000..02ebc29 --- /dev/null +++ b/UPP/Core/UPP/upp_errors.c @@ -0,0 +1,44 @@ +/** +****************************************************************************** +* @file upp_errors.c +* @brief Ошибки УПП и их обработка +****************************************************************************** +* @details +******************************************************************************/ +#include "upp_errors.h" // всё остальное по работе с УПП +UPP_Errors_t errors; + +static UPP_ErrorType_t UPP_SelectCommonError(void) +{ + // Пока нет ошибки + UPP_ErrorType_t best = Err_None; + // Приоритет отсутствия ошибок + uint8_t best_prio = UPP_ErrorPriority[Err_None]; + + // Перебираем все возможные ошибки по enum + for (int e = Err_None + 1; e <= Err_UnderFrequency; e++) + { + // Проверяем: установлен ли соответствующий бит в pui.all + // e-1, потому что ошибка №1 = бит 0, ошибка №2 = бит 1 и т.д. + if (errors.pui.all & (1u << (e - 1))) + { + // Получаем приоритет этой ошибки + uint8_t pr = UPP_ErrorPriority[e]; + + // Если её приоритет лучше (меньше число) — запоминаем + if (pr < best_prio) + { + best_prio = pr; + best = (UPP_ErrorType_t)e; + } + } + } + + // Возвращаем самую важную (наивысшего приоритета) ошибку + return best; +} + +void UPP_ErrorsHandle(void) +{ + errors.common = UPP_SelectCommonError(); +} \ No newline at end of file diff --git a/UPP/Core/UPP/upp_errors.h b/UPP/Core/UPP/upp_errors.h new file mode 100644 index 0000000..9bed663 --- /dev/null +++ b/UPP/Core/UPP/upp_errors.h @@ -0,0 +1,124 @@ +/** +****************************************************************************** +* @file upp_errors.h +* @brief Ошибки УПП и их обработка +****************************************************************************** +* @details +******************************************************************************/ + +#ifndef _UPP_ERRORS_H +#define _UPP_ERRORS_H +#include "upp_defs.h" + + +/** + * @brief Приоритет ПУИ ошибок + */ +static const uint8_t UPP_ErrorPriority[] = +{ + [Err_None] = 255, + + /* Фатальные ошибки */ + [Err_LossPhaseAll] = 1, + [Err_OverCurrent] = 2, + [Err_OverVoltage] = 3, + [Err_OverTemperature] = 4, + [Err_Power_24V] = 5, + [Err_Power_Digit_5V] = 6, + [Err_Power_DIO_24V] = 7, + [Err_Power_Analog_5V] = 8, + + /* Критичные */ + [Err_LossPhaseA] = 10, + [Err_LossPhaseB] = 11, + [Err_LossPhaseC] = 12, + [Err_LongStart] = 13, + [Err_Interlace] = 14, + + /* Пограничные параметры */ + [Err_UnderVoltage] = 20, + [Err_OverFrequency] = 21, + [Err_UnderFrequency] = 22, + + /* Внутренние */ + [Err_Internal_1] = 40, + [Err_Internal_2] = 41, + [Err_Internal_3] = 42, + [Err_Internal_4] = 43, + [Err_Internal_5] = 44, + [Err_Internal_6] = 45, +}; + + + +/** + * @brief Структура с всеми ошибками УПП + */ +typedef struct +{ + UPP_ErrorType_t common; ///< Общая ошибка @ref UPP_ErrorType_t; + + union + { + uint32_t all; + struct + { + /* Програмные ошибки */ + unsigned Internal_1:1; ///< Внутренняя неисправность УПП 1 + unsigned Internal_2:1; ///< Внутренняя неисправность УПП 2 + unsigned Internal_3:1; ///< Внутренняя неисправность УПП 3 + unsigned Internal_4:1; ///< Внутренняя неисправность УПП 4 + unsigned Internal_5:1; ///< Внутренняя неисправность УПП 5 + unsigned Internal_6:1; ///< Внутренняя неисправность УПП 6 + + /* Ошибки по питанию */ + unsigned Power_Digit_5V:1; ///< Неисправность цифрового источника питания (5 В) + unsigned Power_24V:1; ///< Неисправность источника питания 24 В + unsigned Power_Analog_5V:1; ///< Неисправность аналогового источника питания микроконтроллера (± 5 В) + unsigned Power_SCI_5V:1; ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В) + unsigned Power_DIO_24V:1; ///< Неисправность источника питания дискретных входов/выходов (24 В) + + /* Ошибки по допустимым пределам Наряжений/Токов/Температуры */ + unsigned OverCurrent:1; ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t) + unsigned OverVoltage:1; ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t) + unsigned OverTemperature:1; ///< Температура выше допустимой (плюс 85 °C) + unsigned UnderVoltage:1; ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t) + + /* Ошибки по обрывам фаз */ + unsigned LossPhaseA:1; ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t) + unsigned LossPhaseB:1; ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t) + unsigned LossPhaseC:1; ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t) + + /* Другие ошибки */ + unsigned LongStart:1; ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t) + unsigned Interlace:1; ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t) + unsigned OverFrequency:1; ///< Частота сети выше допустимой + unsigned UnderFrequency:1; ///< Частота сети ниже допустимой + }err; + }pui; + + struct + { + union + { + uint64_t all; + struct + { + unsigned :1; + }err; + }f; + + struct + { + uint16_t adc_reinit_err; + uint16_t zc_reinit_err; + uint16_t pwm_reinit_err; + }cnt; + + }prvt; ///< Приватные ошибки, не идущие напрямую в ПУИ +}UPP_Errors_t; +extern UPP_Errors_t errors; + +void UPP_ErrorsHandle(void); + +#endif //_UPP_ERRORS_H \ No newline at end of file diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c index a6a3571..9356f6e 100644 --- a/UPP/Core/UPP/upp_main.c +++ b/UPP/Core/UPP/upp_main.c @@ -6,6 +6,7 @@ * @details ******************************************************************************/ #include "upp_main.h" // всё остальное по работе с УПП + UPP_t upp; float alpha_dbg = 0.5; // ОСНОВНОЙ ЦИКЛ main.c @@ -16,12 +17,18 @@ float alpha_dbg = 0.5; */ int UPP_Init(void) { + // Подключение указателей + upp.errors = &errors; + upp.PUI.params = &MB_DATA.HoldRegs.pui_params; + upp.PUI.values = &MB_DATA.InRegs.pui; + upp.call = &MB_INTERNAL.FuncCalls; + HAL_TIM_Base_Start(&ustim); PowerMonitor_Init(&upp.pm); - upp.hpwm.Config.Frequency = 20000; - upp.hpwm.Config.PulseNumber = 20; PWM_Init(&upp.hpwm); - Angle_Init(&upp.hangle, 0, 0.8); + Angle_Init(&upp.hangle); + + upp.workmode = WM_Ready; return 0; } @@ -31,8 +38,9 @@ int UPP_Init(void) */ int UPP_PreWhile(void) { + UPP_Control_InternalParams(); + Angle_SetRange(&upp.hangle, 0.0, 0.8); PowerMonitor_Start(&upp.pm); - upp.hpwm.Config.PhaseMask.all = 0x7; return 0; } @@ -41,11 +49,85 @@ int UPP_PreWhile(void) * @return 0 - если ОК, >1 если ошибка. */ int UPP_While(void) -{ +{ + // если ошибка вызываем СТОП + if(errors.pui.all) + { + upp.call->stop = 1; + } + // иначе снимаем СТОП + else + { + upp.call->stop = 0; + } + + + // Сброс на дефолтные по запросу + if(upp.call->set_default_pui) + { + UPP_SetDefault(1, 0); + } + if(upp.call->set_default_internal) + { + UPP_SetDefault(0, 1); + } + + + + // Если СТОП - переходим в ошибку + if (upp.call->stop) + upp.workmode = WM_Error; + // Автомат состояний УПП + switch(upp.workmode) + { + case WM_Ready: + // если пришла команда на запуск + if (upp.call->go) + { + upp.workmode = WM_Running; + upp.StartTick = local_time(); + } + break; + + case WM_Running: + // если пришла команда на остановку + if (!upp.call->go) + upp.workmode = WM_Ready; + + // если слишком долгий запуск + if((local_time() - upp.StartTick) > (upp.PUI.params->Tdelay*1000)) + { + errors.pui.err.LongStart = 1; + } + break; + + case WM_Error: + if(errors.common == Err_None) + upp.workmode = WM_Ready; + + PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ + break; + } + return 0; } + + +/** + * @brief Всякое что будет делатся каждую 1 мс. + */ +void UPP_Tick(void) +{ + if(upp.workmode == WM_Not_Init) + return; + UPP_ErrorsHandle(); + UPP_Control_InternalParams(); +} + + + // ПРЕРЫВАНИЯ stm32f4xx_it.c void UPP_ADC_Handle(void) @@ -57,41 +139,53 @@ void UPP_ADC_Handle(void) // Если произошел Zero Cross if(ZC_isOccurred(&upp.pm.zc, phase)) { - // Меняем полуволну тиристора - UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase); - PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave); - Angle_Start(&upp.hangle, phase, alpha_dbg, 100); + // Если УПП в работе + if(upp.workmode == WM_Running) + { + // Меняем полуволну тиристора + UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase); + PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave); + // Начинаем отсчитывать угол + Angle_Start(&upp.hangle, phase, alpha_dbg, 10); + } } } + + // Проверяем на ошибки } void UPP_PWM_Handle(void) { PWM_Handle(&upp.hpwm); } +void UPP_Angle_Handle(void) +{ + UPP_Phase_t phase = Angle_Handle(&upp.hangle); + Angle_Reset(&upp.hangle, phase); + // Если УПП в работе + if(upp.workmode == WM_Running) + { + switch(phase) + { + case UPP_PHASE_A: + PWM_Start(&upp.hpwm, UPP_PHASE_A); + break; + case UPP_PHASE_B: + PWM_Start(&upp.hpwm, UPP_PHASE_B); + break; + case UPP_PHASE_C: + PWM_Start(&upp.hpwm, UPP_PHASE_C); + break; + default: + break; + } + } +} + void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim) { if (htim == upp.hangle.htim) { UPP_Angle_Handle(); } -} -void UPP_Angle_Handle(void) -{ - UPP_Phase_t phase = Angle_Handle(&upp.hangle); - Angle_Reset(&upp.hangle, phase); - switch(phase) - { - case UPP_PHASE_A: - PWM_Start(&upp.hpwm, UPP_PHASE_A); - break; - case UPP_PHASE_B: - PWM_Start(&upp.hpwm, UPP_PHASE_B); - break; - case UPP_PHASE_C: - PWM_Start(&upp.hpwm, UPP_PHASE_C); - break; - default: - break; - } } \ No newline at end of file diff --git a/UPP/Core/UPP/upp_main.h b/UPP/Core/UPP/upp_main.h index 54b3f56..62bc657 100644 --- a/UPP/Core/UPP/upp_main.h +++ b/UPP/Core/UPP/upp_main.h @@ -1,6 +1,6 @@ /** ****************************************************************************** -* @file modbus_data.h +* @file upp_main.h * @brief Определения структур данных Modbus устройства ****************************************************************************** * @details @@ -9,19 +9,35 @@ #ifndef _UPP_MAIN_H #define _UPP_MAIN_H -#include "main.h" // либы из AllLibs и вербальные имена из CubeMX -#include "upp_config.h" +#include "main.h" // общие библиотеки, конфигурации и вербальные имена из CubeMX #include "power_monitor.h" // статистика сети и АЦП #include "pwm_thyristors.h" // Управление тиристорами #include "angle_control.h" // Управление углом открытия +#include "upp_status.h" // статус упп +#include "upp_control.h" // управление упп + extern float alpha_dbg; + typedef struct { - PowerMonitor_t pm; - PWM_Handle_t hpwm; - Angle_Handle_t hangle; + UPP_WorkModeType_t workmode; ///< Режим УПП + UPP_FuncCalls_t *call; ///< Вызов функций УПП + + PowerMonitor_t pm; ///< Мониторинг сети + PWM_Handle_t hpwm; ///< Хендл ШИМ тиристоров + Angle_Handle_t hangle; ///< Хендл отсчитывания угла открытия + + struct + { + UPP_PUI_Params_t *params; ///< Параметры от ПУИ + UPP_PUI_Values_t *values; ///< Данные для ПУИ + } PUI; ///< Общение с ПУИ + + + UPP_Errors_t *errors; ///< Ошибки УПП + uint32_t StartTick; }UPP_t; extern UPP_t upp; @@ -32,7 +48,10 @@ int UPP_Init(void); int UPP_PreWhile(void); /* Основной цикл УПП. */ int UPP_While(void); +/* Всякое что будет делатся каждую 1 мс. */ +void UPP_Tick(void); +// Прерывания void UPP_ADC_Handle(void); void UPP_PWM_Handle(void); void UPP_Angle_Handle(void); diff --git a/UPP/Core/UPP/upp_status.c b/UPP/Core/UPP/upp_status.c new file mode 100644 index 0000000..ed27e20 --- /dev/null +++ b/UPP/Core/UPP/upp_status.c @@ -0,0 +1,12 @@ +/** +****************************************************************************** +* @file upp_status.c +* @brief Модуль определяющий состояние УПП +****************************************************************************** +* @details +******************************************************************************/ +#include "upp_main.h" // всё остальное по работе с УПП + +void UPP_Status_Handler(void) +{ +} \ No newline at end of file diff --git a/UPP/Core/UPP/upp_status.h b/UPP/Core/UPP/upp_status.h new file mode 100644 index 0000000..e33d67f --- /dev/null +++ b/UPP/Core/UPP/upp_status.h @@ -0,0 +1,13 @@ +/** +****************************************************************************** +* @file upp_status.h +* @brief Модуль определяющий состояние УПП +****************************************************************************** +* @details +******************************************************************************/ + +#ifndef _UPP_STATUS_H +#define _UPP_STATUS_H + + +#endif //_UPP_STATUS_H \ No newline at end of file diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx index 7736db4..a8f9a56 100644 --- a/UPP/MDK-ARM/UPP.uvoptx +++ b/UPP/MDK-ARM/UPP.uvoptx @@ -206,6 +206,18 @@ 0 0 0 + ..\Core\Configs\upp_defs.h + upp_defs.h + 0 + 0 + + + 1 + 3 + 5 + 0 + 0 + 0 ..\Core\Inc\main.h main.h 0 @@ -213,7 +225,7 @@ 1 - 3 + 4 5 0 0 @@ -225,7 +237,7 @@ 1 - 4 + 5 1 0 0 @@ -237,7 +249,7 @@ 1 - 5 + 6 5 0 0 @@ -249,7 +261,7 @@ 1 - 6 + 7 5 0 0 @@ -261,7 +273,7 @@ 1 - 7 + 8 5 0 0 @@ -273,7 +285,7 @@ 1 - 8 + 9 5 0 0 @@ -285,7 +297,7 @@ 1 - 9 + 10 5 0 0 @@ -305,7 +317,7 @@ 0 2 - 10 + 11 1 0 0 @@ -317,7 +329,7 @@ 2 - 11 + 12 5 0 0 @@ -329,7 +341,7 @@ 2 - 12 + 13 1 0 0 @@ -341,7 +353,7 @@ 2 - 13 + 14 5 0 0 @@ -353,7 +365,7 @@ 2 - 14 + 15 1 0 0 @@ -365,7 +377,7 @@ 2 - 15 + 16 5 0 0 @@ -375,6 +387,78 @@ 0 0 + + 2 + 17 + 1 + 0 + 0 + 0 + ..\Core\UPP\upp_control.c + upp_control.c + 0 + 0 + + + 2 + 18 + 5 + 0 + 0 + 0 + ..\Core\UPP\upp_control.h + upp_control.h + 0 + 0 + + + 2 + 19 + 1 + 0 + 0 + 0 + ..\Core\UPP\upp_status.c + upp_status.c + 0 + 0 + + + 2 + 20 + 5 + 0 + 0 + 0 + ..\Core\UPP\upp_status.h + upp_status.h + 0 + 0 + + + 2 + 21 + 1 + 0 + 0 + 0 + ..\Core\UPP\upp_errors.c + upp_errors.c + 0 + 0 + + + 2 + 22 + 5 + 0 + 0 + 0 + ..\Core\UPP\upp_errors.h + upp_errors.h + 0 + 0 + @@ -385,7 +469,7 @@ 0 3 - 16 + 23 1 0 0 @@ -397,7 +481,7 @@ 3 - 17 + 24 5 0 0 @@ -409,7 +493,7 @@ 3 - 18 + 25 1 0 0 @@ -421,7 +505,7 @@ 3 - 19 + 26 5 0 0 @@ -433,7 +517,7 @@ 3 - 20 + 27 1 0 0 @@ -445,7 +529,7 @@ 3 - 21 + 28 5 0 0 @@ -465,7 +549,7 @@ 0 4 - 22 + 29 1 0 0 @@ -477,7 +561,7 @@ 4 - 23 + 30 1 0 0 @@ -489,7 +573,7 @@ 4 - 24 + 31 1 0 0 @@ -501,7 +585,7 @@ 4 - 25 + 32 1 0 0 @@ -513,7 +597,7 @@ 4 - 26 + 33 1 0 0 @@ -525,7 +609,7 @@ 4 - 27 + 34 1 0 0 @@ -537,7 +621,7 @@ 4 - 28 + 35 1 0 0 @@ -549,7 +633,7 @@ 4 - 29 + 36 1 0 0 @@ -561,7 +645,7 @@ 4 - 30 + 37 1 0 0 @@ -573,7 +657,7 @@ 4 - 31 + 38 1 0 0 @@ -585,7 +669,7 @@ 4 - 32 + 39 1 0 0 @@ -597,7 +681,7 @@ 4 - 33 + 40 1 0 0 @@ -609,7 +693,7 @@ 4 - 34 + 41 1 0 0 @@ -629,7 +713,7 @@ 0 5 - 35 + 42 5 0 0 @@ -641,7 +725,7 @@ 5 - 36 + 43 5 0 0 @@ -653,7 +737,7 @@ 5 - 37 + 44 5 0 0 @@ -665,7 +749,7 @@ 5 - 38 + 45 5 0 0 @@ -677,7 +761,7 @@ 5 - 39 + 46 5 0 0 @@ -689,7 +773,7 @@ 5 - 40 + 47 5 0 0 @@ -701,7 +785,7 @@ 5 - 41 + 48 1 0 0 @@ -713,7 +797,7 @@ 5 - 42 + 49 5 0 0 @@ -733,7 +817,7 @@ 0 6 - 43 + 50 1 0 0 @@ -745,7 +829,7 @@ 6 - 44 + 51 1 0 0 @@ -757,7 +841,7 @@ 6 - 45 + 52 1 0 0 @@ -769,7 +853,7 @@ 6 - 46 + 53 1 0 0 @@ -781,7 +865,7 @@ 6 - 47 + 54 1 0 0 @@ -793,7 +877,7 @@ 6 - 48 + 55 1 0 0 @@ -805,7 +889,7 @@ 6 - 49 + 56 1 0 0 @@ -817,7 +901,7 @@ 6 - 50 + 57 1 0 0 @@ -829,7 +913,7 @@ 6 - 51 + 58 1 0 0 @@ -841,7 +925,7 @@ 6 - 52 + 59 1 0 0 @@ -853,7 +937,7 @@ 6 - 53 + 60 1 0 0 @@ -865,7 +949,7 @@ 6 - 54 + 61 1 0 0 @@ -885,7 +969,7 @@ 0 7 - 55 + 62 1 0 0 @@ -897,7 +981,7 @@ 7 - 56 + 63 1 0 0 @@ -917,7 +1001,7 @@ 0 8 - 57 + 64 1 0 0 @@ -929,7 +1013,7 @@ 8 - 58 + 65 1 0 0 @@ -941,7 +1025,7 @@ 8 - 59 + 66 1 0 0 @@ -953,7 +1037,7 @@ 8 - 60 + 67 1 0 0 @@ -965,7 +1049,7 @@ 8 - 61 + 68 1 0 0 @@ -985,7 +1069,7 @@ 0 9 - 62 + 69 1 0 0 @@ -997,7 +1081,7 @@ 9 - 63 + 70 1 0 0 @@ -1009,7 +1093,7 @@ 9 - 64 + 71 1 0 0 @@ -1021,7 +1105,7 @@ 9 - 65 + 72 1 0 0 @@ -1033,7 +1117,7 @@ 9 - 66 + 73 1 0 0 @@ -1045,7 +1129,7 @@ 9 - 67 + 74 1 0 0 @@ -1057,7 +1141,7 @@ 9 - 68 + 75 1 0 0 @@ -1069,7 +1153,7 @@ 9 - 69 + 76 1 0 0 @@ -1081,7 +1165,7 @@ 9 - 70 + 77 1 0 0 @@ -1093,7 +1177,7 @@ 9 - 71 + 78 1 0 0 @@ -1105,7 +1189,7 @@ 9 - 72 + 79 1 0 0 @@ -1117,7 +1201,7 @@ 9 - 73 + 80 1 0 0 @@ -1129,7 +1213,7 @@ 9 - 74 + 81 1 0 0 @@ -1141,7 +1225,7 @@ 9 - 75 + 82 1 0 0 @@ -1153,7 +1237,7 @@ 9 - 76 + 83 1 0 0 @@ -1165,7 +1249,7 @@ 9 - 77 + 84 1 0 0 @@ -1177,7 +1261,7 @@ 9 - 78 + 85 1 0 0 @@ -1189,7 +1273,7 @@ 9 - 79 + 86 1 0 0 @@ -1201,7 +1285,7 @@ 9 - 80 + 87 1 0 0 @@ -1213,7 +1297,7 @@ 9 - 81 + 88 1 0 0 @@ -1225,7 +1309,7 @@ 9 - 82 + 89 1 0 0 @@ -1237,7 +1321,7 @@ 9 - 83 + 90 1 0 0 @@ -1249,7 +1333,7 @@ 9 - 84 + 91 1 0 0 @@ -1261,7 +1345,7 @@ 9 - 85 + 92 1 0 0 @@ -1281,7 +1365,7 @@ 0 10 - 86 + 93 1 0 0 @@ -1301,7 +1385,7 @@ 0 11 - 87 + 94 2 0 0 diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index 585e041..ff631f5 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -17,8 +17,8 @@ STM32F427ZGTx STMicroelectronics - Keil.STM32F4xx_DFP.2.17.1 - https://www.keil.com/pack/ + Keil.STM32F4xx_DFP.2.16.0 + http://www.keil.com/pack/ IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ @@ -390,6 +390,11 @@ 5 ..\Core\Configs\upp_config.h + + upp_defs.h + 5 + ..\Core\Configs\upp_defs.h + main.h 5 @@ -465,6 +470,36 @@ 5 ..\Core\UPP\angle_control.h + + upp_control.c + 1 + ..\Core\UPP\upp_control.c + + + upp_control.h + 5 + ..\Core\UPP\upp_control.h + + + upp_status.c + 1 + ..\Core\UPP\upp_status.c + + + upp_status.h + 5 + ..\Core\UPP\upp_status.h + + + upp_errors.c + 1 + ..\Core\UPP\upp_errors.c + + + upp_errors.h + 5 + ..\Core\UPP\upp_errors.h +