Какие-то тесты и построение алгоритма. Но ничего прям интересного

This commit is contained in:
Razvalyaev 2025-11-17 01:38:12 +03:00
parent b0813fb7e8
commit b236975f9b
22 changed files with 349 additions and 192 deletions

View File

@ -9,7 +9,7 @@
#endif #endif
#ifdef STM32F4 #ifdef STM32F4
#define ADC_NOISE_LSB 10 // Шум в LSB (квантах АЦП) #define ADC_NOISE_LSB 3 // Шум в LSB (квантах АЦП)
#endif #endif
/////////////////////////////---STRUCTURES---/////////////////////////// /////////////////////////////---STRUCTURES---///////////////////////////

View File

@ -59,7 +59,7 @@
#define OUT_PORT_NUMB 3 #define OUT_PORT_NUMB 3
#define THYR_PORT_1_WIDTH 6 #define THYR_PORT_1_WIDTH 6
#define PM_PORT_2_WIDTH 16 #define PM_PORT_2_WIDTH 32
#define OUT_PORT_3_WIDTH 16 #define OUT_PORT_3_WIDTH 16
// INPUT/OUTPUTS PARAMS END // INPUT/OUTPUTS PARAMS END

View File

@ -32,25 +32,31 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port)
{ {
int nn = 0; int nn = 0;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ { //0-2
WriteOutputArray(upp.pm.U[i], ind_port, nn++); WriteOutputArray(upp.pm.measured.Ureal[i], ind_port, nn++);
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ { //3-5
WriteOutputArray(upp.pm.zc.Channel[i].HalfWave, ind_port, nn++); WriteOutputArray(upp.pm.zc.Channel[i].HalfWave, ind_port, nn++);
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ { //6-8
WriteOutputArray(upp.pm.F[i], ind_port, nn++); WriteOutputArray(upp.pm.measured.F[i], ind_port, nn++);
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ { //9-11
WriteOutputArray(upp.pm.I[i], ind_port, nn++); WriteOutputArray(upp.pm.measured.Ireal[i], ind_port, nn++);
} }
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ { //12-13
WriteOutputArray(upp.pm.T[i], ind_port, nn++); WriteOutputArray(upp.pm.measured.T[i], ind_port, nn++);
} }
{ //14-16
WriteOutputArray(upp.pm.measured.U_mean, ind_port, nn++);
WriteOutputArray(upp.pm.measured.I_mean, ind_port, nn++);
WriteOutputArray(upp.pm.measured.F_mean, ind_port, nn++);
}
} }
/** /**
* @brief Функция для записи входов в приложение МК * @brief Функция для записи входов в приложение МК

View File

@ -1,7 +1,7 @@
clear all clear all
Ts = 5e-6; Ts = 5e-6;
Vnom = 380; Vnom = 690;
Fnom = 50; Fnom = 50;
Temperature1 = 2.22; % 20 градусов Temperature1 = 2.22; % 20 градусов

Binary file not shown.

@ -1 +1 @@
Subproject commit 99652a9ad5ea0686ad9242b165508a9d92ac80a1 Subproject commit 9bff9ad44dd625819ef654e98ca351d5bc5568a9

View File

@ -23,7 +23,7 @@
#include "modbus_devid.h" #include "modbus_devid.h"
/* DEFINE DATA FOR MODBUS */ /* DEFINE DATA FOR MODBUS */
MB_DataStructureTypeDef MB_DATA = {0};; ///< Coils & Registers MB_DataStructureTypeDef MB_DATA = {0}; ///< Coils & Registers
MB_DataInternalTypeDef MB_INTERNAL; MB_DataInternalTypeDef MB_INTERNAL;
/** /**

View File

@ -65,7 +65,7 @@
//#define FILTER_MEDIAN_MAX_SIZE ///< Максимальный размер окна медианного фильтра (по умолчанию 5) //#define FILTER_MEDIAN_MAX_SIZE ///< Максимальный размер окна медианного фильтра (по умолчанию 5)
//#define FILTER_AVERAGE_MAX_SIZE ///< Максимальный размер окна усредняющего фильтра (по умолчанию 8) //#define FILTER_AVERAGE_MAX_SIZE ///< Максимальный размер окна усредняющего фильтра (по умолчанию 8)
//#define FILTER_POLY_MAX_ORDER ///< Максимальный порядок полинома (по умолчанию 4) //#define FILTER_POLY_MAX_ORDER ///< Максимальный порядок полинома (по умолчанию 4)
#define FILTERS_DISABLE_MOVING_AVERAGE
/** GEN_CONFIG /** GEN_CONFIG
* @} * @}
*/ */
@ -96,9 +96,12 @@
*/ */
//#define BENCH_TIME_ENABLE ///< Включить бенч времени #define BENCH_TIME_ENABLE ///< Включить бенч времени
#define BENCH_TIME_MAX_CHANNELS 16 ///< Максимальное количество каналов измерения #define BENCH_TIME_MAX_CHANNELS 5 ///< Максимальное количество каналов измерения
#define BT_ADC 0
#define BT_PWM 1
#define BT_SYSTICK 2
/** GEN_CONFIG /** GEN_CONFIG
* @} * @}
*/ */
@ -133,7 +136,7 @@ extern float dbg[16];
#define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами #define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами
//#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами //#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами
#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией #define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией
//#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени #define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени
#define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами #define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами
#endif //MATLAB #endif //MATLAB

View File

@ -34,6 +34,19 @@
* @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке * @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке
* @{ * @{
*/ */
/* Параметри мониторинга сети */
#define PM_EXP_ALPHA_COEF_DEFAULT 0.01
/* Номинальные параметры */
#define NOM_PHASE_NUMB 3
#define NOM_U_V_DEFAULT 690
#define NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT 6
#define NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT 10
#define NOM_F_HZ_DEFAULT 50
#define NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT 5
#define NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT 5
#define NOM_I_A_DEFAULT 5
/* Параметры ПУИ */ /* Параметры ПУИ */
#define PUI_Iref_PERCENT_DEFAULT 150 #define PUI_Iref_PERCENT_DEFAULT 150
#define PUI_Tnt_MS_DEFAULT 300 #define PUI_Tnt_MS_DEFAULT 300
@ -52,8 +65,8 @@
#define ADC_I_ZERO_DEFAULT 2048 #define ADC_I_ZERO_DEFAULT 2048
/* Параметры определения перехода через ноль */ /* Параметры определения перехода через ноль */
#define ZERO_CROSS_HYSTERESIS_V_DEFAULT 10.0 #define ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT 2.0
#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2.5*100 // (2.5 * 100 = 2.5 мс) #define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2*100 // (2.5 * 100 = 2.5 мс)
/* Параметры ШИМ для тиристоров */ /* Параметры ШИМ для тиристоров */
#define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000 #define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000
@ -70,11 +83,11 @@
* @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять * @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять
* @{ * @{
*/ */
#define PM_U_NOM_V 690 /* Периоды вызова всякого */
#define PM_I_NOM_V 5 #define PM_ADC_PERIOD_US 10 ///< Период опроса АЦП в мкс
#define PM_F_NOM_HZ 50 #define PM_SLOW_PERIOD_10US 50 ///< Период обновление медленных расчетов в 10мкс
#define PM_TEMP_PERIOD_10US 5000 ///< Период обновление датчиков температуры в 10мкс
#define PM_ADC_PERIOD_MKS 10 ///< Период опроса АЦП в мкс
/* Частоты таймеров в МГц*/ /* Частоты таймеров в МГц*/
#define ADC_TIM8_FREQ_MZH 180 ///< Частота тиков таймера АЦП #define ADC_TIM8_FREQ_MZH 180 ///< Частота тиков таймера АЦП
#define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы) #define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы)

View File

@ -29,7 +29,8 @@ typedef enum {
WM_Not_Init = 0, ///< УПП не инициализирован WM_Not_Init = 0, ///< УПП не инициализирован
WM_Ready = 1, ///< УПП в готовности WM_Ready = 1, ///< УПП в готовности
WM_Running = 2, ///< УПП в работе, управляет тиристорами WM_Running = 2, ///< УПП в работе, управляет тиристорами
WM_Error = 3, ///< УПП в аварии WM_Done = 3, ///< УПП закончил свою работу
WM_Error = 4, ///< УПП в аварии
} UPP_WorkModeType_t; } UPP_WorkModeType_t;
/** /**
@ -147,7 +148,8 @@ typedef struct {
* @brief Дефайны УПП которые используютяс исключительно внутри программы * @brief Дефайны УПП которые используютяс исключительно внутри программы
* @{ * @{
*/ */
#define ANGLE_PERIOD_MS (((float)1/(PM_F_NOM_HZ*2))*1000) #define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000)
/** /**
* @brief Состояния полуволны * @brief Состояния полуволны
*/ */

View File

@ -156,7 +156,7 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc)
{ {
ADC_Coefs_t *coefs = &adc->Coefs[i]; ADC_Coefs_t *coefs = &adc->Coefs[i];
data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero); data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero);
ADC_UpdateStatistics(adc, i, ADC_LEVEL_AC); // ADC_UpdateStatistics(adc, i, ADC_LEVEL_AC);
} }
// Фильтрация от шумов для всех каналов // Фильтрация от шумов для всех каналов
@ -169,19 +169,15 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc)
} }
} }
// Преобразования температуры по таблице // Преобразования температуры по таблице
for (int i = ADC_TEMP_CHANNELS_START; i < ADC_NUMB_OF_CHANNELS; i++) for (int i = ADC_TEMP_CHANNELS_START; i < ADC_NUMB_OF_CHANNELS; i++)
{ {
data[i] = Filter_Process(&adc->temp_map[i-ADC_TEMP_CHANNELS_START], raw[i]); data[i] = Filter_Process(&adc->temp_map[i-ADC_TEMP_CHANNELS_START], raw[i]);
ADC_UpdateStatistics(adc, i, ADC_LEVEL_BASE); // ADC_UpdateStatistics(adc, i, ADC_LEVEL_BASE);
} }
if(Filter_isDataReady(&adc->filter[0]))
adc->f.DataReady = 1; adc->f.DataReady = 1;
return HAL_OK; return HAL_OK;
} }
@ -221,7 +217,7 @@ void ADC_UpdateStatistics(ADC_Periodic_t *adc, uint8_t channel, ADC_StatLevel_t
} }
// Накопление для Avg/RMS // Накопление для Avg/RMS
stat->Sum += value; stat->Sum += ABS(value);
stat->SumSquares += value * value; stat->SumSquares += value * value;
stat->SampleCount++; stat->SampleCount++;

