375 lines
18 KiB
C
375 lines
18 KiB
C
#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;
|
||
}
|