tdse-tf_3-02

Controlador PID para derretidor de miel con control local via botones y remoto via WiFi
Index Commits Files Refs Submodules README
commit aa121b145f2ed4d312b927afcc02c14409203d8b
parent ebcaec6086118627e36090fb482b5c0546d7ed7f
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Mon, 23 Mar 2026 14:02:10 -0300

Mejorar lectura de datos de DS18B20

Usar funcion `HAL_UARTEx_ReceiveToIdle_DMA` en lugar de
`HAL_UART_Receive_DMA`, esto permite que el DMA detecte si la linea esta
en IDLE y de por termianda la tranmision evitando errores de lectura en
los cuales el DMA se queda esperando indefinidamente.

Diffstat:
Mfirmware/app/inc/ds18b20.h | 10+++++++++-
Mfirmware/app/src/ds18b20.c | 330+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 241 insertions(+), 99 deletions(-)
diff --git a/firmware/app/inc/ds18b20.h b/firmware/app/inc/ds18b20.h
@@ -49,6 +49,12 @@ extern "C" {
  *
  */
 
+#define DS18B20_SKIP_ROM_CMD                   0xCC
+#define DS18B20_CONVERT_T_CMD                  0x44
+#define DS18B20_READ_SCRATCHPAD_CMD            0xBE
+#define DS18B20_WRITE_SCRATCHPAD_CMD           0x4E
+#define DS18B20_WRITE_SCRATCHPAD_TO_EEPROM_CMD 0x48
+
 typedef enum {
     ST_DS18B20_READY,
     ST_DS18B20_BUSY_SENDING_RESET,
@@ -56,10 +62,12 @@ typedef enum {
     ST_DS18B20_BUSY_SENDING_CONV_T,
     ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD,
     ST_DS18B20_BUSY_WAITING_CONV,
+    ST_DS18B20_BUSY_WAITING_LSB,
+    ST_DS18B20_BUSY_WAITING_MSB,
+    ST_DS18B20_BUSY_WAITING,
     ST_DS18B20_BUSY_WAITING_DMA
 } DS18B20_st_t;
 
-
 void DS18B20_Init(void);
 void DS18B20_Update(void);
 
diff --git a/firmware/app/src/ds18b20.c b/firmware/app/src/ds18b20.c
@@ -14,22 +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 10ul
-#define G_TEMP_PERIOD_MS         1000ul
+#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
 
 // 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};
-static bool b_DS18B20_Received_data_LSB;
 DS18B20_st_t g_DS18B20_state, g_DS18B20_prev_state;
-uint32_t g_DS18B20_tick;
+uint32_t g_DS18B20_tick, g_DS18B20_tick_delay;
 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;
+
 // Public global variables
 uint16_t g_DS18B20_update_count;
 uint16_t g_DS18B20_DMA_error_count;
@@ -62,6 +65,23 @@ uint8_t DS18B20_Reset(void)
     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;
+    g_DS18B20_state = ST_DS18B20_BUSY_SENDING_RESET;
+
+    __HAL_UART_DISABLE(&huart1);
+    LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), 9600);
+    __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_UART_Transmit_DMA(&huart1, &g_DS18B20_Reset_data_tx, 1);
+}
+
 void DS18B20_SetResolution(uint8_t resolution)
 {
     uint8_t config;
@@ -76,16 +96,16 @@ void DS18B20_SetResolution(uint8_t resolution)
     }
 
     DS18B20_Reset();
-    DS18B20_Write(0xCC); // Send 'Skip ROM' command
-    DS18B20_Write(0x4E); // Send 'write scratchpad' command
+    DS18B20_Write(DS18B20_SKIP_ROM_CMD);
+    DS18B20_Write(DS18B20_WRITE_SCRATCHPAD_CMD);
 
     DS18B20_Write(0x00); // TH
     DS18B20_Write(0x00); // TL
     DS18B20_Write(config);
 
     DS18B20_Reset();
-    DS18B20_Write(0xCC); // Skip ROM
-    DS18B20_Write(0x48); // Write scratchpad to EEPROM
+    DS18B20_Write(DS18B20_SKIP_ROM_CMD);
+    DS18B20_Write(DS18B20_WRITE_SCRATCHPAD_TO_EEPROM_CMD);
 }
 
 void DS18B20_Init(void)
@@ -96,7 +116,7 @@ void DS18B20_Init(void)
     }
     DS18B20_SetResolution(9);
     g_DS18B20_state = g_DS18B20_prev_state = ST_DS18B20_READY;
