Compare commits

...

2 Commits

Author SHA1 Message Date
854ea6f6c2 Улушения:
- логики дма (только по полному заполнению)
- фильтров
- расчетов действующих значений
- параметров (сатурация, сделан параметр время нарастания пуска Tnt, добавлен параметр скважность пачки импульсов)
2025-11-28 18:25:05 +03:00
5624468d09 изменения под старую плату УПП 2025-11-27 12:17:58 +03:00
29 changed files with 426 additions and 212 deletions

View File

@ -95,16 +95,76 @@ void DMA_Sim_Transfer(DMA_TypeDef* DMAx, uint32_t stream)
stream_sim->current_index++;
// Проверяем завершение передачи
// Определяем какой регистр использовать (LISR или HISR) в зависимости от потока
volatile uint32_t* lisr_reg = NULL;
volatile uint32_t* hisr_reg = NULL;
uint32_t tcif_mask = 0;
uint32_t htif_mask = 0;
// Настраиваем маски флагов в зависимости от потока
if (DMAx == DMA1) {
lisr_reg = &DMA1->LISR;
hisr_reg = &DMA1->HISR;
}
#ifdef DMA2
else if (DMAx == DMA2) {
lisr_reg = &DMA2->LISR;
hisr_reg = &DMA2->HISR;
}
#endif
// Устанавливаем маски для конкретного потока
switch (stream) {
case 0:
case 4:
tcif_mask = DMA_FLAG_TCIF0_4; htif_mask = DMA_FLAG_HTIF0_4; break;
case 1:
case 5:
tcif_mask = DMA_FLAG_TCIF1_5; htif_mask = DMA_FLAG_HTIF1_5; break;
case 2:
case 6:
tcif_mask = DMA_FLAG_TCIF2_6; htif_mask = DMA_FLAG_HTIF2_6; break;
case 3:
case 7:
tcif_mask = DMA_FLAG_TCIF3_7; htif_mask = DMA_FLAG_HTIF3_7; break;
};
// Проверяем и выставляем флаги
if (stream_sim->current_index == stream_sim->buffer_size / 2) {
// Половинное заполнение - выставляем флаг HTIF
if (stream < 4) {
*lisr_reg |= htif_mask; // Потоки 0-3 в LISR
}
else {
*hisr_reg |= htif_mask; // Потоки 4-7 в HISR
}
// Вызываем обработчик прерывания
//DMA_Call_IRQHandller(DMAx, stream); //todo
}
if (stream_sim->current_index >= stream_sim->buffer_size) {
// Полное заполнение - выставляем флаг TCIF
if (stream < 4) {
*lisr_reg |= tcif_mask; // Потоки 0-3 в LISR
}
else {
*hisr_reg |= tcif_mask; // Потоки 4-7 в HISR
}
stream_sim->transfer_complete = 1;
if (stream_sim->circular_mode) {
stream_sim->current_index = 0;
} else {
// В циклическом режиме не сбрасываем флаги - они должны быть сброшены программно
}
else {
stream_sim->transfer_enabled = 0;
stream_sim->enabled = 0;
DMA_Call_IRQHandller(DMAx, stream);
}
// Вызываем обработчик прерывания
DMA_Call_IRQHandller(DMAx, stream);
}
}

View File

