Проектирование распределителей ДСТ

Проектирование распределителей специальной и дорожно-строительной техники
В данном примере рассмотрим проектирование секционного распределителя экскаватора, а именно геометрии золотниковой пары (золотника и гильзы). Представим, что в ходе испытаний текущий распределитель не отрабатывает сигнал управления от гидравлического джойстика - имеется зона, где требуемая скорость выдвижения гидроцилиндра рабочего органа не достигается при отклонении джойстика на максимум. На регулирование и проливку при этом очень влияет геометрия канавок (Notch), которые фрезеруются на поясках золотника. Для исправления ситуации конструкторы разработали новую геометрию канавок, и применили моделирование в Engee, с целью провести виртуальный эксперимент по проливке секции распределителя. Пример золотника с канавками показан на рисунке.

Откроем модель
include("geometry_core.jl")
include("parameters_exporter.jl")
modelName = "DCV_HCD"
if !(modelName in [m.name for m in engee.get_all_models()])
engee.load("$(@__DIR__)/$(modelName).engee");
end
Смоделирован золотниковый распределитель с гидравлическим управлением. Для упрощения процедуры проливки исследуется выдвижение гидроцилиндра, задействуются каналы распределителя P-A и B-T. Справа на торец золотника подается управляющий сигнал по давлению от 0 до 30 бар (избыточн.), распределитель сдвигается влево, сжимая возвратную пружину и открывая соответствующие каналы. На канал P распределителя подключен постоянный источник расхода, 1000 л/мин. При проливке проверяется расход в порту A распределителя (порт подключения к поршневой полости цилиндра) в зависимости от перемещения золотника.