View File

@ -67,7 +67,7 @@ typedef struct
typedef enum typedef enum
{ {
ADC_LEVEL_DISABLE=0, ///< Базовая статистика - Max/Min ADC_LEVEL_DISABLE=0, ///< Статистика отключена
ADC_LEVEL_BASE, ///< Базовая статистика - Max/Min ADC_LEVEL_BASE, ///< Базовая статистика - Max/Min
ADC_LEVEL_AC, ///< Статистика для переменных сигналов - AVG, RMS ADC_LEVEL_AC, ///< Статистика для переменных сигналов - AVG, RMS
}ADC_StatLevel_t; }ADC_StatLevel_t;

View File

@ -12,9 +12,14 @@
HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
{ {
if(hpm == NULL)
return HAL_ERROR;
/* Инициализация АЦП */
if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK) if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
/* Инициализация каналов АЦП */
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA], MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA], MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA],
@ -40,9 +45,11 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
return HAL_ERROR; return HAL_ERROR;
/* Инициализация алгоритма перехода через ноль */
if(ZC_Init(&hpm->zc, 3, (float)MB_INTERNAL.param.zc.Hysteresis/100, MB_INTERNAL.param.zc.DebouneCouner) != 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; return HAL_ERROR;
/* Инициализация каналов алгоритма перехода через ноль */
if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK) if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
if(ZC_ConfigChannel(&hpm->zc, U_AC, ZC_BOTH_EDGES) != HAL_OK) if(ZC_ConfigChannel(&hpm->zc, U_AC, ZC_BOTH_EDGES) != HAL_OK)
@ -50,41 +57,136 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
if(ZC_ConfigChannel(&hpm->zc, U_BC, ZC_BOTH_EDGES) != HAL_OK) if(ZC_ConfigChannel(&hpm->zc, U_BC, ZC_BOTH_EDGES) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
/* Инициализация экпоненциального фильтра медленного алга */
for(int i = 0; i < 3; i++)
{
if(FilterExp_Init(&hpm->measured.exp[i], (float)MB_INTERNAL.param.pm.mean_alpha/65535))
return HAL_ERROR;
Filter_Start(&hpm->measured.exp[i]);
}
/* Инициализация среднего фильтра медленного алга */
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{
if(FilterAverage_Init(&hpm->measured.avg[i], PM_SLOW_PERIOD_10US, FILTER_MODE_DEFAULT))
return HAL_ERROR;
Filter_Start(&hpm->measured.avg[i]);
}
for(int i = 0; i < ADC_NUMB_OF_T_CHANNELS; i++)
{
if(FilterAverage_Init(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i], PM_TEMP_PERIOD_10US, FILTER_MODE_DEFAULT))
return HAL_ERROR;
Filter_Start(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i]);
}
return HAL_OK; return HAL_OK;
} }
HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm)
{ {
if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_MKS) != HAL_OK) if(hpm == NULL)
return HAL_ERROR;
if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_US) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
return HAL_OK; return HAL_OK;
} }
void PowerMonitor_SlowHandle(PowerMonitor_t *hpm)
{
if(hpm == NULL)
return;
if(!hpm->f.runSlow)
return;
hpm->f.runSlow = 0;
PowerMonitor_Measured_t *meas = &hpm->measured;
meas->Uslow[U_BC] = -meas->Uslow[U_BA] - meas->Uslow[U_AC];
meas->Islow[I_B] = -meas->Islow[I_A] - meas->Islow[I_C];
float umean = 0;
float imean = 0;
float fmean = 0;
for(int i = 0; i < 3; i++)
{
umean += ABS(meas->Uslow[i]);
imean += ABS(meas->Islow[i]);
fmean += ABS(meas->F[i]);
}
umean /=3;
imean /=3;
fmean /=3;
meas->U_mean = Filter_Process(&meas->exp[0], umean);
meas->I_mean = Filter_Process(&meas->exp[1], imean);
meas->F_mean = Filter_Process(&meas->exp[2], fmean);
}
void PowerMonitor_Handle(PowerMonitor_t *hpm) void PowerMonitor_Handle(PowerMonitor_t *hpm)
{ {
if(hpm == NULL)
return;
/* Считываем АЦП */ /* Считываем АЦП */
static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0};
ADC_Handle(&hpm->adc); ADC_Handle(&hpm->adc);
hpm->U[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA];
hpm->U[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC];
hpm->U[U_BC] = -hpm->U[U_BA] - hpm->U[U_AC];
hpm->I[I_C] = hpm->adc.Data[ADC_CHANNEL_IC]; /* Заполняем величины */
hpm->I[I_A] = hpm->adc.Data[ADC_CHANNEL_IA]; PowerMonitor_Measured_t *meas = &hpm->measured;
hpm->I[I_B] = -hpm->I[I_A] - hpm->I[I_C]; meas->Ureal[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA];
meas->Ureal[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC];
meas->Ureal[U_BC] = -meas->Ureal[U_BA] - meas->Ureal[U_AC];
meas->Ireal[I_C] = hpm->adc.Data[ADC_CHANNEL_IC];
meas->Ireal[I_A] = hpm->adc.Data[ADC_CHANNEL_IA];
meas->Ireal[I_B] = -meas->Ireal[I_A] - meas->Ireal[I_C];
meas->T[TEMP_1] = hpm->adc.Data[ADC_CHANNEL_TEMP1];
meas->T[TEMP_2] = hpm->adc.Data[ADC_CHANNEL_TEMP2];
hpm->T[TEMP_1] = hpm->adc.Data[ADC_CHANNEL_TEMP1]; /* Преобразуем в относительные единицы (о.е.) */
hpm->T[TEMP_2] = hpm->adc.Data[ADC_CHANNEL_TEMP2];
ZC_ProcessAllChannels(&hpm->zc, hpm->U, usTick);
for(int i = 0; i < 3; i++) for(int i = 0; i < 3; i++)
{ {
meas->U[i] = 10*meas->Ureal[i]/MB_INTERNAL.param.nominal.U;
meas->I[i] = 10*meas->Ireal[i]/MB_INTERNAL.param.nominal.I;
}
hpm->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; /* Ищем переход через ноль */
ZC_ProcessAllChannels(&hpm->zc, meas->U, usTick);
for(int i = 0; i < 3; i++)
{
meas->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2;
}
/* Накопление Average для медленной фильтрации */
meas->Uslow[U_BA] = Filter_Process(&meas->avg[0], meas->U[U_BA]);
meas->Uslow[U_AC] = Filter_Process(&meas->avg[1], meas->U[U_AC]);
meas->Islow[I_C] = Filter_Process(&meas->avg[2], meas->I[I_C]);
meas->Islow[I_A] = Filter_Process(&meas->avg[3], meas->I[I_A]);
meas->T[TEMP_1] = Filter_Process(&meas->avg[4], meas->T[TEMP_1]);
meas->T[TEMP_2] = Filter_Process(&meas->avg[5], meas->T[TEMP_2]);
/* Запускаем медленную обработку через slow_period прерываний */
// if(hpm->isr_cnt == PM_SLOW_PERIOD_10US)
/* Запускаем медленную когда фильтры среднего зациклились */
if(Filter_isDataReady(&meas->avg[0]))
{
hpm->isr_cnt = 0;
if(!hpm->f.runSlow)
{
hpm->f.runSlow = 1;
}
else // если уже запущена - ставим overrun slow calc
{
errors.prvt.f.err.slow_calc_overrun = 1;
errors.prvt.cnt.slow_calc_overrun++;
}
}
else
{
hpm->isr_cnt++;
} }
} }

