diff --git a/UPP/Core/Configs/modbus_config.h b/UPP/Core/Configs/modbus_config.h
index 806e78d..27434b6 100644
--- a/UPP/Core/Configs/modbus_config.h
+++ b/UPP/Core/Configs/modbus_config.h
@@ -59,7 +59,7 @@
* @details Терминалка от двигателей использует для чтения регистров комманду R_HOLD_REGS вместо R_IN_REGS
* Поэтому чтобы считывать Input Regs - надо поменять их местами.
*/
-//#define MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
+#define MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
/////////////////////////////////////////////////////////////////////
/////////////////////////---CALC DEFINES---//////////////////////////
diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h
index 39bd452..5c24c99 100644
--- a/UPP/Core/Configs/upp_config.h
+++ b/UPP/Core/Configs/upp_config.h
@@ -22,11 +22,14 @@
* @{
*/
+#define UPP_SET_DEFAULT ///< Установить настройки по умолчанию
#define UPP_DISABLE_ERROR_BLOCK ///< Отключить блокировку УПП при ошибках
//#define UPP_SIMULATE_I ///< Симулировт токи (Iref/2) а не брать с АЦП
//#define UPP_DISABLE_PROTECT_BOARDPOWER ///< Отключить проверки питания плат (+24, +5 В)
//#define UPP_DISABLE_PROTECT_LOSS_PHASE ///< Отключить проверки на потерянные фазы
+
+
//#define ZC_DISABLE_HYSTERESIS_DEBOUNCE ///< Отключить гиситерезис и дребезг на определении перехода через ноль
/** //UPP_PARAMS_TEST
@@ -117,10 +120,14 @@
#define PM_RMS_EXT_TAU_US_DEFAULT 0.02*3 // 3 периода 50 Гц
/* Параметры АЦП */
-#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
+// Колво квантов ацп для 1.5 Вольт при опорном 3.3 В
+#define ADC_U_ZERO_DEFAULT ((1.5/3.3)*4095)
+#define ADC_I_ZERO_DEFAULT ((1.5/3.3)*4095)
+#define ADC_T_ZERO_DEFAULT ((1.5/3.3)*4095)
+// Максимальное значение для 3.3 В рассчитанное из максимального значения X для 3 В
+// X/ZERO_DEFAULT*(4095-ZERO_DEFAULT)
+#define ADC_U_MAX_V_DEFAULT (1216.0/ADC_U_ZERO_DEFAULT*(4095-ADC_U_ZERO_DEFAULT))
+#define ADC_I_MAX_A_DEFAULT (53.0/ADC_I_ZERO_DEFAULT*(4095-ADC_I_ZERO_DEFAULT))
/* Параметры определения перехода через ноль */
#define ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT 2.0
diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c
index 33c5b31..372f8fb 100644
--- a/UPP/Core/PowerMonitor/adc_tools.c
+++ b/UPP/Core/PowerMonitor/adc_tools.c
@@ -13,8 +13,7 @@
#define FreqTableSize 200
float phase_table[FreqTableSize];
float freq_table[FreqTableSize];
-//float freq_table[FreqTableSize] = { 49.0f, 49.1f, 49.2f, 49.3f, 49.4f, 49.5f, 49.6f, 49.7f, 49.8f, 49.9f, \
-// 50.0f, 50.1f, 50.2f, 50.3f, 50.4f, 50.5f, 50.6f, 50.7f, 50.8f, 50.9f, 51.0f };
+
static void ADC_InitAllFilters(ADC_Periodic_t *adc)
{
@@ -26,7 +25,7 @@ static void ADC_InitAllFilters(ADC_Periodic_t *adc)
FilterLUT_Init(&adc->temp_map[i],
(float *)adc_temp_quants,
(float *)adc_temp_vals,
- numbof(adc_temp_quants), 1);
+ numbof(adc_temp_quants), 1, 0);
}
float freq_temp = FreqTableFreqStart;
@@ -91,7 +90,7 @@ HAL_StatusTypeDef ADC_Init(ADC_Periodic_t *adc, TIM_HandleTypeDef *htim, ADC_Han
adc->htim = htim;
adc->hadc = hadc;
- ADC_InitAllFilters(adc);
+ ADC_InitAllFilters(adc);
adc->f.AdcRunning = 0;
adc->f.DataReady = 0;
@@ -192,9 +191,9 @@ HAL_StatusTypeDef ADC_UpdateRegular(ADC_Periodic_t *adc)
int u_ind = ADC_U_CHANNELS_START + i;
int i_ind = ADC_I_CHANNELS_START + i;
// заменяем сырые данные на отфильтрованные данные
- int raw_u = Filter_Process(&adc->u_fltr[i], (int)raw[u_ind]-2048);
+ int raw_u = Filter_Process(&adc->u_fltr[i], (int)raw[u_ind]-coefs->lZero);
int raw_i = Filter_Process(&adc->i_fltr[i], raw[i_ind]);
- raw[u_ind] = raw_u+2048;
+ raw[u_ind] = raw_u+coefs->lZero;
raw[i_ind] = raw_i;
}
@@ -223,7 +222,7 @@ HAL_StatusTypeDef ADC_UpdateTemperatures(ADC_Periodic_t *adc)
uint16_t *raw = adc->RawData;
// Преобразования температуры по таблице
- for (int i = ADC_TEMP_CHANNELS_START; i < ADC_TEMP_CHANNELS_END; i++)
+ for (int i = ADC_TEMP_CHANNELS_START; i <= ADC_TEMP_CHANNELS_END; i++)
{
data[i] = Filter_Process(&adc->temp_map[i-ADC_TEMP_CHANNELS_START], raw[i]);
}
diff --git a/UPP/Core/PowerMonitor/adc_tools.h b/UPP/Core/PowerMonitor/adc_tools.h
index 5b577bd..951eb14 100644
--- a/UPP/Core/PowerMonitor/adc_tools.h
+++ b/UPP/Core/PowerMonitor/adc_tools.h
@@ -55,8 +55,8 @@
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, \
82, 83, 84, 85, 86, 87, 88, 89, 90}
-static const float adc_temp_vals[] = ADC_TEMPERATURES;
-static const float adc_temp_quants[] = ADC_TEMPERATURES_QUANTS;
+static float adc_temp_vals[] = ADC_TEMPERATURES;
+static float adc_temp_quants[] = ADC_TEMPERATURES_QUANTS;
/**
* @brief Коэфициенты канала АЦП для пересчета в единицы измерения
diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c
index f1cdc9f..6bca9cd 100644
--- a/UPP/Core/PowerMonitor/power_monitor.c
+++ b/UPP/Core/PowerMonitor/power_monitor.c
@@ -88,7 +88,8 @@ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm)
return HAL_OK;
}
-
+int temp_i_max = 0;
+int temp_reset = 0;
/**
* @brief Медленные расчеты АЦП.
* @param hpm Указатель на структуру мониторинга сети
@@ -163,7 +164,17 @@ void PowerMonitor_SlowCalc(PowerMonitor_t *hpm)
float iamp = imean / 3;
meas->final.Uamp = uamp;//Filter_Process(&hpm->rms_exp[RMS_EXP_U], uamp);
meas->final.Iamp = iamp;//Filter_Process(&hpm->rms_exp[RMS_EXP_I], iamp);
+ static int ch_i = 3;
+ if(hpm->adc.RawData[ch_i] > temp_i_max)
+ {
+ temp_i_max = hpm->adc.RawData[ch_i];
+ }
+ if(temp_reset)
+ {
+ temp_reset = 0;
+ temp_i_max = 0;
+ }
hpm->slow_cnt++;
}
diff --git a/UPP/Core/Src/main.c b/UPP/Core/Src/main.c
index 6ba0496..a13d917 100644
--- a/UPP/Core/Src/main.c
+++ b/UPP/Core/Src/main.c
@@ -133,7 +133,8 @@ int main(void)
#endif //defined(STM32F417xx)
#else //MATLAB
#endif //MATLAB
- UPP_App_Init();
+ if(UPP_App_Init())
+ Error_Handler();
TxHeader.StdId = 0x0100 + 1;
TxHeader.ExtId = 0;
@@ -146,7 +147,8 @@ int main(void)
/* Infinite loop */
/* USER CODE BEGIN WHILE */
- UPP_PreWhile();
+ if(UPP_PreWhile())
+ Error_Handler();
while (1)
{
UPP_While();
diff --git a/UPP/Core/UPP/upp_io.c b/UPP/Core/UPP/upp_io.c
index 324e138..24f1de2 100644
--- a/UPP/Core/UPP/upp_io.c
+++ b/UPP/Core/UPP/upp_io.c
@@ -109,14 +109,17 @@ static void UPP_CEN_Write(int state)
static void UPP_RDO1_Write(int state)
{
HAL_GPIO_WritePin(RDO1_GPIO_Port, RDO1_Pin, state);
+ GPIO_LED_Set(&UPP_LEDS.red, state);
}
static void UPP_RDO2_Write(int state)
{
HAL_GPIO_WritePin(RDO2_GPIO_Port, RDO2_Pin, state);
+ GPIO_LED_Set(&UPP_LEDS.green2, state);
}
static void UPP_RDO3_Write(int state)
{
HAL_GPIO_WritePin(RDO3_GPIO_Port, RDO3_Pin, state);
+ GPIO_LED_Set(&UPP_LEDS.green1, state);
}
static void UPP_RDO4_Write(int state)
{
diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c
index 367a502..b039168 100644
--- a/UPP/Core/UPP/upp_main.c
+++ b/UPP/Core/UPP/upp_main.c
@@ -38,6 +38,10 @@ int UPP_App_Init(void)
upp.PUI.values = &MB_DATA.InRegs.pui;
upp.call = &MB_INTERNAL.FuncCalls;
+#ifdef UPP_SET_DEFAULT
+ UPP_Params_SetDefault(1, 1);
+#endif
+
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim, UPP_UART2_SetDirection);
MODBUS_FirstInit(&hmodbus_pui, &mb_pui_huart, &mb_pui_htim, UPP_UART1_SetDirection);
@@ -81,9 +85,9 @@ int UPP_PreWhile(void)
#endif
// GPIO_LED_Fading_Start(&UPP_LEDS.red, 1000);
- GPIO_LED_Duty_Set(&UPP_LEDS.green1, 25);
- GPIO_LED_Duty_Set(&UPP_LEDS.green2, 50);
- GPIO_LED_Duty_Set(&UPP_LEDS.red, 5);
+// GPIO_LED_Duty_Set(&UPP_LEDS.green1, 25);
+// GPIO_LED_Duty_Set(&UPP_LEDS.green2, 50);
+// GPIO_LED_Duty_Set(&UPP_LEDS.red, 5);
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING |
@@ -91,7 +95,8 @@ int UPP_PreWhile(void)
MODBUS_SlaveStart(&hmodbus1, NULL);
-// UPP_DO.CEN(ENABLE);
+
+ UPP_DO.CEN(ENABLE);
return 0;
}
@@ -108,6 +113,10 @@ int UPP_While(void)
{
PWM_SetPolarity(&upp.hpwm, dbg_polarity);
int retval = 0;
+ if(upp.pm.adc.RawData[0] < 2000)
+ {
+ __NOP();
+ }
if(upp.pm.f.runSlow)
{
GPIO_LED_Duty_Set(&UPP_LEDS.green1, test_green1);
diff --git a/UPP/Core/UPP/upp_params.c b/UPP/Core/UPP/upp_params.c
index 05333bf..3cd2944 100644
--- a/UPP/Core/UPP/upp_params.c
+++ b/UPP/Core/UPP/upp_params.c
@@ -105,7 +105,7 @@ void UPP_Params_ControlInternal(void)
// флаги обновились ли конфиги
static int alpha_update = 0;
- static int adc_channel_update[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
+ static int adc_channel_update[ADC_NUMB_OF_CHANNELS] = {0};
static int zc_update = 0;
static int pwm_update = 0;
@@ -118,6 +118,7 @@ void UPP_Params_ControlInternal(void)
// временная переменная для параметров каналов АЦП
float adc_channel_max[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
uint16_t adc_channel_zero[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
+ uint16_t adc_temp_offset[ADC_NUMB_OF_T_CHANNELS] = {0};
// временная переменная для параметров перехода через ноль
float zc_hysteresis = upp.pm.zc.Config.Hysteresis;
uint16_t zc_debounce = upp.pm.zc.Config.DebounceSamples;
@@ -172,7 +173,15 @@ void UPP_Params_ControlInternal(void)
adc_channel_update[i] = 1;
}
}
-
+ for(int i = 0; i < ADC_NUMB_OF_T_CHANNELS; i++)
+ {
+ adc_temp_offset[i] = (int)upp.pm.adc.temp_map[i].offset + 2048;
+
+ if(__CheckParamU16(&adc_temp_offset[i], PARAM_INTERNAL->adc.Temp_Zero[i]))
+ {
+ adc_channel_update[ADC_TEMP_CHANNELS_START+i] = 1;
+ }
+ }
// Параметры алгоритма перехода через ноль
if(__CheckParamF(&zc_hysteresis, PARAM_INTERNAL->zc.Hysteresis, 10000))
{
@@ -240,14 +249,26 @@ void UPP_Params_ControlInternal(void)
ERR_PRIVATE_CNT->angle_reinit_err++;
}
// Обновление АЦП конфигов
- for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
+ for(int i = 0; i < ADC_NUMB_OF_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;
+ if(i < ADC_NUMB_OF_REGULAR_CHANNELS)
+ {
+ if(ADC_ConfigChannel(&upp.pm.adc, i, adc_channel_zero[i], adc_channel_max[i], 4095) == HAL_OK)
+ adc_channel_update[i] = 0;
+ else
+ ERR_PRIVATE_CNT->adc_reinit_err++;
+ }
else
- ERR_PRIVATE_CNT->adc_reinit_err++;
+ {
+ int temp_i = i-ADC_TEMP_CHANNELS_START;
+ upp.pm.adc.temp_map[temp_i].reset(&upp.pm.adc.temp_map[temp_i],
+ (float *)adc_temp_quants,
+ (float *)adc_temp_vals,
+ numbof(adc_temp_quants), 1, (int)adc_temp_offset[temp_i]-2048);
+ Filter_Start(&upp.pm.adc.temp_map[temp_i]);
+ }
}
}
// Обновление Zero-Cross конфигов
@@ -449,6 +470,8 @@ void UPP_Params_SetDefault(int pui_default, int internal_default)
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_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->adc.Temp_Zero[TEMP_1] = ADC_T_ZERO_DEFAULT;
+ PARAM_INTERNAL->adc.Temp_Zero[TEMP_2] = ADC_T_ZERO_DEFAULT;
PARAM_INTERNAL->pwm.PhaseMask = 7; // (все три фазы)
PARAM_INTERNAL->pwm.Frequency = PWM_THYR_FREQUENCY_HZ_DEFAULT;
diff --git a/UPP/Core/UPP/upp_params.h b/UPP/Core/UPP/upp_params.h
index a944f25..5daa4bb 100644
--- a/UPP/Core/UPP/upp_params.h
+++ b/UPP/Core/UPP/upp_params.h
@@ -53,50 +53,57 @@ typedef struct
{
uint16_t TemperatureWarn; ///< Адрес 1010: Предупредительный порог температуры [Градусы x 100]
uint16_t TemperatureErr; ///< Адрес 1011: Аварийный порог температуры [Градусы x 100]
+ uint16_t reserved[8];
}temp;
/* Параметры АЦП */
struct
{
- uint16_t ADC_Max[4]; ///< Адрес 1020: Величина в единицах измерения при АЦП = 4095 [В или А x 10]
- uint16_t ADC_Zero[4]; ///< Адрес 1021: Кванты АЦП когда на входе ноль
+ uint16_t ADC_Max[4]; ///< Адрес 1020-1023: Величина в единицах измерения при АЦП = 4095 [В или А x 10]
+ uint16_t ADC_Zero[4]; ///< Адрес 1024-1027: Кванты АЦП когда на входе ноль
+ uint16_t Temp_Zero[2]; ///< Адрес 1028-1029: Кванты АЦП когда датчик не подключен
+ uint16_t reserved[10];
}adc;
/* Параметры Мониторинга напряжения */
struct
{
- uint16_t lImaxAmp; ///< Адрес 1031: Амплитудное значение максимально допустимого тока (рассчитывается само)
- uint16_t rms_window_size; ///< Адрес 1032: Размер окна для RMS
- uint16_t rms_exp_alpha; ///< Адрес 1033: Постоянная времени для сглаживания RMS
+ uint16_t lImaxAmp; ///< Адрес 1040: Амплитудное значение максимально допустимого тока (рассчитывается само)
+ uint16_t rms_window_size; ///< Адрес 1041: Размер окна для RMS
+ uint16_t rms_exp_alpha; ///< Адрес 1042: Постоянная времени для сглаживания RMS
+ uint16_t reserved[7];
}pm;
/* Параметры ШИМ */
struct
{
- uint16_t PhaseMask; ///< Адрес 1040: Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c
- uint16_t Frequency; ///< Адрес 1041: Частота ШИМ для пачки импульсов на тиристоры [Герцы]
- uint16_t Duty; ///< Адрес 1042: Скважность ШИМ для пачки импульсов на тиристоры [Проценты]
- uint16_t PulseLength; ///< Адрес 1043: Количесво импульсов в пачке [Количество]
+ uint16_t PhaseMask; ///< Адрес 1050: Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c
+ uint16_t Frequency; ///< Адрес 1051: Частота ШИМ для пачки импульсов на тиристоры [Герцы]
+ uint16_t Duty; ///< Адрес 1052: Скважность ШИМ для пачки импульсов на тиристоры [Проценты]
+ uint16_t PulseLength; ///< Адрес 1053: Количесво импульсов в пачке [Количество]
+ uint16_t reserved[6];
}pwm;
/* Параметры Перехода через ноль */
struct
{
- uint16_t Hysteresis; ///< Адрес 1050: Гистерезис для определения перехода через ноль [Проценты x 100]
- uint16_t DebouneCouner; ///< Адрес 1051: Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль [Количество]
+ uint16_t Hysteresis; ///< Адрес 1060: Гистерезис для определения перехода через ноль [Проценты x 100]
+ uint16_t DebouneCouner; ///< Адрес 1061: Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль [Количество]
+ uint16_t reserved[8];
}zc;
/* Параметры Угла */
struct
{
- uint16_t PulseLengthReserve;/*!< @brief Адрес 1060: Сколько запаса закладывать на длительность пачки импульсов [Проценты] @ref __AngleSetLimit
+ uint16_t PulseLengthReserve;/*!< @brief Адрес 1070: Сколько запаса закладывать на длительность пачки импульсов [Проценты] @ref __AngleSetLimit
@details Пример: 100% - будет запас в одну пачку импульсов */
- uint16_t Angle_Max; ///< Адрес 1061: Максимальный угол открытия тиристора [0..1 x 65535]
- uint16_t Angle_Min; ///< Адрес 1062: Минимальный угол открытия тиристора [0..1 x 65535]
- uint16_t PID_Kp; ///< Адрес 1063: Пропорциональный коэфициент ПИ регулятора угла [x 10000]
- uint16_t PID_Ki; ///< Адрес 1064: Интегральный коэфициент ПИ регулятора угла [x 10000]
- uint16_t PID_Kd; ///< Адрес 1065: Интегральный коэфициент ПИ регулятора угла [x 10000]
+ uint16_t Angle_Max; ///< Адрес 1071: Максимальный угол открытия тиристора [0..1 x 65535]
+ uint16_t Angle_Min; ///< Адрес 1072: Минимальный угол открытия тиристора [0..1 x 65535]
+ uint16_t PID_Kp; ///< Адрес 1073: Пропорциональный коэфициент ПИ регулятора угла [x 10000]
+ uint16_t PID_Ki; ///< Адрес 1074: Интегральный коэфициент ПИ регулятора угла [x 10000]
+ uint16_t PID_Kd; ///< Адрес 1075: Интегральный коэфициент ПИ регулятора угла [x 10000]
+ uint16_t reserved[4];
}angle;
}UPP_PrvtParams_t;
diff --git a/UPP/Core/UPP/upp_status.c b/UPP/Core/UPP/upp_status.c
index 45043e4..eebab4a 100644
--- a/UPP/Core/UPP/upp_status.c
+++ b/UPP/Core/UPP/upp_status.c
@@ -16,6 +16,16 @@ void UPP_Status_Handler(void)
GPIO_LED_Dynamic_Handle(&UPP_LEDS.red);
+ MB_DATA.InRegs.pui.Uall = upp.pm.measured.final.Uamp * MB_INTERNAL.param.nominal.U;
+ MB_DATA.InRegs.pui.Uab = upp.pm.measured.final.U[U_AB] * MB_INTERNAL.param.nominal.U;
+ MB_DATA.InRegs.pui.Ubc = upp.pm.measured.final.U[U_BC] * MB_INTERNAL.param.nominal.U;
+ MB_DATA.InRegs.pui.Uca = upp.pm.measured.final.U[U_CA] * MB_INTERNAL.param.nominal.U;
+
+ MB_DATA.InRegs.pui.Iall = upp.pm.measured.final.Iamp * MB_INTERNAL.param.nominal.I;
+ MB_DATA.InRegs.pui.Ia = upp.pm.measured.final.U[I_A] * MB_INTERNAL.param.nominal.I;
+ MB_DATA.InRegs.pui.Ib = upp.pm.measured.final.U[I_B] * MB_INTERNAL.param.nominal.I;
+ MB_DATA.InRegs.pui.Ic = upp.pm.measured.final.U[I_C] * MB_INTERNAL.param.nominal.I;
+
if(GPIO_Read_Switch(&UPP_DIN.Pusk))
{
upp.call->go = 1;
diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx
index 85341ea..5f3f0dc 100644
--- a/UPP/MDK-ARM/UPP.uvoptx
+++ b/UPP/MDK-ARM/UPP.uvoptx
@@ -154,7 +154,7 @@