-    g_DS18B20_tick = G_TEMP_PERIOD_MS;
+    g_DS18B20_tick = g_DS18B20_tick_delay = G_TEMP_PERIOD_MS;
     g_DS18B20_update_count = 0;
     g_DS18B20_DMA_error_count = 0;
 
@@ -124,9 +144,6 @@ void DS18B20_Write(uint8_t data)
     HAL_UART_Transmit(&huart1, buffer, 8, 100);
 }
 
-uint8_t g_DS18B20_TX_buffer[8];
-bool b_DS18B20_DMA_done = false;
-
 void DS18B20_Write_DMA(uint8_t data)
 {
     for (uint8_t i = 0; i < 8; ++i)
@@ -141,10 +158,29 @@ void DS18B20_Write_DMA(uint8_t data)
         }
     }
 
-    b_DS18B20_DMA_done = false;
+    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));
+
+    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);
+}
 
 void DS18B20_Start_conv(void)
 {
@@ -164,41 +200,48 @@ void DS18B20_Update(void)
         case ST_DS18B20_READY:
             if (0 == g_DS18B20_tick)
             {
-                // DS18B20_Start_conv();
-                g_DS18B20_prev_state = g_DS18B20_state;
-                g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
                 l_DS18B20_DMA_error_count = 0;
-                DS18B20_Reset(); // Blocking ~500us
-                DS18B20_Write_DMA(0xCC); // Send 'Skip ROM' command
+                DS18B20_Reset_DMA();
             }
             else
             {
                 g_DS18B20_tick--;
             }
             break;
+        case ST_DS18B20_BUSY_SENDING_RESET:
+            if (true == b_DS18B20_DMA_TX_done)
+            {
+                __HAL_UART_DISABLE(&huart1);
+                LL_USART_SetBaudRate(USART1, HAL_RCC_GetPCLK2Freq(), 115200);
+                __HAL_UART_ENABLE(&huart1);
+                g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
+                DS18B20_Write_DMA(DS18B20_SKIP_ROM_CMD);
+            }
+            break;
         case ST_DS18B20_BUSY_SENDING_SKIP_ROM:
-            if (true == b_DS18B20_DMA_done)
+            if (true == b_DS18B20_DMA_TX_done)
             {
                 switch (g_DS18B20_prev_state)
                 {
                     case ST_DS18B20_READY:
                         g_DS18B20_prev_state = g_DS18B20_state;
                         g_DS18B20_state = ST_DS18B20_BUSY_SENDING_CONV_T;
-                        DS18B20_Write_DMA(0x44); // Send 'Convert T' command
-                        break;
+                        DS18B20_Write_DMA(DS18B20_CONVERT_T_CMD);
+                    break;
                     case ST_DS18B20_BUSY_WAITING_CONV:
                         g_DS18B20_prev_state = g_DS18B20_state;
                         g_DS18B20_state = ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD;
-                        DS18B20_Write_DMA(0xBE); // Send 'read scratchpad' command
-                        break;
+                        g_DS18B20_tick = G_DS18B20_BYTE_READ_DELAY_MS;
+                        DS18B20_Write_DMA(DS18B20_READ_SCRATCHPAD_CMD);
+                    break;
                     default: 
                         g_DS18B20_state = ST_DS18B20_READY;
-                        break;
+                    break;
                 }
             }
             break;
         case ST_DS18B20_BUSY_SENDING_CONV_T:
-            if (true == b_DS18B20_DMA_done)
+            if (true == b_DS18B20_DMA_TX_done)
             {
                 g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
                 g_DS18B20_tick = G_DS18B20_CONV_TIME_MS;
@@ -207,48 +250,148 @@ void DS18B20_Update(void)
         case ST_DS18B20_BUSY_WAITING_CONV:
             if (0 == g_DS18B20_tick)
             {
-                DS18B20_Reset();
-                DS18B20_Write_DMA(0xCC); // Send 'Skip ROM' command
+                // Start reading sensor data
+                DS18B20_Reset_DMA();
+            }
+            else
+            {
+                g_DS18B20_tick--;
+            }
+            break;
 
-                g_DS18B20_prev_state = g_DS18B20_state;
-                g_DS18B20_state = ST_DS18B20_BUSY_SENDING_SKIP_ROM;
+        case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
+            if (0 == g_DS18B20_tick)
+            {
+                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;
+                }
+            }
+            else
+            {
+                g_DS18B20_tick--;
+            }
+            break;
+
+        case ST_DS18B20_BUSY_WAITING_LSB:
+            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);
+                    }
+                }
 