View File

@ -13,14 +13,55 @@
typedef struct typedef struct
{ {
ADC_Periodic_t adc; unsigned runSlow:1; ///< Запустить медленный алгоритм в while(1)
ZeroCross_Handle_t zc;
UPP_HalfWave_t CurrentHalfWave[3];
float U[3]; unsigned isU:1; ///< Есть ли напряжение
float F[3]; unsigned isI:1; ///< Есть ли ток
float I[3];
float T[2]; unsigned protectUmax:1; ///< Отработка защиты по макс. напряжению
unsigned protectUmin:1; ///< Отработка защиты по мак с. напряжению
unsigned protectImax:1; ///< Отработка защиты по макс. току
unsigned protectImin:1; ///< Отработка защиты по мин. току
}PowerMonitor_Flags_t;
typedef struct
{
float U_mean; ///< Среднее Напряжение по трем фазам
float I_mean; ///< Средний Ток по трем фазам
float F_mean; ///< Средняя Частота по трем фазам
float Uslow[3]; ///< Напряжение от АЦП (в о.е.)
float Islow[3]; ///< Ток от АЦП (в о.е.)
float U[3]; ///< Напряжение от АЦП (в о.е.)
float I[3]; ///< Ток от АЦП (в о.е.)
float F[3]; ///< Частота от Zero Cross
float T[2]; ///< Температура от АЦП
float Ureal[3]; ///< Напряжение от АЦП
float Ireal[3]; ///< Ток от АЦП
FilterExp_t exp[3]; ///< Фильтры для mean
FilterAverage_t avg[6]; ///< Фильтры для avg
}PowerMonitor_Measured_t;
typedef struct
{
}PowerMonitor_Filters_t;
typedef struct
{
ADC_Periodic_t adc; ///< Хендл периодического АЦП
ZeroCross_Handle_t zc; ///< Хендл перехода через ноль
PowerMonitor_Filters_t fltr;
PowerMonitor_Measured_t measured; ///< Измеренные/рассчитанные величины
PowerMonitor_Flags_t f; ///< Флаги мониторинга
uint32_t slow_period;
uint32_t isr_cnt;
}PowerMonitor_t; }PowerMonitor_t;
extern PowerMonitor_t pm; extern PowerMonitor_t pm;
@ -28,6 +69,7 @@ extern PowerMonitor_t pm;
HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm); HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm);
HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm); HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm);
void PowerMonitor_SlowHandle(PowerMonitor_t *hpm);
void PowerMonitor_Handle(PowerMonitor_t *hpm); void PowerMonitor_Handle(PowerMonitor_t *hpm);
#endif /* _POWER_MONITOR_H_ */ #endif /* _POWER_MONITOR_H_ */