@ -84,6 +84,12 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port)
WriteOutputArray(upp.pm.measured.final.I[2], ind_port, nn++);
WriteOutputArray(upp.pm.measured.final.Fmean, ind_port, nn++);
}
{ //20-21
WriteOutputArray(upp.pm.isr_cnt, ind_port, nn++);
WriteOutputArray(upp.pm.slow_cnt, ind_port, nn++);
}
}
@ -123,7 +129,7 @@ void app_readInputs(const real_T* Buffer) {
MB_INTERNAL.param.angle.PID_Kp = ReadInputArray(1, 4) * 10000;
MB_INTERNAL.param.angle.PID_Ki = ReadInputArray(1, 5) * 10000;
MB_INTERNAL.param.angle.PID_Kd = ReadInputArray(1, 6) * 10000;
MB_INTERNAL.param.angle.PID_ExpAlpha = ReadInputArray(1, 7) * 65535;
MB_DATA.HoldRegs.pui_params.Tnt = ReadInputArray(1, 7) * 1000;
MB_INTERNAL.param.nominal.U = ReadInputArray(1, 8) * 10;
MB_INTERNAL.param.nominal.I = ReadInputArray(1, 9) * 10;

Binary file not shown.

@ -1 +1 @@
Subproject commit 513f56fe7dbf0fa8e6a075c22e138c908a01d33f
Subproject commit 30fdbc35ddb1a72a5102aece8863921af0e4078d

@ -1 +1 @@
Subproject commit 11c00f1e0c94ebd2cae77e17453005e32dfe5a3c
Subproject commit c0733a1d31ebd7b334dee6b1a8c2b00767fdbfca

View File

@ -97,12 +97,14 @@
#define BENCH_TIME_ENABLE ///< Включить бенч времени
#define BENCH_TIME_MAX_CHANNELS 5 ///< Максимальное количество каналов измерения
#define BENCH_TIME_MAX_CHANNELS 6 ///< Максимальное количество каналов измерения
#define BT_SLOWCALC 0
#define BT_ADC 1
#define BT_PWM 2
#define BT_SYSTICK 3
#define BT_SLOWCALC_PRD 0
#define BT_SLOWCALC 1
#define BT_ADC 2
#define BT_ADC_PRD 3
#define BT_PWM 4
#define BT_SYSTICK 5
/** GEN_CONFIG
* @}
*/

View File

@ -51,7 +51,7 @@
/* Номинальные параметры */
#define NOM_PHASE_NUMB 3
#define NOM_U_V_DEFAULT 1216
#define NOM_U_V_DEFAULT 380
#define NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT 6
#define NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT 10
#define NOM_F_HZ_DEFAULT 50
@ -62,6 +62,7 @@
/* Параметры ПУИ */
#define PUI_Iref_PERCENT_DEFAULT 1.5
#define PUI_Tnt_MS_DEFAULT 300
#define PUI_Tnt_CalcAlpha(...) FilterExp_CalcAlpha95(__VA_ARGS__) ///< Уровень в процентах, до куда нарастет ток за время Tnt
#define PUI_Umin_PERCENT_DEFAULT 0.8
#define PUI_Umax_PERCENT_DEFAULT 1.2
#define PUI_Imax_PERCENT_DEFAULT 0.99
@ -83,7 +84,6 @@
#define ANGLE_PID_KP_COEF_DEFAULT 0.0001
#define ANGLE_PID_KI_COEF_DEFAULT 0.0001
#define ANGLE_PID_KD_COEF_DEFAULT 0
#define ANGLE_REF_TAU_COEF_DEFAULT 20.0
/* Параметри мониторинга сети */
#define PM_EXP_TAU_COEF_DEFAULT 0.05
@ -99,7 +99,8 @@
#define ZERO_CROSS_DEBOUNCE_CNT_DEFAULT 2*100 // (2.5 * 100 = 2.5 мс)
/* Параметры ШИМ для тиристоров */
#define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000
#define PWM_THYR_FREQUENCY_HZ_DEFAULT 16000
#define PWM_THYR_DUTY_PERCENT_DEFAULT 0.5
#define PWM_THYR_PULSE_NUMBER_DEFAULT 20
/** //UPP_PARAMS_DEFAULT
@ -115,11 +116,11 @@
*/
/* Периоды обновления всякого */
#define PM_ADC_PERIOD_US 30 ///< Период опроса АЦП в мкс
#define PM_SLOW_PERIOD_US 500 ///< Период обновления медленных расчетов в мкс (чтобы делилось на @ref PM_ADC_PERIOD_US)
#define PM_TEMP_SLOW_PERIOD_MS 1000 ///< Период опроса АЦП в мс
#define PM_F_SLOW_PERIOD_MS 40 ///< Период обновления частоты в мс
#define UPP_INIT_BEFORE_READY_MS 2000 ///< Сколько сканировать сеть, перед выставлением состояния готовности
#define PM_ADC_PERIOD_US 25 ///< Период опроса АЦП в мкс
#define PM_SLOW_PERIOD_US 500 ///< Период обновления медленных расчетов в мкс (чтобы делилось на @ref PM_ADC_PERIOD_US)
#define PM_TEMP_SLOW_PERIOD_MS 1000 ///< Период обновлениия (фильтрации) датчиков температуры в мс
#define PM_F_SLOW_PERIOD_MS 40 ///< Период обновления (фильтрации) частоты в мс
#define UPP_INIT_BEFORE_READY_MS 2000 ///< Сколько сканировать сеть, перед выставлением состояния готовности
/* Частоты таймеров в МГц*/
#define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы)
@ -128,19 +129,32 @@
#define ADC_TIM3_FREQ_MZH 90 ///< Частота тиков таймера АЦП
#define ANGLE_TIM2_FREQ_MHZ 90 ///< Частота тиков таймера отсчета угла открытия тиристоров
/** //UPP_COMPILED_PARAMS
* @}
*/
// ===== ОТЛАДОЧНЫЕ ШТУКИ ДЛЯ 417 ======
#if defined(STM32F417xx)
// У старой платы УПП другие диапазоны датчиков
#undef ADC_U_MAX_V_DEFAULT
#undef ADC_I_MAX_A_DEFAULT
#define ADC_U_MAX_V_DEFAULT 707.11
#define ADC_I_MAX_A_DEFAULT 424.26
// У 417 меньше частота поэтому меняем прескалер
#undef PWM_TIM1_FREQ_MHZ
#undef PWM_TIM8_FREQ_MHZ
#undef US_TIM5_FREQ_MHZ
#undef ADC_TIM3_FREQ_MZH
#undef ANGLE_TIM2_FREQ_MHZ
// У 417 меньше частота поэтому меняем прескалер
#define PWM_TIM1_FREQ_MHZ 168 ///< Частота тиков таймера ШИМ (1-4 каналы)
#define PWM_TIM8_FREQ_MHZ 168 ///< Частота тиков таймера ШИМ (5-6 каналы)
#define US_TIM5_FREQ_MHZ 84 ///< Частота тиков микросекундного таймера
@ -148,9 +162,10 @@
#define ANGLE_TIM2_FREQ_MHZ 84 ///< Частота тиков таймера отсчета угла открытия тиристоров
#define HAL_PWREx_EnableOverDrive() HAL_ERROR
#endif
// ===== ОТЛАДОЧНЫЕ ШТУКИ ДЛЯ MATLAB ======
#endif //defined(STM32F417xx)
// ===== ОТЛАДОЧНЫЕ ШТУКИ ДЛЯ MATLAB ======
#if defined(MATLAB)
#undef UPP_INIT_BEFORE_READY_MS
@ -158,8 +173,5 @@
#define UPP_INIT_BEFORE_READY_MS 100 ///< Сколько сканировать сеть, перед выставлением состояния готовности
#endif
/** //UPP_COMPILED_PARAMS
* @}
*/
#endif //defined(MATLAB)
#endif //_UPP_CONFIG_H_

View File

@ -158,8 +158,7 @@ typedef struct {
/* Перерасчеты в тики */
#define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000) ///< Период обновления частоты в тиках @ref PM_SLOW_PERIOD_CNT
/* Расчет коэффициента альфа для экспоненциального фильтра */
#define CALC_TAU_COEF(tau, TsUs) (((float)TsUs/1000000) / (((float)TsUs/1000000) + (tau)))
#define SQRT2 1.4142135
/* Дефайны для "удобного" доступа к структурам */
#define PARAM_INTERNAL MB_INTERNAL.param

View File

@ -104,7 +104,7 @@ HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs)
HAL_TIM_Base_Stop(adc->htim);
// Запускаем таймер который будет запускать опрос АЦП с заданным периодом
__HAL_TIM_SET_AUTORELOAD_FORCE(adc->htim, TIM_MicrosToTick(PeriodUs, ADC_TIM3_FREQ_MZH-1));
__HAL_TIM_SET_AUTORELOAD_FORCE(adc->htim, TIM_MicrosToTick(PeriodUs, ADC_TIM3_FREQ_MZH));
res = HAL_TIM_Base_Start(adc->htim);
if(res != HAL_OK)

View File

@ -162,15 +162,17 @@ void PowerMonitor_SlowCalc(PowerMonitor_t *hpm)
/* Средниее напряжение фазы */
uphase_mean = fabsf(meas->slow.U[i]);
meas->final.U[i] = Filter_Process(&hpm->exp[EXP_UBA+i], uphase_mean);
uphase_mean = Filter_Process(&hpm->exp[EXP_UBA+i], uphase_mean);
meas->final.U[i] = uphase_mean*PI/2/SQRT2; /*PI/2 - получить амплитудное, SQRT2 - получить действующее */
/* Средний ток фазы */
iphase_mean = fabsf(meas->slow.I[i]);
meas->final.I[i] = Filter_Process(&hpm->exp[EXP_IC+i], iphase_mean);
iphase_mean = Filter_Process(&hpm->exp[EXP_IC+i], iphase_mean)*PI/2;
meas->final.I[i] = iphase_mean*PI/2/SQRT2; /*PI/2 - получить амплитудное, SQRT2 - получить действующее */
/* Реальные единицы измерения (Вольты/Амперы) */
meas->real.I[i] = meas->slow.I[i]*i_base;
meas->real.U[i] = meas->slow.U[i]*u_base;
meas->real.I[i] = meas->final.I[i]*i_base;
meas->real.U[i] = meas->final.U[i]*u_base;
}
/* Получение средней частоты по трем фазам */
meas->final.Fmean = fmean / 3;
@ -186,12 +188,13 @@ void PowerMonitor_SlowCalc(PowerMonitor_t *hpm)
/* Расчет амплитуд трехфазной сети */
float uamp = vector_abs_linear_calc(meas->slow.U[U_BA], meas->slow.U[U_AC]);
float iamp = vector_abs_phase_calc(meas->slow.I[I_A], meas->slow.I[I_C]);
float uamp = vector_abs_linear_calc(meas->slow.U[U_BA], meas->slow.U[U_AC])/SQRT2; /* SQRT2 - получить действующее */
float iamp = vector_abs_phase_calc(meas->slow.I[I_A], meas->slow.I[I_C])/SQRT2; /* SQRT2 - получить действующее */
meas->final.Uamp = Filter_Process(&hpm->exp[EXP_U], uamp);
meas->final.Iamp = Filter_Process(&hpm->exp[EXP_I], iamp);
hpm->slow_cnt++;
}
/**

View File

@ -80,11 +80,11 @@ typedef struct
float I[3]; ///< Ток
}slow;
/** @brief Реальные величины - обновляются кто где, и содержат значения в В/А */
/** @brief Реальные величины - обновляются в main в @ref PowerMonitor_SlowCalc, и содержат значения в В/А */
struct
{
float U[3]; ///< Напряжение (обновляется в прерывании АЦП)
float I[3]; ///< Ток (обновляется в прерывании АЦП)
float U[3]; ///< Напряжение (Действующее)
float I[3]; ///< Ток (Действующее)
}real;
}PowerMonitor_Measured_t;
@ -104,6 +104,7 @@ typedef struct
PowerMonitor_Flags_t f; ///< Флаги мониторинга
uint32_t isr_cnt;
uint32_t slow_cnt;
}PowerMonitor_t;
extern PowerMonitor_t pm;

