#include "../Inc/stend_logic.h" #include "../../controllers/Inc/ui_controller.h" // Макросы для различных пороговых значений и констант #define THRESHOLD_TIME 500 // Время для проверки концевика (в миллисекундах) #define PRESSURE_TOLERANCE 5 // Допустимая погрешность давления #define PRESSURE_MEASUREMENTS_DURATION 3000 // Время для измерений давления (в миллисекундах) #define PRESSURE_NUMBER_OF_CHECKS 10 // Количество проверок давления #define SEND_FRAME_NUMBER_OF_ATTEMPTS 3 // Количество попыток для отправки кадра калибровки #define MAX_PRESSURE_THRESHOLD 700 // Максимальное давление в контуре для проверки (7.00 бар) #define PRESSURE_DROP_TOLERANCE 5 // Допустимое падение давления (0.05 бар) #define SENSOR_RESPONSE_TIMEOUT 5000 // Таймаут ожидания ответа от датчика (в миллисекундах) // Глобальные переменные static PressureData pressure_data; static ErrorData error_data; static ActionState current_action = ACTION_WAIT_SENSOR; static EtalonSensor etalonSensor; static TestSensor testSensor; static SxTransmit sxTransmit_data; static SxResive sxResive_data; static uint8_t rxBuffer[SX1278_PAYLOAD]; static uint8_t txBuffer[SX1278_PAYLOAD]; static char LabelText[100]; void reset_pressure_data() { pressure_data.min_pressure = UINT16_MAX; // Устанавливаем максимальное значение pressure_data.max_pressure = 0; pressure_data.counter_pressure = 0; pressure_data.sum_pressure = 0; pressure_data.avg_pressure = 0; log_debug("Данные давления сброшены"); } void reset_sxResive_data() { memset(&sxResive_data, 0, sizeof(SxResive)); log_debug("Данные приёма SX1278 сброшены"); } void reset_sxTransmit_data() { memset(&sxTransmit_data, 0, sizeof(SxTransmit)); log_debug("Данные передачи SX1278 сброшены"); } void reset_error_data() { *(uint8_t*)&error_data = 0; // Сбрасываем все биты в 0 log_debug("Данные ошибок сброшены"); } void reset_test_data() { memset(&testSensor, 0, sizeof(TestSensor)); log_debug("Данные тестового датчика сброшены"); } void reset_all_data() { reset_pressure_data(); reset_error_data(); reset_test_data(); reset_sxTransmit_data(); reset_sxResive_data(); log_info("Все данные сброшены"); } bool check_gpio() { // Проверка сработки концевика в течение THRESHOLD_TIME uint32_t start_time = millis(); log_trace("Проверка состояния GPIO"); while ((millis() - start_time) < THRESHOLD_TIME) { if (!digitalRead(PIN_KONCEVIK)) { // Концевик сработал log_debug("Концевой выключатель активирован"); return true; } delay(100); // Задержка 100 миллисекунд } // Концевик не сработал log_warn("Концевой выключатель не активирован в течение порогового времени"); return false; } void release_pressure() { log_info("Спуск давления"); digitalWrite(PIN_AIR_INPUT, LOW); digitalWrite(PIN_AIR_OUTPUT, HIGH); delay(1000); // Подождать 1 секунду digitalWrite(PIN_AIR_OUTPUT, LOW); } void read_sx1278_data() { if (digitalRead(PIN_DIO0) == HIGH) { SX1278_FIFO_ReadData(rxBuffer); memcpy(&sxResive_data, rxBuffer, sizeof(SxResive)); log_trace("Данные получены от SX1278"); if (sxResive_data.type == 0x90) { set_etalonSensor_data(); } } } void set_testSensor_data(){ memcpy(&testSensor, &sxResive_data.data, sizeof(TestSensor)); testSensor.rssi = SX1278_ReadRegister(REG_RSSIVALUE) >> 1; log_debug("Обновлены данные тестового датчика: ID = %X, Давление = %u", testSensor.id_sensor, testSensor.pressure); } void set_etalonSensor_data(){ memcpy(&etalonSensor, &sxResive_data.data, sizeof(EtalonSensor)); snprintf(LabelText, sizeof(LabelText), "Текущее давление: %d.%02d", etalonSensor.pressure / 100, etalonSensor.pressure % 100); Set_New_LableCurrentPressure(LabelText); log_trace("Обновлены данные эталонного датчика: Давление = %u", etalonSensor.pressure); } void* stend_logic() { int8_t serial_port; log_set_level(LOG_DEBUG); // Инициализация проекта uint8_t init = InitializationProject(API_URL, PIN_NSS, PIN_RST, PIN_DIO0, PIN_KONCEVIK, PIN_AIR_INPUT, PIN_AIR_OUTPUT, &serial_port, SerialDevice); if (init != 0) { log_fatal("Ошибка инициализации проекта"); return NULL; } log_info("Проект успешно инициализирован"); SX1278_SetMode(SX1278_MODE_RECEIVER); log_info("SX1278 установлен в режим приёма"); while (1) { // Чтение данных из модуля read_sx1278_data(); // Проверка состояния концевика if (digitalRead(PIN_KONCEVIK)) { current_action = ACTION_WAIT_SENSOR; log_trace("Состояние концевого выключателя изменилось, возвращаемся к ACTION_WAIT_SENSOR"); } switch (current_action) { case ACTION_WAIT_SENSOR: Set_New_ButtonMain_Label("Ожидание установки датчика..."); log_trace("Состояние: ACTION_WAIT_SENSOR"); if (!digitalRead(PIN_KONCEVIK)) { delay(500); // Подождать полсекунды if (!digitalRead(PIN_KONCEVIK)) { current_action = ACTION_CHECK_SENSOR_ACTIVATION; log_debug("Датчик обнаружен, переходим к ACTION_CHECK_SENSOR_ACTIVATION"); } } break; case ACTION_CHECK_SENSOR_ACTIVATION: log_trace("Состояние: ACTION_CHECK_SENSOR_ACTIVATION"); if (check_gpio()) { Set_New_ButtonMain_Label("Начало цикла проверки..."); Set_New_LableSensorPressure("Поиск датчика..."); Set_Color_ButtonMain_white(); Update_Error_Table(0); reset_all_data(); current_action = ACTION_SET_PRESSURE; log_debug("Проверка GPIO пройдена, переходим к ACTION_SET_PRESSURE"); } else { // Если концевик не активен, возвращаемся к ожиданию current_action = ACTION_WAIT_SENSOR; log_warn("Проверка GPIO не пройдена, возвращаемся к ACTION_WAIT_SENSOR"); } break; case ACTION_SET_PRESSURE: log_trace("Состояние: ACTION_SET_PRESSURE"); Set_New_ButtonMain_Label("Установка давления..."); digitalWrite(PIN_AIR_INPUT, HIGH); log_debug("Вход воздуха активирован"); delay(2000); // Подождать 2 секунды digitalWrite(PIN_AIR_INPUT, LOW); log_debug("Вход воздуха деактивирован"); current_action = ACTION_GET_SENSOR_ID; break; case ACTION_GET_SENSOR_ID: log_trace("Состояние: ACTION_GET_SENSOR_ID"); Set_New_ButtonMain_Label("Поиск датчика..."); SX1278_SetMode(SX1278_MODE_RECEIVER); uint32_t start_time = millis(); while ((millis() - start_time) < SENSOR_RESPONSE_TIMEOUT * 2) { read_sx1278_data(); if (sxResive_data.type == 0x41) { set_testSensor_data(); current_action = ACTION_CHECK_PRESSURE; snprintf(LabelText, sizeof(LabelText), "Датчик найден ID: %X", testSensor.id_sensor); Set_New_LableSensorPressure(LabelText); log_debug("ID тестового датчика получен %X, переходим к ACTION_CHECK_PRESSURE", testSensor.id_sensor); break; } delay(100); } if (current_action != ACTION_CHECK_PRESSURE) { log_error("Не удалось получить ID датчика в течение таймаута"); current_action = ACTION_WAIT_SENSOR_RELEASE; Set_New_LableSensorPressure("Датчик не найден"); release_pressure(); } break; case ACTION_CHECK_PRESSURE: { log_trace("Состояние: ACTION_CHECK_PRESSURE"); Set_New_ButtonMain_Label("Проверка давления..."); delay(2000); bool received_data = false; for (int i = 0; i < PRESSURE_NUMBER_OF_CHECKS; i++) { // Чтение данных из модуля read_sx1278_data(); if (sxResive_data.type == 0x90) { uint16_t pressure = etalonSensor.pressure; pressure_data.sum_pressure += pressure; pressure_data.counter_pressure++; if (pressure < pressure_data.min_pressure) pressure_data.min_pressure = pressure; if (pressure > pressure_data.max_pressure) pressure_data.max_pressure = pressure; received_data = true; log_trace("Данные давления собраны: %u", pressure); } delay(500); } current_action = ACTION_SEND_DATA; if (!received_data) { // Не получили данных от эталонного датчика error_data.reference_sensor_error = 1; // Устанавливаем бит ошибки log_error("Нет данных от эталонного датчика"); current_action = ACTION_RELEASE_PRESSURE; break; } // Расчет среднего значения давления pressure_data.avg_pressure = pressure_data.sum_pressure / pressure_data.counter_pressure; // Проверка максимального давления if (pressure_data.max_pressure < MAX_PRESSURE_THRESHOLD) { error_data.compressor_pressure_error = 1; // Устанавливаем бит ошибки log_error("Недостаточное давление компрессора"); } // Проверка падения давления if ((pressure_data.max_pressure - pressure_data.min_pressure) > PRESSURE_DROP_TOLERANCE) { error_data.pressure_leak_error = 1; // Устанавливаем бит ошибки log_error("Травит датчик"); current_action = ACTION_RELEASE_PRESSURE; } log_info("Данные давления рассчитаны: MIN = %u, MAX = %u, AVG = %u", pressure_data.min_pressure, pressure_data.max_pressure, pressure_data.avg_pressure); break; } case ACTION_SEND_DATA: { log_trace("Состояние: ACTION_SEND_DATA"); // Отправка кадра на датчик, несколько попыток bool sensor_response = false; for (int i = 0; i < SEND_FRAME_NUMBER_OF_ATTEMPTS; i++) { log_info("Попытка отправки данных №%d", i + 1); snprintf(LabelText, sizeof(LabelText), "Отправка данных на датчик...%d/%d", i + 1, SEND_FRAME_NUMBER_OF_ATTEMPTS); Set_New_ButtonMain_Label(LabelText); // Формирование кадра для отправки sxTransmit_data.payload = 0x16; sxTransmit_data.type = 0x91; sxTransmit_data.id_sensor = testSensor.id_sensor; sxTransmit_data.pressure = pressure_data.avg_pressure; sxTransmit_data.temperature = 0x0000; sxTransmit_data.timestamp = (int)time(NULL); uint8_t array[9] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; memcpy(sxTransmit_data.otherData, array, sizeof(array)); SX1278_SetMode(SX1278_MODE_TRANSMITTER); log_trace("SX1278 установлен в режим передачи"); for (int j = 0; j < 2; j++) { SX1278_FIFO_SendData(&sxTransmit_data); log_debug("Калибровочный кадр отправлен (%d/2)", j + 1); delay(100); } SX1278_SetMode(SX1278_MODE_RECEIVER); log_trace("SX1278 возвращён в режим приёма"); // Ожидание ответа uint32_t start_time = millis(); while ((millis() - start_time) < SENSOR_RESPONSE_TIMEOUT) { read_sx1278_data(); if (sxResive_data.type == 0x92) { set_testSensor_data(); snprintf(LabelText, sizeof(LabelText), "Давленние датчика: %d.%02d", testSensor.pressure / 100, testSensor.pressure % 100); Set_New_LableSensorPressure(LabelText); sensor_response = true; log_info("Получен ответ от тестового датчика"); break; } delay(100); } if (sensor_response) { break; } else { log_warn("Нет ответа от тестового датчика на попытке %d", i + 1); } } if (!sensor_response) { error_data.sensor_response_error = 1; // Устанавливаем бит ошибки log_error("Нет ответа от испытуемого датчика"); } current_action = ACTION_RELEASE_PRESSURE; break; } case ACTION_RELEASE_PRESSURE: log_trace("Состояние: ACTION_RELEASE_PRESSURE"); Set_New_ButtonMain_Label("Спуск давления..."); release_pressure(); current_action = ACTION_PRINT_RESULTS; break; case ACTION_PRINT_RESULTS: log_trace("Состояние: ACTION_PRINT_RESULTS"); // Обработка результатов и вывод информации // Здесь можно добавить функции для печати наклеек и записи в БД uint8_t error_code = *(uint8_t*)&error_data; log_info("Код ошибки: %u", error_code); if (error_code == 0) { log_info("Тест пройден, датчик соответствует спецификациям"); Set_Color_ButtonMain_green(); } else { log_error("Тест не пройден, датчик не прошёл все проверки"); Set_Color_ButtonMain_red(); snprintf(LabelText, sizeof(LabelText), "Ошибка тестирования. Код: %u", error_code); Set_New_LableSensorPressure(LabelText); Update_Error_Table(error_code); } current_action = ACTION_WAIT_SENSOR_RELEASE; break; case ACTION_WAIT_SENSOR_RELEASE: log_trace("Состояние: ACTION_WAIT_SENSOR_RELEASE"); Set_New_ButtonMain_Label("Ожидание снятия датчика..."); // Здесь можно добавить логику ожидания снятия датчика break; default: log_warn("Обнаружено неизвестное состояние, возвращаемся к ACTION_WAIT_SENSOR"); current_action = ACTION_WAIT_SENSOR; break; } delay(30); // Задержка между циклами } return NULL; }