View File

@ -15,6 +15,9 @@ static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state
* @brief Инициализация ШИМ тиристоров. * @brief Инициализация ШИМ тиристоров.
* @param hpwm Указатель на хендл ШИМ тиристоров * @param hpwm Указатель на хендл ШИМ тиристоров
* @return HAL Status. * @return HAL Status.
* @details Инициализируется 6 структур на каждый канал ШИМ для тиристора.
* И одна dummy структура для безопасной инициализации неизвестной фазы.
* В конце запускаются все каналы ШИМ (с запрещенным выходом).
*/ */
HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
{ {
@ -75,6 +78,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
* @param hpwm Указатель на хендл ШИМ тиристоров * @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase На какой фазе надо запустить ШИМ * @param Phase На какой фазе надо запустить ШИМ
* @return HAL Status. * @return HAL Status.
* @details Переводит автомат канала ШИМ в состояние запуска ШИМ.
*/ */
HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
{ {
@ -91,6 +95,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
switch(hpwm->Phase[Phase]->State) switch(hpwm->Phase[Phase]->State)
{ {
// Если мы НЕ в режиме ожидание - ошибка
case PWM_THYR_DISABLED: case PWM_THYR_DISABLED:
case PWM_THYR_TIM_START: case PWM_THYR_TIM_START:
case PWM_THYR_TIM_ACTIVE: case PWM_THYR_TIM_ACTIVE:
@ -103,7 +108,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
return HAL_OK; return HAL_OK;
default: default:
return HAL_ERROR;; return HAL_ERROR;
} }
return HAL_ERROR; return HAL_ERROR;
@ -113,7 +118,11 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
* @brief Остановить ШИМ. * @brief Остановить ШИМ.
* @param hpwm Указатель на хендл ШИМ тиристоров * @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase На какой фазе надо остановить ШИМ * @param Phase На какой фазе надо остановить ШИМ
* @param force_stop_all Принудительно остановить ВЕСЬ ШИМ
* @return HAL Status. * @return HAL Status.
* @details Переводит автомат канала ШИМ в состояние отключенного ШИМ и
* включает канал в режим форсированного неактивного выхода.
* При передаче 1 в force_stop_all, отключаются все каналы ШИМ и выдается дискрет на запрет ШИМ
*/ */
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all) HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all)
{ {
@ -148,6 +157,7 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
* @brief Хендл ШИМ тиристоров. * @brief Хендл ШИМ тиристоров.
* @param hpwm Указатель на хендл ШИМ тиристоров * @param hpwm Указатель на хендл ШИМ тиристоров
* @return HAL Status. * @return HAL Status.
* @details Автомат состояний, который определяет поведение каналов ШИМ
*/ */
HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
{ {
@ -165,22 +175,22 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
switch (hPhase->State) switch (hPhase->State)
{ {
case PWM_THYR_DISABLED: case PWM_THYR_DISABLED: // канал отключен
__PWM_SetOutputState(hPhase, PWM_DISABLE); __PWM_SetOutputState(hPhase, PWM_DISABLE);
break; break;
case PWM_THYR_TIM_WAIT: case PWM_THYR_TIM_WAIT: // канал ожидает команды
__PWM_SetOutputState(hPhase, PWM_DISABLE); __PWM_SetOutputState(hPhase, PWM_DISABLE);
break; break;
case PWM_THYR_TIM_START: case PWM_THYR_TIM_START: // начать ШИМ (пачка импульсов)
__PWM_SetOutputState(hPhase, PWM_ENABLE); __PWM_SetOutputState(hPhase, PWM_ENABLE);
hPhase->PulseCnt = hpwm->Config.PulseNumber; hPhase->PulseCnt = hpwm->Config.PulseNumber;
hPhase->State = PWM_THYR_TIM_ACTIVE; hPhase->State = PWM_THYR_TIM_ACTIVE;
hpwm->f.Running++; hpwm->f.Running++;
break; break;
case PWM_THYR_TIM_ACTIVE: case PWM_THYR_TIM_ACTIVE: // управление пачкой импульсов ШИМ
hPhase->PulseCnt--; hPhase->PulseCnt--;
if (hPhase->PulseCnt <= 0) if (hPhase->PulseCnt <= 0)
{ {
@ -189,13 +199,13 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
} }
break; break;
case PWM_THYR_TIM_DONE: case PWM_THYR_TIM_DONE: // пачка импульсов отправлена - отключение
hPhase->State = PWM_THYR_TIM_WAIT; hPhase->State = PWM_THYR_TIM_WAIT;
if(hpwm->f.Running) if(hpwm->f.Running)
hpwm->f.Running--; hpwm->f.Running--;
break; break;
default: default: // чзх
__PWM_SetOutputState(hPhase, PWM_DISABLE); __PWM_SetOutputState(hPhase, PWM_DISABLE);
break; break;
} }
@ -204,7 +214,7 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
} }
/** /**
* @brief Установка частоты ШИМ. * @brief Установка параметров ШИМ.
* @param hpwm Указатель на хендл ШИМ тиристоров * @param hpwm Указатель на хендл ШИМ тиристоров
* @param Frequency Частота в ГЦ * @param Frequency Частота в ГЦ
* @return HAL Status. * @return HAL Status.
@ -213,16 +223,19 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t
{ {
if(assert_upp(hpwm)) if(assert_upp(hpwm))
return HAL_ERROR; return HAL_ERROR;
if(hpwm->f.Running) if(hpwm->f.Running) // Если есть активные каналы - ниче не меняем
return HAL_BUSY; return HAL_BUSY;
HAL_TIM_Base_Stop(&hpwm1); // Остановка таймера
HAL_TIM_Base_Stop_IT(&hpwm1);
hpwm->Config.PhaseMask.all = PhaseMask; hpwm->Config.PhaseMask.all = PhaseMask;
hpwm->Config.PulseNumber = PulseNumber; hpwm->Config.PulseNumber = PulseNumber;
hpwm->Config.Frequency = Frequency; hpwm->Config.Frequency = Frequency;
// Высставление периодов
__HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(Frequency, PWM_TIM1_FREQ_MHZ)); __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_AUTORELOAD(&hpwm2, TIM_FreqToTick(Frequency, PWM_TIM3_FREQ_MHZ));
// Скважности 50/50
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); __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_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_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
@ -230,6 +243,10 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/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); __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2);
// Сброс счетчиков таймера и запуск заного
__HAL_TIM_SET_COUNTER(&hpwm1, 0);
__HAL_TIM_SET_COUNTER(&hpwm2, 0);
return HAL_TIM_Base_Start_IT(&hpwm1); return HAL_TIM_Base_Start_IT(&hpwm1);
} }
@ -240,13 +257,13 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t
* @param Phase Для какой фазы надо установить полуволну * @param Phase Для какой фазы надо установить полуволну
* @param halfwave Какую полуволну установить * @param halfwave Какую полуволну установить
* @return HAL Status. * @return HAL Status.
* @details Меняет указатель канала фазы на канал соответствующей полуволны
*/ */
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave) HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave)
{ {
if(assert_upp(hpwm)) if(assert_upp(hpwm))
return HAL_ERROR; return HAL_ERROR;
// Сбрасываем текущий канал // Сбрасываем текущий канал
PWM_Stop(hpwm, Phase, 0); PWM_Stop(hpwm, Phase, 0);
@ -315,39 +332,3 @@ static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state
} }
return HAL_OK; return HAL_OK;
} }
/**
* @brief Установка полуволны для слежения.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase Для какой фазы надо установить полуволну
* @param halfwave Какую полуволну установить
* @return HAL Status.
*/
UPP_HalfWave_t PWM_GetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
{
if(assert_upp(hpwm))
return UPP_WAVE_UNKNOWED;
// Если канал дурацкий - возвращаем UNKNOWED
if (Phase >= 3)
{
return UPP_WAVE_UNKNOWED;
}
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return UPP_WAVE_UNKNOWED;
// Выставляем канал
if(hpwm->Phase[Phase] == &hpwm->AllPhases[Phase])
{
return UPP_WAVE_POSITIVE;
}
else if(hpwm->Phase[Phase] == &hpwm->AllPhases[Phase+3])
{
return UPP_WAVE_NEGATIVE;
}
else
{
return UPP_WAVE_UNKNOWED;
}
}