View File

@ -80,6 +80,7 @@ int main(void)
__HAL_FREEZE_TIM8_DBGMCU();
__HAL_FREEZE_TIM11_DBGMCU();
__HAL_FREEZE_TIM12_DBGMCU();
__HAL_FREEZE_TIM14_DBGMCU();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/

View File

@ -238,6 +238,10 @@ void TIM2_IRQHandler(void)
void TIM8_TRG_COM_TIM14_IRQHandler(void)
{
/* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 0 */
if (__HAL_TIM_GET_FLAG(&htim8, TIM_FLAG_UPDATE) != RESET) {
UPP_PWM_Handle();
}
#ifndef MATLAB // в матлабе нет htim14, т.к. это систем тики
/* USER CODE END TIM8_TRG_COM_TIM14_IRQn 0 */
HAL_TIM_IRQHandler(&htim8);
@ -253,11 +257,14 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void)
void DMA2_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
// Вторая половина буфера (Transfer Complete)
if (DMA2->LISR & DMA_LISR_TCIF0) {
UPP_ADC_Handle();
}
/* USER CODE END DMA2_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc3);
/* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
UPP_ADC_Handle();
/* USER CODE END DMA2_Stream0_IRQn 1 */
}

View File

@ -209,7 +209,7 @@ void MX_TIM3_Init(void)
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();

View File

@ -21,12 +21,6 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle)
hangle->htim = &angletim;
// Инициализация ПИД
float kp = to_float(PARAM_INTERNAL.angle.PID_Kp, 10000);
float ki = to_float(PARAM_INTERNAL.angle.PID_Ki, 10000);
float kd = to_float(PARAM_INTERNAL.angle.PID_Kd, 10000);
float ref_alpha = to_float(PARAM_INTERNAL.angle.PID_ExpAlpha, 65535);
Angle_PID_Init(hangle, kp, ki, kd, ref_alpha);
// Инициализация каналов
HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_1);
@ -43,7 +37,14 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle)
float angle_min = to_float(PARAM_INTERNAL.angle.Angle_Min, 65535);
hangle->f.Initialized = 1;
return HAL_OK;
// Инициализация ПИД
float kp = to_float(PARAM_INTERNAL.angle.PID_Kp, 10000);
float ki = to_float(PARAM_INTERNAL.angle.PID_Ki, 10000);
float kd = to_float(PARAM_INTERNAL.angle.PID_Kd, 10000);
float ref_alpha = PUI_Tnt_CalcAlpha(to_float(PARAM_PUI.Tnt, 1000), PM_SLOW_PERIOD_US);
return Angle_PID_Init(hangle, kp, ki, kd, ref_alpha);;
}
@ -52,10 +53,10 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle)
* @param hangle Указатель на таймер
* @param kp, ki kd Коэффициенты регулятора
*/
void Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd, float alpha)
HAL_StatusTypeDef Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd, float alpha)
{
if(assert_upp(hangle))
return;
return HAL_ERROR;
// Сам ПИД регулятор
hangle->pid.Kp = kp;
@ -67,6 +68,8 @@ void Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd, float
FilterExp_Init(&hangle->refFilter, alpha);
Filter_Start(&hangle->refFilter);
Filter_Process(&hangle->refFilter, 0);
return HAL_OK;
}
/**

View File

@ -44,7 +44,7 @@ typedef struct
/* Инициализация Таймера для рассчета угла открытия. */
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle);
/* Инициализация ПИД регулятора. */
void Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd, float alpha);
HAL_StatusTypeDef Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd, float alpha);
// ====== УПРАВЛЕНИЕ ==========
/* Управление углом через ПИД регулятор */

View File