Параметризация канавок
Сложная форма канавок задается при помощи нескольких областей (Regions) - пользователь параметризует геометрические параметры каждой области, и задает количество канавок на одном пояске.
В случае, когда на одном пояске есть несколько разных типов канавок (например, 2 с одной геометрией и 2 с другой), для моделирования этого пояска два блока поясков с идентичными геометрическими параметрами (диаметра пояска и шейки, но разной праметризацией канавок) включаются параллельно, количество канавок у каждого блока при этом будет по два у каждого. Для исключения из силового расчета (учета воздействия жидкости) влияния дублирующего торца золотника проставляются соотвествующие флаги, отключающие силовой расчет для одной из поверхностей составного пояска.
Имеется 5 типов геометрии областей (см. документацию на Spool Edge with Notches (IL)).
Пояснения к параметризации приведены в коде параметризации золотников ниже.
Задание параметров поясков золотника
Модернизированная геометрия
Сравним 2 комплекта параметров, отличающихся друг от друга конфигурацией канавок - первый вариант - модернизированный, второй - исходный
# ==============================================================================
# ПАРАМЕТРИЗАЦИЯ ПРОИЗВОЛЬНОГО КОЛИЧЕСТВА БЛОКОВ КАНАВОК ЗОЛОТНИКА В МОДЕЛИ
# ==============================================================================
# СЛОВАРЬ НАЗНАЧЕНИЯ АРГУМЕНТОВ СТРУКТУРЫ UniversalRegion ДЛЯ ВСЕХ ТИПОВ ФОРМ:
#
# Аргументы по порядку: (shape, length, radial_depth_start, radial_depth_end, width_start, width_end, r_edge)
#
# 1. shape = "circular" (Круговой носик тупика распределительного паза)
# - length: Физическая осевая длина скругленного носика (ΔZ), мм
# - radial_depth_start: Постоянная радиальная глубина реза фрезы на данном участке (hRmin), мм
# - radial_depth_end: Не используется (дублирует значение radial_depth_start для непрерывности)
# - width_start: Начальная ширина контура (всегда равна 0.0 в крайней точке тупика), мм
# - width_end: Конечная окружная ширина, на которую плавно выходит круговая дуга носика, мм
# - r_edge: Не используется для данного типа формы (всегда равен 0.0)
#
# 2. shape = "triangular" (Треугольный / V-образный регулирующий участок)
# - length: Осевая длина участка раскрытия конуса (ΔZ), мм
# - radial_depth_start: Постоянная радиальная глубина реза на всем участке (hRmin), мм
# - radial_depth_end: Не используется (дублирует значение radial_depth_start)
# - width_start: Начальная окружная ширина паза на левой границе региона, мм
# - width_end: Конечная окружная ширина на правой границе региона (определяет угол раскрытия), мм
# - r_edge: Не используется для данного типа формы (всегда равен 0.0)
#
# 3. shape = "rectangular" (Прямоугольный рабочий участок с возможностью уклона дна)
# - length: Физическая осевая длина участка (ΔZ), мм
# - radial_depth_start: Радиальная глубина на левом краю региона (начальный уровень уклона дна), мм
# - radial_depth_end: Радиальная глубина на правом краю региона (конечный заглубленный уровень клина), мм
# - width_start: Постоянная окружная ширина паза (width_start должна быть строго равна width_end), мм
# - width_end: Постоянная окружная ширина паза (width_start должна быть строго равна width_end), мм
# - r_edge: Не используется для данного типа формы (всегда равен 0.0)
#
# 4. shape = "trapezoidal" (Классический трапециевидный участок с острыми боковыми гранями)
# - length: Осевая длина участка линейного расширения щек (ΔZ), мм
# - radial_depth_start: Постоянная радиальная глубина реза на всем участке (hRmin), мм
# - radial_depth_end: Не используется (дублирует значение radial_depth_start)
# - width_start: Начальная окружная ширина контура на левом стыке региона, мм
# - width_end: Конечная окружная ширина на правом выходе региона (максимальный раструб конуса), мм
# - r_edge: Не используется для данного типа формы (всегда равен 0.0)
#
# 5. shape = "trapezoidal_rounded" (Трапециевидный участок, образованный образующей окружностью фрезы)
# - length: Осевая длина области по оси Z (lengthtrapr1), мм
# - radial_depth_start: Постоянная глубина области (hRmin1), мм
# - radial_depth_end: Дублирует значение radial_depth_start для обеспечения непрерывности
# - width_start: Начальная окружная ширина у кромки золотника (inwidthr1), мм
# - width_end: Конечная окружная ширина у точки сопряжения со следующей областью (endwidthr1), мм
# - r_edge: РАДИУС ОКРУЖНОСТИ, образующей боковые стороны (dedger1 / 2.0), мм
# ==============================================================================
# ЭКСПЕРИМЕНТ №1: МОДЕРНИЗИРОВАННЫЕ ПАРАМЕТРЫ БЛОКОВ
# ==============================================================================
список_блоков_case1 = [
# Блок №1: Кромка Нагнетания P-A Геометрия канавок 1
SpoolComponent(
"Кромка Нагнетания P-A_1",
"DCV_HCD/Spool Edge with Notches (IL)",
45.0, # spool_diameter (Диаметр золотника), мм
28.0, # rod_diameter (Диаметр шейки/штока), мм
2, # nslots (Количество слотов / пазов)
20.0, # chamber_length_0 (Длина камеры при 0 смещении), мм
-4.0, # underlap (Величина перекрытия / смещения), мм
16.0, # underlap_max_area (Перекрытие при макс. площади), мм
29.5, # edge_to_edge (Расстояние между кромками), мм
0.003, # clearance (Зазор по диаметру), мм
0.0, # eccentricity_ratio (Коэффициент эксцентриситета)
true, # enable_annular_area (Учитывать ли площадь пазов при открытии)
true, # enable_pressure_force (Учитывать силы давления и вариацию объема)
true, # couette_effect (Учитывать эффект Куэтта для трения жидкости)
[
UniversalRegion("circular", 4.0, 8.0, 8.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 6.0, 8.0, 8.0, 4.0, 4.0, 0.0)
]
),
# Блок №2: Кромка Нагнетания P-A Геометрия канавок 2
SpoolComponent(
"Кромка нагнетания P-A_2",
"DCV_HCD/Spool Edge with Notches (IL)-1",
45.0, # spool_diameter (Диаметр золотника), мм
28.0, # rod_diameter (Диаметр шейки/штока), мм
2, # nslots (Количество слотов / пазов)
20.0, # chamber_length_0 (Длина камеры при 0 смещении), мм
-5.0, # underlap (Величина перекрытия / смещения), мм
15.0, # underlap_max_area (Перекрытие при макс. площади), мм
29.5, # edge_to_edge (Расстояние между кромками), мм
0.003, # clearance (Зазор по диаметру), мм
0.0, # eccentricity_ratio (Коэффициент эксцентриситета)
false, # enable_annular_area (Учитывать ли площадь пазов при открытии)
false, # enable_pressure_force (Учитывать силы давления и вариацию объема)
false, # couette_effect (Учитывать эффект Куэтта для трения жидкости)
[
UniversalRegion("circular", 4.0, 7.0, 7.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 5.0, 7.0, 7.0, 4.0, 4.0, 0.0)
]
),
# Блок №3: Кромка слива B-T Геометрия канавок 1
SpoolComponent(
"Кромка слива B-T_1",
"DCV_HCD/Spool Edge with Notches (IL)-2",
45.0, # spool_diameter (Диаметр золотника), мм
28.0, # rod_diameter (Диаметр шейки/штока), мм
2, # nslots (Количество слотов / пазов)
20.0, # chamber_length_0 (Длина камеры при 0 смещении), мм
-12.0, # underlap (Величина перекрытия / смещения), мм
8.0, # underlap_max_area (Перекрытие при макс. площади), мм
96.0, # edge_to_edge (Расстояние между кромками), мм
0.003, # clearance (Зазор по диаметру), мм
0.0, # eccentricity_ratio (Коэффициент эксцентриситета)
true, # enable_annular_area (Учитывать ли площадь пазов при открытии)
true, # enable_pressure_force (Учитывать силы давления и вариацию объема)
true, # couette_effect (Учитывать эффект Куэтта для трения жидкости)
[
UniversalRegion("circular", 4.0, 5.0, 5.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 3.0, 5.0, 5.0, 4.0, 4.0, 0.0)
]
),
# Блок №4: Кромка слива B-T Геометрия канавок 2
SpoolComponent(
"Кромка Слива B-T_2",
"DCV_HCD/Spool Edge with Notches (IL)-3",
45.0, # spool_diameter (Диаметр золотника), мм
28.5, # rod_diameter (Диаметр шейки/штока), мм
2, # nslots (Количество слотов / пазов)
20.0, # chamber_length_0 (Длина камеры при 0 смещении), мм
-5.0, # underlap (Величина перекрытия / смещения), мм
15.0, # underlap_max_area (Перекрытие при макс. площади), мм
95.0, # edge_to_edge (Расстояние между кромками), мм
0.003, # clearance (Зазор по диаметру), мм
0.0, # eccentricity_ratio (Коэффициент эксцентриситета)
false, # enable_annular_area (Учитывать ли площадь пазов при открытии)
false, # enable_pressure_force (Учитывать силы давления и вариацию объема)
false, # couette_effect (Учитывать эффект Куэтта для трения жидкости)
[
UniversalRegion("circular", 4.0, 8.0, 8.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 11.0, 8.0, 8.0, 4.0, 4.0, 0.0)
]
)
]
Параметризация блоков для сравниваемого золотника (исходная геометрия)
# ==============================================================================
# ЭКСПЕРИМЕНТ №2: ИСХОДНЫЕ ПАРАМЕТРЫ БЛОКОВ (КОМПЛЕКТ ПРОПИСАН ПОЛНОСТЬЮ С НУЛЯ)
# ==============================================================================
# Здесь вы можете вручную модифицировать любые параметры для проведения сравнительного анализа
список_блоков_case2 = [
# Блок №1: Кромка Нагнетания P-A Геометрия канавок 1 (Модифицированный)
SpoolComponent(
"Кромка Нагнетания P-A_1 (Мод)",
"DCV_HCD/Spool Edge with Notches (IL)",
45.0, # spool_diameter (Диаметр золотника), мм
25.0, # rod_diameter (Диаметр шейки/штока), мм
2, # nslots (Количество слотов / пазов)
20.0, # chamber_length_0 (Длина камеры при 0 смещении), мм
-4.0, # underlap (Величина перекрытия / смещения), мм
16.0, # underlap_max_area (Перекрытие при макс. площади), мм
36.0, # edge_to_edge (Расстояние между кромками), мм
0.003, # clearance (Зазор по диаметру), мм
0.0, # eccentricity_ratio (Коэффициент эксцентриситета)
true, # enable_annular_area (Учитывать ли площадь пазов при открытии)
true, # enable_pressure_force (Учитывать силы давления и вариацию объема)
true, # couette_effect (Учитывать эффект Куэтта для трения жидкости)
[
UniversalRegion("circular", 4.0, 4.0, 4.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 12.5, 4.0, 4.0, 4.0, 4.0, 0.0)
]
),
# Блок №2 (Модифицированный)
SpoolComponent(
"Кромка нагнетания P-A_2 (Мод)", "DCV_HCD/Spool Edge with Notches (IL)-1",
45.0, 25.0, 2, 20.0, -4.0, 16.0, 36.0, 0.003, 0.0, false, false, false,
[
UniversalRegion("circular", 4.0, 4.0, 4.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 12.5, 4.0, 4.0, 4.0, 4.0, 0.0)
]
),
# Блок №3 (Модифицированный)
SpoolComponent(
"Кромка слива B-T_1 (Мод)", "DCV_HCD/Spool Edge with Notches (IL)-2",
45.0, 25.0, 2, 20.0, -4.0, 16.0, 96.0, 0.003, 0.0, true, true, true,
[
UniversalRegion("circular", 4.0, 4.0, 4.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 12.5, 4.0, 4.0, 4.0, 4.0, 0.0)
]
),
# Блок №4 (Модифицированный)
SpoolComponent(
"Кромка Слива B-T_2 (Мод)", "DCV_HCD/Spool Edge with Notches (IL)-3",
45.0, 25.0, 2, 20.0, -4.0, 16.0, 96.0, 0.003, 0.0, false, false, false,
[
UniversalRegion("circular", 4.0, 4.0, 4.0, 0.0, 4.0, 0.0),
UniversalRegion("rectangular", 12.5, 4.0, 4.0, 4.0, 4.0, 0.0)
]
)
]
Отрисовка компонентов золотника
Визуально проверяем геометрию - параметры и расположение канавок, диаметр золотника, окна для каждого компонента Notch Edge
# Отрисовка первого компонента из массива для контроля геометрии (например, из Кейса 1)
# Отобразим желаемый элемент в 3D и 2D-проекциях
draw_spool_component_3d(список_блоков_case1[1])
Параметры запуска модели
Выбираем, какой золотник хотим проверить - первый, второй или оба сразу
# ==============================================================================
# НАСТРОЙКА ЗАПУСКА: ВЫБЕРИТЕ, КАКОЙ ЭКСПЕРИМЕНТ ПРОГНАТЬ СЕЙЧАС
# ==============================================================================
run_case1 = true # Запустить расчет для Эксперимента №1 (Модернизированный)?
run_case2 = true # Запустить расчет для Эксперимента №2 (Исходный)?
Запуск эксперимента и сбор данных. Отрисовка графиков
# =============================================================================
# ФУНКЦИЯ ДЛЯ ВЫПОЛНЕНИЯ И СБОРА ОДНОГО ЭКСПЕРИМЕНТА (ОРИГИНАЛЬНАЯ ЛОГИКА)
# =============================================================================
function run_simulation_case(список_блоков_case)
println("\n--> Шаг 1: Запись параметров в блоки Engee...")
for блок in список_блоков_case
send_params_to_engee(блок)
end
println("--> Шаг 2: Запуск расчета модели '$(modelName)'...")
try
engee.run("$(modelName)")
println("🚀 Расчет успешно завершен!")
catch e
println("⚠ Ошибка расчета: ", e)
return nothing
end
println("--> Шаг 3: Экспорт результатов и прореживание точек...")
# Выкачиваем WorkspaceArray напрямую из структуры результатов симуляции Engee
df_Disp_DCV = collect(WorkspaceArray{Float64}("$(modelName)/Displacement_DCV"))
df_Disp_Cylinder = collect(WorkspaceArray{Float64}("$(modelName)/Displacement_Cylinder"))
df_q_Piston = collect(WorkspaceArray{Float64}("$(modelName)/Расходомер-1/Q_Piston"))
step_decim = 100
# Разделяем структуры времени и значений, переводя их в чистые векторы Float64
time_cylinder = df_Disp_Cylinder.time[1:step_decim:end]
val_cylinder = df_Disp_Cylinder.value[1:step_decim:end]
val_disp_dcv = df_Disp_DCV.value[1:step_decim:end]
val_q_piston = df_q_Piston.value[1:step_decim:end]
return Dict(
"time_cylinder" => time_cylinder,
"val_cylinder" => val_cylinder,
"val_disp_dcv" => val_disp_dcv,
"val_q_piston" => val_q_piston
)
end
# =============================================================================
# ИСПОЛНЕНИЕ СИМУЛЯЦИЙ С СОХРАНЕНИЕМ ПРЕДЫДУЩИХ ДАННЫХ В СЕССИИ
# =============================================================================
if !@isdefined(res1) global res1 = nothing end
if !@isdefined(res2) global res2 = nothing end
if run_case1
println("=== СИМУЛЯЦИЯ №1: ЗАПУСК ===")
global res1 = run_simulation_case(список_блоков_case1)
else
println("=== СИМУЛЯЦИЯ №1: ПРОПУЩЕНА (используются данные из памяти) ===")
end
if run_case2
println("=== СИМУЛЯЦИЯ №2: ЗАПУСК ===")
global res2 = run_simulation_case(список_блоков_case2)
else
println("=== СИМУЛЯЦИЯ №2: ПРОПУЩЕНА (используются данные из памяти) ===")
end
# =============================================================================
# АДАПТИВНОЕ ПОСТРОЕНИЕ И НАЛОЖЕНИЕ ГРАФИКОВ (ЛОКАЛЬНЫЙ GR БЭКЕНД)
# =============================================================================
using Plots.PlotMeasures
has_data1 = !isnothing(res1)
has_data2 = !isnothing(res2)
if !has_data1 && !has_data2
println("⚠ Нет данных для отображения графиков. Запустите хотя бы один эксперимент (поставьте true).")
else
# Переключаем бэкенд на GR для генерации легковесного статического PNG-изображения
gr()
println("\nКомпоновка графиков (Режим: ",
(has_data1 && has_data2) ? "Сравнение двух комплектов" :
(has_data1 ? "Только Эксперимент 1 (Исходный)" : "Только Эксперимент 2 (Модифицированный)"), ")...")
# --- ГРАФИК 1: Расход Q_Piston от перемещения золотника Displacement_DCV ---
p1 = plot(
title = "Статическая характеристика: Расход поршня от смещения золотника",
xlabel = "Смещение золотника Displacement_DCV (мм)",
ylabel = "Расход Q_Piston (л/мин)",
grid = true,
titlefont = font(10),
bottom_margin = 15mm
)
if has_data1
p_idx1 = sortperm(res1["val_disp_dcv"])
plot!(p1, res1["val_disp_dcv"][p_idx1], res1["val_q_piston"][p_idx1],
label="Эксперимент 1 (Модернизированный)", lw=2.5, color=:blue)
end
if has_data2
p_idx2 = sortperm(res2["val_disp_dcv"])
plot!(p1, res2["val_disp_dcv"][p_idx2], res2["val_q_piston"][p_idx2],
label="Эксперимент 2 (Исходный)", lw=2.5, color=:red, style=:dash)
end
# --- ГРАФИК 2: Перемещение гидроцилиндра Displacement_Cylinder от времени t ---
p2 = plot(
title = "Динамика выдвижения цилиндра экскаватора во времени",
xlabel = "Время симуляции t (с)",
ylabel = "Смещение поршня Cylinder (м)",
grid = true,
titlefont = font(10),
top_margin = 10mm
)
if has_data1
plot!(p2, res1["time_cylinder"], res1["val_cylinder"],
label="Эксперимент 1 (Модернизированный)", lw=2.5, color=:darkgreen)
end
if has_data2
plot!(p2, res2["time_cylinder"], res2["val_cylinder"],
label="Эксперимент 2 (Исходный)", lw=2.5, color=:orange, style=:dash)
end
# Объединяем оба холста в единый вертикальный отчет (2 строки, 1 столбец)
combined_canvas = plot(p1, p2, layout=(2, 1), leg=true, size=(1200, 950))
# Принудительно экспортируем результат в файл и рендерим его как статичную PNG
savefig(combined_canvas, "final_simulation_report.png")
display("image/png", read("final_simulation_report.png"))
# Возвращаем интерактивный бэкенд PlotlyJS для комфортной 3D-работы в остальных ячейках
plotlyjs()
end
Заключение
Как видно из графиков, применение ассиметричных канавок дало положительный результат при проектировании золотника распределителя - при подаче сигнала регулирования от 0 до 30 бар исчезла мертвая зона, распределитель регулирует поток подачи на гидроцилиндр во всем диапазоне расходов от 0 до 1000 литров в минуту.
Компоненты библиотеки конструктивно-геометрического проектирования гидроклапанной аппаратуры значительно упрощают разработку клапанов, и ускоряют время проектирования, значительно снижая затраты разработчика.
Инструментарий и подход может быть полезен при разработке гидравлических распределителей и клапанов огромной номенклатуры изделий спецтехники - гидравлических экскаваторов, автокранов, погрузчиков, манипуляторов, систем выравнивания буровых платформ, самоходной техники специального назначения. Компоненты библиотеки конструктивно-геометрического проектирования гидроклапанной аппаратуры значительно упрощают разработку клапанов, и ускоряют время проектирования.
