UART 4 bit numeric value communication
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 2:10 AM - last edited on ‎2024-03-08 2:32 AM by Peter BENSCH
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
- 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);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 4:04 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 4:13 AM - edited ‎2024-03-08 4:18 AM
You can put more than one image in a post!
You know that you can set the debugger to display values as characters?
You've shown that "start" is received - but you haven't shown any numbers being received.
Why is your buffer uint16_t ?
Things like strlen are not going to work with that!
EDIT
And, again, What is going on here:
rxbuffer[strlen(rxbuffer)] = '\0';
strlen is only going to work if the rxbuffer is already NULL-terminated - so this is either pointless, or broken.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 4:21 AM
In 1st image 850 is received, in second image i sent 1000 it received 100
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 4:36 AM - edited ‎2024-03-08 4:37 AM
You still haven't addressed the fundamental flaw that your buffer seems to be uint16_t when it should be char.
And what you intend with this:
rxbuffer[strlen(rxbuffer)] = '\0';
In your screenshot, the Docklight is obscuring important detail of the debug output - so we can't see what's going on.
@soundarya_h_s wrote:In 1st image 850 is received, in second image i sent 1000 it received 100
So the receiving is not working.
So you need to look into what's going wrong.
Send one character at a time, and follow-through step-by-step how that gets handled - to see where the handling goes wrong.
With the above-mentioned issues, it's not surprising that things go wrong ...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 4:46 AM - edited ‎2024-03-08 4:47 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 5:03 AM
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;
}
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 6:33 AM
Have you tested that code?
You still have problems if rxbuffer is uint16_t; eg,
uint16_t rpmValue = atoi((char*)rxbuffer);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 8:24 AM
How could this possibly work? rx_index is never changed from 0. The logic is better, but you're still not there yet. Yu're close, keep going. Debug, step through code, verify the logic is what you need it to be.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-08 11:52 AM
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.
TimerCallback tutorial! | UART and DMA Idle tutorial!
If you find my solution useful, please click the Accept as Solution so others see the solution.

- « Previous
-
- 1
- 2
- Next »