Skip to main content
Associate III
March 8, 2024
Question

UART 4 bit numeric value communication

  • March 8, 2024
  • 4 replies
  • 5428 views

I am doing the project to control linear motor, For that I am using UART to send start and stop command to start and stop motor, as like this i sending different rpm value from 100 to 3000 randomly to change the ramp of the motor.

The problem that i am facing is for 3 digit number RPM i am getting output, but when is comes to 4 digit value i am not getting proper putput, 
For example:

For 1000 RPM, I am getting 100 RPM as out put

soundarya_h_s_0-1709892543564.png

  • Baud Rate: 115200 bps
  • Data Bits: 8
  • Parity: None
  • Stop Bits: 1

 

void
HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)
{
 int cmd_ok = 0;
 rxbuffer[strlen(rxbuffer)] = '\0';
 if (strncmp((const char*)rxbuffer, "start", 6) == 0)
 {
 rxbuffer[strlen(rxbuffer)] = '\0';
 flag = 1;
 cmd_ok = 1;
 // MC_StartMotor1();
 }
 else if (strncmp((const char*)rxbuffer, "stop", 5) == 0)
 {
 rxbuffer[strlen(rxbuffer)] = '\0';
 flag = 0;
 cmd_ok = 1;
 // MC_StopMotor1();
 }
 else
 {
 rxbuffer[strlen(rxbuffer)] = '\0';
 char* endptr;
 uint16_t rpmValue = strtol((char*)rxbuffer, &endptr, 10);
 // rpmValue = atoi((char*)rxbuffer);
 if (rxbuffer[0] != '\0' && *endptr == '\0' && rpmValue >= 100 && rpmValue <= 3000)
 {
 MC_ProgramSpeedRampMotor1(rpmValue, 30000);
 // HAL_Delay(60000);
 cmd_ok = 1;
 }
 }

 if (cmd_ok == 1)
 {
 memset(rxbuffer, 0, sizeof(rxbuffer));
 cmd_ok = 0;
 rxindex = 0;
 }
 else
 {
 rxindex++;
 }
 HAL_UART_Receive_IT(&huart2, ((uint8_t*)rxbuffer) + strlen(rxbuffer), 1);
}
    This topic has been closed for replies.

    4 replies

    Andrew Neil
    Super User
    March 8, 2024

    Please use this button to properly post source code:

    AndrewNeil_0-1709892866672.png

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    Associate III
    March 8, 2024
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    
    
    		int cmd_ok = 0;
    
    		rxbuffer[strlen(rxbuffer)] = '\0';
    
    		if (strncmp((const char*)rxbuffer, "start", 6) == 0)
    		{
    			rxbuffer[strlen(rxbuffer)] = '\0';
    			flag = 1;
    			cmd_ok = 1;
    			//MC_StartMotor1();
    
    		}
    		else if (strncmp((const char*)rxbuffer, "stop", 5) == 0)
    		{
    			rxbuffer[strlen(rxbuffer)] = '\0';
    			flag = 0;
    			cmd_ok = 1;
    			//MC_StopMotor1();
    		}
    		else
    		{
    			rxbuffer[strlen(rxbuffer)] = '\0';
    			char *endptr;
    			uint16_t rpmValue = strtol((char*)rxbuffer, &endptr, 10);
    
    			//rpmValue = atoi((char*)rxbuffer);
    			if (rxbuffer[0] != '\0' && *endptr == '\0' && rpmValue >= 100 && rpmValue <= 3000)
    			{
    				MC_ProgramSpeedRampMotor1(rpmValue,30000);
    				//HAL_Delay(60000);
    				 cmd_ok = 1;
    			}
    
    		}
    		if(cmd_ok == 1)
    		{
    			memset(rxbuffer, 0, sizeof(rxbuffer));
    			cmd_ok = 0;
    			rxindex = 0;
    		}
    		else
    		{
    			rxindex++;
    		}
    
    		HAL_UART_Receive_IT(&huart2, ((uint8_t *)rxbuffer) + strlen(rxbuffer), 1);
    
    }
    Karl Yamashita
    Principal
    March 8, 2024

    You should use HAL_UARTEx_ReceiveToIdle_DMA since you have variable size strings. Check this git project which explains how it's used. https://github.com/karlyamashita/Nucleo-G431RB_Three_UART/wiki

     

    Also you should not be doing any calculations or calls to another function within a interrupt. Save the data and set a flag. Then check the flag in the main loop and then do your calculation or calls.

    If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
    Peter BENSCH
    Technical Moderator
    March 8, 2024

    @soundarya_h_s For your convenience, I have prettied it up with a code beautifier and inserted it with </>.

    Andrew Neil
    Super User
    March 8, 2024

    A bit confused by this: Is the problem in the sending, or the receiving?

    You've only shown receive code, but are you certain that the transmitting code is working properly?

    Have you tried stepping the code to see what happens, character-by-character, as the command is received?

    It looks like your commands are text-based, so you could test using a terminal ...

     

    What is going on here:


    @soundarya_h_s wrote:

     

     

     

     rxbuffer[strlen(rxbuffer)] = '\0';

     


    strlen is only going to work if the rxbuffer is already NULL-terminated - so this is either pointless, or broken.

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    Associate III
    March 8, 2024

    Start and stop commands are working properly, when it comes to sending 4 digit numeric value through uart, it is taking as 3 digit number

    Andrew Neil
    Super User
    March 8, 2024

    @soundarya_h_s wrote:

     when it comes to sending 4 digit numeric value through uart, it is taking as 3 digit number


    Still unclear whether the problem is in the sending or the receiving?

    1. Have you confirmed that the commands are being sent correctly?
    2. If the sending is correct, Have you tried stepping the receiving code to see what happens, character-by-character, as the command is received?

    Again, It looks like your commands are text-based, so you could test using a terminal ...


    You titled the post, "UART 4 bit (sic?) numeric value communication" - is that a typo?

    Did you mean 4-digit ?

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    TDK
    Super User
    March 8, 2024

    You're terminating things before the last digit comes in.

    > if (rxbuffer[0] != '\0' && *endptr == '\0' && rpmValue >= 100 && rpmValue <= 3000)

    Imagine that you've received 3 digits "100". Code gets to this line, it passes (since rpmValue >= 100), so you terminate things and set the speed to 100.

    The proper way would be to terminate commands with a "\n" and only act upon those when the terminating character is sent.

     

    "If you feel a post has answered your question, please click ""Accept as Solution""."
    Associate III
    March 8, 2024
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	int cmd_ok = 0;
     static int rx_index = 0;
    	if (rxbuffer[rx_index] == '\n' )
    	{
    		if (rx_index > 0 && rxbuffer[rx_index - 1] == '\r')
    		{
    			rxbuffer[rx_index] = '\0';
    			rxbuffer[rx_index - 1] = '\0';
    			rx_index = 0;
    			int j = 0;
    			while (rxbuffer[j] != '\0' && rxbuffer[j] == "stop"[j])
    			{
    				j++;
    			}
    			if (j == 4 && rxbuffer[j] == '\0')
    			{
    				stopflag = 1;
    				cmd_ok = 1;
    				//MC_StartMotor1();
    			}
    			else if(j == 2)
    			{
    				int i = 0;
    				while (rxbuffer[i] != '\0' && rxbuffer[i] == "start"[i])
    				{
    					i++;
    				}
    				if (i == 5 && rxbuffer[i] == '\0')
    				{
    					startflag = 1;
    					cmd_ok = 1;
    					//MC_StopMotor1();
    				}
    			}
    			else
    			{
    				uint16_t rpmValue = atoi((char*)rxbuffer);
    				 for (int i = 0; rxbuffer[i] != '\0'; i++)
    				{
    					if (!isdigit(rxbuffer[i]))
    					{
    						rxbuffer[i] = '\0';
    						break;
    					}
    				}
    				if (100 <= rpmValue && rpmValue <= 3000)
    				{
    					 MC_ProgramSpeedRampMotor1(rpmValue,60000);
    					 cmd_ok = 1;
    				}
    				else
    				{
    					 txflag = 1;
    					 cmd_ok =1;
    				}
    			}
    		 }
    	 }
    
    Andrew Neil
    Super User
    March 8, 2024

    Have you tested that code?

    You still have problems if rxbuffer is uint16_t; eg,

    uint16_t rpmValue = atoi((char*)rxbuffer);

     

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.