Debugging using printf() Output through UART for in Micromouse - Basic Concept, Coding for STM32 printf(), Important Note

 

Debugging using printf() Output through UART for  in Micromouse - Basic Concept, Coding for STM32 printf(), Important Note

Using printf() with UART is one of the easiest ways to display debugging messages, sensor values, and system status in Micromouse robot. It is widely used in microcontroller projects such as STM32, AVR, ESP32, and Arduino-compatible boards.

Instead of manually transmitting characters one by one, developers can use the familiar C standard library function printf() to send formatted text directly through UART.


What is UART?

UART (Universal Asynchronous Receiver Transmitter) is a serial communication protocol used for communication between:

  • Microcontrollers
  • PCs
  • Bluetooth modules
  • GPS modules
  • Sensors
  • Debug terminals

UART transfers data using two lines:

  • TX (Transmit)
  • RX (Receive)


Why Use printf() with UART?

Using printf() provides several advantages:

  • Easier debugging
  • Formatted output support
  • Faster development
  • Human-readable serial logs
  • Simple variable monitoring

Example:

printf("Temperature = %d C\r\n", temp);

This is much easier than manually converting numbers to strings.


Basic Concept

Normally, printf() sends output to the standard console.
In embedded systems, there is no default console.

Therefore, developers redirect the printf() output to UART.

The process is:

printf() → low-level write function → UART transmit → Serial terminal

Hardware Required

Typical setup includes:

  • Microcontroller board
  • USB-to-UART converter
  • Serial terminal software

Examples of USB-UART converters:

  • CP2102
  • FT232
  • CH340

Popular serial terminal software:

  • PuTTY
  • Arduino IDE Serial monitor


UART Configuration Parameters

Common UART settings:  The baud rate should be set to the required speed depending on the system's conditions. However, if it is too fast, data may be missed.

ParameterTypical Value
Baud Rate115200  
Data Bits8
Stop Bits1
ParityNone

Coding for STM32 printf() via UART

  Include Required Header

  #include "stdio.h"

  Redirect printf()

  Assume UART1 is used: Modify a part of the source file(Core/Src/syscalls.c) as follows.

extern UART_HandleTypeDef huart1;

__attribute__((weak)) int _read(int file, char *ptr, int len)

{

// modified for serial communication

int DataIdx = 0;

uint8_t thechar;

thechar= ' ';

while(thechar!= '\n' && thechar != '\r' && DataIdx<len)

{

__HAL_UART_CLEAR_OREFLAG(&huart1);


HAL_UART_Receive(&huart1, (uint8_t *)&thechar, 1, 100);


if ( thechar >= 0xFF)

{

printf("\n\r !!! Please enter a valid ASCII character \n");

return 0xFF;

}

*ptr++ =thechar;

DataIdx+=1;

}

*ptr = '\0';

return DataIdx;

}


__attribute__((weak)) int _write(int file, char *ptr, int len)

{

// modified for serial communication

HAL_StatusTypeDef hstatus;


hstatus = HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);

if (hstatus == HAL_OK) return len;


return EIO;

}

  Example Code

  #include "main.h"
  #include "stdio.h"


  int main(void)
  {
    HAL_Init();
    SystemClock_Config();
    MX_USART1_UART_Init();

    int speed = 120;
    float voltage = 3.3;
    uint8_t data = 0x5A;
while (1) { printf("Hello UART\r\n");
        printf("Speed = %d\r\n", speed); // for integer
        printf("Voltage = %.2f V\r\n", voltage); // for float number
        printf("Data = 0x%X\r\n", data); // hexadicimal
HAL_Delay(1000); } }

Any type of number can be naturally used by listing it together with a string.

printf("Left=%ld Right=%ld Error=%d\r\n",  // 32 bit long integer
       left_encoder,
       right_encoder,
       position_error);

This helps monitor robot behavior in real time.


Important Note About Floating Point

Some embedded compilers disable float formatting to save memory.

If float values do not print correctly:

Voltage = ?

Enable floating-point support in project settings.

For STM32 GCC:

-u _printf_float

Common Applications

UART printf() is commonly used for:

  • Sensor debugging
  • Motor tuning
  • PID monitoring
  • Micromouse debugging
  • Bluetooth communication logs
  • Error reporting
  • State machine tracing


Best Practices

  • Keep debug messages short
  • Avoid printing inside interrupts
  • Use \r\n for terminal compatibility
  • Disable debug logs in release firmware


Conclusion

Using printf() with UART is a powerful and convenient debugging technique in embedded systems. By redirecting standard output to UART, developers can easily monitor variables, sensor readings, and system behavior in real time.

Whether developing STM32 firmware, AVR applications, or Micromouse robots, UART printf() remains one of the most valuable tools for embedded debugging and diagnostics.

Comments

Popular posts from this blog

How to Build a Micromouse Robot - Mechanical, Hardware, Software

Micromouse Competitions - Types, Overview, Comparison, Advantages, Worldwide

Complete Guide to Micromouse Maze - Dimensions, Structure and Components, Building