2024-03-08 02:10 AM - last edited on 2024-03-08 02: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
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);
}
2024-03-08 04:04 AM
2024-03-08 04:13 AM - edited 2024-03-08 04: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.
2024-03-08 04:21 AM
In 1st image 850 is received, in second image i sent 1000 it received 100
2024-03-08 04:36 AM - edited 2024-03-08 04: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 ...
2024-03-08 04:46 AM - edited 2024-03-08 04: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.
2024-03-08 05: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;
}
}
}
}
2024-03-08 06:33 AM
Have you tested that code?
You still have problems if rxbuffer is uint16_t; eg,
uint16_t rpmValue = atoi((char*)rxbuffer);
2024-03-08 08: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.
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.