#include "SoilSensor.h" #include "string.h" extern UART_HandleTypeDef huart2; #define SOIL_SENSOR_CMD_LEN 8U #define SOIL_SENSOR_MAX_REG_COUNT 7U #define SOIL_SENSOR_MAX_DATA_LEN (SOIL_SENSOR_MAX_REG_COUNT * 2U) #define SOIL_SENSOR_MAX_RESP_LEN (3U + SOIL_SENSOR_MAX_DATA_LEN + 2U) #define SOIL_SENSOR_TX_TIMEOUT 500UL #define SOIL_SENSOR_RX_TIMEOUT 1000UL #define SOIL_SENSOR_TX_ENABLE_DELAY_MS 5UL #define SOIL_SENSOR_BETWEEN_DEVICE_DELAY_MS 1000UL #define SOIL_SENSOR_BAUDRATE 9600UL #define SHT_SENSOR_BAUDRATE 4800UL #define SOIL_NPK_SENSOR_ADDR 0x01U #define SOIL_ENV_SENSOR_ADDR 0x02U #define SHT_SENSOR_ADDR 0x03U #define SOIL_NPK_CHANGE_ID 0U #define SOIL_NPK_OLD_ADDRESS 0x03U #define SOIL_NPK_NEW_ADDRESS SOIL_NPK_SENSOR_ADDR #define SOIL_ENV_CHANGE_ID 0U #define SOIL_ENV_OLD_ADDRESS 0x01U #define SOIL_ENV_NEW_ADDRESS SOIL_ENV_SENSOR_ADDR #define SHT_SENSOR_CHANGE_ID 0U #define SHT_SENSOR_OLD_ADDRESS 0x01U #define SHT_SENSOR_NEW_ADDRESS SHT_SENSOR_ADDR #define SOIL_ID_SCAN_FIRST_ADDRESS 0x01U #define SOIL_ID_SCAN_LAST_ADDRESS 0x0AU #if ((SOIL_NPK_CHANGE_ID + SOIL_ENV_CHANGE_ID + SHT_SENSOR_CHANGE_ID) > 1U) #error "Enable only one sensor ID change at a time" #endif #define SOIL_REG_DEVICE_ADDRESS 0x07D0U #define SHT_REG_DEVICE_ADDRESS 0x07D0U #define SOIL_REG_HUMIDITY 0x0000U #define SOIL_REG_TEMPERATURE 0x0001U #define SOIL_REG_PH 0x0003U #define SOIL_REG_NITROGEN 0x001EU #define SOIL_REG_PHOSPHORUS 0x001FU #define SOIL_REG_POTASSIUM 0x0020U #define SHT_REG_HUMIDITY 0x0000U #define SHT_REG_TEMPERATURE 0x0001U volatile uint8_t soil_last_status = 0; volatile uint8_t soil_last_rx_len = 0; volatile uint8_t soil_last_response[SOIL_SENSOR_RAW_MAX_LEN]; volatile uint8_t soil_last_command = 0; volatile uint8_t soil_last_hal_error = 0; volatile uint16_t soil_last_value = 0U; volatile uint8_t soil_env_humidity_status = 0; volatile uint8_t soil_env_temperature_status = 0; volatile uint8_t soil_env_ph_status = 0; volatile uint8_t soil_npk_status = 0; volatile uint8_t soil_sht_status = 0; volatile uint8_t soil_npk_debug_command = 0; volatile uint8_t soil_npk_debug_rx_len = 0; volatile uint8_t soil_npk_debug_data_hi = 0; volatile uint8_t soil_npk_debug_data_lo = 0; volatile uint8_t soil_npk_debug_source = 0; volatile uint8_t soil_npk_debug_low_status = 0; volatile uint8_t soil_npk_debug_n_status = 0; volatile uint8_t soil_npk_debug_p_status = 0; volatile uint8_t soil_npk_debug_k_status = 0; volatile uint16_t soil_dma_rx_remaining = 0U; volatile HAL_StatusTypeDef soil_tx_ret = HAL_OK; volatile HAL_StatusTypeDef soil_rx_ret = HAL_OK; volatile uint8_t soil_scan_done = 0U; volatile uint32_t soil_scan_active_baud = 0U; volatile uint8_t soil_scan_current_address = 0U; volatile uint8_t soil_scan_9600_count = 0U; volatile uint8_t soil_scan_4800_count = 0U; volatile uint8_t soil_scan_9600_addresses[SOIL_SENSOR_SCAN_RESULT_MAX] = {0}; volatile uint8_t soil_scan_4800_addresses[SOIL_SENSOR_SCAN_RESULT_MAX] = {0}; volatile uint16_t soil_scan_9600_values[SOIL_SENSOR_SCAN_RESULT_MAX] = {0}; volatile uint16_t soil_scan_4800_values[SOIL_SENSOR_SCAN_RESULT_MAX] = {0}; volatile uint8_t soil_id_change_sensor = 0U; volatile uint8_t soil_id_change_status = 0xFFU; volatile uint8_t soil_id_change_old_address = 0U; volatile uint8_t soil_id_change_new_address = 0U; static uint8_t SoilSensor_ReadBlock(uint8_t address, uint16_t reg, uint8_t count, uint8_t commandIndex, uint8_t *response); static uint8_t SoilSensor_ChangeAddressRegister(uint8_t oldAddress, uint8_t newAddress, uint16_t addressReg); static void SoilSensor_TxMode(void) { HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(RS485_RE_GPIO_Port, RS485_RE_Pin, GPIO_PIN_SET); } static void SoilSensor_RxMode(void) { HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(RS485_RE_GPIO_Port, RS485_RE_Pin, GPIO_PIN_RESET); } static void SoilSensor_ClearRx(void) { uint8_t dummy; __HAL_UART_CLEAR_PEFLAG(&huart2); __HAL_UART_CLEAR_FEFLAG(&huart2); __HAL_UART_CLEAR_NEFLAG(&huart2); __HAL_UART_CLEAR_OREFLAG(&huart2); while (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) != RESET) { dummy = (uint8_t)(huart2.Instance->DR & 0xFF); (void)dummy; } } static uint8_t SoilSensor_SetBaudRate(uint32_t baudRate) { if (huart2.Init.BaudRate == baudRate) { return 0U; } SoilSensor_RxMode(); (void)HAL_UART_Abort(&huart2); if (HAL_UART_DeInit(&huart2) != HAL_OK) { return SOIL_SENSOR_STATUS_UART_ERROR; } huart2.Init.BaudRate = baudRate; if (HAL_UART_Init(&huart2) != HAL_OK) { return SOIL_SENSOR_STATUS_UART_ERROR; } SoilSensor_RxMode(); SoilSensor_ClearRx(); HAL_Delay(10U); return 0U; } static uint16_t SoilSensor_Crc16(const uint8_t *data, uint8_t len) { uint16_t crc = 0xFFFFU; for (uint8_t i = 0U; i < len; i++) { crc ^= data[i]; for (uint8_t j = 0U; j < 8U; j++) { if ((crc & 0x0001U) != 0U) { crc = (uint16_t)((crc >> 1U) ^ 0xA001U); } else { crc >>= 1U; } } } return crc; } static void SoilSensor_BuildReadCommand(uint8_t address, uint16_t reg, uint16_t count, uint8_t *cmd) { uint16_t crc; cmd[0] = address; cmd[1] = 0x03U; cmd[2] = (uint8_t)(reg >> 8); cmd[3] = (uint8_t)(reg & 0xFFU); cmd[4] = (uint8_t)(count >> 8); cmd[5] = (uint8_t)(count & 0xFFU); crc = SoilSensor_Crc16(cmd, 6U); cmd[6] = (uint8_t)(crc & 0xFFU); cmd[7] = (uint8_t)(crc >> 8); } static void SoilSensor_BuildWriteRegisterCommand(uint8_t address, uint16_t reg, uint16_t value, uint8_t *cmd) { uint16_t crc; cmd[0] = address; cmd[1] = 0x06U; cmd[2] = (uint8_t)(reg >> 8); cmd[3] = (uint8_t)(reg & 0xFFU); cmd[4] = (uint8_t)(value >> 8); cmd[5] = (uint8_t)(value & 0xFFU); crc = SoilSensor_Crc16(cmd, 6U); cmd[6] = (uint8_t)(crc & 0xFFU); cmd[7] = (uint8_t)(crc >> 8); } void SoilSensor_Init(void) { SoilSensor_RxMode(); SoilSensor_ClearRx(); HAL_Delay(500); } static uint8_t SoilSensor_ReadResponse(uint8_t *response, uint8_t expectedLen) { uint32_t startTick = HAL_GetTick(); uint8_t index = 0U; while ((HAL_GetTick() - startTick) < SOIL_SENSOR_RX_TIMEOUT) { if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) == RESET) { continue; } response[index] = (uint8_t)(huart2.Instance->DR & 0xFF); index++; soil_last_rx_len = index; if (index >= expectedLen) { break; } } if (index >= expectedLen) { soil_rx_ret = HAL_OK; return 1U; } soil_rx_ret = HAL_TIMEOUT; return 0U; } static uint8_t SoilSensor_FindValidFrame(uint8_t address, uint8_t expectedDataLen, uint8_t *buffer, uint8_t len, uint8_t *frame) { uint8_t expectedLen = (uint8_t)(3U + expectedDataLen + 2U); if (len < expectedLen) { return 0U; } for (uint8_t start = 0U; start <= (uint8_t)(len - expectedLen); start++) { uint16_t responseCrc; uint16_t calculatedCrc; if ((buffer[start] != address) || (buffer[start + 1U] != 0x03U) || (buffer[start + 2U] != expectedDataLen)) { continue; } responseCrc = ((uint16_t)buffer[start + expectedLen - 1U] << 8) | buffer[start + expectedLen - 2U]; calculatedCrc = SoilSensor_Crc16(&buffer[start], (uint8_t)(expectedLen - 2U)); if (responseCrc != calculatedCrc) { continue; } memcpy(frame, &buffer[start], expectedLen); return 1U; } return 0U; } static uint16_t SoilSensor_ReadWord(const uint8_t *response, uint8_t index) { uint8_t offset = (uint8_t)(3U + (index * 2U)); return ((uint16_t)response[offset] << 8) | response[offset + 1U]; } static void SoilSensor_DelayMs(uint32_t delayMs) { uint32_t tick = HAL_GetTick(); while ((HAL_GetTick() - tick) < delayMs) { } } static uint8_t SoilSensor_ReadRegisterValue(uint8_t address, uint8_t commandIndex, uint16_t reg, uint16_t *value) { uint8_t response[SOIL_SENSOR_MAX_RESP_LEN] = {0}; uint8_t status = SoilSensor_ReadBlock(address, reg, 1U, commandIndex, response); if (status != 0U) { return status; } *value = SoilSensor_ReadWord(response, 0U); return 0U; } uint8_t SoilSensor_ChangeAddress(uint8_t oldAddress, uint8_t newAddress) { return SoilSensor_ChangeAddressRegister(oldAddress, newAddress, SOIL_REG_DEVICE_ADDRESS); } void SoilSensor_ScanAddresses(void) { uint16_t value; soil_scan_done = 0U; soil_scan_active_baud = 0U; soil_scan_current_address = 0U; soil_scan_9600_count = 0U; soil_scan_4800_count = 0U; memset((void *)soil_scan_9600_addresses, 0, sizeof(soil_scan_9600_addresses)); memset((void *)soil_scan_4800_addresses, 0, sizeof(soil_scan_4800_addresses)); memset((void *)soil_scan_9600_values, 0, sizeof(soil_scan_9600_values)); memset((void *)soil_scan_4800_values, 0, sizeof(soil_scan_4800_values)); soil_scan_active_baud = SOIL_SENSOR_BAUDRATE; if (SoilSensor_SetBaudRate(SOIL_SENSOR_BAUDRATE) == 0U) { for (uint8_t address = SOIL_ID_SCAN_FIRST_ADDRESS; address <= SOIL_ID_SCAN_LAST_ADDRESS; address++) { soil_scan_current_address = address; if (SoilSensor_ReadRegisterValue(address, 60U, SOIL_REG_DEVICE_ADDRESS, &value) == 0U) { uint8_t index = soil_scan_9600_count; if (index < SOIL_SENSOR_SCAN_RESULT_MAX) { soil_scan_9600_addresses[index] = address; soil_scan_9600_values[index] = value; soil_scan_9600_count = (uint8_t)(index + 1U); } } HAL_Delay(50U); } } soil_scan_active_baud = SHT_SENSOR_BAUDRATE; if (SoilSensor_SetBaudRate(SHT_SENSOR_BAUDRATE) == 0U) { for (uint8_t address = SOIL_ID_SCAN_FIRST_ADDRESS; address <= SOIL_ID_SCAN_LAST_ADDRESS; address++) { soil_scan_current_address = address; if (SoilSensor_ReadRegisterValue(address, 61U, SHT_REG_DEVICE_ADDRESS, &value) == 0U) { uint8_t index = soil_scan_4800_count; if (index < SOIL_SENSOR_SCAN_RESULT_MAX) { soil_scan_4800_addresses[index] = address; soil_scan_4800_values[index] = value; soil_scan_4800_count = (uint8_t)(index + 1U); } } HAL_Delay(50U); } } soil_scan_current_address = 0U; soil_scan_active_baud = 0U; soil_scan_done = 1U; } void SoilSensor_RunIdTool(void) { soil_id_change_sensor = 0U; soil_id_change_status = 0xFFU; soil_id_change_old_address = 0U; soil_id_change_new_address = 0U; #if (SOIL_NPK_CHANGE_ID != 0U) soil_id_change_sensor = 1U; soil_id_change_old_address = SOIL_NPK_OLD_ADDRESS; soil_id_change_new_address = SOIL_NPK_NEW_ADDRESS; soil_id_change_status = SoilSensor_SetBaudRate(SOIL_SENSOR_BAUDRATE); if (soil_id_change_status == 0U) { soil_id_change_status = SoilSensor_ChangeAddressRegister(SOIL_NPK_OLD_ADDRESS, SOIL_NPK_NEW_ADDRESS, SOIL_REG_DEVICE_ADDRESS); } #elif (SOIL_ENV_CHANGE_ID != 0U) soil_id_change_sensor = 2U; soil_id_change_old_address = SOIL_ENV_OLD_ADDRESS; soil_id_change_new_address = SOIL_ENV_NEW_ADDRESS; soil_id_change_status = SoilSensor_SetBaudRate(SOIL_SENSOR_BAUDRATE); if (soil_id_change_status == 0U) { soil_id_change_status = SoilSensor_ChangeAddressRegister(SOIL_ENV_OLD_ADDRESS, SOIL_ENV_NEW_ADDRESS, SOIL_REG_DEVICE_ADDRESS); } #elif (SHT_SENSOR_CHANGE_ID != 0U) soil_id_change_sensor = 3U; soil_id_change_old_address = SHT_SENSOR_OLD_ADDRESS; soil_id_change_new_address = SHT_SENSOR_NEW_ADDRESS; soil_id_change_status = SoilSensor_SetBaudRate(SHT_SENSOR_BAUDRATE); if (soil_id_change_status == 0U) { soil_id_change_status = SoilSensor_ChangeAddressRegister(SHT_SENSOR_OLD_ADDRESS, SHT_SENSOR_NEW_ADDRESS, SHT_REG_DEVICE_ADDRESS); } #endif HAL_Delay(500U); SoilSensor_ScanAddresses(); } static uint8_t SoilSensor_ChangeAddressRegister(uint8_t oldAddress, uint8_t newAddress, uint16_t addressReg) { uint8_t cmd[SOIL_SENSOR_CMD_LEN] = {0}; uint8_t response[SOIL_SENSOR_CMD_LEN] = {0}; uint16_t responseCrc; uint16_t calculatedCrc; if ((oldAddress == 0U) || (newAddress == 0U)) { return SOIL_SENSOR_STATUS_FRAME_ERROR; } soil_tx_ret = HAL_OK; soil_rx_ret = HAL_OK; soil_last_status = 0U; soil_last_rx_len = 0U; soil_last_command = 100U; soil_last_hal_error = 0U; soil_last_value = newAddress; memset((void *)soil_last_response, 0, sizeof(soil_last_response)); SoilSensor_ClearRx(); SoilSensor_BuildWriteRegisterCommand(oldAddress, addressReg, newAddress, cmd); SoilSensor_TxMode(); SoilSensor_DelayMs(SOIL_SENSOR_TX_ENABLE_DELAY_MS); soil_tx_ret = HAL_UART_Transmit(&huart2, cmd, SOIL_SENSOR_CMD_LEN, SOIL_SENSOR_TX_TIMEOUT); if (soil_tx_ret != HAL_OK) { soil_last_status = SOIL_SENSOR_STATUS_UART_ERROR; soil_last_hal_error = (uint8_t)HAL_UART_GetError(&huart2); SoilSensor_RxMode(); return soil_last_status; } while (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) == RESET) { } SoilSensor_RxMode(); if (SoilSensor_ReadResponse(response, SOIL_SENSOR_CMD_LEN) == 0U) { soil_last_status = SOIL_SENSOR_STATUS_UART_ERROR; soil_last_hal_error = (uint8_t)HAL_UART_GetError(&huart2); return soil_last_status; } memcpy((void *)soil_last_response, response, SOIL_SENSOR_CMD_LEN); responseCrc = ((uint16_t)response[7] << 8) | response[6]; calculatedCrc = SoilSensor_Crc16(response, 6U); if ((response[0] != oldAddress) || (response[1] != 0x06U) || (response[2] != (uint8_t)(addressReg >> 8)) || (response[3] != (uint8_t)(addressReg & 0xFFU)) || (response[4] != 0x00U) || (response[5] != newAddress) || (responseCrc != calculatedCrc)) { soil_last_status = SOIL_SENSOR_STATUS_FRAME_ERROR; return soil_last_status; } soil_last_status = 0U; return 0U; } static uint8_t SoilSensor_ReadBlock(uint8_t address, uint16_t reg, uint8_t count, uint8_t commandIndex, uint8_t *response) { uint8_t cmd[SOIL_SENSOR_CMD_LEN] = {0}; uint8_t rawResponse[SOIL_SENSOR_RAW_MAX_LEN] = {0}; uint8_t expectedDataLen = (uint8_t)(count * 2U); uint8_t expectedRespLen = (uint8_t)(3U + expectedDataLen + 2U); uint16_t responseCrc; uint16_t calculatedCrc; if ((count == 0U) || (count > SOIL_SENSOR_MAX_REG_COUNT)) { soil_last_status = SOIL_SENSOR_STATUS_FRAME_ERROR; return soil_last_status; } soil_tx_ret = HAL_OK; soil_rx_ret = HAL_OK; soil_last_status = 0; soil_last_rx_len = 0; soil_last_command = commandIndex; soil_last_hal_error = 0; soil_last_value = 0U; soil_dma_rx_remaining = 0U; memset((void *)soil_last_response, 0, sizeof(soil_last_response)); SoilSensor_ClearRx(); SoilSensor_BuildReadCommand(address, reg, count, cmd); SoilSensor_TxMode(); SoilSensor_DelayMs(SOIL_SENSOR_TX_ENABLE_DELAY_MS); soil_tx_ret = HAL_UART_Transmit(&huart2, cmd, SOIL_SENSOR_CMD_LEN, SOIL_SENSOR_TX_TIMEOUT); if (soil_tx_ret != HAL_OK) { soil_last_status = SOIL_SENSOR_STATUS_UART_ERROR; soil_last_hal_error = (uint8_t)HAL_UART_GetError(&huart2); SoilSensor_RxMode(); return soil_last_status; } while (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) == RESET) { } SoilSensor_RxMode(); if (SoilSensor_ReadResponse(rawResponse, expectedRespLen) == 0U) { soil_last_status = SOIL_SENSOR_STATUS_UART_ERROR; soil_last_hal_error = (uint8_t)HAL_UART_GetError(&huart2); return soil_last_status; } memcpy((void *)soil_last_response, rawResponse, expectedRespLen); if (SoilSensor_FindValidFrame(address, expectedDataLen, rawResponse, soil_last_rx_len, response) == 0U) { soil_last_status = SOIL_SENSOR_STATUS_FRAME_ERROR; return soil_last_status; } if ((response[0] != address) || (response[1] != 0x03U) || (response[2] != expectedDataLen)) { soil_last_status = SOIL_SENSOR_STATUS_FRAME_ERROR; return soil_last_status; } responseCrc = ((uint16_t)response[expectedRespLen - 1U] << 8) | response[expectedRespLen - 2U]; calculatedCrc = SoilSensor_Crc16(response, (uint8_t)(expectedRespLen - 2U)); if (responseCrc != calculatedCrc) { soil_last_status = SOIL_SENSOR_STATUS_CRC_ERROR; return soil_last_status; } soil_last_value = SoilSensor_ReadWord(response, 0U); soil_last_status = 0; return 0; } uint8_t SoilSensor_Read(SoilNpkData_t *data) { uint16_t temperatureRaw = 0U; uint16_t shtTemperatureRaw = 0U; uint8_t shtResponse[SOIL_SENSOR_MAX_RESP_LEN] = {0}; uint8_t npkResponse[SOIL_SENSOR_MAX_RESP_LEN] = {0}; uint8_t finalStatus = 0U; memset(data, 0, sizeof(*data)); soil_env_humidity_status = 0U; soil_env_temperature_status = 0U; soil_env_ph_status = 0U; soil_npk_status = 0U; soil_sht_status = 0U; soil_npk_debug_source = 0U; soil_npk_debug_low_status = 0U; soil_npk_debug_n_status = 0U; soil_npk_debug_p_status = 0U; soil_npk_debug_k_status = 0U; if (SoilSensor_SetBaudRate(SOIL_SENSOR_BAUDRATE) != 0U) { soil_last_status = SOIL_SENSOR_STATUS_UART_ERROR; return soil_last_status; } soil_npk_status = SoilSensor_ReadBlock(SOIL_NPK_SENSOR_ADDR, SOIL_REG_NITROGEN, 3U, 30U, npkResponse); soil_npk_debug_source = 30U; soil_npk_debug_low_status = soil_npk_status; if (soil_npk_status != 0U) { finalStatus |= (uint8_t)(SOIL_SENSOR_STATUS_NPK_ERROR | soil_npk_status); } else { data->nitrogen = SoilSensor_ReadWord(npkResponse, 0U); data->phosphorus = SoilSensor_ReadWord(npkResponse, 1U); data->potassium = SoilSensor_ReadWord(npkResponse, 2U); } SoilSensor_DelayMs(SOIL_SENSOR_BETWEEN_DEVICE_DELAY_MS); soil_env_humidity_status = SoilSensor_ReadRegisterValue(SOIL_ENV_SENSOR_ADDR, 1U, SOIL_REG_HUMIDITY, &data->humidity); if (soil_env_humidity_status != 0U) { finalStatus |= (uint8_t)(SOIL_SENSOR_STATUS_ENV_ERROR | soil_env_humidity_status); } SoilSensor_DelayMs(SOIL_SENSOR_BETWEEN_DEVICE_DELAY_MS); soil_env_temperature_status = SoilSensor_ReadRegisterValue(SOIL_ENV_SENSOR_ADDR, 2U, SOIL_REG_TEMPERATURE, &temperatureRaw); if (soil_env_temperature_status != 0U) { finalStatus |= (uint8_t)(SOIL_SENSOR_STATUS_ENV_ERROR | soil_env_temperature_status); } else { data->temperature = (int16_t)temperatureRaw; } SoilSensor_DelayMs(SOIL_SENSOR_BETWEEN_DEVICE_DELAY_MS); soil_env_ph_status = SoilSensor_ReadRegisterValue(SOIL_ENV_SENSOR_ADDR, 3U, SOIL_REG_PH, &data->ph); if (soil_env_ph_status != 0U) { finalStatus |= (uint8_t)(SOIL_SENSOR_STATUS_ENV_ERROR | soil_env_ph_status); } SoilSensor_DelayMs(SOIL_SENSOR_BETWEEN_DEVICE_DELAY_MS); if (SoilSensor_SetBaudRate(SHT_SENSOR_BAUDRATE) != 0U) { soil_sht_status = SOIL_SENSOR_STATUS_UART_ERROR; finalStatus |= (uint8_t)(SOIL_SENSOR_STATUS_SHT_ERROR | soil_sht_status); soil_last_status = finalStatus; return finalStatus; } soil_sht_status = SoilSensor_ReadBlock(SHT_SENSOR_ADDR, SHT_REG_HUMIDITY, 2U, 40U, shtResponse); if (soil_sht_status != 0U) { finalStatus |= (uint8_t)(SOIL_SENSOR_STATUS_SHT_ERROR | soil_sht_status); } else { data->sht_humidity = SoilSensor_ReadWord(shtResponse, 0U); shtTemperatureRaw = SoilSensor_ReadWord(shtResponse, 1U); data->sht_temperature = (int16_t)shtTemperatureRaw; } soil_last_status = finalStatus; return finalStatus; }