@ -59,7 +59,10 @@ 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_SetConfig(hpwm, PARAM_INTERNAL.pwm.PhaseMask, PARAM_INTERNAL.pwm.Frequency, PARAM_INTERNAL.pwm.PulseNumber);
PWM_SetConfig(hpwm, PARAM_INTERNAL.pwm.PhaseMask,
PARAM_INTERNAL.pwm.Frequency,
to_float(PARAM_INTERNAL.pwm.Duty, 100),
PARAM_INTERNAL.pwm.PulseNumber);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2);
@ -154,7 +157,6 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
{
// в первую очередь выключаем канал, потом выставим режим каналов
__HAL_TIM_MOE_DISABLE(&hpwm1);
// в первую очередь выключаем канал, потом выставим режим каналов
__HAL_TIM_MOE_DISABLE(&hpwm2);
@ -197,7 +199,7 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
* @param Frequency Частота в ГЦ
* @return HAL Status.
*/
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber)
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, float Duty, uint8_t PulseNumber)
{
if(assert_upp(hpwm))
return HAL_ERROR;
@ -210,16 +212,19 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t
hpwm->Config.PhaseMask.all = PhaseMask;
hpwm->Config.PulseNumber = PulseNumber;
hpwm->Config.Frequency = Frequency;
hpwm->Config.Duty = Duty;
// Высставление периодов
__HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(Frequency, PWM_TIM1_FREQ_MHZ-1));
__HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(Frequency, PWM_TIM8_FREQ_MHZ-1));
// Скважности 50/50
__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);
// Скважности
uint32_t pwm1_duty_ccr = (float)__HAL_TIM_GET_AUTORELOAD(&hpwm1)*(1-Duty);
uint32_t pwm2_duty_ccr = (float)__HAL_TIM_GET_AUTORELOAD(&hpwm2)*(1-Duty);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, pwm1_duty_ccr);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, pwm1_duty_ccr);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, pwm1_duty_ccr);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, pwm1_duty_ccr);
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, pwm2_duty_ccr);
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, pwm2_duty_ccr);
// Сброс счетчиков таймера и запуск заного

View File

@ -74,6 +74,7 @@ typedef struct {
}PhaseMask; ///< Какими каналами управлять
uint8_t PulseNumber; ///< Сколько импульсов отправить в пакете для открытия тиристоров
uint16_t Frequency; ///< Частота импульсов
float Duty; ///< Скважность импульсов
} PWM_ThyrConfig_t;
/**
@ -100,7 +101,7 @@ 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_all);
/* Установка частоты ШИМ. */
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber);
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, float Duty, uint8_t PulseNumber);
/* Установка полуволны для слежения. */
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave);
/* Установка полярности шим. */

View File

