# ATS0002 — Расчёт падения давления воздуха в теплообменнике **ATS0002** — это программа для расчёта падения давления воздуха на теплообменниках аэрокосмического оборудования. Программа поддерживает 6 моделей теплообменников от Honeywell и Liebherr, обеспечивает ввод параметров воздушного потока и статического давления на входе, автоматическую коррекцию показаний с учётом барометрического давления и температуры, а также оценку результата «пройдено/не пройдено» по допустимому пределу падения давления. ## Основные возможности 1. **Поддержка 6 моделей теплообменников** — Honeywell CMM 21-50-14, Honeywell Ram CMM 21-52-80, Honeywell NGS CMM 47-32-06, Honeywell NGS Regen CMM 47-32-14, Liebherr Reheater CMM 21-53-89, Liebherr Condenser CMM 21-53-88. 2. **Несколько номеров деталей (P/N)** для каждого теплообменника с индивидуальными характеристиками. 3. **Конфигурация воздушных каналов** — выбор стороны обдува (охлаждающая, горячая, primary bleed, main bleed и т.д.). 4. **Ввод расхода воздуха и статического давления** с валидацией в пределах допустимых диапазонов. 5. **Коррекция давления** по барометрическому давлению и температуре воздуха для получения скорректированного значения. 6. **Логарифмическая интерполяция** предела падения давления по якорным точкам (anchor points). 7. **Автоматическая оценка** «PASSED» или «FAILED» по допустимому пределу. 8. **Поддержка единиц KPA и PSIG** — в зависимости от конфигурации теплообменника. 9. **Поддержка запятых как десятичного разделителя** — автоматическая нормализация в точку. ## Внутреннее устройство ### Иерархия структур данных Данные теплообменников организованы в трёхуровневую иерархию: | Уровень | Структура | Описание | |---------|-----------|----------| | 1 | `heat_exchanger_data_t` | Модель теплообменника (описание + массив типов) | | 2 | `heat_exchanger_type_data_t` | Номер детали (P/N) — описание + массив воздушных каналов | | 3 | `air_passage_data_t` | Воздушный канал — описание + якорные точки + лимиты | **`airflow_to_pressure_anchors_data_t`** — пара «расход-давление», используемая как якорная точка для интерполяции: | Поле | Тип | Описание | |------|-----|----------| | `airflow` | `double` | Расход воздуха (LB/MIN) | | `pressure` | `double` | Соответствующее падение давления (KPA или PSIG) | **`air_passage_data_t`** — конфигурация одного воздушного канала: | Поле | Тип | Описание | |------|-----|----------| | `air_passage_description` | `const char *` | Человеко-читаемое описание канала | | `air_passage_anchors` | `const airflow_to_pressure_anchors_data_t *` | Указатель на массив якорных точек | | `anchors_data_size` | `const uint8_t` | Количество якорных точек | | `recalculated_required` | `const bool` | Флаг необходимости коррекции давления | | `airflow_pressure_unit` | `const airflow_pressure_unit_t` | Единицы давления (KPA или PSIG) | | `min_barometric_pressure` | `const double` | Минимальное барометрическое давление (MBAR) | | `max_barometric_pressure` | `const double` | Максимальное барометрическое давление (MBAR) | | `min_airflow_temperature` | `const double` | Минимальная температура воздуха (°C) | | `max_airflow_temperature` | `const double` | Максимальная температура воздуха (°C) | | `min_airflow_pressure` | `const double` | Минимальное давление воздушного потока | | `max_airflow_pressure` | `const double` | Максимальное давление воздушного потока | **`heat_exchanger_type_data_t`** — конфигурация типа теплообменника (номера деталей): | Поле | Тип | Описание | |------|-----|----------| | `part_number_description` | `const char *` | Описание номера детали | | `air_passages_data` | `const air_passage_data_t *` | Указатель на массив конфигураций воздушных каналов | | `air_passages_data_size` | `const uint8_t` | Количество воздушных каналов | **`heat_exchanger_data_t`** — конфигурация модели теплообменника: | Поле | Тип | Описание | |------|-----|----------| | `heat_exchanger_description` | `const char *` | Описание модели теплообменника | | `heat_exchanger_type_data` | `const heat_exchanger_type_data_t *` | Указатель на массив номеров деталей | | `heat_exchanger_type_data_size` | `const uint8_t` | Количество номеров деталей | ### Управление памятью Все данные теплообменников объявлены как `static const` и хранятся в сегменте данных исполняемого файла. Динамическое выделение памяти не используется — компонент не требует `malloc`/`free`. ### Глобальная таблица теплообменников В файле `heat_exchander_airflow_pressure_drop.c` определяется массив `heat_exchanger_data[]` из 6 элементов, связывающий описания моделей с их конфигурационными данными: | Индекс | Модель | |--------|--------| | 0 | Honeywell Heat Exchanger CMM 21-50-14 | | 1 | Honeywell Ram Heat Exchanger CMM 21-52-80 | | 2 | Honeywell NGS Heat Exchanger CMM 47-32-06 | | 3 | Honeywell NGS Regen Heat Exchanger CMM 47-32-14 | | 4 | Liebherr Reheater CMM 21-53-89 | | 5 | Liebherr Condenser CMM 21-53-88 | ## API (интерфейс) ### Ввод команд | Функция | Описание | |---------|----------| | `get_user_command()` | Ввод команды пользователя: числовой выбор, `q`/`Q` для выхода (EXIT), `r`/`R` для повтора (REPEAT) | ### Выбор параметров | Функция | Описание | |---------|----------| | `get_heat_exchanger_number()` | Ввод номера модели теплообменника из доступных вариантов | | `get_heat_exchanger_part_number()` | Ввод номера детали (P/N) для выбранной модели | | `get_heat_exchanger_air_passage_number()` | Ввод номера воздушного канала для выбранной детали | ### Ввод физических параметров | Функция | Описание | |---------|----------| | `get_airflow()` | Ввод расхода воздуха (LB/MIN) с валидацией по диапазону якорных точек | | `get_airflow_pressure()` | Ввод статического давления на входе (KPA или PSIG) с валидацией по лимитам | | `get_barometric_pressure()` | Ввод барометрического давления (MBAR) с валидацией по лимитам | | `get_airflow_temperature()` | Ввод температуры воздуха (°C) с валидацией по лимитам | ### Расчёт | Функция | Описание | |---------|----------| | `get_pressure_drop()` | Расчёт предела падения давления: при необходимости — коррекция давления по барометрии и температуре, затем логарифмическая интерполяция по якорным точкам | ## Потокобезопасность Компонент **не является потокобезопасным**. Программа работает в однопоточном режиме и не использует механизмы синхронизации (мьютексы, критические секции). Все функции работают с глобальным стандартным вводом (`stdin`) и не содержат разделяемого состояния, кроме `static` константных данных. ## Алгоритмы ### Логарифмическая интерполяция предела падения давления Алгоритм `_get_log_interpolated_airflow_pressure_drop_limit()` вычисляет допустимое падение давления для заданного расхода воздуха методом линейной интерполяции в логарифмическом пространстве между двумя ближайшими якорными точками: - Если расход воздуха **меньше или равен** первой якорной точке — возвращается давление первой точки. - Если расход воздуха **больше или равен** последней якорной точке — возвращается давление последней точки. - Для расхода внутри диапазона: - Вычисляются натуральные логарифмы: `log_x = log(airflow)`, `log_x1 = log(airflow[i])`, `log_x2 = log(airflow[i+1])`, `log_y1 = log(pressure[i])`, `log_y2 = log(pressure[i+1])`. - Выполняется линейная интерполяция: `log_y = log_y1 + (log_x - log_x1) * (log_y2 - log_y1) / (log_x2 - log_x1)`. - Результат: `limit = exp(log_y)`. ### Коррекция давления по плотности Функция `_calculate_density_corrected_pressure()` корректирует показание давления с учётом барометрического давления и температуры по формуле: 1. `value_4 = airflow_pressure * 0.5` 2. `value_5 = barometric_pressure + value_4` 3. `value_6 = airflow_temperature + 273.2` (перевод в Кельвины) 4. `value_7 = (0.28443 * value_5) / value_6` 5. `corrected_airflow_pressure = airflow_pressure * value_7` Результат вычисляется в **гектопаскалях (HPA)**. При входе в `get_pressure_drop()` результат конвертируется обратно в исходные единицы (KPA или PSIG): - **KPA**: деление на 10.0 - **PSIG**: умножение на 0.0145038 ## Примеры использования ### Базовый сценарий ```c #include "ats0002/ats0002.h" #include "ats0002/21_50_14.h" // Глобальная таблица теплообменников определяется в main-файле. // Для демонстрации — прямой вызов функций ввода и расчёта: int main(void) { setlocale(LC_NUMERIC, "C"); // 1. Выбор теплообменника (индекс 0 — Honeywell CMM 21-50-14) const heat_exchanger_data_t *he = &heat_exchanger_data[0]; // 2. Выбор номера детали (индекс 0 — 182820-1) const heat_exchanger_type_data_t *hetd = &he->heat_exchanger_type_data[0]; // 3. Выбор воздушного канала (индекс 0 — Cooling Air Side) const air_passage_data_t *apd = &hetd->air_passages_data[0]; // 4. Ввод параметров (в реальном коде — через get_* функции) double airflow = 50.0; // LB/MIN double airflow_pressure = 0.33; // KPA double barometric_pressure = 1013.25; // MBAR double airflow_temperature = 20.0; // °C double pressure_drop_limit = 0.0; double corrected_airflow_pressure = 0.0; // 5. Расчёт предела падения давления get_pressure_drop(&pressure_drop_limit, &airflow, &airflow_pressure, &corrected_airflow_pressure, &barometric_pressure, &airflow_temperature, apd); // 6. Оценка результата bool passed = corrected_airflow_pressure <= pressure_drop_limit; printf("Test result: %s\n", passed ? "PASSED" : "FAILED"); return 0; } ``` ### Работа с разными единицами (PSIG) ```c #include "ats0002/ats0002.h" #include "ats0002/21_50_14.h" int main(void) { setlocale(LC_NUMERIC, "C"); const heat_exchanger_data_t *he = &heat_exchanger_data[0]; const heat_exchanger_type_data_t *hetd = &he->heat_exchanger_type_data[0]; // Индекс 1 — Bleed Air Side (использует PSIG) const air_passage_data_t *apd = &hetd->air_passages_data[1]; double airflow = 50.0; // LB/MIN double airflow_pressure = 3.05; // PSIG double barometric_pressure = 1013.25; // MBAR double airflow_temperature = 20.0; // °C double pressure_drop_limit = 0.0; double corrected_airflow_pressure = 0.0; get_pressure_drop(&pressure_drop_limit, &airflow, &airflow_pressure, &corrected_airflow_pressure, &barometric_pressure, &airflow_temperature, apd); printf("Max allowed: %.2f PSIG\n", pressure_drop_limit); printf("Corrected: %.2f PSIG\n", corrected_airflow_pressure); printf("Result: %s\n", corrected_airflow_pressure <= pressure_drop_limit ? "PASSED" : "FAILED"); return 0; } ``` ### Использование без коррекции (Liebherr Reheater) ```c #include "ats0002/ats0002.h" #include "ats0002/21_53_89.h" int main(void) { setlocale(LC_NUMERIC, "C"); const heat_exchanger_data_t *he = &heat_exchanger_data[4]; const heat_exchanger_type_data_t *hetd = &he->heat_exchanger_type_data[0]; const air_passage_data_t *apd = &hetd->air_passages_data[0]; // У Liebherr Reheater recalculated_required = false, // поэтому коррекция не требуется. double airflow = 50.0; // LB/MIN double airflow_pressure = 0.37; // PSIG (без коррекции) double pressure_drop_limit = 0.0; double corrected_airflow_pressure = 0.0; // Не используется get_pressure_drop(&pressure_drop_limit, &airflow, &airflow_pressure, &corrected_airflow_pressure, NULL, NULL, apd); printf("Max allowed: %.2f PSIG\n", pressure_drop_limit); printf("Result: %s\n", airflow_pressure <= pressure_drop_limit ? "PASSED" : "FAILED"); return 0; } ``` ## Логирование Компонент не использует ESP-IDF логирование. Все сообщения выводятся через стандартную функцию `printf` в консоль. ## Ошибки | Код | Описание | |-----|----------| | `EXIT` (0xFFFF) | Команда выхода из программы — выводит «Goodbye.» и завершает работу | | `REPEAT` (0xFFEE) | Команда повтора — возвращается к началу цикла ввода без завершения | | `-1.0` | Внутренний код ошибки интерполяции — возвращается если якорные точки не найдены (не должно происходить при валидных данных) | ## Ограничения 1. **Однопоточная работа** — программа не поддерживает параллельное выполнение и не использует механизмы синхронизации. 2. **Статические данные** — все конфигурационные данные теплообменников зашиты в код. Добавление новых моделей требует изменения исходного кода и перекомпиляции. 3. **Текстовый интерфейс** — программа работает исключительно через стандартный ввод/вывод (`stdin`/`stdout`), графический интерфейс отсутствует. 4. **Жёстко заданные диапазоны** — лимиты для барометрического давления (840–1070 MBAR) и температуры (15–35 °C или 15–33 °C) фиксированы в конфигурации. 5. **Экстраполяция не поддерживается** — если расход воздуха выходит за пределы якорных точек, возвращается значение первой или последней точки без экстраполяции. 6. **Зависимость от `setlocale`** — для корректной работы с десятичными разделителями необходимо вызов `setlocale(LC_NUMERIC, "C")`. 7. **Максимум 65 535 элементов меню** — выбор элементов используется тип `uint16_t`, что ограничивает количество моделей, деталей и каналов. ## Требования для сборки - C99 или новее (стандарт C11 рекомендуется) - Стандартная библиотека C (`stdlib.h`, `stdio.h`, `string.h`, `math.h`, `locale.h`) - Компилятор GCC (cross-compile для ESP-IDF) или MSVC (для Windows) - Библиотека `libm` (математическая библиотека, подключается флагом `-lm`) ## Установка ```bash # Клонирование репозитория git clone https://github.com/aZholtikov/ats0002 cd ats0002 # Сборка # Для Linux/macOS: gcc -o ats0002 heat_exchander_airflow_pressure_drop.c \ ats0002/ats0002.c -lm # Для Windows (MSVC): cl heat_exchander_airflow_pressure_drop.c \ ats0002/ats0002.c # Запуск ./ats0002 ``` ```c #include "ats0002/ats0002.h" #include "ats0002/21_50_14.h" #include "ats0002/21_52_80.h" #include "ats0002/47_32_06.h" #include "ats0002/47_32_14.h" #include "ats0002/21_53_89.h" #include "ats0002/21_53_88.h" ```