Files
2026-10-14 08:19:39 +03:00

326 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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"
```