commit 406c9d8acca3b3c85844741148c819bab0c0f447
parent aa121b145f2ed4d312b927afcc02c14409203d8b
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Tue, 24 Mar 2026 01:38:06 -0300
Reducir errores de lectura de datos de DS18B20
La principal fuente de error es que el DMA es incapaz de leer
correctamente los datos que llegan del sensor entonces se bloquea, esto
ocurre principalmente ante cambios en la temperatura y aleatoriamente.
Reduciendo la tasa de transmisión/recepción de datos del sensor DS18B20
de 115200 a 96500 se redujo notablemente la cantidad de errores. Esto
puede deberse a que los bits de inicio y fin son más anchos (duran más
en el tiempo ya que la velocidad es menor).
Diffstat:
1 file changed, 81 insertions(+), 167 deletions(-)
diff --git a/firmware/app/src/ds18b20.c b/firmware/app/src/ds18b20.c
@@ -14,24 +14,25 @@
#include "task_menu_attribute.h"
#include "task_menu_interface.h"
-#define G_DS18B20_CONV_TIME_MS 100ul // ~188ms for 10 bit resolution
-#define G_DS18B20_DMA_TIMEOUT_MS 200ul
-#define G_DS18B20_BYTE_READ_DELAY_MS 10ul
-#define G_TEMP_PERIOD_MS 1000ul
+
+#define G_DS18B20_CONV_TIME_MS 100ul // ~188ms for 10 bit resolution
+#define G_TEMP_PERIOD_MS 1000ul
+#define G_DATA_BAUDRATE 96500
// Private global variables
-volatile bool b_DS18B20_Received_data;
-static uint8_t g_DS18B20_Received_data_buffer[8];
const uint8_t g_buffer[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
DS18B20_st_t g_DS18B20_state, g_DS18B20_prev_state;
-uint32_t g_DS18B20_tick, g_DS18B20_tick_delay;
+uint32_t g_DS18B20_tick;
uint16_t g_DS18B20_temp;
-
uint8_t Temp_LSB, Temp_MSB;
static uint8_t g_DS18B20_TX_buffer[8];
-bool b_DS18B20_DMA_TX_done = false;
-bool b_DS18B20_DMA_RX_done = false;
+static uint8_t g_DS18B20_RX_buffer[8];
+bool b_DS18B20_DMA_TX_done, b_DS18B20_DMA_RX_done;
+static uint8_t l_DS18B20_DMA_error_count;
+
+const uint8_t g_DS18B20_Reset_data_tx = 0xF0;
+uint8_t g_DS18B20_Reset_data_rx = 0xF0;
// Public global variables
uint16_t g_DS18B20_update_count;
@@ -39,9 +40,10 @@ uint16_t g_DS18B20_DMA_error_count;
// Private functions declaration
void DS18B20_Write(uint8_t data);
+void DS18B20_Write_DMA(uint8_t data);
+void DS18B20_SetResolution(uint8_t resolution);
void DS18B20_Read_temp(void);
-uint8_t DS18B20_Read(void);
-uint8_t DS18B20_Reset(void);
+void DS18B20_Reset_DMA(void);
uint8_t DS18B20_Reset(void)
{
@@ -54,20 +56,17 @@ uint8_t DS18B20_Reset(void)
if ((HAL_UART_Receive(&huart1, &data, 1, 100) != HAL_OK) || (data == 0xF0))
{
- // initialization failed
+ // Initialization failed
LOGGER_ERROR("Couldn't read temperature sensor");
return 1;
}
__HAL_UART_DISABLE(&huart1);
- LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), 115200);
+ LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), G_DATA_BAUDRATE);
__HAL_UART_ENABLE(&huart1);
return 0;
}
-const uint8_t g_DS18B20_Reset_data_tx = 0xF0;
-uint8_t g_DS18B20_Reset_data_rx = 0xF0;
-
void DS18B20_Reset_DMA(void)
{
g_DS18B20_prev_state = g_DS18B20_state;
@@ -78,7 +77,7 @@ void DS18B20_Reset_DMA(void)
__HAL_UART_ENABLE(&huart1);
b_DS18B20_DMA_TX_done = b_DS18B20_DMA_RX_done = false;
- HAL_UART_Receive_DMA(&huart1, &g_DS18B20_Reset_data_rx, 1);
+ HAL_UARTEx_ReceiveToIdle_DMA(&huart1, &g_DS18B20_Reset_data_rx, 1);
HAL_UART_Transmit_DMA(&huart1, &g_DS18B20_Reset_data_tx, 1);
}
@@ -99,8 +98,8 @@ void DS18B20_SetResolution(uint8_t resolution)
DS18B20_Write(DS18B20_SKIP_ROM_CMD);
DS18B20_Write(DS18B20_WRITE_SCRATCHPAD_CMD);
- DS18B20_Write(0x00); // TH
- DS18B20_Write(0x00); // TL
+ DS18B20_Write(0x00); // Alarm TH byte
+ DS18B20_Write(0x00); // Alarm TL byte
DS18B20_Write(config);
DS18B20_Reset();
@@ -116,10 +115,9 @@ void DS18B20_Init(void)
}
DS18B20_SetResolution(9);
g_DS18B20_state = g_DS18B20_prev_state = ST_DS18B20_READY;
- g_DS18B20_tick = g_DS18B20_tick_delay = G_TEMP_PERIOD_MS;
+ g_DS18B20_tick = G_TEMP_PERIOD_MS;
g_DS18B20_update_count = 0;
g_DS18B20_DMA_error_count = 0;
-
Temp_LSB = Temp_MSB = 0xFF;
}
@@ -139,8 +137,7 @@ void DS18B20_Write(uint8_t data)
}
}
- // This is a blocking call and can wait at most 100ms
- // TODO: convert to non-blocking call using DMA
+ // Blocking call and can wait max 100ms
HAL_UART_Transmit(&huart1, buffer, 8, 100);
}
@@ -159,40 +156,16 @@ void DS18B20_Write_DMA(uint8_t data)
}
b_DS18B20_DMA_TX_done = false;
-
- // HAL_StatusTypeDef st = HAL_UART_Transmit_DMA(&huart1, g_DS18B20_TX_buffer, 8);
- // LOGGER_INFO("%d", st);
-
HAL_UART_Transmit_DMA(&huart1, g_DS18B20_TX_buffer, 8);
}
void DS18B20_Read_DMA(void)
{
- HAL_UART_DMAStop(&huart1);
- __HAL_UART_DISABLE(&huart1);
- __HAL_UART_CLEAR_PEFLAG(&huart1);
- __HAL_UART_CLEAR_FEFLAG(&huart1);
- __HAL_UART_CLEAR_NEFLAG(&huart1);
- __HAL_UART_CLEAR_OREFLAG(&huart1);
- __HAL_UART_ENABLE(&huart1);
- memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
-
+ memset(g_DS18B20_RX_buffer, 0, sizeof(g_DS18B20_RX_buffer));
b_DS18B20_DMA_RX_done = false;
- // HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
- HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+ HAL_UARTEx_ReceiveToIdle_DMA(&huart1, g_DS18B20_RX_buffer, 8);
}
-void DS18B20_Start_conv(void)
-{
- // Send start temp conversion command
- // the sensor needs 96ms to 750ms to complete temp conversion depending on
- // resolution
- DS18B20_Reset();
- DS18B20_Write(0xCC); // Send 'Skip ROM' command
- DS18B20_Write(0x44); // Send 'Convert T' command
-}
-
-static uint8_t l_DS18B20_DMA_error_count = 0;
void DS18B20_Update(void)
{
switch (g_DS18B20_state)
@@ -209,10 +182,11 @@ void DS18B20_Update(void)
}
break;
case ST_DS18B20_BUSY_SENDING_RESET:
+ // TODO: Check received value (presence byte)
if (true == b_DS18B20_DMA_TX_done)
{
__HAL_UART_DISABLE(&huart1);
- LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), 115200);
+ LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), G_DS18B20_DATA_BAUDRATE);
__HAL_UART_ENABLE(&huart1);
g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
DS18B20_Write_DMA(DS18B20_SKIP_ROM_CMD);
@@ -231,7 +205,6 @@ void DS18B20_Update(void)
case ST_DS18B20_BUSY_WAITING_CONV:
g_DS18B20_prev_state = g_DS18B20_state;
g_DS18B20_state = ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD;
- g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
DS18B20_Write_DMA(DS18B20_READ_SCRATCHPAD_CMD);
break;
default:
@@ -260,18 +233,12 @@ void DS18B20_Update(void)
break;
case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
- if (0 == g_DS18B20_tick)
+ if (true == b_DS18B20_DMA_TX_done)
{
- if (true == b_DS18B20_DMA_TX_done)
- {
- // Read sensor LSB of data
- DS18B20_Read_DMA();
- DS18B20_Write_DMA(0xFF);
-
- g_DS18B20_prev_state = ST_DS18B20_BUSY_WAITING_LSB;
- g_DS18B20_state = ST_DS18B20_BUSY_WAITING;
- g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
- }
+ // Read sensor LSB of data
+ DS18B20_Read_DMA();
+ DS18B20_Write_DMA(0xFF);
+ g_DS18B20_state = ST_DS18B20_BUSY_WAITING_LSB;
}
else
{
@@ -286,40 +253,42 @@ void DS18B20_Update(void)
uint8_t received_value = 0;
for (uint8_t i = 0; i < 8; ++i)
{
- if (g_DS18B20_Received_data_buffer[i] == 0xFF)
+ if (g_DS18B20_RX_buffer[i] == 0xFF)
{
received_value |= (1 << i);
}
}
-
Temp_LSB = received_value;
- g_DS18B20_prev_state = ST_DS18B20_BUSY_WAITING_MSB;
- g_DS18B20_state = ST_DS18B20_BUSY_WAITING;
- g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
+ g_DS18B20_state = ST_DS18B20_BUSY_WAITING_MSB;
DS18B20_Read_DMA();
DS18B20_Write_DMA(0xFF);
}
-
- if (0 == g_DS18B20_tick)
+ else if (0 == g_DS18B20_tick)
{
// Try again readying scratchpad
g_DS18B20_DMA_error_count++;
l_DS18B20_DMA_error_count++;
put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
- // Give up on reading temp for this update
- HAL_UART_DMAStop(&huart1);
- __HAL_UART_DISABLE(&huart1);
- __HAL_UART_CLEAR_PEFLAG(&huart1);
+ /*
+ HAL_UART_Abort(&huart1);
+ __HAL_DMA_ENABLE_IT(huart1.hdmarx, DMA_IT_TC);
+ __HAL_DMA_ENABLE_IT(huart1.hdmarx, DMA_IT_TE);
+ __HAL_DMA_ENABLE_IT(huart1.hdmatx, DMA_IT_TC);
+ __HAL_DMA_ENABLE_IT(huart1.hdmatx, DMA_IT_TE);
+ */
+
+ HAL_UART_AbortReceive(&huart1);
+ __HAL_UART_CLEAR_OREFLAG(&huart1);
__HAL_UART_CLEAR_FEFLAG(&huart1);
__HAL_UART_CLEAR_NEFLAG(&huart1);
- __HAL_UART_CLEAR_OREFLAG(&huart1);
- __HAL_UART_ENABLE(&huart1);
- memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
+ __HAL_UART_CLEAR_PEFLAG(&huart1);
+ __HAL_UART_CLEAR_IDLEFLAG(&huart1);
- g_DS18B20_state = ST_DS18B20_READY;
- g_DS18B20_tick = G_TEMP_PERIOD_MS;
+
+ g_DS18B20_prev_state = g_DS18B20_state;
+ g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
}
else
{
@@ -334,7 +303,7 @@ void DS18B20_Update(void)
uint8_t received_value = 0;
for (uint8_t i = 0; i < 8; ++i)
{
- if (g_DS18B20_Received_data_buffer[i] == 0xFF)
+ if (g_DS18B20_RX_buffer[i] == 0xFF)
{
received_value |= (1 << i);
}
@@ -347,38 +316,30 @@ void DS18B20_Update(void)
g_DS18B20_update_count++;
put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
}
-
- if (0 == g_DS18B20_tick)
+ else if (0 == g_DS18B20_tick)
{
// Try again readying scratchpad
g_DS18B20_DMA_error_count++;
l_DS18B20_DMA_error_count++;
put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
- // Start again converting temp
- HAL_UART_DMAStop(&huart1);
- __HAL_UART_DISABLE(&huart1);
- __HAL_UART_CLEAR_PEFLAG(&huart1);
+ /*
+ HAL_UART_Abort(&huart1);
+ __HAL_DMA_ENABLE_IT(huart1.hdmarx, DMA_IT_TC);
+ __HAL_DMA_ENABLE_IT(huart1.hdmarx, DMA_IT_TE);
+ __HAL_DMA_ENABLE_IT(huart1.hdmatx, DMA_IT_TC);
+ __HAL_DMA_ENABLE_IT(huart1.hdmatx, DMA_IT_TE);
+ */
+
+ HAL_UART_AbortReceive(&huart1);
+ __HAL_UART_CLEAR_OREFLAG(&huart1);
__HAL_UART_CLEAR_FEFLAG(&huart1);
__HAL_UART_CLEAR_NEFLAG(&huart1);
- __HAL_UART_CLEAR_OREFLAG(&huart1);
- __HAL_UART_ENABLE(&huart1);
- memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
-
- g_DS18B20_state = ST_DS18B20_READY;
- g_DS18B20_tick = G_TEMP_PERIOD_MS;
- }
- else
- {
- g_DS18B20_tick--;
- }
- break;
+ __HAL_UART_CLEAR_PEFLAG(&huart1);
+ __HAL_UART_CLEAR_IDLEFLAG(&huart1);
- case ST_DS18B20_BUSY_WAITING:
- if (0 == g_DS18B20_tick)
- {
- g_DS18B20_state = g_DS18B20_prev_state;
- g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
+ g_DS18B20_prev_state = g_DS18B20_state;
+ g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
}
else
{
@@ -386,75 +347,20 @@ void DS18B20_Update(void)
}
break;
-
case ST_DS18B20_BUSY_WAITING_DMA:
- /*
- if (true == b_DS18B20_DMA_RX_done)
- {
- // Process received byte
- uint8_t received_value = 0;
- for (uint8_t i = 0; i < 8; ++i)
- {
- if (g_DS18B20_Received_data_buffer[i] == 0xFF)
- {
- received_value |= (1 << i);
- }
- }
-
- Temp_MSB = received_value;
- g_DS18B20_temp = ((Temp_MSB << 8) | Temp_LSB) / 16;
- g_DS18B20_state = ST_DS18B20_READY;
- g_DS18B20_tick = G_TEMP_PERIOD_MS;
- g_DS18B20_update_count++;
- put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
- }
- */
- if (0 == g_DS18B20_tick_delay)
+ if ((huart1.hdmarx->State == HAL_DMA_STATE_READY) &&
+ (huart1.RxState == HAL_UART_STATE_READY))
{
- g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
- DS18B20_Read_DMA();
- DS18B20_Write_DMA(0xFF);
- }
- else
- {
- g_DS18B20_tick_delay--;
- }
-
- if (0 == g_DS18B20_tick) // Error handling
- {
- if (1 > l_DS18B20_DMA_error_count)
- {
- // Try again readying scratchpad
- g_DS18B20_DMA_error_count++;
- l_DS18B20_DMA_error_count++;
- put_event_task_menu(EV_MEN_DISPLAY_UPDATE);
-
- g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
- DS18B20_Read_DMA();
- DS18B20_Write_DMA(0xFF);
-
- // g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
- }
- else
+ switch (g_DS18B20_prev_state)
{
- // Give up on reading temp for this update
- HAL_UART_DMAStop(&huart1);
- __HAL_UART_DISABLE(&huart1);
- __HAL_UART_CLEAR_PEFLAG(&huart1);
- __HAL_UART_CLEAR_FEFLAG(&huart1);
- __HAL_UART_CLEAR_NEFLAG(&huart1);
- __HAL_UART_CLEAR_OREFLAG(&huart1);
- __HAL_UART_ENABLE(&huart1);
- memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
- g_DS18B20_state = ST_DS18B20_READY;
- g_DS18B20_tick = G_TEMP_PERIOD_MS;
+ case ST_DS18B20_BUSY_WAITING_LSB:
+ case ST_DS18B20_BUSY_WAITING_MSB:
+ g_DS18B20_state = ST_DS18B20_READY;
+ g_DS18B20_tick = G_TEMP_PERIOD_MS;
+ break;
+ default: break;
}
}
- else
- {
- g_DS18B20_tick--;
- }
-
break;
default: break;
@@ -484,3 +390,11 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
b_DS18B20_DMA_RX_done = true;
}
}
+
+void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+ if(huart->Instance == USART1)
+ {
+ ;
+ }
+}