-                /*
-                DS18B20_Write(0xBE); // Send 'read scratchpad' command
+                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;
 
-                HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
-                HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+                DS18B20_Read_DMA();
+                DS18B20_Write_DMA(0xFF);
+            }
 
-                b_DS18B20_Received_data_LSB = true;
-                g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
-                g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
-                */
+            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_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;
 
-        case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
-            if (true == b_DS18B20_DMA_done)
+        case ST_DS18B20_BUSY_WAITING_MSB:
+            if (true == b_DS18B20_DMA_RX_done)
             {
-                HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
-                HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+                // 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)
+            {
+                // 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_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;
 
-                b_DS18B20_Received_data_LSB = true;
-                g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
+        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;
             }
+            else
+            {
+                g_DS18B20_tick--;
+            }
             break;
 
+
         case ST_DS18B20_BUSY_WAITING_DMA:
-            // Process received byte if any
-            if (true == b_DS18B20_Received_data)
+            /*
+            if (true == b_DS18B20_DMA_RX_done)
             {
-                b_DS18B20_Received_data = false;
-
+                // Process received byte
                 uint8_t received_value = 0;
                 for (uint8_t i = 0; i < 8; ++i)
                 {
@@ -258,40 +401,43 @@ void DS18B20_Update(void)
                     }
                 }
 
-                if (true == b_DS18B20_Received_data_LSB)
-                {
-                    b_DS18B20_Received_data_LSB = false;
-                    // LSB
-                    // g_DS18B20_temp = (0x00FF & received_value);
-                    Temp_LSB = received_value;
-                    g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
-
-                    HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
-                    HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
-                }
-                else
-                {
-                    // MSB
-                    // g_DS18B20_temp = ((g_DS18B20_temp | (0xFF00 & (received_value << 8))) / 16.0);
-                    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);
-                }
+                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)
+            {
+                g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
+                DS18B20_Read_DMA();
+                DS18B20_Write_DMA(0xFF);
+            }
+            else
+            {
+                g_DS18B20_tick_delay--;
             }
-            else if (0 == g_DS18B20_tick) // Error handling
+
+            if (0 == g_DS18B20_tick) // Error handling
             {
-                if (5 > l_DS18B20_DMA_error_count)
+                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
+                {
+                    // Give up on reading temp for this update
                     HAL_UART_DMAStop(&huart1);
                     __HAL_UART_DISABLE(&huart1);
                     __HAL_UART_CLEAR_PEFLAG(&huart1);
@@ -300,18 +446,6 @@ void DS18B20_Update(void)
                     __HAL_UART_CLEAR_OREFLAG(&huart1);
                     __HAL_UART_ENABLE(&huart1);
                     memset(g_DS18B20_Received_data_buffer, 0, sizeof(g_DS18B20_Received_data_buffer));
-
-                    HAL_UART_Transmit_DMA(&huart1, g_buffer, 8);
-                    HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
-                    */
-
-                    g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
-                }
-                else
-                {
-                    // Give up on reading temp for this update
-                    __HAL_UART_DISABLE(&huart1);
-                    __HAL_UART_ENABLE(&huart1);
                     g_DS18B20_state = ST_DS18B20_READY;
                     g_DS18B20_tick = G_TEMP_PERIOD_MS;
                 }
@@ -331,15 +465,7 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
 {
     if (huart->Instance == USART1)
     {
-        switch (g_DS18B20_state)
-        {
-            case ST_DS18B20_BUSY_SENDING_SKIP_ROM:
-            case ST_DS18B20_BUSY_SENDING_CONV_T:
-            case ST_DS18B20_BUSY_SENDING_READ_SCRATCHPAD:
-                b_DS18B20_DMA_done = true;
-                break;
-            default: break;
-        }
+        b_DS18B20_DMA_TX_done = true;
     }
 }
 
@@ -347,6 +473,14 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
 {
     if (huart->Instance == USART1)
     {
-        b_DS18B20_Received_data = true;
+        b_DS18B20_DMA_RX_done = true;
+    }
+}
+
+void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
+{
+    if (huart->Instance == USART1)
+    {
+        b_DS18B20_DMA_RX_done = true;
     }
 }