@ -19,7 +19,7 @@
UPP_Errors_t errors;
static UPP_ErrorType_t UPP_SelectCommonError(void);
static int setError(int condition, int flag, int *timer, int delay);
__STATIC_FORCEINLINE int setError(int condition, int flag, int *timer, int delay);
void UPP_Errors_Program(void);
void UPP_Errors_Power(void);
void UPP_Errors_Ranges(void);
@ -225,7 +225,7 @@ static UPP_ErrorType_t UPP_SelectCommonError(void)
}
static int setError(int condition, int flag, int *timer, int delay)
__STATIC_FORCEINLINE int setError(int condition, int flag, int *timer, int delay)
{
if (condition) {
if (*timer < delay)

View File

@ -145,6 +145,7 @@ typedef struct
struct
{
uint16_t angle_reinit_err;
uint16_t adc_reinit_err;
uint16_t zc_reinit_err;
uint16_t pwm_reinit_err;

View File

@ -29,7 +29,7 @@ static void UPP_DO5_Write(int state);
*/
void UPP_IO_Init(void)
{
/* Дискретне выходы */
/* Дискретные выходы */
UPP_DO.CEN = &UPP_CEN_Write;
UPP_DO.Ready = &UPP_RDO3_Write;
UPP_DO.Work = &UPP_RDO2_Write;
@ -99,7 +99,11 @@ void UPP_UART2_SetDirection(int state)
static void UPP_CEN_Write(int state)
{
#if !defined(STM32F417xx)
HAL_GPIO_WritePin(CEN_GPIO_Port, CEN_Pin, !state);
#else
HAL_GPIO_WritePin(CEN_GPIO_Port, CEN_Pin, state);
#endif
}
static void UPP_RDO1_Write(int state)
{

View File

@ -10,7 +10,10 @@
#define _UPP_IO_H
#include "mylibs_include.h"
#define DIN_Pusk_GPIO_Port DIN1_GPIO_Port
#define DIN_Pusk_Pin DIN1_Pin
#define DIN_MestDist_GPIO_Port DIN2_GPIO_Port
#define DIN_MestDist_Pin DIN2_Pin
typedef struct
{

View File

@ -16,7 +16,7 @@
UPP_t upp;
HAL_StatusTypeDef res; // сюда сохраняется результат от выполения всяких функций
float dbg_iref = 2;
int dbg_polarity = 0;
int dbg_polarity = 1;
/**
* @brief Инициализация УПП.
@ -60,17 +60,12 @@ int UPP_App_Init(void)
* @return 0 - если ОК, >1 если ошибка.
*/
int UPP_PreWhile(void)
{
UPP_Params_ControlInternal();
if(Angle_SetRange(&upp.hangle, 0.0, 0.8) != HAL_OK)
return 1;
{
UPP_Params_Control();
if(PowerMonitor_Start(&upp.pm) != HAL_OK)
return 1;
UPP_DO.CEN(ENABLE);
return 0;
}
@ -86,19 +81,26 @@ int UPP_While(void)
if(upp.pm.f.runSlow)
{
static uint32_t slow_cnt = 0;
upp.Timings.slow_calc_prd_us = BenchTime_Period(BT_SLOWCALC_PRD, angletim.Instance->CNT, HAL_MAX_DELAY)/ANGLE_TIM2_FREQ_MHZ;
BenchTime_Start(BT_SLOWCALC, angletim.Instance->CNT, HAL_MAX_DELAY);
res = HAL_IWDG_Refresh(&hiwdg);
res = HAL_IWDG_Refresh(&hiwdg); // если не вызываются медленные расчеты - что-то не то сбрасываемся по watchdog
// Медленные расчеты
PowerMonitor_SlowCalc(&upp.pm);
PowerMonitor_SlowCalc(&upp.pm);
#ifdef UPP_SIMULATE_I // симулируем токи
upp.pm.measured.final.Iamp = upp.hangle.Iref/2;
upp.pm.measured.final.Iamp = upp.hangle.Iref/2;
// Защиты // При симуляции тока не включаем его проверку
PowerMonitor_Protect(&upp.pm, 0);
#else
// Защиты // Определенные защиты по току включаем только в после разгона
PowerMonitor_Protect(&upp.pm, (fabsf(upp.hangle.Iref - dbg_iref) < 0.1));
#endif
// Обрабока ошибок и выставление итоговой Ошибки
UPP_Errors_Handle();
// Контроль парамеров
UPP_Params_Control();
#ifndef UPP_DISABLE_ERROR_BLOCK
@ -123,6 +125,8 @@ int UPP_While(void)
{
/*======= Состояние Инициализация =========*/
case UPP_Init:
res = PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
// Индикация
UPP_DO.Ready(DISABLE);
UPP_DO.Work(DISABLE);
UPP_DO.Error(DISABLE);
@ -194,7 +198,7 @@ int UPP_While(void)
default:
PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
// Индикация
UPP_DO.Ready(ENABLE);
UPP_DO.Ready(DISABLE);
UPP_DO.Work(DISABLE);
UPP_DO.Error(ENABLE);
// Находимся до тех пор пока ошибки не будет устранена
@ -222,13 +226,10 @@ int UPP_While(void)
*/
void UPP_Tick(void)
{
// Начинаем все проверять только после того как уйдем из режима инициализации
if(upp.workmode == UPP_Init)
return;
// Обрабока ошибок и выставление итоговой Ошибки
UPP_Errors_Handle();
//
UPP_Params_ControlInternal();
if(GPIO_Read_Switch(&UPP_DIN.Pusk))
{
@ -242,10 +243,16 @@ void UPP_Tick(void)
// ПРЕРЫВАНИЯ stm32f4xx_it.c
//================ ПРЕРЫВАНИЯ stm32f4xx_it.c ===================
/**
* @brief @ref DMA2_Stream0_IRQHandler
*/
void UPP_ADC_Handle(void)
{
upp.Timings.isr_adc_prd_us = BenchTime_Period(BT_ADC_PRD, angletim.Instance->CNT, HAL_MAX_DELAY)/ANGLE_TIM2_FREQ_MHZ;
BenchTime_Start(BT_ADC, angletim.Instance->CNT, HAL_MAX_DELAY);
if(upp.pm.f.inIsr)
{
ERR_PRIVATE.overrun_fast_calc = 1;
@ -280,6 +287,9 @@ void UPP_ADC_Handle(void)
upp.Timings.isr_adc_us = BenchTime_End(BT_ADC, angletim.Instance->CNT)/ANGLE_TIM2_FREQ_MHZ;
upp.pm.f.inIsr = 0;
}
/**
* @brief @ref TIM1_UP_TIM10_IRQHandler @ref
*/
void UPP_PWM_Handle(void)
{
BenchTime_Start(BT_PWM, angletim.Instance->CNT, HAL_MAX_DELAY);
@ -287,6 +297,9 @@ void UPP_PWM_Handle(void)
upp.Timings.isr_pwm_us = BenchTime_End(BT_PWM, angletim.Instance->CNT)/ANGLE_TIM2_FREQ_MHZ;
}
/**
* @brief @ref HAL_TIM_OC_DelayElapsedCallback
*/
void UPP_Angle_Handle(void)
{
UPP_Phase_t phase = Angle_Handle(&upp.hangle);
@ -313,7 +326,9 @@ void UPP_Angle_Handle(void)
}
}
// Callback по совпадению CCRx
/**
* @brief Callback по совпадению CCRx c CNT
*/
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim == upp.hangle.htim)
@ -321,6 +336,9 @@ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
UPP_Angle_Handle();
}
}
/**
* @brief @ref HAL_TIM_PeriodElapsedCallback
*/
void HAL_IncTick(void)
{
BenchTime_Start(BT_SYSTICK, angletim.Instance->CNT, HAL_MAX_DELAY);

View File

@ -39,7 +39,9 @@ typedef struct
struct
{
uint32_t slow_calc_prd_us;
uint32_t slow_calc_us;
uint32_t isr_adc_prd_us;
uint32_t isr_adc_us;
uint32_t isr_pwm_us;
uint32_t isr_systick_us;

View File

@ -1,26 +1,105 @@
/**
******************************************************************************
* @file upp_params.c
* @brief Модуль определябщий поведение УПП
* @brief Модуль проверяющий параметры УПП
******************************************************************************
* @details
******************************************************************************/
* ИНСТРУКЦИЯ ПО ДОБАВЛЕНИЮ НОВЫХ ПАРАМЕТРОВ:
*
* 1. Добавить новый параметр в соответствующую структуру в файле параметров:
* - PARAM_PUI для параметров от ПУИ (пульт управления и индикации)
* - PARAM_INTERNAL для внутренних параметров УПП
*
* 2. В функции UPP_Params_ControlInternal() или UPP_Params_ControlPUI():
* a. Объявить временную переменную для хранения текущего значения
* b. Проверить изменение параметра (можно с помощью __CheckParamX() функции)
* c. Обновить параметр в соответствующем модуле новым параметром если он изменился
*
* 3. В функции UPP_Params_SetDefault() добавить установку значения по умолчанию
*
* 4. При необходимости добавить сатурацию параметра в UPP_Params_Saturate()
*
* Пример добавления простого параметра:
*
* // В UPP_Params_ControlInternal():
* float new_param = module.param;
* if(__CheckParamF(&new_param, PARAM_INTERNAL.new_param, 1000))
* {
* module_update = 1;
* }
*
* // В блоке обновления модуля:
* if(module_update)
* {
* if(Module_SetParam(&module, new_param) == HAL_OK)
* module_update = 0;
* }
*
* // В UPP_Params_SetDefault():
* PARAM_INTERNAL.new_param = NEW_PARAM_DEFAULT * 1000;
*
******************************************************************************
*/
#include "upp_main.h" // всё остальное по работе с УПП
#define SATURATE_U16(value, min, max) \
value = ((value) < (min) ? (min) : ((value) > (max) ? (max) : (value)))
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 __CheckParamF(float *paramDist, uint16_t paramSrc, float Coef);
static int __CheckParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef);
static int __CheckParamU16(uint16_t *paramDist, uint16_t paramSrc);
static int __CheckParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef);
static void __AngleSetLimit(void);
/**
* @brief Контроль параметров УПП.
* @return HAL Status.
*/
void UPP_Params_Control(void)
{
/* Проверяем параметры на корректный диапазон */
UPP_Params_Saturate();
/* Чекаем изменились ли параметры от ПУИ */
UPP_Params_ControlPUI();
/* Чекаем изменились ли внутренние параметры */
UPP_Params_ControlInternal();
}
/**
* @brief Контроль параметров от ПУИ.
* @return HAL Status.
*/
void UPP_Params_ControlPUI(void)
{
if(upp.call->go) // при запущеном УПП ничего не меняем
return;
/* Tnt Уставка на скорость нарастания пускового тока Iref */
float angle_ref_alphaPUI = PUI_Tnt_CalcAlpha(to_float(PARAM_PUI.Tnt, 1000), PM_SLOW_PERIOD_US);
float angle_ref_alpha = upp.hangle.refFilter.alpha;
if(angle_ref_alpha != angle_ref_alphaPUI)
{
angle_ref_alpha = angle_ref_alphaPUI;
if(Angle_PID_Init(&upp.hangle,
upp.hangle.pid.Kp,
upp.hangle.pid.Ki,
upp.hangle.pid.Kd,
angle_ref_alpha) != HAL_OK)
ERR_PRIVATE_CNT.angle_reinit_err++;
}
}
/**
* @brief Контроль внутренних параметров УПП.
* @return HAL Status.
*/
void UPP_Params_ControlInternal(void)
{
__AngleSetLimit();
if(upp.call->go) // при запущеном УПП ничего не меняем
return;
@ -36,7 +115,6 @@ void UPP_Params_ControlInternal(void)
float angle_pid_kp = upp.hangle.pid.Kp;
float angle_pid_ki = upp.hangle.pid.Ki;
float angle_pid_kd = upp.hangle.pid.Kd;
float angle_ref_alpha = upp.hangle.refFilter.alpha;
// временная переменная для параметров каналов АЦП
float adc_channel_max[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
uint16_t adc_channel_zero[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
@ -46,6 +124,7 @@ void UPP_Params_ControlInternal(void)
// временная переменная для параметров ШИМ
uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all;
uint16_t pwm_freq = upp.hpwm.Config.Frequency;
float pwm_duty = upp.hpwm.Config.Duty;
uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber;
// временная переменная для параметров Мониторинга сети
float pm_alpha = upp.pm.exp[0].alpha;
@ -53,31 +132,26 @@ void UPP_Params_ControlInternal(void)
// Параметры регулятора Угла открытия
if(__CheckSimpleParamF(&angle_max, PARAM_INTERNAL.angle.Angle_Max, 65535))
if(__CheckParamF(&angle_max, PARAM_INTERNAL.angle.Angle_Max, 65535))
{
alpha_update = 1;
}
if(__CheckSimpleParamF(&angle_min, PARAM_INTERNAL.angle.Angle_Min, 65535))
if(__CheckParamF(&angle_min, PARAM_INTERNAL.angle.Angle_Min, 65535))
{
alpha_update = 1;
}
if(__CheckSimpleParamF(&angle_pid_kp, PARAM_INTERNAL.angle.PID_Kp, 10000))
if(__CheckParamF(&angle_pid_kp, PARAM_INTERNAL.angle.PID_Kp, 10000))
{
alpha_update = 1;
}
if(__CheckSimpleParamF(&angle_pid_ki, PARAM_INTERNAL.angle.PID_Ki, 10000))
if(__CheckParamF(&angle_pid_ki, PARAM_INTERNAL.angle.PID_Ki, 10000))
{
alpha_update = 1;
}
if(__CheckSimpleParamF(&angle_pid_kd, PARAM_INTERNAL.angle.PID_Kd, 10000))
if(__CheckParamF(&angle_pid_kd, PARAM_INTERNAL.angle.PID_Kd, 10000))
{
alpha_update = 1;
}
if(__CheckSimpleParamF(&angle_ref_alpha, PARAM_INTERNAL.angle.PID_ExpAlpha, 65535))
{
alpha_update = 1;
}
}
// Параметры АЦП
@ -87,56 +161,72 @@ void UPP_Params_ControlInternal(void)
adc_channel_zero[i] = upp.pm.adc.Coefs[i].lZero;
// Максимальное измеряемое напряжение
if(__CheckSimpleParamF(&adc_channel_max[i], PARAM_INTERNAL.adc.ADC_Max[i], 10))
if(__CheckParamF(&adc_channel_max[i], PARAM_INTERNAL.adc.ADC_Max[i], 10))
{
adc_channel_update[i] = 1;
}
// Значение АЦП при нулевом входе
if(__CheckSimpleParamU16(&adc_channel_zero[i], PARAM_INTERNAL.adc.ADC_Zero[i]))
if(__CheckParamU16(&adc_channel_zero[i], PARAM_INTERNAL.adc.ADC_Zero[i]))
{
adc_channel_update[i] = 1;
}
}
// Параметры алгоритма перехода через ноль
if(__CheckSimpleParamF(&zc_hysteresis, PARAM_INTERNAL.zc.Hysteresis, 10000))
if(__CheckParamF(&zc_hysteresis, PARAM_INTERNAL.zc.Hysteresis, 10000))
{
zc_update = 1;
}
if(__CheckSimpleParamU16(&zc_debounce, PARAM_INTERNAL.zc.DebouneCouner))
if(__CheckParamU16(&zc_debounce, PARAM_INTERNAL.zc.DebouneCouner))
{
zc_update = 1;
}
// Параметры ШИМ токов
if(__CheckSimpleParamU8(&pwm_phase_mask, PARAM_INTERNAL.pwm.PhaseMask, 1))
if(__CheckParamU8(&pwm_phase_mask, PARAM_INTERNAL.pwm.PhaseMask, 1))
{
pwm_update = 1;
}
if(__CheckSimpleParamU16(&pwm_freq, PARAM_INTERNAL.pwm.Frequency))
if(__CheckParamU16(&pwm_freq, PARAM_INTERNAL.pwm.Frequency))
{
pwm_update = 1;
}
if(__CheckSimpleParamU8(&pwm_pulse_num, PARAM_INTERNAL.pwm.PulseNumber, 1))
if(__CheckParamF(&pwm_duty, PARAM_INTERNAL.pwm.Duty, 100))
{
pwm_update = 1;
}
}
if(__CheckParamU8(&pwm_pulse_num, PARAM_INTERNAL.pwm.PulseNumber, 1))
{
pwm_update = 1;
}
// Параметры мониторинга
if(__CheckSimpleParamF(&pm_alpha, PARAM_INTERNAL.pm.mean_alpha, 65535))
if(__CheckParamF(&pm_alpha, PARAM_INTERNAL.pm.mean_alpha, 65535))
{
for(int i = 0; i < EXP_ALL; i++)
{
Filter_ReInit(&upp.pm.exp[i], pm_alpha);
Filter_Start(&upp.pm.exp[i]);
}
}
// Обновление регулятора угла открытия
__AngleSetLimit();
if(alpha_update)
{
Angle_SetRange(&upp.hangle, angle_min, angle_max);
Angle_PID_Init(&upp.hangle, angle_pid_kp, angle_pid_ki, angle_pid_kd, angle_ref_alpha);
if(Angle_SetRange(&upp.hangle, angle_min, angle_max) == HAL_OK)
{
if(Angle_PID_Init(&upp.hangle, angle_pid_kp, angle_pid_ki, angle_pid_kd, upp.hangle.refFilter.alpha) == HAL_OK)
{
alpha_update = 0;
}
else
ERR_PRIVATE_CNT.angle_reinit_err++;
}
else
ERR_PRIVATE_CNT.angle_reinit_err++;
}
// Обновление АЦП конфигов
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
@ -160,7 +250,7 @@ void UPP_Params_ControlInternal(void)
// Обновление ШИМ конфигов
if(pwm_update)
{
if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_pulse_num) == HAL_OK)
if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_duty, pwm_pulse_num) == HAL_OK)
{
pwm_update = 0;
}
@ -178,6 +268,46 @@ void UPP_Params_ControlInternal(void)
*/
void UPP_Params_Saturate(void)
{
SATURATE_U16(PARAM_PUI.Iref, 100, 500);
// SATURATE_U16(PARAM_PUI.Tnt, 50, 5000);
SATURATE_U16(PARAM_PUI.Umin, 5, 99);
SATURATE_U16(PARAM_PUI.Umax, 100, 120);
SATURATE_U16(PARAM_PUI.Imax, 5, 99);
SATURATE_U16(PARAM_PUI.Imin, 0, 40);
SATURATE_U16(PARAM_PUI.TiMax, 500, 10000);
SATURATE_U16(PARAM_PUI.Tdelay, 5, 60);
SATURATE_U16(PARAM_PUI.Interlace, 0, 1);
SATURATE_U16(PARAM_INTERNAL.setpoints.TemperatureWarn, 0, 90);
SATURATE_U16(PARAM_INTERNAL.setpoints.TemperatureErr, 0, 90);
SATURATE_U16(PARAM_INTERNAL.nominal.PhaseNumber, 0, 3);
SATURATE_U16(PARAM_INTERNAL.nominal.U, 0, ADC_U_MAX_V_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL.nominal.U_deviation_plus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL.nominal.U_deviation_minus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL.nominal.F, 40*100, 60*100);
SATURATE_U16(PARAM_INTERNAL.nominal.F_deviation_plus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL.nominal.F_deviation_minus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL.nominal.I, 0, ADC_I_MAX_A_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UBA], 0, ADC_U_MAX_V_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UAC], 0, ADC_U_MAX_V_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IC], 0, ADC_I_MAX_A_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IA], 0, ADC_I_MAX_A_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UBA], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UAC], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IC], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IA], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL.pwm.PhaseMask, 0, 7);
SATURATE_U16(PARAM_INTERNAL.pwm.Frequency, 1000, 40000);
SATURATE_U16(PARAM_INTERNAL.pwm.PulseNumber, 1, 50);
SATURATE_U16(PARAM_INTERNAL.zc.Hysteresis, 0, 0.1*100);
SATURATE_U16(PARAM_INTERNAL.zc.DebouneCouner, 0, 1000);
SATURATE_U16(PARAM_INTERNAL.angle.PulseLengthReserve, 50, 1000);
}
/**
@ -215,7 +345,7 @@ void UPP_Params_SetDefault(int pui_default, int internal_default)
PARAM_INTERNAL.nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100;
PARAM_INTERNAL.nominal.I = NOM_I_A_DEFAULT*10;
PARAM_INTERNAL.pm.mean_alpha = CALC_TAU_COEF(PM_EXP_TAU_COEF_DEFAULT,PM_SLOW_PERIOD_US)*65535;
PARAM_INTERNAL.pm.mean_alpha = FilterExp_CalcAlpha(PM_EXP_TAU_COEF_DEFAULT,PM_SLOW_PERIOD_US)*65535;
PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10;
PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10;
@ -226,9 +356,10 @@ void UPP_Params_SetDefault(int pui_default, int internal_default)
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT;
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IA] = ADC_I_ZERO_DEFAULT;
PARAM_INTERNAL.pwm.PhaseMask = 1; // (все три фазы)
PARAM_INTERNAL.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT;
PARAM_INTERNAL.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT;
PARAM_INTERNAL.pwm.PhaseMask = 7; // (все три фазы)
PARAM_INTERNAL.pwm.Frequency = PWM_THYR_FREQUENCY_HZ_DEFAULT;
PARAM_INTERNAL.pwm.Duty = PWM_THYR_DUTY_PERCENT_DEFAULT*100;
PARAM_INTERNAL.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT;
PARAM_INTERNAL.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100;
PARAM_INTERNAL.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_CNT_DEFAULT;
@ -237,7 +368,6 @@ void UPP_Params_SetDefault(int pui_default, int internal_default)
PARAM_INTERNAL.angle.PID_Kp = ANGLE_PID_KP_COEF_DEFAULT*10000;
PARAM_INTERNAL.angle.PID_Ki = ANGLE_PID_KI_COEF_DEFAULT*10000;
PARAM_INTERNAL.angle.PID_Kd = ANGLE_PID_KD_COEF_DEFAULT*10000;
PARAM_INTERNAL.angle.PID_ExpAlpha = CALC_TAU_COEF(ANGLE_REF_TAU_COEF_DEFAULT,PM_SLOW_PERIOD_US)*65535;
PARAM_INTERNAL.angle.Angle_Max = ANGLE_MAX_PERCENT_DEFAULT*65535;
PARAM_INTERNAL.angle.Angle_Min = ANGLE_MIN_PERCENT_DEFAULT*65535;
PARAM_INTERNAL.angle.PulseLengthReserve = ANGLE_PULSE_LENGTH_RESERVE_PERCENT_DEFAULT*100;
@ -266,7 +396,7 @@ static void __AngleSetLimit(void)
* @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)
static int __CheckParamF(float *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
@ -289,7 +419,7 @@ static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef)
* @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)
static int __CheckParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
@ -311,7 +441,7 @@ static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float C
* @param paramSrc Значение для сравнения с uint16_t параметром
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc)
static int __CheckParamU16(uint16_t *paramDist, uint16_t paramSrc)
{
if(paramDist == NULL)
return 0;
@ -335,7 +465,7 @@ static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc)
* @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)
static int __CheckParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;

View File

@ -65,9 +65,10 @@ typedef struct
/* Параметры ШИМ */
struct
{
uint16_t PhaseMask; ///< Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c
uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры [Герцы]
uint16_t PulseNumber; ///< Количесво импульсов в пачке [Количество]
uint16_t PhaseMask; ///< Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c
uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры [Герцы]
uint16_t Duty; ///< Скважность ШИМ для пачки импульсов на тиристоры [Проценты]
uint16_t PulseNumber; ///< Количесво импульсов в пачке [Количество]
}pwm;
/* Параметры Угла */
@ -87,16 +88,20 @@ typedef struct
uint16_t PID_Kp; ///< Пропорциональный коэфициент ПИ регулятора угла [x 10000]
uint16_t PID_Ki; ///< Интегральный коэфициент ПИ регулятора угла [x 10000]
uint16_t PID_Kd; ///< Интегральный коэфициент ПИ регулятора угла [x 10000]
uint16_t PID_ExpAlpha; ///< Коэффициент сглаживающего фильтра задания регулятора [0..1 x 65535]
}angle;
}UPP_PrvtParams_t;
/* Контроль параметров УПП. */
void UPP_Params_Control(void);
/* Контроль параметров от ПУИ. */
void UPP_Params_ControlPUI(void);
/* Контроль внутренних параметров УПП. */
void UPP_Params_ControlInternal(void);
/* Контроль параметров УПП на корректные значения. */
void UPP_Params_Saturate(void);
/* Установка параметров на дефолтные значения */
void UPP_Params_SetDefault(int pui_default, int internal_default);