View File

@ -96,8 +96,6 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
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, uint8_t PulseNumber);
/* Установка полуволны для слежения. */ /* Установка полуволны для слежения. */
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave); HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave);
/* Установка полуволны для слежения. */
UPP_HalfWave_t PWM_GetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase);
/* Хендл ШИМ тиристоров. */ /* Хендл ШИМ тиристоров. */
HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm); HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm);

View File

@ -12,7 +12,7 @@ static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef);
static int __CheckSimpleParamU32(uint32_t *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 __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc);
static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef); static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef);
static int __AngleSetLimit(void); static void __AngleSetLimit(void);
/** /**
* @brief Контроль внутренних параметров УПП. * @brief Контроль внутренних параметров УПП.
@ -38,6 +38,8 @@ void UPP_Control_InternalParams(void)
uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all; uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all;
uint16_t pwm_freq = upp.hpwm.Config.Frequency; uint16_t pwm_freq = upp.hpwm.Config.Frequency;
uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber; uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber;
// временная переменная для параметров Мониторинга сети
float pm_alpha = upp.pm.measured.exp[0].alpha;
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
@ -58,11 +60,11 @@ void UPP_Control_InternalParams(void)
} }
// Параметры алгоритма перехода через ноль // Параметры алгоритма перехода через ноль
if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 100)) if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 10000))
{ {
zc_update = 1; zc_update = 1;
} }
if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.Hysteresis)) if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.DebouneCouner))
{ {
zc_update = 1; zc_update = 1;
} }
@ -80,6 +82,15 @@ void UPP_Control_InternalParams(void)
{ {
pwm_update = 1; pwm_update = 1;
} }
// Параметры мониторинга
if(__CheckSimpleParamF(&pm_alpha, MB_INTERNAL.param.pm.mean_alpha, 65535))
{
for(int i = 0; i < 3; i++)
{
Filter_ReInit(&upp.pm.measured.exp[i], pm_alpha);
}
}
// Обновление АЦП конфигов // Обновление АЦП конфигов
@ -142,6 +153,17 @@ void UPP_SetDefault(int pui_default, int internal_default)
if(internal_default) if(internal_default)
{ {
MB_INTERNAL.param.nominal.PhaseNumber = NOM_PHASE_NUMB;
MB_INTERNAL.param.nominal.U = NOM_U_V_DEFAULT*10;
MB_INTERNAL.param.nominal.U_deviation_plus = NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.U_deviation_minus = NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.F = NOM_F_HZ_DEFAULT*100;
MB_INTERNAL.param.nominal.F_deviation_plus = NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.I = NOM_I_A_DEFAULT*10;
MB_INTERNAL.param.pm.mean_alpha = PM_EXP_ALPHA_COEF_DEFAULT*65535;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10; 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_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_IC] = ADC_I_MAX_A_DEFAULT*10;
@ -155,7 +177,7 @@ void UPP_SetDefault(int pui_default, int internal_default)
MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT; MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT;
MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_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.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT; MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT;
//__AngleSetLimit(); //__AngleSetLimit();
} }
@ -163,10 +185,10 @@ void UPP_SetDefault(int pui_default, int internal_default)
static int __AngleSetLimit(void) static void __AngleSetLimit(void)
{ {
// Перерасчет максимально допустимого угла // Перерасчет максимально допустимого угла
float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS; float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS(NOM_F_HZ_DEFAULT);
float angle_limit = 1 - pulses_percent_of_period; float angle_limit = 1 - pulses_percent_of_period;
Angle_SetLimit(&upp.hangle, angle_limit); Angle_SetLimit(&upp.hangle, angle_limit);
} }

View File

@ -12,10 +12,10 @@
typedef struct typedef struct
{ {
unsigned set_default_pui:1; unsigned set_default_pui:1; ///< Выставить настройки ПУИ в дефолтные
unsigned set_default_internal:1; unsigned set_default_internal:1;///< Выставить внутренние настройки в дефолтные
unsigned go:1; unsigned go:1; ///< Запустить УПП
unsigned stop:1; unsigned stop:1; ///< Выставить внутренние настройки в дефолтные
unsigned reserved:11; unsigned reserved:11;
@ -25,33 +25,51 @@ typedef struct
typedef struct typedef struct
{ {
struct
{
uint16_t mean_alpha; ///< Коэф альфа x10000 для эксп. фильтра Umean, Imean, Fmean
}pm;
struct
{
uint16_t PhaseNumber; ///< Количество
uint16_t U; ///< В x 10
uint16_t U_deviation_plus; ///< Проценты x 100
uint16_t U_deviation_minus; ///< Проценты x 100
uint16_t F; ///< Гц x 100
uint16_t F_deviation_plus; ///< Проценты x 100
uint16_t F_deviation_minus; ///< Проценты x 100
uint16_t I; ///< Амперы x 10
}nominal;
/* Параметры АЦП */ /* Параметры АЦП */
struct struct
{ {
uint16_t ADC_Max[4]; uint16_t ADC_Max[4]; ///< В x 10
uint16_t ADC_Zero[4]; uint16_t ADC_Zero[4]; ///< Кванты АЦП
}adc; }adc;
/* Параметры ШИМ */ /* Параметры ШИМ */
struct struct
{ {
uint16_t PhaseMask; uint16_t PhaseMask; ///< Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c
uint16_t Frequency; uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры
uint16_t PulseNumber; uint16_t PulseNumber; ///< Количесво импульсов в пачке
}pwm; }pwm;
/* Параметры Угла */ /* Параметры Угла */
struct struct
{ {
uint16_t Hysteresis; uint16_t Hysteresis; ///< Гистерезис для определения перехода через ноль
uint16_t DebouneCouner; uint16_t DebouneCouner; ///< Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль
}zc; }zc;
/* Параметры Угла */ /* Параметры Угла */
struct struct
{ {
uint16_t Angle_Max; uint16_t Angle_Max; ///< Максимальный угол открытия тиристора
uint16_t Angle_Min; uint16_t Angle_Min; ///< Минимальный угол открытия тиристора
}angle; }angle;

