diff --git a/MATLAB/upp_demo.m b/MATLAB/upp_demo.m
index c299d55..13cdb36 100644
--- a/MATLAB/upp_demo.m
+++ b/MATLAB/upp_demo.m
@@ -242,57 +242,102 @@ function update_plots(alpha_deg, alpha_rad, t, f, U_phase, U_line, angle_text)
thyristor_state(6, i) = 1;
end
end
-
+
%% 2. Определяем, когда тиристоры ФИЗИЧЕСКИ открыты
+ % В схеме без нейтрали тиристоры открываются парами (фаза-фаза)
- % VS1+ (A+): открыт, если есть импульс и положительная полуволна фазы A
- if thyristor_state(1, i) == 1 && (theta_a_mod >= 0 && theta_a_mod <= pi) && (Ua(i) > Ub(i) && Ua(i) > Uc(i))
+ % Пары тиристоров для линейных напряжений:
+ % Uab: VS1+ (A+) и VS4- (B-)
+ % Uba: VS3+ (B+) и VS2- (A-)
+ % Ubc: VS3+ (B+) и VS6- (C-)
+ % Ucb: VS5+ (C+) и VS4- (B-)
+ % Uca: VS5+ (C+) и VS2- (A-)
+ % Uac: VS1+ (A+) и VS6- (C-)
+
+ % Проверяем каждую пару
+ % Пара A+ и B- (Uab)
+ if thyristor_state(1, i) == 1 && thyristor_state(4, i) == 1 && Ua(i) > Ub(i)
thyristor_conducting(1, i) = 1;
- end
-
- % VS1- (A-): открыт, если есть импульс и отрицательная полуволна фазы A
- if thyristor_state(2, i) == 1 && (theta_a_mod >= pi && theta_a_mod <= 2*pi) && (Ua(i) < Ub(i) && Ua(i) < Uc(i))
- thyristor_conducting(2, i) = 1;
- end
-
- % VS2+ (B+): открыт, если есть импульс и положительная полуволна фазы B
- if thyristor_state(3, i) == 1 && (theta_b_mod >= 0 && theta_b_mod <= pi) && (Ub(i) > Ua(i) && Ub(i) > Uc(i))
- thyristor_conducting(3, i) = 1;
- end
-
- % VS2- (B-): открыт, если есть импульс и отрицательная полуволна фазы B
- if thyristor_state(4, i) == 1 && (theta_b_mod >= pi && theta_b_mod <= 2*pi) && (Ub(i) < Ua(i) && Ub(i) < Uc(i))
thyristor_conducting(4, i) = 1;
+ elseif i > 1 && thyristor_conducting(1, i-1) == 1 && thyristor_conducting(4, i-1) == 1
+ if Ua(i) > Ub(i)
+ thyristor_conducting(1, i) = 1;
+ thyristor_conducting(4, i) = 1;
+ end
end
- % VS3+ (C+): открыт, если есть импульс и положительная полуволна фазы C
- if thyristor_state(5, i) == 1 && (theta_c_mod >= 0 && theta_c_mod <= pi) && (Uc(i) > Ub(i) && Uc(i) > Ua(i))
- thyristor_conducting(5, i) = 1;
+ % Пара B+ и A- (Uba)
+ if thyristor_state(3, i) == 1 && thyristor_state(2, i) == 1 && Ub(i) > Ua(i)
+ thyristor_conducting(3, i) = 1;
+ thyristor_conducting(2, i) = 1;
+ elseif i > 1 && thyristor_conducting(3, i-1) == 1 && thyristor_conducting(2, i-1) == 1
+ if Ub(i) > Ua(i)
+ thyristor_conducting(3, i) = 1;
+ thyristor_conducting(2, i) = 1;
+ end
end
- % VS3- (C-): открыт, если есть импульс и отрицательная полуволна фазы C
- if thyristor_state(6, i) == 1 && (theta_c_mod >= pi && theta_c_mod <= 2*pi) && (Uc(i) < Ub(i) && Uc(i) < Ua(i))
+ % Пара B+ и C- (Ubc)
+ if thyristor_state(3, i) == 1 && thyristor_state(6, i) == 1 && Ub(i) > Uc(i)
+ thyristor_conducting(3, i) = 1;
thyristor_conducting(6, i) = 1;
+ elseif i > 1 && thyristor_conducting(3, i-1) == 1 && thyristor_conducting(6, i-1) == 1
+ if Ub(i) > Uc(i)
+ thyristor_conducting(3, i) = 1;
+ thyristor_conducting(6, i) = 1;
+ end
end
- %% 3. Расчет выходных напряжений
+ % Пара C+ и B- (Ucb)
+ if thyristor_state(5, i) == 1 && thyristor_state(4, i) == 1 && Uc(i) > Ub(i)
+ thyristor_conducting(5, i) = 1;
+ thyristor_conducting(4, i) = 1;
+ elseif i > 1 && thyristor_conducting(5, i-1) == 1 && thyristor_conducting(4, i-1) == 1
+ if Uc(i) > Ub(i)
+ thyristor_conducting(5, i) = 1;
+ thyristor_conducting(4, i) = 1;
+ end
+ end
+ % Пара C+ и A- (Uca)
+ if thyristor_state(5, i) == 1 && thyristor_state(2, i) == 1 && Uc(i) > Ua(i)
+ thyristor_conducting(5, i) = 1;
+ thyristor_conducting(2, i) = 1;
+ elseif i > 1 && thyristor_conducting(5, i-1) == 1 && thyristor_conducting(2, i-1) == 1
+ if Uc(i) > Ua(i)
+ thyristor_conducting(5, i) = 1;
+ thyristor_conducting(2, i) = 1;
+ end
+ end
+
+ % Пара A+ и C- (Uac)
+ if thyristor_state(1, i) == 1 && thyristor_state(6, i) == 1 && Ua(i) > Uc(i)
+ thyristor_conducting(1, i) = 1;
+ thyristor_conducting(6, i) = 1;
+ elseif i > 1 && thyristor_conducting(1, i-1) == 1 && thyristor_conducting(6, i-1) == 1
+ if Ua(i) > Uc(i)
+ thyristor_conducting(1, i) = 1;
+ thyristor_conducting(6, i) = 1;
+ end
+ end
+
+ %% 3. Расчет выходных напряжений
% Фазные выходные напряжения
Ua_out = 0;
if thyristor_conducting(1, i) || thyristor_conducting(2, i)
Ua_out = Ua(i);
end
-
+
Ub_out = 0;
if thyristor_conducting(3, i) || thyristor_conducting(4, i)
Ub_out = Ub(i);
end
-
+
Uc_out = 0;
if thyristor_conducting(5, i) || thyristor_conducting(6, i)
Uc_out = Uc(i);
end
-
+
% Линейные выходные напряжения
Uab_out(i) = Ua_out - Ub_out;
Ubc_out(i) = Ub_out - Uc_out;
@@ -313,7 +358,7 @@ function update_plots(alpha_deg, alpha_rad, t, f, U_phase, U_line, angle_text)
title('Входные напряжения (сплошные - фазные, пунктир - линейные)');
xlabel('Время, с');
ylabel('Напряжение, В');
- legend('Location', 'best');
+ legend('Location', 'west');
xlim([0, max(t)]);
ylim([-700, 700]);
@@ -327,7 +372,7 @@ function update_plots(alpha_deg, alpha_rad, t, f, U_phase, U_line, angle_text)
title(sprintf('Выходные линейные напряжения (α = %d°)', alpha_deg));
xlabel('Время, с');
ylabel('Напряжение, В');
- legend('Location', 'best');
+ legend('Location', 'west');
xlim([0, max(t)]);
ylim([-700, 700]);
@@ -338,8 +383,13 @@ function update_plots(alpha_deg, alpha_rad, t, f, U_phase, U_line, angle_text)
% Цвета для тиристоров
colors = {'r', 'r', 'g', 'g', 'b', 'b'};
line_styles = {'-', '--', '-', '--', '-', '--'};
+ names = {'VS1+', 'VS1-', 'VS2+', 'VS2-', 'VS3+', 'VS3-'};
+ % Измененный порядок отрисовки: VS1+, VS1-, VS2+, VS2-, VS3+, VS3-
+ order = [6, 5, 4, 3, 2, 1];
- for k = 1:6
+ for idx = 1:6
+ k = order(idx); % Берем тиристор в нужном порядке
+
% Находим интервалы, где подан управляющий импульс
state = thyristor_state(k, :);
diff_state = diff([0, state, 0]);
@@ -348,7 +398,19 @@ function update_plots(alpha_deg, alpha_rad, t, f, U_phase, U_line, angle_text)
% Рисуем горизонтальные линии для каждого интервала
for m = 1:length(start_idx)
- plot(t(start_idx(m):end_idx(m)), k*ones(1, length(start_idx(m):end_idx(m))), ...
+ plot(t(start_idx(m):end_idx(m)), idx*ones(1, length(start_idx(m):end_idx(m))), ...
+ 'Color', colors{k}, 'LineStyle', line_styles{k}, 'LineWidth', 1);
+ end
+
+ % Находим интервалы, где тиристор открыт
+ state = thyristor_conducting(k, :);
+ diff_state = diff([0, state, 0]);
+ start_idx = find(diff_state == 1);
+ end_idx = find(diff_state == -1) - 1;
+
+ % Рисуем горизонтальные линии для каждого интервала
+ for m = 1:length(start_idx)
+ plot(t(start_idx(m):end_idx(m)), idx*ones(1, length(start_idx(m):end_idx(m))), ...
'Color', colors{k}, 'LineStyle', line_styles{k}, 'LineWidth', 2);
end
end
@@ -358,15 +420,12 @@ function update_plots(alpha_deg, alpha_rad, t, f, U_phase, U_line, angle_text)
ylabel('Тиристор');
ylim([0.5, 6.5]);
yticks(1:6);
- yticklabels({'VS1+', 'VS1-', 'VS2+', 'VS2-', 'VS3+', 'VS3-'});
+ yticklabels(names(order));
xlim([0, max(t)]);
% Обновление текста с текущим углом
set(angle_text, 'String', sprintf('Угол α = %d°', alpha_deg));
- % Добавление пояснений к тиристорам
- legend({'Фаза A (+)', 'Фаза A (-)', 'Фаза B (+)', 'Фаза B (-)', ...
- 'Фаза C (+)', 'Фаза C (-)'}, 'Location', 'best');
end
%% Функция обратного вызова для ползунка
diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h
index f2996dd..a2e11de 100644
--- a/UPP/Core/Configs/upp_config.h
+++ b/UPP/Core/Configs/upp_config.h
@@ -23,10 +23,12 @@
*/
#define UPP_SET_DEFAULT ///< Установить настройки по умолчанию
-#define UPP_DISABLE_ERROR_BLOCK ///< Отключить блокировку УПП при ошибках
-#define UPP_SIMULATE_I ///< Симулировт токи (Iref/2) а не брать с АЦП
+//#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 UPP_DISABLE_PROTECT_LOSS_PHASE ///< Отключить проверки на потерянные фазы
+#define UPP_DISABLE_PROTECT_VOLTAGE ///< Отключить проверки на потерянные фазы
+#define UPP_DISABLE_PROTECT_LONGSTART ///< Отключить проверки на потерянные фазы
@@ -86,15 +88,15 @@
#define NOM_F_HZ_DEFAULT 50
#define NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT 10
#define NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT 10
-#define NOM_I_A_DEFAULT 5
+#define NOM_I_A_DEFAULT 3
/* Параметры ПУИ */
-#define PUI_Iref_PERCENT_DEFAULT 1.5
-#define PUI_Tnt_MS_DEFAULT 300
+#define PUI_Iref_PERCENT_DEFAULT 3.0
+#define PUI_Tnt_MS_DEFAULT 5000
#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
+#define PUI_Imax_PERCENT_DEFAULT 0.24
#define PUI_Imin_PERCENT_DEFAULT 0.07
#define PUI_TiMax_US_DEFAULT 5000
#define PUI_Tdelay_SECONDS_DEFAULT 30
@@ -109,9 +111,9 @@
/* Параметры регулятора угла */
#define ANGLE_MAX_PERCENT_DEFAULT (140.0f/180.0f) // note: не больше 150!
-#define ANGLE_MIN_PERCENT_DEFAULT (10.0f/180.0f)
-#define ANGLE_PID_KP_COEF_DEFAULT 0.0001
-#define ANGLE_PID_KI_COEF_DEFAULT 0.0001
+#define ANGLE_MIN_PERCENT_DEFAULT (40.0f/180.0f)
+#define ANGLE_PID_KP_COEF_DEFAULT (0.0025)//(0.0025)
+#define ANGLE_PID_KI_COEF_DEFAULT (0.125)//(0.0450)
#define ANGLE_PID_KD_COEF_DEFAULT 0
/* Параметри мониторинга сети */
@@ -134,8 +136,8 @@
/* Параметры ШИМ для тиристоров */
#define PWM_THYR_FREQUENCY_HZ_DEFAULT 16000
-#define PWM_THYR_DUTY_PERCENT_DEFAULT 0.5
-#define PWM_THYR_PULSE_LENGTH_DEFAULT (60.0/180.0)
+#define PWM_THYR_DUTY_PERCENT_DEFAULT 0.16
+#define PWM_THYR_PULSE_LENGTH_DEFAULT (140.0/180.0)
/** //UPP_PARAMS_DEFAULT
* @}
diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c
index 602259d..4bcc300 100644
--- a/UPP/Core/PowerMonitor/power_monitor.c
+++ b/UPP/Core/PowerMonitor/power_monitor.c
@@ -204,7 +204,7 @@ void PowerMonitor_FastCalc(PowerMonitor_t *hpm)
// meas->fast.U[U_CA] = Filter_Process(&hpm->ufltr[U_CA], uac_fast);
meas->fast.U[U_BC] = U_BC_calc(meas->fast.U[U_AB], meas->fast.U[U_CA]);
- meas->fast.I[I_C] = hpm->adc.Data[ADC_CHANNEL_IC]/i_base;
+ meas->fast.I[I_C] = -hpm->adc.Data[ADC_CHANNEL_IC]/i_base;
meas->fast.I[I_A] = hpm->adc.Data[ADC_CHANNEL_IA]/i_base;
meas->fast.I[I_B] = I_B_calc(meas->fast.I[I_A], meas->fast.I[I_C]);
diff --git a/UPP/Core/UPP/pwm_thyristors.c b/UPP/Core/UPP/pwm_thyristors.c
index 38ee66a..292f95e 100644
--- a/UPP/Core/UPP/pwm_thyristors.c
+++ b/UPP/Core/UPP/pwm_thyristors.c
@@ -136,6 +136,7 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
hpwm->AllPhases[ch].State = PWM_THYR_DISABLED;
__PWM_SetOutputState(&hpwm->AllPhases[ch], PWM_DISABLE);
}
+ hpwm->f.Running = 0;
return HAL_OK;
}
// Если НЕ force_stop_all - сбрасываем ТОЛЬКО заданный канал
diff --git a/UPP/Core/UPP/upp_errors.c b/UPP/Core/UPP/upp_errors.c
index be3d023..2f68376 100644
--- a/UPP/Core/UPP/upp_errors.c
+++ b/UPP/Core/UPP/upp_errors.c
@@ -86,6 +86,7 @@ void UPP_Errors_Ranges(void)
static int FMinCnt = 0;
static int TMaxCnt = 0;
+#ifndef UPP_DISABLE_PROTECT_VOLTAGE
/* Напряжения */
ERR_PUI->OverVoltage = setError(ERR_PRIVATE->uamp_max,
ERR_PUI->OverVoltage,
@@ -96,18 +97,6 @@ void UPP_Errors_Ranges(void)
&UMinCnt,
MS_TO_SLOW_TICKS(ERRORS_DELAY_MS_UAMP_ERR));
-
- /* Токи */
- int i_max = ( ERR_PRIVATE->iamp_max ||
- ERR_PRIVATE->ia_max ||
- ERR_PRIVATE->ib_max ||
- ERR_PRIVATE->ic_max);
- ERR_PUI->OverCurrent = setError(i_max,
- ERR_PUI->OverCurrent,
- &IMaxCnt,
- ticksTiMax);
-
-
/* Частота */
int f_max = ( ERR_PRIVATE->fac_max ||
ERR_PRIVATE->fba_max ||
@@ -124,6 +113,17 @@ void UPP_Errors_Ranges(void)
ERR_PUI->UnderFrequency,
&FMinCnt,
MS_TO_SLOW_TICKS(ERRORS_DELAY_MS_F_ERR));
+#endif
+
+ /* Токи */
+ int i_max = ( ERR_PRIVATE->iamp_max ||
+ ERR_PRIVATE->ia_max ||
+ ERR_PRIVATE->ib_max ||
+ ERR_PRIVATE->ic_max);
+ ERR_PUI->OverCurrent = setError(i_max,
+ ERR_PUI->OverCurrent,
+ &IMaxCnt,
+ ticksTiMax);
/* Температуры */
@@ -181,11 +181,12 @@ void UPP_Errors_Other(void)
{
static int InterlaceCnt = 0;
-
+#ifndef UPP_DISABLE_PROTECT_LONGSTART
if(ERR_PRIVATE->longstart)
ERR_PUI->LongStart = 1;
else
ERR_PUI->LongStart = 0;
+#endif
ERR_PUI->Interlace = setError(ERR_PRIVATE->interlance,
ERR_PUI->Interlace,
diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c
index fd05954..e59841b 100644
--- a/UPP/Core/UPP/upp_main.c
+++ b/UPP/Core/UPP/upp_main.c
@@ -111,8 +111,9 @@ int test_green2 = 0;
*/
int UPP_While(void)
{
- PWM_SetPolarity(&upp.hpwm, dbg_polarity);
int retval = 0;
+ PWM_SetPolarity(&upp.hpwm, dbg_polarity);
+
if(upp.pm.adc.RawData[0] < 2000)
{
__NOP();
@@ -132,7 +133,7 @@ int UPP_While(void)
PowerMonitor_SlowCalc(&upp.pm);
// Защиты // Защиты по току включаем только после разгона и в режиме работы
- PowerMonitor_Protect(&upp.pm, upp.hangle.f.RazgonDone /*&& (upp.workmode == UPP_Work)*/);
+ PowerMonitor_Protect(&upp.pm, upp.hangle.f.RazgonDone && (upp.workmode == UPP_Work));
#ifdef UPP_SIMULATE_I // симулируем токи
upp.pm.measured.final.Iamp = upp.hangle.Iref/2;
@@ -172,7 +173,6 @@ int UPP_While(void)
upp.call->set_default_internal = 0;
}
-
#ifndef UPP_DISABLE_ERROR_BLOCK
// если ошибка вызываем СТОП
upp.call->stop = (errors.common != Err_None);
@@ -180,7 +180,10 @@ int UPP_While(void)
// Если СТОП - переходим в ошибку
if (upp.call->stop)
+ {
+ Angle_PID_Reset(&upp.hangle);
upp.workmode = UPP_Error;
+ }
// Автомат состояний УПП
switch(upp.workmode)
@@ -237,7 +240,11 @@ int UPP_While(void)
UPP_DO.Error(DISABLE);
// если пришла команда на остановку
if (!upp.call->go)
+ {
+ Angle_PID_Reset(&upp.hangle);
upp.workmode = UPP_Init;
+ break;
+ }
// Коррекция для отсчета угла открытия
// 30 градусов - сдвиг между линейными и фазными напряжениями
diff --git a/UPP/Core/UPP/upp_status.c b/UPP/Core/UPP/upp_status.c
index 76e567a..8283f2c 100644
--- a/UPP/Core/UPP/upp_status.c
+++ b/UPP/Core/UPP/upp_status.c
@@ -7,7 +7,7 @@
******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП
#include "upp_status.h"
-
+int cnt_oscil_size = 100;
void UPP_Status_Handler(void)
{
/* Хендлы для отладочных светодиодов (если выбран режим моргания) */
@@ -49,10 +49,25 @@ void UPP_Status_Handler(void)
{
mb_u_cnt = 0;
}
- MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.U[U_AB]+1)*127;
- MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.U[U_BC]+1)*127;
- MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.U[U_CA]+1)*127;
- MB_INTERNAL.oscil.data[mb_u_cnt++] = local_time();
+// MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.U[U_AB]+1)*127;
+// MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.U[U_BC]+1)*127;
+// MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.U[U_CA]+1)*127;
+// MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.I[I_A]+1)*127;
+// MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.I[I_B]+1)*127;
+// MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.pm.measured.slow.I[I_C]+1)*127;
+ static int cnt_oscil = 0;
+
+ if(cnt_oscil == 0)
+ {
+ MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.hangle.Iref)*32;
+ MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.hangle.Imeas)*32;
+ MB_INTERNAL.oscil.data[mb_u_cnt++] = (upp.hangle.alpha)*127;
+ MB_INTERNAL.oscil.data[mb_u_cnt++] = 0;
+ }
+ if (++cnt_oscil>cnt_oscil_size)
+ {
+ cnt_oscil = 0;
+ }
if(GPIO_Read_Switch(&UPP_DIN.Pusk))
diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx
index 93f9c3a..0090099 100644
--- a/UPP/MDK-ARM/UPP.uvoptx
+++ b/UPP/MDK-ARM/UPP.uvoptx
@@ -312,12 +312,12 @@
12
2
- hpm->adc.RawData[3],0x0A
+ MB_DATA.HoldRegs.pui_params,0x0A
13
2
- MB_DATA,0x0A
+ MB_DATA.InRegs.pui
14
@@ -332,12 +332,12 @@
16
2
- MB_INTERNAL
+ MB_INTERNAL.param,0x0A
17
2
- upp.hangle
+ upp.hangle,0x0A
18
@@ -349,6 +349,11 @@
2
hmodbus1
+
+ 20
+ 2
+ cnt_oscil_size,0x0A
+
0