View File

@ -322,59 +322,10 @@
<SetRegEntry>
<Number>0</Number>
<Key>ST-LINKIII-KEIL_SWO</Key>
<Name>-U005600373433510237363934 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131123 -TC168000000 -TT10000000 -TP21 -TDS800D -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F417ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2</Name>
<Name>-U005600373433510237363934 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131123 -TC168000000 -TT10000000 -TP21 -TDS800D -TDT1 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F417ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2</Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>407</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>134233766</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\Debug_F417\../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c\407</Expression>
</Bp>
<Bp>
<Number>1</Number>
<Type>0</Type>
<LineNumber>136</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>134256316</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>../Core/Src/stm32f4xx_it.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\Debug_F417\../Core/Src/stm32f4xx_it.c\136</Expression>
</Bp>
<Bp>
<Number>2</Number>
<Type>0</Type>
<LineNumber>27</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>0</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>0</BreakIfRCount>
<Filename>.\startup_stm32f417xx.s</Filename>
<ExecCommand></ExecCommand>
<Expression></Expression>
</Bp>
</Breakpoint>
<Breakpoint/>
<WatchWindow1>
<Ww>
<count>0</count>
@ -456,6 +407,21 @@
<WinNumber>1</WinNumber>
<ItemText>\\Debug_F417\../Core/UPP/upp_io.c\UPP_DIN.Pusk.Sw_FilterDelay</ItemText>
</Ww>
<Ww>
<count>16</count>
<WinNumber>1</WinNumber>
<ItemText>hadc3</ItemText>
</Ww>
<Ww>
<count>17</count>
<WinNumber>1</WinNumber>
<ItemText>upp.hangle.Iref</ItemText>
</Ww>
<Ww>
<count>18</count>
<WinNumber>1</WinNumber>
<ItemText>upp.pm.measured.final.U[0]</ItemText>
</Ww>
</WatchWindow1>
<WatchWindow2>
<Ww>
@ -466,7 +432,7 @@
<Ww>
<count>1</count>
<WinNumber>2</WinNumber>
<ItemText>MB_DATA</ItemText>
<ItemText>MB_DATA,0x0A</ItemText>
</Ww>
<Ww>
<count>2</count>
@ -523,6 +489,11 @@
<WinNumber>2</WinNumber>
<ItemText>upp.pm.measured.slow.U[0]</ItemText>
</Ww>
<Ww>
<count>13</count>
<WinNumber>2</WinNumber>
<ItemText>upp,0x0A</ItemText>
</Ww>
</WatchWindow2>
<Tracepoint>
<THDelay>0</THDelay>
@ -530,7 +501,7 @@
<DebugFlag>
<trace>0</trace>
<periodic>1</periodic>
<aLwin>1</aLwin>
<aLwin>0</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
@ -569,37 +540,17 @@
<LogicAnalyzers>
<Wi>
<IntNumber>0</IntNumber>
<FirstString>`upp.pm.zc.Channel[0].HalfWave</FirstString>
<SecondString>0000000000000000000000000000000000000040000000000000000000000000000000007570702E706D2E7A632E4368616E6E656C5B305D2E48616C66576176650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000001000000000000000000F03F1400000000000000000000000000000000000000FC9E0008</SecondString>
<FirstString>`upp.pm.measured.final.U[0]</FirstString>
<SecondString>008000000000000000000000000000000000F03F000000000000000000000000000000007570702E706D2E6D656173757265642E66696E616C2E555B305D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700000001000000000000000000F03F140000000000000000000000000000000000000020B20008</SecondString>
</Wi>
</LogicAnalyzers>
<SystemViewers>
<Entry>
<Name>System Viewer\DBG</Name>
<WinId>35902</WinId>
</Entry>
<Entry>
<Name>System Viewer\GPIOG</Name>
<WinId>35899</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM1</Name>
<WinId>35901</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM14</Name>
<WinId>35903</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM2</Name>
<WinId>35900</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM5</Name>
<Name>System Viewer\ADC3</Name>
<WinId>35905</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM8</Name>
<Name>System Viewer\DMA2</Name>
<WinId>35904</WinId>
</Entry>
</SystemViewers>
@ -1223,7 +1174,7 @@
<Group>
<GroupName>MyLibs</GroupName>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@ -1511,7 +1462,7 @@
<Group>
<GroupName>PeriphGeneral</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>

View File

@ -1122,11 +1122,11 @@
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4101</DriverSelection>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>

View File

@ -488,7 +488,7 @@ TIM2.OCMode_2=TIM_OCMODE_TIMING
TIM2.OCMode_3=TIM_OCMODE_TIMING
TIM3.IPParameters=TIM_MasterSlaveMode,TIM_MasterOutputTrigger
TIM3.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
TIM3.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_ENABLE
TIM3.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_DISABLE
TIM5.IPParameters=Prescaler
TIM5.Prescaler=90-1
TIM8.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3