Calibration_Stand/backend/Src/stend_logic.c

375 lines
18 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}