View File

@ -104,7 +104,7 @@ typedef struct
uint64_t all; uint64_t all;
struct struct
{ {
unsigned :1; unsigned slow_calc_overrun:1;
}err; }err;
}f; }f;
@ -113,6 +113,7 @@ typedef struct
uint16_t adc_reinit_err; uint16_t adc_reinit_err;
uint16_t zc_reinit_err; uint16_t zc_reinit_err;
uint16_t pwm_reinit_err; uint16_t pwm_reinit_err;
uint16_t slow_calc_overrun;
}cnt; }cnt;
}prvt; ///< Приватные ошибки, не идущие напрямую в ПУИ }prvt; ///< Приватные ошибки, не идущие напрямую в ПУИ

View File

@ -6,6 +6,7 @@
* @details * @details
******************************************************************************/ ******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП #include "upp_main.h" // всё остальное по работе с УПП
#include "tim.h"
UPP_t upp; UPP_t upp;
float alpha_dbg = 0.5; float alpha_dbg = 0.5;
@ -17,6 +18,7 @@ float alpha_dbg = 0.5;
*/ */
int UPP_Init(void) int UPP_Init(void)
{ {
BenchTime_Init();
// Подключение указателей // Подключение указателей
upp.errors = &errors; upp.errors = &errors;
upp.PUI.params = &MB_DATA.HoldRegs.pui_params; upp.PUI.params = &MB_DATA.HoldRegs.pui_params;
@ -60,8 +62,6 @@ int UPP_While(void)
{ {
upp.call->stop = 0; upp.call->stop = 0;
} }
// Сброс на дефолтные по запросу // Сброс на дефолтные по запросу
if(upp.call->set_default_pui) if(upp.call->set_default_pui)
{ {
@ -74,6 +74,8 @@ int UPP_While(void)
PowerMonitor_SlowHandle(&upp.pm);
// Если СТОП - переходим в ошибку // Если СТОП - переходим в ошибку
if (upp.call->stop) if (upp.call->stop)
upp.workmode = WM_Error; upp.workmode = WM_Error;
@ -107,6 +109,13 @@ int UPP_While(void)
PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
break; break;
case WM_Done:
PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
break;
default:
break;
} }
@ -132,6 +141,8 @@ void UPP_Tick(void)
void UPP_ADC_Handle(void) void UPP_ADC_Handle(void)
{ {
BenchTime_Start(BT_ADC, angletim.Instance->CNT, HAL_MAX_DELAY);
PowerMonitor_Handle(&upp.pm); PowerMonitor_Handle(&upp.pm);
for(int phase = 0; phase < 3; phase++) for(int phase = 0; phase < 3; phase++)
@ -152,10 +163,14 @@ void UPP_ADC_Handle(void)
} }
// Проверяем на ошибки // Проверяем на ошибки
upp.Timings.isr_adc = BenchTime_End(BT_ADC, angletim.Instance->CNT);
} }
void UPP_PWM_Handle(void) void UPP_PWM_Handle(void)
{ {
BenchTime_Start(BT_PWM, angletim.Instance->CNT, HAL_MAX_DELAY);
PWM_Handle(&upp.hpwm); PWM_Handle(&upp.hpwm);
upp.Timings.isr_pwm = BenchTime_End(BT_PWM, angletim.Instance->CNT);
} }
void UPP_Angle_Handle(void) void UPP_Angle_Handle(void)
@ -186,6 +201,8 @@ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
{ {
if (htim == upp.hangle.htim) if (htim == upp.hangle.htim)
{ {
BenchTime_Start(BT_SYSTICK, angletim.Instance->CNT, HAL_MAX_DELAY);
UPP_Angle_Handle(); UPP_Angle_Handle();
upp.Timings.isr_systick = BenchTime_End(BT_SYSTICK, angletim.Instance->CNT);
} }
} }

View File

@ -38,6 +38,13 @@ typedef struct
UPP_Errors_t *errors; ///< Ошибки УПП UPP_Errors_t *errors; ///< Ошибки УПП
uint32_t StartTick; uint32_t StartTick;
struct
{
uint32_t isr_adc;
uint32_t isr_pwm;
uint32_t isr_systick;
}Timings;
}UPP_t; }UPP_t;
extern UPP_t upp; extern UPP_t upp;

View File

@ -564,57 +564,6 @@
<FileName>dma.c</FileName> <FileName>dma.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>../Core/Src/dma.c</FilePath> <FilePath>../Core/Src/dma.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File> </File>
<File> <File>
<FileName>iwdg.c</FileName> <FileName>iwdg.c</FileName>