From 8c0160dd7756d420f3e4eaa8f8f4773f3a25764d Mon Sep 17 00:00:00 2001 From: Alexey Zholtikov Date: Mon, 12 Oct 2026 18:57:28 +0300 Subject: [PATCH] feat: initial --- .gitignore | 3 + .vscode/launch.json | 4 + .vscode/tasks.json | 49 ++++ CMakeLists.txt | 1 - README.md | 27 +- ats0002/21_50_14.h | 274 +++++++++++++++++++ ats0002/21_53_88.h | 154 +++++++++++ ats0002/21_53_89.h | 154 +++++++++++ ats0002/ats0002.c | 333 +++++++++++++++++++++++ ats0002/ats0002.h | 207 ++++++++++++++ heat_exchander_airflow_pressure_drop | Bin 0 -> 38200 bytes heat_exchander_airflow_pressure_drop.c | 103 +++++++ heat_exchander_airflow_pressure_drop.exe | Bin 0 -> 175070 bytes include/main.h | 0 main.c | 0 version.txt | 1 + 16 files changed, 1307 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json delete mode 100644 CMakeLists.txt create mode 100644 ats0002/21_50_14.h create mode 100644 ats0002/21_53_88.h create mode 100644 ats0002/21_53_89.h create mode 100644 ats0002/ats0002.c create mode 100644 ats0002/ats0002.h create mode 100755 heat_exchander_airflow_pressure_drop create mode 100644 heat_exchander_airflow_pressure_drop.c create mode 100755 heat_exchander_airflow_pressure_drop.exe delete mode 100644 include/main.h delete mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a0ed1f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +heat_exchander_airflow_pressure_drop.dSYM +commit.md \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..cd4d5eb --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,4 @@ +{ + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..cb24e3f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,49 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build MAC", + "command": "/usr/bin/gcc", + "args": [ + "-fdiagnostics-color=always", + "-g", + "-I${fileDirname}", + "${workspaceFolder}/*.c", + "${workspaceFolder}/ats0002/*.c", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "C/C++: gcc build WIN", + "type": "shell", + "command": "x86_64-w64-mingw32-gcc", + "args": [ + "-g", + "-Wall", + "-o", + "${workspaceFolder}/heat_exchander_airflow_pressure_drop.exe", + "${workspaceFolder}/*.c", + "${workspaceFolder}/ats0002/*.c" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [ + "$gcc" + ] + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 9ab5c51..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -idf_component_register(SRCS "main.c" INCLUDE_DIRS "include") \ No newline at end of file diff --git a/README.md b/README.md index 3df3e4d..0f39e15 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,26 @@ -# esp_component_template +# Heat Exchanger Airflow Pressure Drop Calculation -esp_component_template \ No newline at end of file +## Features + +1. Calculation of pressure drop across heat exchangers. +2. Support for three heat exchanger models: + - Honeywell Heat Exchanger CMM 21-50-14 + - Liebherr Reheater CMM 21-53-89 + - Liebherr Condenser CMM 21-53-88 +3. Multiple part number selection for each heat exchanger. +4. Air passage configuration selection. +5. Airflow and static inlet pressure measurement input. +6. Automatic pass/fail evaluation against max allowed pressure drop limit. +7. Recalculation support based on barometric pressure and airflow temperature. +8. Logarithmic interpolation of pressure drop limits from anchor points. +9. Support for KPA and PSIG pressure units. + +## Using + +Clone and build the project: + +```text +git clone https://github.com/aZholtikov/ats0002 +cd ats0002 +build +``` diff --git a/ats0002/21_50_14.h b/ats0002/21_50_14.h new file mode 100644 index 0000000..dcf0184 --- /dev/null +++ b/ats0002/21_50_14.h @@ -0,0 +1,274 @@ +#pragma once + +#include "ats0002.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @file 21_50_14.h + * + * @brief Honeywell Heat Exchanger CMM 21-50-14 configuration data. + * + * This module provides static configuration data for Honeywell Heat Exchanger + * CMM 21-50-14, including pressure-to-airflow anchor points for + * cooling and hot sides, air passage definitions, and heat exchanger type + * mappings for part numbers 182820-1 through 182820-4. + * + * Key features: + * - Cooling side performance data (Figures 4002 and 4003) + * - Hot side performance data (Figures 4005 and 4006) + * - Complete air passage configuration with operational limits + * + * @note All data arrays are static and const-qualified for read-only access. + */ + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4002 (P/N 182820-1). + * + * Cooling side dependence of ΔPS (KPA) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_182820_1[] = { + {30.0, 0.14}, + {40.0, 0.23}, + {50.0, 0.33}, + {60.0, 0.45}, + {70.0, 0.57}, + {80.0, 0.72}, + {90.0, 0.87}, + {100.0, 1.07}, + {200.0, 3.48}, + {300.0, 6.72}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4002 (P/N 182820-2). + * + * Cooling side dependence of ΔPS (KPA) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_182820_2[] = { + {30.0, 0.14}, + {40.0, 0.23}, + {50.0, 0.33}, + {60.0, 0.45}, + {70.0, 0.57}, + {80.0, 0.72}, + {90.0, 0.87}, + {100.0, 1.07}, + {200.0, 3.48}, + {300.0, 6.72}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4003 (P/N 182820-3). + * + * Cooling side dependence of ΔPS (KPA) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_182820_3[] = { + {30.0, 0.12}, + {40.0, 0.19}, + {50.0, 0.29}, + {60.0, 0.39}, + {70.0, 0.47}, + {80.0, 0.60}, + {90.0, 0.72}, + {100.0, 0.85}, + {200.0, 2.59}, + {300.0, 4.85}, + {400.0, 7.96}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4003 (P/N 182820-4). + * + * Cooling side dependence of ΔPS (KPA) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_182820_4[] = { + {30.0, 0.12}, + {40.0, 0.19}, + {50.0, 0.29}, + {60.0, 0.39}, + {70.0, 0.47}, + {80.0, 0.60}, + {90.0, 0.72}, + {100.0, 0.85}, + {200.0, 2.59}, + {300.0, 4.85}, + {400.0, 7.96}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4005 (P/N 182820-1). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _hot_side_182820_1[] = { + {30.0, 1.18}, + {40.0, 1.96}, + {50.0, 3.05}, + {60.0, 4.13}, + {70.0, 5.65}, + {80.0, 7.02}, + {90.0, 8.94}, + {100.0, 10.81}, + {200.0, 43.22}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4005 (P/N 182820-2). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _hot_side_182820_2[] = { + {30.0, 1.18}, + {40.0, 1.96}, + {50.0, 3.05}, + {60.0, 4.13}, + {70.0, 5.65}, + {80.0, 7.02}, + {90.0, 8.94}, + {100.0, 10.81}, + {200.0, 43.22}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4006 (P/N 182820-3). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _hot_side_182820_3[] = { + {30.0, 1.67}, + {40.0, 2.65}, + {50.0, 3.93}, + {60.0, 5.60}, + {70.0, 7.17}, + {80.0, 9.33}, + {90.0, 11.30}, + {100.0, 13.75}, + {200.0, 44.20}}; + + /** + * @brief Honeywell Heat Exchanger CMM 21-50-14, Figure 4006 (P/N 182820-4). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER LIMIT. + */ + static const airflow_to_pressure_anchors_data_t _hot_side_182820_4[] = { + {30.0, 1.67}, + {40.0, 2.65}, + {50.0, 3.93}, + {60.0, 5.60}, + {70.0, 7.17}, + {80.0, 9.33}, + {90.0, 11.30}, + {100.0, 13.75}, + {200.0, 44.20}}; + + static const air_passage_data_t _air_passage_182820_1_data[] = { + {.air_passage_description = "Cooling Air Side", + .air_passage_anchors = _cooling_side_182820_1, + .anchors_data_size = ARRAY_SIZE(_cooling_side_182820_1), + .recalculated_required = true, + .airflow_pressure_unit = KPA, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 2.0}, + {.air_passage_description = "Bleed Air Side", + .air_passage_anchors = _hot_side_182820_1, + .anchors_data_size = ARRAY_SIZE(_hot_side_182820_1), + .recalculated_required = true, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const air_passage_data_t _air_passage_182820_2_data[] = { + {.air_passage_description = "Cooling Air Side", + .air_passage_anchors = _cooling_side_182820_2, + .anchors_data_size = ARRAY_SIZE(_cooling_side_182820_2), + .recalculated_required = true, + .airflow_pressure_unit = KPA, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 2.0}, + {.air_passage_description = "Bleed Air Side", + .air_passage_anchors = _hot_side_182820_2, + .anchors_data_size = ARRAY_SIZE(_hot_side_182820_2), + .recalculated_required = true, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const air_passage_data_t _air_passage_182820_3_data[] = { + {.air_passage_description = "Cooling Air Side", + .air_passage_anchors = _cooling_side_182820_3, + .anchors_data_size = ARRAY_SIZE(_cooling_side_182820_3), + .recalculated_required = true, + .airflow_pressure_unit = KPA, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 2.0}, + {.air_passage_description = "Bleed Air Side", + .air_passage_anchors = _hot_side_182820_3, + .anchors_data_size = ARRAY_SIZE(_hot_side_182820_3), + .recalculated_required = true, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const air_passage_data_t _air_passage_182820_4_data[] = { + {.air_passage_description = "Cooling Air Side", + .air_passage_anchors = _cooling_side_182820_4, + .anchors_data_size = ARRAY_SIZE(_cooling_side_182820_4), + .recalculated_required = true, + .airflow_pressure_unit = KPA, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 2.0}, + {.air_passage_description = "Bleed Air Side", + .air_passage_anchors = _hot_side_182820_4, + .anchors_data_size = ARRAY_SIZE(_hot_side_182820_4), + .recalculated_required = true, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const heat_exchanger_type_data_t heat_exchanger_21_50_14_data[] = { + {.part_number_description = "182820-1", + .air_passages_data = _air_passage_182820_1_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_182820_1_data)}, + {.part_number_description = "182820-2", + .air_passages_data = _air_passage_182820_2_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_182820_2_data)}, + {.part_number_description = "182820-3", + .air_passages_data = _air_passage_182820_3_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_182820_3_data)}, + {.part_number_description = "182820-4", + .air_passages_data = _air_passage_182820_4_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_182820_4_data)}}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/ats0002/21_53_88.h b/ats0002/21_53_88.h new file mode 100644 index 0000000..75afca0 --- /dev/null +++ b/ats0002/21_53_88.h @@ -0,0 +1,154 @@ +#pragma once + +#include "ats0002.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @file 21_53_88.h + * + * @brief Liebherr Condenser CMM 21-53-88 configuration data. + * + * This module provides static configuration data for Liebherr Condenser CMM + * 21-53-88 heat exchanger, including pressure-to-airflow anchor points for + * cooling and hot sides, air passage definitions, and heat exchanger type + * mappings for part numbers 969A0000-01 and 969A0000-02. + * + * Key features: + * - Cooling side performance data (Figure 4002) + * - Hot side performance data (Figures 4003 and 4004) + * - Complete air passage configuration with operational limits + * + * @note All data arrays are static and const-qualified for read-only access. + */ + + /** + * @brief Liebherr Condenser CMM 21-53-88, Figure 4002 (P/N 969A0000-01). + * + * Cooling side dependence of ΔPS (KPA) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_969A0000_01[] = { + {25.0, 0.26}, + {30.0, 0.36}, + {40.0, 0.61}, + {50.0, 0.91}, + {60.0, 1.26}, + {70.0, 1.75}, + {80.0, 2.33}, + {90.0, 2.80}, + {100.0, 3.50}, + {200.0, 13.20}}; + + /** + * @brief Liebherr Condenser CMM 21-53-88, Figure 4002 (P/N 969A0000-02). + * + * Cooling side dependence of ΔPS (KPA) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_969A0000_02[] = { + {25.0, 0.26}, + {30.0, 0.36}, + {40.0, 0.61}, + {50.0, 0.91}, + {60.0, 1.26}, + {70.0, 1.75}, + {80.0, 2.33}, + {90.0, 2.80}, + {100.0, 3.50}, + {200.0, 13.20}}; + + /** + * @brief Liebherr Condenser CMM 21-53-88, Figure 4003 (P/N 969A0000-01). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _hot_side_969A0000_01[] = { + {20.0, 0.25}, + {30.0, 0.48}, + {40.0, 0.80}, + {50.0, 1.25}, + {60.0, 1.67}, + {70.0, 2.25}, + {80.0, 2.75}, + {90.0, 3.57}, + {100.0, 4.70}, + {120.0, 11.00}}; + + /** + * @brief Liebherr Condenser CMM 21-53-88, Figure 4004 (P/N 969A0000-02). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _hot_side_969A0000_02[] = { + {20.0, 0.17}, + {30.0, 0.34}, + {40.0, 0.57}, + {50.0, 0.83}, + {60.0, 1.18}, + {70.0, 1.56}, + {80.0, 1.93}, + {90.0, 2.55}, + {100.0, 3.42}, + {120.0, 9.51}}; + + static const air_passage_data_t _air_passage_969A0000_01_data[] = { + {.air_passage_description = "Cold Air Side", + .air_passage_anchors = _cooling_side_969A0000_01, + .anchors_data_size = ARRAY_SIZE(_cooling_side_969A0000_01), + .recalculated_required = false, + .airflow_pressure_unit = KPA, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 33.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 2.0}, + {.air_passage_description = "Hot Air Side", + .air_passage_anchors = _hot_side_969A0000_01, + .anchors_data_size = ARRAY_SIZE(_hot_side_969A0000_01), + .recalculated_required = false, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 33.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const air_passage_data_t _air_passage_969A0000_02_data[] = { + {.air_passage_description = "Cold Air Side", + .air_passage_anchors = _cooling_side_969A0000_02, + .anchors_data_size = ARRAY_SIZE(_cooling_side_969A0000_02), + .recalculated_required = false, + .airflow_pressure_unit = KPA, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 33.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 2.0}, + {.air_passage_description = "Hot Air Side", + .air_passage_anchors = _hot_side_969A0000_02, + .anchors_data_size = ARRAY_SIZE(_hot_side_969A0000_02), + .recalculated_required = false, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 33.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const heat_exchanger_type_data_t heat_exchanger_21_53_88_data[] = { + {.part_number_description = "969A0000-01", + .air_passages_data = _air_passage_969A0000_01_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_969A0000_01_data)}, + {.part_number_description = "969A0000-02", + .air_passages_data = _air_passage_969A0000_02_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_969A0000_02_data)}}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/ats0002/21_53_89.h b/ats0002/21_53_89.h new file mode 100644 index 0000000..292383f --- /dev/null +++ b/ats0002/21_53_89.h @@ -0,0 +1,154 @@ +#pragma once + +#include "ats0002.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @file 21_53_89.h + * + * @brief Liebherr Reheater CMM 21-53-89 configuration data. + * + * This module provides static configuration data for Liebherr Reheater CMM + * 21-53-89 heat exchanger, including pressure-to-airflow anchor points for + * cooling and hot sides, air passage definitions, and heat exchanger type + * mappings for part numbers 968B0000-01 and 968A0000-03. + * + * Key features: + * - Cooling side performance data (Figures 4002 and 4003) + * - Hot side performance data (Figures 4004 and 4005) + * - Complete air passage configuration with operational limits + * + * @note All data arrays are static and const-qualified for read-only access. + */ + + /** + * @brief Liebherr Reheater CMM 21-53-89, Figure 4002 (P/N 968B0000-01). + * + * Cooling side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_968B0000_01[] = { + {20.0, 0.11}, + {30.0, 0.22}, + {40.0, 0.37}, + {50.0, 0.55}, + {60.0, 0.78}, + {70.0, 1.00}, + {80.0, 1.40}, + {90.0, 1.70}, + {100.0, 2.00}, + {200.0, 7.00}}; + + /** + * @brief Liebherr Reheater CMM 21-53-89, Figure 4003 (P/N 968A0000-03). + * + * Cooling side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _cooling_side_968A0000_03[] = { + {20.0, 0.09}, + {30.0, 0.19}, + {40.0, 0.32}, + {50.0, 0.47}, + {60.0, 0.65}, + {70.0, 0.85}, + {80.0, 1.10}, + {90.0, 1.40}, + {100.0, 1.70}, + {200.0, 5.60}}; + + /** + * @brief Liebherr Reheater CMM 21-53-89, Figure 4004 (P/N 968B0000-01). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _hot_side_968B0000_01[] = { + {20.0, 0.09}, + {30.0, 0.19}, + {40.0, 0.32}, + {50.0, 0.47}, + {60.0, 0.65}, + {70.0, 0.85}, + {80.0, 1.10}, + {90.0, 1.40}, + {100.0, 1.70}, + {200.0, 5.60}}; + + /** + * @brief Liebherr Reheater CMM 21-53-89, Figure 4005 (P/N 968A0000-03). + * + * Hot side dependence of ΔPS (PSIG) on air flow rate (LB/MIN), UPPER line (+20%). + */ + static const airflow_to_pressure_anchors_data_t _hot_side_968A0000_03[] = { + {20.0, 0.08}, + {30.0, 0.17}, + {40.0, 0.27}, + {50.0, 0.40}, + {60.0, 0.55}, + {70.0, 0.72}, + {80.0, 0.91}, + {90.0, 1.25}, + {100.0, 1.45}, + {200.0, 4.70}}; + + static const air_passage_data_t _air_passage_968B0000_01_data[] = { + {.air_passage_description = "Cold Air Side", + .air_passage_anchors = _cooling_side_968B0000_01, + .anchors_data_size = ARRAY_SIZE(_cooling_side_968B0000_01), + .recalculated_required = false, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}, + {.air_passage_description = "Hot Air Side", + .air_passage_anchors = _hot_side_968B0000_01, + .anchors_data_size = ARRAY_SIZE(_hot_side_968B0000_01), + .recalculated_required = false, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const air_passage_data_t _air_passage_968A0000_03_data[] = { + {.air_passage_description = "Cold Air Side", + .air_passage_anchors = _cooling_side_968A0000_03, + .anchors_data_size = ARRAY_SIZE(_cooling_side_968A0000_03), + .recalculated_required = false, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}, + {.air_passage_description = "Hot Air Side", + .air_passage_anchors = _hot_side_968A0000_03, + .anchors_data_size = ARRAY_SIZE(_hot_side_968A0000_03), + .recalculated_required = false, + .airflow_pressure_unit = PSIG, + .min_barometric_pressure = 840.0, + .max_barometric_pressure = 1070.0, + .min_airflow_temperature = 15.0, + .max_airflow_temperature = 35.0, + .min_airflow_pressure = 0.01, + .max_airflow_pressure = 15.0}}; + + static const heat_exchanger_type_data_t heat_exchanger_21_53_89_data[] = { + {.part_number_description = "968B0000-01", + .air_passages_data = _air_passage_968B0000_01_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_968B0000_01_data)}, + {.part_number_description = "968A0000-03", + .air_passages_data = _air_passage_968A0000_03_data, + .air_passages_data_size = ARRAY_SIZE(_air_passage_968A0000_03_data)}}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/ats0002/ats0002.c b/ats0002/ats0002.c new file mode 100644 index 0000000..b2281b4 --- /dev/null +++ b/ats0002/ats0002.c @@ -0,0 +1,333 @@ +#include "ats0002.h" + +/** + * @brief Normalize the decimal separator in a string from comma to dot. + * + * Replaces all comma characters with dots in-place, supporting locales + * that use comma as the decimal separator. + * + * @param str Pointer to the string to normalize (must not be NULL) + */ +static void _normalize_decimal_separator(char *str); + +/** + * @brief Get a numeric value or special commands from user input. + * + * Reads a line from standard input, handles EOF and special commands + * ('q'/'Q' for EXIT, 'r'/'R' for REPEAT), normalizes the decimal + * separator, and converts the input to a double value. + * + * @param data Pointer to store the parsed numeric value or EXIT/REPEAT + */ +static void _get_user_input(double *data); + +/** + * @brief Get a menu selection from user input with validation. + * + * Prompts the user for a selection, validates that the value is within + * the specified range, and handles EXIT and REPEAT commands. + * + * @param result Pointer to store the selected value (must not be NULL) + * @param size Number of available options + * @param prompt Prompt message to display to the user + * @param error_msg Error message to display for invalid input + */ +static void _get_selection(uint16_t *result, uint8_t size, const char *prompt, const char *error_msg); + +/** + * @brief Get a double value from user input within a specified range. + * + * Prompts the user for a value, validates it is within the given range, + * and handles EXIT and REPEAT commands. Supports REPEAT for re-prompting + * without terminating. + * + * @param result Pointer to store the entered value (must not be NULL) + * @param min Minimum allowed value + * @param max Maximum allowed value + * @param prompt Prompt message to display to the user + * @param error_msg Error message to display for invalid input + */ +static void _get_double_in_range(double *result, double min, double max, const char *prompt, const char *error_msg); + +/** + * @brief Get a log-interpolated pressure drop limit based on airflow. + * + * Reads a pressure drop limit from the user and calculates the interpolated + * value using logarithmic interpolation on the anchor points from the + * provided air passage data. + * + * @param limit Pointer to store the calculated pressure drop limit + * @param airflow Pointer to the current airflow value + * @param data Pointer to air passage data containing anchor points (must not be NULL) + */ +static void _get_log_interpolated_airflow_pressure_drop_limit(double *limit, const double *airflow, const air_passage_data_t *data); + +/** + * @brief Calculate density-corrected static inlet pressure. + * + * Applies barometric pressure and temperature compensation to the raw + * airflow pressure value, producing a density-corrected result in HPA + * (hectopascal) units. + * + * @param corrected_airflow_pressure Pointer to store the corrected pressure + * @param airflow_pressure Pointer to the raw static inlet pressure value + * @param barometric_pressure Pointer to the current barometric pressure + * @param airflow_temperature Pointer to the current air temperature in Celsius + */ +static void _calculate_density_corrected_pressure(double *corrected_airflow_pressure, const double *airflow_pressure, const double *barometric_pressure, const double *airflow_temperature); + +void get_user_command(uint16_t *user_command) +{ + printf("Enter 'q' to quit or 'r' to REPEAT:\n"); + for (;;) + { + double input = 0.0; + _get_user_input(&input); + if (input == (double)EXIT) + { + *user_command = EXIT; + return; + } + if (input == (double)REPEAT) + { + *user_command = REPEAT; + return; + } + printf("Incorrect command. Try again.\n"); + } +} + +static void _get_selection(uint16_t *result, uint8_t size, const char *prompt, const char *error_msg) +{ + printf("%s (or 'q' to quit):\n", prompt); + for (;;) + { + double input = 0.0; + _get_user_input(&input); + + if (input == (double)EXIT) + { + *result = EXIT; + return; + } + if (input >= 1.0 && input <= (double)size) + { + uint16_t val = (uint16_t)input; + if ((double)val == input) + { + *result = val - 1; + return; + } + } + printf("%s\n", error_msg); + } +} + +void get_heat_exchanger_number(uint16_t *num, uint8_t size) +{ + _get_selection(num, size, "Enter the heat exchanger number", "Incorrect heat exchanger number. Try again."); +} + +void get_heat_exchanger_part_number(uint16_t *num, uint8_t size) +{ + _get_selection(num, size, "Enter the heat exchanger part number", "Incorrect heat exchanger part number. Try again."); +} + +void get_heat_exchanger_air_passage_number(uint16_t *num, uint8_t size) +{ + _get_selection(num, size, "Enter the heat exchanger air passage number", "Incorrect heat exchanger air passage number. Try again."); +} + +static void _get_double_in_range(double *result, double min, double max, const char *prompt, const char *error_msg) +{ + printf("%s (or 'q' to quit):\n", prompt); + for (;;) + { + double input = 0.0; + _get_user_input(&input); + if (input == (double)EXIT) + { + *result = (double)EXIT; + return; + } + if (input == (double)REPEAT) + { + printf("%s\n", error_msg); + continue; + } + if (input >= min && input <= max) + { + *result = input; + return; + } + printf("%s\n", error_msg); + } +} + +void get_airflow(double *airflow, const air_passage_data_t *data) +{ + double min = data->air_passage_anchors[0].airflow; + double max = data->air_passage_anchors[data->anchors_data_size - 1].airflow; + _get_double_in_range(airflow, min, max, "Enter airflow in LB/MIN", "Incorrect airflow. Try again."); +} + +void get_airflow_pressure(double *airflow_pressure, const air_passage_data_t *data) +{ + double min = data->min_airflow_pressure; + double max = data->max_airflow_pressure; + const char *prompt = (data->airflow_pressure_unit == KPA) ? "Enter static inlet pressure in KPA" : "Enter static inlet pressure in PSIG"; + _get_double_in_range(airflow_pressure, min, max, prompt, "Incorrect static inlet pressure. Try again."); +} + +void get_barometric_pressure(double *barometric_pressure, const air_passage_data_t *data) +{ + double min = data->min_barometric_pressure; + double max = data->max_barometric_pressure; + _get_double_in_range(barometric_pressure, min, max, "Enter barometric pressure in MBAR", "Incorrect barometric pressure. Try again."); +} + +void get_airflow_temperature(double *airflow_temperature, const air_passage_data_t *data) +{ + double min = data->min_airflow_temperature; + double max = data->max_airflow_temperature; + _get_double_in_range(airflow_temperature, min, max, "Enter air temperature in C", "Incorrect air temperature. Try again."); +} + +void get_pressure_drop(double *pressure_drop_limit, const double *airflow, const double *airflow_pressure, double *corrected_airflow_pressure, const double *barometric_pressure, const double *airflow_temperature, const air_passage_data_t *data) +{ + if (data->recalculated_required == true) + { + double hpa_pressure = 0.0; + double hpa_corrected_pressure = 0.0; + switch (data->airflow_pressure_unit) + { + case KPA: + hpa_pressure = *airflow_pressure * 10.0; + _calculate_density_corrected_pressure(&hpa_corrected_pressure, &hpa_pressure, barometric_pressure, airflow_temperature); + *corrected_airflow_pressure = hpa_corrected_pressure / 10.0; + break; + case PSIG: + hpa_pressure = *airflow_pressure * 68.9476; + _calculate_density_corrected_pressure(&hpa_corrected_pressure, &hpa_pressure, barometric_pressure, airflow_temperature); + *corrected_airflow_pressure = hpa_corrected_pressure * 0.0145038; + break; + default: + break; + } + } + _get_log_interpolated_airflow_pressure_drop_limit(pressure_drop_limit, airflow, data); +} + +static void _normalize_decimal_separator(char *str) +{ + char *src = str; + char *dst = str; + while (*src != '\0') + { + if (*src == ',') + { + *dst++ = '.'; + src++; + } + else + { + *dst++ = *src++; + } + } + *dst = '\0'; +} + +static void _get_user_input(double *data) +{ + char input[64]; + for (;;) + { + printf("> "); + fflush(stdout); + if (fgets(input, sizeof(input), stdin) == NULL) + { + if (feof(stdin)) + { + *data = EXIT; + return; + } + printf("Input error. Try again.\n"); + continue; + } + if (strchr(input, '\n') == NULL) + { + int c; + while ((c = getchar()) != '\n' && c != EOF) + { + } + } + input[strcspn(input, "\n")] = '\0'; + if (strcmp(input, "q") == 0 || strcmp(input, "Q") == 0) + { + *data = EXIT; + break; + } + if (strcmp(input, "r") == 0 || strcmp(input, "R") == 0) + { + *data = REPEAT; + break; + } + _normalize_decimal_separator(input); + char *endptr = NULL; + *data = strtod(input, &endptr); + if (endptr == input) + { + printf("Error: Not a valid number. Try again.\n"); + continue; + } + while (*endptr == ' ') + { + endptr++; + } + if (*endptr != '\0') + { + printf("Error: Unexpected characters after number. Try again.\n"); + continue; + } + break; + } +} + +static void _get_log_interpolated_airflow_pressure_drop_limit(double *limit, const double *airflow, const air_passage_data_t *data) +{ + if (*airflow <= data->air_passage_anchors[0].airflow) + { + *limit = data->air_passage_anchors[0].pressure; + return; + } + if (*airflow >= data->air_passage_anchors[data->anchors_data_size - 1].airflow) + { + *limit = data->air_passage_anchors[data->anchors_data_size - 1].pressure; + return; + } + for (uint8_t i = 0; i < data->anchors_data_size - 1; ++i) + { + if (*airflow >= data->air_passage_anchors[i].airflow && + *airflow <= data->air_passage_anchors[i + 1].airflow) + { + double log_x = log(*airflow); + double log_x1 = log(data->air_passage_anchors[i].airflow); + double log_x2 = log(data->air_passage_anchors[i + 1].airflow); + double log_y1 = log(data->air_passage_anchors[i].pressure); + double log_y2 = log(data->air_passage_anchors[i + 1].pressure); + double log_y = log_y1 + (log_x - log_x1) * (log_y2 - log_y1) / (log_x2 - log_x1); + *limit = exp(log_y); + return; + } + } + *limit = -1.0; +} + +static void _calculate_density_corrected_pressure(double *corrected_airflow_pressure, const double *airflow_pressure, const double *barometric_pressure, const double *airflow_temperature) +{ + double value_4 = *airflow_pressure * 0.5; + double value_5 = *barometric_pressure + value_4; + double value_6 = *airflow_temperature + 273.2; + double value_7 = (0.28443 * value_5) / value_6; + *corrected_airflow_pressure = *airflow_pressure * value_7; +} \ No newline at end of file diff --git a/ats0002/ats0002.h b/ats0002/ats0002.h new file mode 100644 index 0000000..cde4e90 --- /dev/null +++ b/ats0002/ats0002.h @@ -0,0 +1,207 @@ +#pragma once + +/** + * @file ats0002.h + * + * @brief Heat exchanger data management and user input handling for ATS0002. + * + * This module provides data structures and functions for managing heat + * exchanger configuration data including air passage descriptions, pressure + * to airflow anchor points, and user interaction functions for selecting + * heat exchanger models and retrieving operational parameters. + * + * Key features: + * - Hierarchical data structures for heat exchanger, type, and air passage configuration + * - User input functions for command selection and parameter retrieval + * - Pressure drop calculation support with temperature and barometric compensation + * + * @note All data structures use const pointers to read-only configuration data. + */ + +#include "stdint.h" +#include "stdio.h" +#include "stdbool.h" +#include "stdlib.h" +#include "string.h" +#include "math.h" +#include "locale.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +#define EXIT 0xFFFF +#define REPEAT 0xFFEE + +#define EXIT_CHECK(cond) \ + if (cond == EXIT) \ + { \ + printf("Goodbye.\n"); \ + return 0; \ + } + +#define ASK_CHOICE(var, getter, count) \ + (var) = 0; \ + getter(&(var), (count)); \ + EXIT_CHECK(var); + +typedef enum +{ + KPA, + PSIG +} airflow_pressure_unit_t; + +/** + * @brief Airflow to pressure anchor point data structure. + * + * Represents a pair of airflow and corresponding pressure values used as + * interpolation anchor points for heat exchanger performance curves. + */ +typedef struct +{ + double airflow; /*!< Airflow rate value (LB/MIN) */ + double pressure; /*!< Corresponding pressure drop value (KPA or PSIG) */ +} airflow_to_pressure_anchors_data_t; + +/** + * @brief Air passage configuration data structure. + * + * Contains description, pressure-to-airflow anchor points, and operational + * parameter limits for a single air passage within a heat exchanger. + */ +typedef struct +{ + const char *air_passage_description; /*!< Human-readable description of the air passage */ + const airflow_to_pressure_anchors_data_t *air_passage_anchors; /*!< Pointer to anchor point array */ + const uint8_t anchors_data_size; /*!< Number of anchor points in the array */ + const bool recalculated_required; /*!< Flag indicating if recalculation is required */ + const airflow_pressure_unit_t airflow_pressure_unit; + const double min_barometric_pressure; /*!< Minimum allowed barometric pressure (Pa) */ + const double max_barometric_pressure; /*!< Maximum allowed barometric pressure (Pa) */ + const double min_airflow_temperature; /*!< Minimum allowed air temperature (C) */ + const double max_airflow_temperature; /*!< Maximum allowed air temperature (C) */ + const double min_airflow_pressure; /*!< Minimum allowed air pressure (KPA or PSIG) */ + const double max_airflow_pressure; /*!< Maximum allowed air pressure (KPA or PSIG) */ +} air_passage_data_t; + +/** + * @brief Heat exchanger type configuration data structure. + * + * Contains description and an array of air passage configurations for a + * specific heat exchanger part number. + */ +typedef struct +{ + const char *part_number_description; /*!< Human-readable part number description */ + const air_passage_data_t *air_passages_data; /*!< Pointer to air passage configuration array */ + const uint8_t air_passages_data_size; /*!< Number of air passages in the array */ +} heat_exchanger_type_data_t; + +/** + * @brief Heat exchanger configuration data structure. + * + * Contains description and an array of heat exchanger type configurations + * representing all supported part numbers for a given heat exchanger model. + */ +typedef struct +{ + const char *heat_exchanger_description; /*!< Human-readable heat exchanger model description */ + const heat_exchanger_type_data_t *heat_exchanger_type_data; /*!< Pointer to heat exchanger type array */ + const uint8_t heat_exchanger_type_data_size; /*!< Number of heat exchanger types in the array */ +} heat_exchanger_data_t; + +/** + * @brief Retrieve a user command from standard input. + * + * Reads a command selection from the user. The user can select a numeric + * command or enter EXIT to terminate the program. + * + * @param[out] user_command Pointer to store the selected command value + */ +void get_user_command(uint16_t *user_command); + +/** + * @brief Retrieve a heat exchanger model number from user input. + * + * Prompts the user to select a heat exchanger model from the available options. + * + * @param[out] heat_exchanger_number Pointer to store the selected model number + * @param[in] structure_size Number of available heat exchanger models + */ +void get_heat_exchanger_number(uint16_t *heat_exchanger_number, uint8_t structure_size); + +/** + * @brief Retrieve a heat exchanger part number from user input. + * + * Prompts the user to select a part number for the selected heat exchanger model. + * + * @param[out] heat_exchanger_part_number Pointer to store the selected part number + * @param[in] structure_size Number of available part numbers + */ +void get_heat_exchanger_part_number(uint16_t *heat_exchanger_part_number, uint8_t structure_size); + +/** + * @brief Retrieve an air passage number from user input. + * + * Prompts the user to select an air passage for the selected heat exchanger part. + * + * @param[out] heat_exchanger_air_passage_number Pointer to store the selected passage number + * @param[in] structure_size Number of available air passages + */ +void get_heat_exchanger_air_passage_number(uint16_t *heat_exchanger_air_passage_number, uint8_t structure_size); + +/** + * @brief Retrieve an airflow value from user input. + * + * Validates the entered airflow against the operational limits defined in the + * provided air passage data. + * + * @param[out] airflow Pointer to store the entered airflow value + * @param[in] data Pointer to air passage data containing operational limits (must not be NULL) + */ +void get_airflow(double *airflow, const air_passage_data_t *data); + +/** + * @brief Retrieve an airflow pressure value from user input. + * + * Validates the entered pressure against the operational limits defined in the + * provided air passage data. + * + * @param[out] airflow_pressure Pointer to store the entered pressure value + * @param[in] data Pointer to air passage data containing operational limits (must not be NULL) + */ +void get_airflow_pressure(double *airflow_pressure, const air_passage_data_t *data); + +/** + * @brief Retrieve a barometric pressure value from user input. + * + * Validates the entered barometric pressure against the operational limits + * defined in the provided air passage data. + * + * @param[out] barometric_pressure Pointer to store the entered pressure value + * @param[in] data Pointer to air passage data containing operational limits (must not be NULL) + */ +void get_barometric_pressure(double *barometric_pressure, const air_passage_data_t *data); + +/** + * @brief Retrieve an airflow temperature value from user input. + * + * Validates the entered temperature against the operational limits defined in + * the provided air passage data. + * + * @param[out] airflow_temperature Pointer to store the entered temperature value + * @param[in] data Pointer to air passage data containing operational limits (must not be NULL) + */ +void get_airflow_temperature(double *airflow_temperature, const air_passage_data_t *data); + +/** + * @brief Retrieve a pressure drop limit value from user input. + * + * Reads a pressure drop limit from the user and validates it against the + * operational limits defined in the provided air passage data. + * + * @param[out] pressure_drop_limit Pointer to store the entered pressure drop limit + * @param[in] airflow Pointer to store the current airflow value + * @param[in] barometric_pressure Pointer to store the current barometric pressure value + * @param[in] airflow_temperature Pointer to store the current airflow temperature value + * @param[in] data Pointer to air passage data containing operational limits (must not be NULL) + */ +void get_pressure_drop(double *pressure_drop_limit, const double *airflow, const double *airflow_pressure, double *corrected_airflow_pressure, const double *barometric_pressure, const double *airflow_temperature, const air_passage_data_t *data); \ No newline at end of file diff --git a/heat_exchander_airflow_pressure_drop b/heat_exchander_airflow_pressure_drop new file mode 100755 index 0000000000000000000000000000000000000000..05f11718c0915dd4d795969df9bd3e7c19545a70 GIT binary patch literal 38200 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 literal 0 HcmV?d00001 diff --git a/heat_exchander_airflow_pressure_drop.c b/heat_exchander_airflow_pressure_drop.c new file mode 100644 index 0000000..bfe7a43 --- /dev/null +++ b/heat_exchander_airflow_pressure_drop.c @@ -0,0 +1,103 @@ +#include "ats0002/ats0002.h" +#include "ats0002/21_53_89.h" +#include "ats0002/21_53_88.h" +#include "ats0002/21_50_14.h" + +static const heat_exchanger_data_t heat_exchanger_data[] = { + {"Honeywell Heat Exchanger CMM 21-50-14", heat_exchanger_21_50_14_data, ARRAY_SIZE(heat_exchanger_21_50_14_data)}, + {"Liebherr Reheater CMM 21-53-89", heat_exchanger_21_53_89_data, ARRAY_SIZE(heat_exchanger_21_53_89_data)}, + {"Liebherr Condenser CMM 21-53-88", heat_exchanger_21_53_88_data, ARRAY_SIZE(heat_exchanger_21_53_88_data)}}; + +int main(void) +{ + setlocale(LC_NUMERIC, "C"); + for (;;) + { +#ifdef _WIN32 + system("cls"); +#else + system("clear"); +#endif + printf("************************************************************\n" + "* *\n" + "* Heat Exchanger Airflow Pressure Drop Calculation Program *\n" + "* *\n" + "* Developed by @rick_professor *\n" + "* Participation by @cabanleo *\n" + "* Property of Aerotech LLC *\n" + "* *\n" + "************************************************************\n" + "\n"); + for (uint8_t i = 0; i < ARRAY_SIZE(heat_exchanger_data); ++i) + { + printf("%d. %s\n", i + 1, heat_exchanger_data[i].heat_exchanger_description); + } + printf("\n"); + uint16_t heat_exchanger_number = 0; + ASK_CHOICE(heat_exchanger_number, get_heat_exchanger_number, ARRAY_SIZE(heat_exchanger_data)); + printf("\n"); + const heat_exchanger_data_t *he = &heat_exchanger_data[heat_exchanger_number]; + for (uint8_t i = 0; i < he->heat_exchanger_type_data_size; ++i) + { + printf("%d. %s\n", i + 1, he->heat_exchanger_type_data[i].part_number_description); + } + printf("\n"); + uint16_t part_number = 0; + ASK_CHOICE(part_number, get_heat_exchanger_part_number, he->heat_exchanger_type_data_size); + printf("\n"); + const heat_exchanger_type_data_t *hetd = &he->heat_exchanger_type_data[part_number]; + for (uint8_t i = 0; i < hetd->air_passages_data_size; ++i) + { + printf("%d. %s\n", i + 1, hetd->air_passages_data[i].air_passage_description); + } + printf("\n"); + uint16_t air_passage_number = 0; + ASK_CHOICE(air_passage_number, get_heat_exchanger_air_passage_number, hetd->air_passages_data_size); + printf("\n"); + const air_passage_data_t *apd = &hetd->air_passages_data[air_passage_number]; + double airflow = 0.0; + get_airflow(&airflow, apd); + EXIT_CHECK(airflow); + printf("\n"); + double airflow_pressure = 0.0; + get_airflow_pressure(&airflow_pressure, apd); + EXIT_CHECK(airflow_pressure); + printf("\n"); + double barometric_pressure = 0.0; + double airflow_temperature = 0.0; + if (apd->recalculated_required == true) + { + get_barometric_pressure(&barometric_pressure, apd); + EXIT_CHECK(barometric_pressure); + printf("\n"); + get_airflow_temperature(&airflow_temperature, apd); + EXIT_CHECK(airflow_temperature); + printf("\n"); + } + 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); + const char *unit = apd->airflow_pressure_unit == KPA ? "KPA" : "PSIG"; + printf("****************** Test summary *******************\n"); + printf("Name: %s\n", he->heat_exchanger_description); + printf("P/N: %s\n", he->heat_exchanger_type_data[part_number].part_number_description); + printf("Side: %s\n", hetd->air_passages_data[air_passage_number].air_passage_description); + printf("Airflow: %0.2f LB/MIN\n", airflow); + printf("Static inlet pressure: %0.2f %s\n", airflow_pressure, unit); + if (apd->recalculated_required == true) + { + printf("Barometric pressure: %0.2f MBAR\n", barometric_pressure); + printf("Airflow temperature: %0.2f C\n", airflow_temperature); + printf("Corrected static inlet pressure: %0.2f %s\n", corrected_airflow_pressure, unit); + } + printf("Max allowed pressure drop: %0.2f %s\n", pressure_drop_limit, unit); + double test_pressure = apd->recalculated_required == true ? corrected_airflow_pressure : airflow_pressure; + printf("Test result: %s\n", test_pressure <= pressure_drop_limit ? "PASSED" : "FAILED"); + printf("***************************************************\n"); + printf("\n"); + uint16_t command = 0; + get_user_command(&command); + EXIT_CHECK(command); + } + return 0; +} \ No newline at end of file diff --git a/heat_exchander_airflow_pressure_drop.exe b/heat_exchander_airflow_pressure_drop.exe new file mode 100755 index 0000000000000000000000000000000000000000..7db0a55c30cc68b671ef652ac5429fc0ed92e431 GIT binary patch literal 175070 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 z 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

TzLeQ$mEmHPYZ)mwfo zq0ff*gyHwXsk(4t&eT!dIC#Dmy9~dai~Wg*=V5CBk8TR@uY0I2{8rr~K*DK#5WYO; z!*kV%d4Rp#Yv-ynZU|EMyE>f1eszw^cm#`&a0Deg_;OO7Imd^&Q-bjN%&nR5ATp8V z=D`}&jzdW7FT`ID)%>6a73X7FAfRNaf(3;5>jWyEs&_&7)A;K+N;3-cB+jwFAAg++ zKUS+|gCKl0{<^pJmRigqKdB8c&0k&@eiYMgxF2Q=!fWkU$o~JgHEzaJi6BCRf3N;A z2)1N!e~kW>m?PMw<|q^7u-%yK(r5RC+=PGi_~+xORRB?fJMb@ue?HEsfa>;Dd`#kj zuAHT^87{SAhI)+@1kV9FRRw1rhEY0lC#?XR3qjCXVHB=x7l=nK^e9|@>?S0agzO-s z!9sZS*Pu*EV_vHOnW(^vqxyj}Rt4vJ;2fxe^Ht!CSHbxOaGI*%U{fI&t%7qRa5~>o z**nXD(^>`RJmAz<;q?LF6sq9t15Q&FUiShgR|V%gz!|NA^Bi#6tKhr}ocby_$1xnM z;QSSEatL2$3O0WejSn@~?R4NQR5*;h#y&jdtml$oxrGqxEa0@3q;r}gf>G*G11s$) zO(zKWZgn!Q!$T){2L$|Hl8z#y{#*cFBUSY32Tq{^P9u1Mm1^Xk&E&y#m4WDwM)kNb z{T=2`RV0J6X=q4)Gg+BgD2Mj5ac4{j=VqYOgTHu8V4^h^VjKtpoHqPDHi4nPegb;2 z@u7j)%=L?c;7)a%{Ik#C9IbFJB}=dUv%&c<=*eb=p&q%q?LmV>Nwb+I{G}D#_FaQR zNwb+HZl^i=vBAMRQGxSbFv9zAQtbtUgBP0u=g)mcfd4Op!@8Nxbe6=)g8G>CyKg_T zJ;tbdjH1J5GSgCVliBM10GZip*B0JM`Zmm3oAO)KLrKv0CeSJ1pPxJ3mRJ+|M@r&o z6p2GkhkDT?P9g>~i9>ox%?>UJ#Z2O`2S+*%IhVLi;*ik?u_2GlKrSBbJYK=hV#C`p zOxuv-U!`bHJDW_<=vwXGE6w)Nd;cLkQ zBxww}3y?7f@;#11lEyf{1f&&#ts%VO3RHqo*xAn=_5^|Cg~q|i44;Mn9^GmFzGit* zjBBrwF!K~12)@kaWomdIpmb6;P zc_1~R58ri7AkN#^qMiE}#qR%#wACYl+~`(XVjI zui4sdZQ=cdC`O4UwdGHNqiak2+_eN+a1&yzaD1tle_5dw8d*_wqk$dW6iRVk93<^Z5F`kddP#w?j zbOkoJJWt`-2}koTk5Y{>KZ=e@G0%8@9g<7O^C{rPOmiD!^$93m4{$cqT~Z##YHk{_ zIu2SWPf(O6q< zfKs})_;E;7`fE8-LHn!MX9OJjtF?l^#24?dzDPVZ&&V?qU*s@G`@#%Pe26dF0n@%< z2KkM?xEx4&F3@k}OJmU&ArQ1L8q?kCn7)|Aw`#ulxb+3!@8ruwJCC8HXgfcnXs7?s z&Yjb+^99z<@#Fi1R)hx&^C^Nl=5wk2D2?U&0>Y)574MQq*4U)1SJX=7>HWso+zham~*+FX>w6%Om;4?9{a`@mNE{M|@hCMy<vs8mr(7vGXm~ z&UkKzex{=%(aXqVZRd1;@hX9Ce*n&C$yEwoOm5oIoboHKc6Q=r4R{;W0^|fxvv}D8 zAiKfcLP%->V-V%N+=|GLjax9v_18@Dy@1g=-)U{PNxrv1OP%k>xd=FteCJw}(N${w z(}+ikEbLgbvO_dYU0otkgR`Q&5{}uI7{Tkzvx-+6{-$(SyjEUlty*dgpmENyz9@^c z=E6=#9!eTFBl8(;m2ePt3opFzLWGdIQl+n~#WeV>5jX-NUMU>*Gfy|JlRSMKGyO6d zWlP$z ziN@N?b6B14<<~9a74n^AS$p|*IbD1A0^-goQWNfjq`LMd9t3LSlKjf49HcKyN8)29 z`89%ZI={---c#NyJ}qB+FN0~Tt!+lEzjEN}3(ng6Nf@VE?Y#|*s@2}f3ce6K|G?Tg z@uW~l#`ap``Lc*0Eg?JASd?m z_a(&dd<&<}FZ0k-43j3$QqlR9o^v&p9~+0!fdY|eGs(e(vNjs;sLi*Hxg4yf7 z2t9fpL~%$pnFqO}Lo-!c_x8U}@|{9v-`@;>>3qkVnoBg+@SozJuHjb!!<`2? zgt0M>(ba1Bu_(@zBAfXt{`zsq*mw-`=-6l}DGy^Kmn$C|AguSpAtp$HR|o#OYjugA zIRKmbY#(3C@oY9W;4ca?z549eUOD%y6dUBnJiWV9{B;W;zMbi>`LJQN`aETQkpmsy zjI7TS))(d1#@wUUz9@g5(h3$J2m6%I(>GZ=>&F_!57M2Potwaio-FALv(Gk){%Z5! zhAy%5K46!&bNe*xTn}M%%;!L-w4INF0d>rmxAXJB!T-=}3V;2k&hc~A?ffol=j4Ot z8oPz!+p*@)sd&z%Y#3kn{~O?N-OKX=*Uk%Qdezng=T>}Eb`J0WTWlb75AC-QB6R|1 z>W!L?dw&aib=wV`F?`i@2>UP~trgC0i1Q`jv{%6KGq(U2pTeQGNmXwGq*_Fc0Y^s^ zedM-AQ`K|0u|j9Td%ZA_vl~`y#+tsPBSpvDg)#yhUDX!?0g9#?tHl55lIVRA=ZZI{ zF!a@mzq8T%Rf^>`R`p&m(p7yiS$d6Cy$QytRMmM!V>L!H_p_Nz9t{FmZC1i`Itw0# z32-?o)wp{9K6pWF(DC&qI%kI`Auzp=%{=7UnK)|aB!^Fh<5wi&aP`i2CF|K?3J`iX zZZbP;gFJe6aGyUcn9o5>-cjbCLG#`>-TnhO2ky2A&WO8P4o2)m8!!Rj#UkW30a+gGA4UYVCc+Ov^!})stI<}+-8JRa? zX`mx>*cHYcF)}-0<4TdqsGEx`M>^{6#7K9oMN*8Y>miShDBjWOH%8Q0u6jiAt=2lC z+CjukD2b^5ZX+u3m}kRM{LX9r6vVB)8fhkeAIA_~wOm;=CB5Ew_JiWDPXf%^2 zT)45?dSlf3A_oG#8R?7rtS`#XgFgZ^asZ~)GYGBZ zHkpY=@M>diAFg|0^hA?fegJeB6_s-Nk`GC2Jd0FpO;FKa85Y+zAsBUppI;J(5k83?n9|7Oqj4Q|JNorH3QS8hR?$ykWv*wmeIUYE zcN-(T4a0SWkHHFlV}u7MR*&#Sm@svOKZOBqRgws&UN*wbbIXOJt&j^<07G}_i9h|= za5IURat7Us@j5o*@yT!WY445V)9ca2C~+HodK+w5ZAPmHp7vJ`1bo5ii@!#t)xIb{ zqrHF)9PNwpXVAF{z7RX}R|ne8iKnI;)$r(c^*-!LW#{ya_A?c11|=wsqY3%`f|98w z{%QrBgiHF=oQYTRm*g_98|Yjv;dhhEAsDf@(oWYOt>142CZoh{^!t<6?{9NE&5=6a zv3_p?RGH4frQe6G-#4Jok1^)px4=vL{TXMx954r4EBKvwoMo7HItP7uBsPu(KOGw! z^=pQ$ZQ|3Zh1GMg6{Du_Q{OgZ${f7qQ<8%}0i?7q!Z%6|QZK)$6+UQH%fWxKz9^rA zp93%Li&uO`fY2A66?`FfUTN)YA4c!c%VHMMc24Ku@ffMw@xaNQRBFy`usA0Hr%)2- zjTYyxfm45SDLN-uoc91{v?R`3EY2Ws#!KSlEY4-XY5I#&yyjb+e*jKrNt}fi=T6{E zmBi7u@niKM#=3g}GpRqks>tXoS)w-DOMD%;dM)vwCkp|rVZT#ufFS;GbSmuTS;rL)N-mU=p2Qov^0gm|r6m@{1!_>zZt>%Ylx&@|GOD z5d3tl+uXG+@AINBrVfZNxISbAxQ%ncw^29r8UXGp(P*D{%@_Mz1Ps?55~~Nmf=ZYA z1=ed7s}zrR&ca{X&L1bpYmAKp_*W@5=+g-Qv`=sJXb?bOv?J~Gywe7V8?NGu0npLD zh~L^E1jRm6);`h`f6mT6xtKuW8~xt!Me+OF5j>^+{v+%6FC|9DUunZh{Hr$aeAdPW z?SqAKs?lH9T7R8YHZR61lvBw^GDcPiAIkRx`KB8oK~V%hgPdpqRbK-|0_4)cq;S6gGVs8+M{%ht~2=l3VEW2W=sw`A`%)}Qfd*m=y_Sv|Qq@hXfU zkOOV!^!%<_`Z0ehI#Rh~e(=<8dP>esX8l~r7qWgn0p#g{O23NwAaLmMO6%v}TAzLj zR$%74jXr(I`n2?wS-(5DpCM)=z6j|%`+FDosN-?jZ=p0nBVP9=Q8u|e9*I$-eBM~FcQ;kDktOFE8 z6HV&jYZV)drV$%gOd~cv_HD`cZ$n^u#chm@e@71Le7~%uFBlsWHa5zif3;5|Ha@>V zV&fknNa@&E0l(|msPM~|`Pu`ec9N+fV`FL>vB7vv#76uA4$v?M!RRz%L*ply5Y;feu-Xi-kKqf21hIuPW zU~7Wian++J;apI574f5mIBuKHj4!iHtBn?@ooaHHG&YTB`Ooi5wD3+}f7QfF@}m3g&6d0xo0CVBcEI-kq`mX=fxSM5jZ*$KIIzFaAqX5P9qY=Y$P;cBn**g zvWok!prxxs`b8%i`B;?CsS1%mtQ>GgFbhL;&+p`FS0IWGaTsu}Y7!fr=;4@>@iT)J z$Vw2=D-bA{Y7!f~3c=n=E08lMBsPvN8yjz*FR?L{;-nAN>K%-##m2IeBsMO_Kz{|R zRu{n0u~B|i*$H{HFUnVmiD|?JpXid9L6YyJQHs5jQ|n(t!}_WS2nId zR^Zy7UY+{8IK*N6)I;EE@pBzwL$6NvV3b$X)!F*}CrkY7EGZ9b%LrsHXG6-vS%&2G zEYpGm7%S1FwhRGJ#}7L@Xa=Xf3y`L1#E-^dY_MkXJTPt&KO+E9ivQQT(GDUyHkf5@ zle+ORaA<-`bz}TViH+}|$op5$IHw%7P-5e6OZtMbaj}gJW{BSy8?DobjRyE#$Hp%} zg!?RR;|>g01$qa@? z`2+`-``E0w^Sr>&F}fe}xZ|0GF3z%_dEEEUiu?cexKDW8Cp_*i$K1_R0WZZUT{ryQ z)U5+u{dxE@_Tc8>t=k8-0TS~v9y}mgl!#O>qDtYUW2_X8w)2vEAd|9u2B!?Fdg8-0 z6Ni4(B_q@5{^JU|OI{p7y_%mAf0epV&&1eMV)^no%MVLzWKI;b*iTQd8Rh$@g|f}} z4v|M7%^jkJK$e{qN1ch5gAy$>;y&ha@ASBLdfYoa?&GuKeyhiQtH*t-$9=2E{m`tq z@AtSDJnjXL`wox$#H_gA;c?&Tao_22AN9CDH7o81JnkbN_Ysf#UXT0athnFfalgXj z&OJ1+i)X!MH+$S)m=*Vf9(O*K%i+~L>T&F^CQs34z%yIhJnV7b?{VMnasO7#-OMt-#HeaBY+N&ChE3E}qeZ=F zQEFy1*A(oUtrX4-X4o;rG8Dn8yZj6r%PecZgv>_wF07Wz=`J(T5!9>sfcUHY?78%S zc)2{z@Y{KIw7q^SI*)-D=NiW*N8ATz%NxG(XzkIahuu*bd4_wf2g3ltU!*SUd`>|ukx#=rS0P7@;J+PN^E52r(I#MZCSl$ zw6-}~D9ik{^q@Dx9`t6|C0?!DE739|?)4t`agY1B$NgO%_pw=VKhEQR$m4#<s%phU}zxc|)KKIU;B z^SGbvaUY)*_ZK|w`#tXaJ??LfxtpkatU}aD#>F<2j7!+r*l?I&X=Ge1 zvt(RCW~2MBD(Eg5cLeonJ|O-opG`}7_qCqi5df)XG+q9Z#6||UFQ%HO*NkHR9-%DR zv~)z|5lHihXd#egQ?RqiQxh#uNwmy}`$3QU6(091JnnT~%>TZE-zDZ_EhOd>ni?%8 zMT;X4^X>3swRK%Av&4KtW)t%#!5Y6_6TK(=cOGYk3gC`L<@l|<1_N%*gqKae2X8gIj^LSYuk{>v zIv7;T_gH4h_k_$w_qGbU%Uo~-^=jTJ{wkl#OLvNw%i}D+PGY0N9B1{KQO0!$Wy$5G zZ6c3An%hJRfh@bni@FUJEH6zred2rFvx&OPE9fp!cLeonZWVu(kEo@s;^p!< z%bO)ON}WL)-MM40*L6|UJJ36f_mDPrCt|ekX#9!@@&GNsRkK-n8Daz=k!aqXdnL3W z`X`{}RZq)Zl#c>JIo!s(D2GpyyC_$?o#u#lNb*U0N8vb|$>Fan4*=@7U9X-jcSx51 zP2bP{Qtp2I1&4W!cR!9}lMpPy%fI{Dv!TuRF^s@=CGBjkiI2pV*V(8F6p$xaU0XIgk4l9`~kMaX-%E-r#X>@VM{xxVOxTd%efK z-s4{HaW8t@TW7`nXpj3`kNaGY`+ARi+pM_H^|&**XIVTR~rBfdFDUUnv)irD(fafmIJ*9rJLUgVrCg%%|zm~xJQ@Z*76nUzD zO;FfA+`YA{80h;db1D<`n|}hst0w3h+@fUBR}ch;Z@iQ{4VXXptp_0DWexdLxLWQ5 z(Gb1^Q_kZwq}hZ6k2GWjM_KNqd_Ev@{Y&Fq3W&^%8uA%H#>_7YHRK^cI$=m=rG|VL zkgcZLXvj|hdCI}zyHwc_u4dF90GVBj)kS4L=OwwnNHak$?NNC7?U*EkOY5^J$}OMaNYvD9}>3!Nu`Bfme@ zqh11pP0QS$@9!?`!V?v&FYscq9h%J9RzxZlaPpy&pT(mde395 z``Ms8=Gbs8AWe>)-v`J+Cky@-5Vkm4b`r;-^9exqI-_pls0E@s$3IL6{>2gXV;mKn zQU3{utcbKVUWXqtwp$yL&WV7`bw-^92rED=VJ9G49SOGqk^@d`jS)cPDwXE-1waC2 z4e`$XfQ&kk`2-*Z%WL!IzU@O>Q6;P|&=vd&IC4&;DZfGpdg5xsXZP%M?DI}QwmOit zEYgk^eSmZVn9u@{Q572+iZ{{#GGS%z+B8@k#t41?nCSH-;IvvCbO)1w#N49@Z_kVP z>&T?Prhwx@YG03PY$KC>^?)2USKGDjt$^%w{Pk`?I-RKN1f&(CW4%5E$e1(g3P2_u zUVNr?&WVkG0wi$sx)+ch0AtHPLmY?luLyA>GmGsY?g+*5ya|VL7eP(XZ8A<@PZ6uG z0nQknhzOUdkwLHlkl3n2!^Po22vhIG*jC_7I`RwyGVb{OQb6KtTGyA)GX~|{Q`>nT zaQHNJ%{}TK?C&4!$&Uap&Wi)U83QEN>p?*FJKVqH@B(u1KLP1*<>oC6N!-viQSN8w9wES}lC$kAdUAZ^yF z@cTe_e<9Gnf|O`k44l}fq|*vWJ3eEJ4FJ;VXz_7CS}kRc`V=7dIHMi`gieg<90ufo zL+1_n32~DHc^e>dXPUOp#ef`gcx?kju77EqorKt^qdYeNLifdW{_}vyS+*YaFMzZ< zcK$a&+MSw^ZGhh$?#BQ!2I8?^rvU<#1g~~LMzsJC0@J%%!Rp^7iRC+iGYLUrIs<^b zU?W_uWDuF1)~68{Ev6oVIMqY@07lKVqw+hMlb9K;Uhq5J9*jEi^BIh4NKi%=bfqKw zcHneaI;8p)KxB_dbN?0~Zu~qCi0sLzm1j38yOH?{aQ0i7Nx2RcYp(-&Ga$^u*n`Ue ziR&19+f1F)IMj5gFc9punns&heUO#FjqA?_j2d@*+5<>~!+i%JPbuBS&U{bH0mmBG z0@CV4-OYe>I+X7P%NTI>g87(KBKzXnLV1Nj~x@@pNV7a+76 zh?`hF4v&J6>y?O&f&3-(Pp3oYOyIORTC4%2#gT9$AQO&+TL9^Fe6a(N4hQFIK-l7l zy48c+3&d51_fQ&la13bec_NhLPLe+9KJr+3R z5lh$z$cRJdG}3W!)&Y`paJB++g@r_hS&PGqPgV{bi~T(yi!2VZsV_f(TIc9>BXF9W zQMVCdM^UnS0jalDomsiH2s#eVzXC^g@U&H@0GV#}tw1iIsG73EH_bD7T_T)Eh-x75d zy9T!8hvcw#VDq4S@7lDfnBO5seZ2#D`M$Zx-~1a2Fp_*FPLwqa z$5EsoQQ14NqpPpCryWxC=ZEvfwyuGmzI-tl>e`%-^r=A<4fl8T4&Z!j9o{`XyuA?U zH&`reEao>ChKr3+gqO4T?jU2;AK_GPTU8_=59foeT|-fK_wXPzP>-ug5bfDDpiZ`V z9WLT>byF9}_IC|*ZOQj^6-tPqRT}K;$?xng*w=~pltuO4;lAOap5owew0W@D4SS|V za1kNTbnu3@50=AQ-4EH%>>4V|3Tj2ey9$24o{Q1~niaAq_&KZ3J^MY;>T}nvKV!|B zXyvLiFE~3o=Zy7jtIj{)!;QA|4Q^5=16_T2I%PYeC2a_`&MgJ)@^DRE_TW8(^4fT> zOK;oxY(6I0!ylqM_cNeDscG zEoU~NMNNyb*_P@#L-(8-L|YN>K7JA!<978Hqe9ov5W+S|K2kqqj#9lcO!schcMa3b zc&X18=&@vRwDi=dPgQqDjZ%l7dU`l1hTNloEV# z%aWEQO;K8E1BMumng$FPlma&=REgN*Seh0Nb(p7*{YL zA*w}Tun&_e-YQ?pqETOOe=kO0D(&7*Jdht4>K)z%`xc9^DF%up*!1riG&4ig1I9xR zgcEj&Sz^Wd^UjaftX{Vs=b4QOp;x3mD~# zMG)xkDsJP8ELHu!q}V&$1s?&rbDf4k*h0Sd)RtvYar?k1(xRgsp^IM{qoyt&YV*R5*P8rw-KDm`}@I(TsvHIBCBcWI|JGU}meqQ846 zkZuIT5aJ<eI-H%IbJSoI|8N*FXpRDdTKnYic7k2Ek%bVv5VlNg6$$AwT=am!GkIVB*VtOc{A z-6ce%*WSFa+-R2X=Jj3ip?dyfe5jJYaoN(Pr!EEe3Q5Bppxk-`ANu!hLZIRAwtR6Q z-*@Vgs0&hQrz-uZJ*rrLL^o@Vp*8H$TSU1>6~WW&^x6-}2-YhT^@jDnCuY%A=#Bb^ zqDxS?`DQ^lWCtr=-{NR-)P!Z_y8Q431Nwb~J*#9bcvf#8*u(g8UgNI+;}Zof9m5+J ztrDW@ReAz|v%4+CP$x3VzN(A}{nUArJ|#kB8-`ufc^MX8=ETgF0L1N@uAyO+4^>L3 z+>k17L)tV6@k^}iwQS&^qJnnjWfJZ%c3}c2A~k!vhm>`PH~|fACeiL~Y6`|_SX|by z_p+T6;}8jejEm0KToq9j6n@v=4i=-K?VI$4z-ULlIK+jwav`0A%gbUKE#68@@x%EQ zDD1tku`LHWBr01c_FZx^+R%&h)~>#_+w;X;Nq^BjJGdMh*xb7X#SbB5?V{oa=RK}y zPUZ=U-dT-Vr;?Rdj1`sGHSwv5gu-;D67S4bn~U4F>-&Zf7$~XRC3m=Wg00&q!c9JD zC88D4PyuU;%~+wBmu?!f$PE(}6I;)QvColug=BFywyq3YRae~+yE^&%z za)=c{uOd)q5%HHuHRwle2Cd2os`h43ApH~EL@`QL3VOzt30s~LWynfvnA=nKlr-@+ zfQi0#)DNsru*|PisZ6z_epU=9sza^EY~sstA?4UL`K}%1^2V88qEZo%*31jH7@>T$ zN^EF>3szuw3RPfm$Vq?BX*vbVR&InbPjIDhTaPft)O`f2xbXFAMWr1O9b4*V232dZ zV-cyX{#ZYCMZ+G-inOBRoWL<*t~XDSC}ypS70;FduP$`jeyGFhh7p8PavF|{ zv^8txfLFys+$(l-7B#8y@#+ECEN&u|vFDEN?mkQ%u|2g>x(%My%`F~rx~i3!?6*mI zPR-PqCAJw^OUEC5g2ilpC$PFW$@LCyiZ*W_;9?*}3%GOstsg6NRjd@p*bETdQL6#L~QMagftH z2_MM_6@(C#*C4cV<_06nzub8g?^2E2G-cMTw)2ozX(~@q6$UCH)zy`1Cg&-Is0e-f z)q*NjO7)yeVR-%!Ma=uS3aDOv|DCqSx(e&x)WTZT$iys1TKfJCAg)?-#>Qy%Iqm1+ zZmpH8&tJtL-DnwCn2&hZr51(dF?ISYi%C@*l50tw%Gd-E-cL&Mu} znu&u{O*iv{7d$vKS9fzn5rW8`x53-m(q+$+$k^Per(6O=UtA)oWQtPRs_zlC#^B|a zE;;MreydqptCd&+i}yCEgfr1@yDBZNDxSOP6RkAM%H=Oz<6)`lt50Q$5~p=m1%1g$ dCS7bSs+(hAJ+*)1pR|+<&D2yY!I?fc_`mA*n9KkG literal 0 HcmV?d00001 diff --git a/include/main.h b/include/main.h deleted file mode 100644 index e69de29..0000000 diff --git a/main.c b/main.c deleted file mode 100644 index e69de29..0000000 diff --git a/version.txt b/version.txt index e69de29..afaf360 100644 --- a/version.txt +++ b/version.txt @@ -0,0 +1 @@ +1.0.0 \ No newline at end of file