cancel
Showing results for 
Search instead for 
Did you mean: 

UART Commands to control B-G431B-ESC1

garivin
Associate II

I am currently working or a project with microcontrollers STM32 and this is my current situation:

- I want to send from my NUCLEO f4476ZE the desired speed via UART to my other controller which is B-G431B-ESC1 discovery kit with STM32G431CB MCU.

- I have this discovery kit connected to the motor (I can make it run with the CubeIDE project generated from the Motor Control Workbench that i have created with this Discovery kit and a Maxon 251601 motor).

 

The problem that I have is that i don't know which structure of message should I send from the Nucleo to the ESC1 for the ESC1 to read and interpret it correctly to move the motor at the desired speed of the message.

I was trying sending this as desired speed:

char tx_buff[32];
int velocidad = 1500;

while (1)
{
  sprintf(tx_buff, "SPD%d\n", velocidad);
  HAL_UART_Transmit(&huart2, (uint8_t*)tx_buff, strlen(tx_buff), 1000);
  HAL_Delay(1000);
}

And for the receiver I wanted to add this: 

HAL_UART_Receive_IT(&huart2, &rx_buf[rx_index], 1); //after MX_USART2_UART_Init();
#include <string.h>
#include <stdlib.h>

void process_command(char *cmd)
{
  if (strncmp(cmd, "SPD", 3) == 0)
  {
    int rpm = atoi(&cmd[3]);
    MC_ProgramSpeedRampMotor1(rpm, 1000);  // Cambia velocidad con rampa de 1s
  }
  else if (strcmp(cmd, "START") == 0)
  {
    MC_StartMotor1();
  }
  else if (strcmp(cmd, "STOP") == 0)
  {
    MC_StopMotor1();
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART2)
  {
    if (rx_buf[rx_index] == '\n')
    {
      rx_buf[rx_index] = '\0';
      process_command((char*)rx_buf);
      rx_index = 0;
    }
    else
    {
      if (rx_index < RX_BUF_LEN - 1)
        rx_index++;
      else
        rx_index = 0;
    }

    HAL_UART_Receive_IT(&huart2, &rx_buf[rx_index], 1);
  }
}




The problem is that the motor is not moving at the desired speed that i tell him, but with the osciloscope i can see that there is a signal in the tx,rx,ground that i have connected correctly between the two boards, as i did the getting started tutorial from uart and the receiver received the messages from the trasmiter.
I think that the problem that i have is that it can not read correctly the velocity. Can somebody help me to send the desired speed to the motor for it to run at that speed?
Even if the code does not have anything to do with mine, I may have written it incorrectly.

 

20 REPLIES 20

@Karl Yamashita do you know where can I find this function? In the main.c or in which archive?

garivin_0-1750351836519.png

(This photo is from a computer that can not debug the code, just to see it).

No i don't know where that function is in what file. You can place your cursor on the function and press F3, which will jump to that function.

I was told that if a devices starts to smoke, put the smoke back in. I guess I never got all the smoke because the device never worked afterwards.
Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

@Karl Yamashita but if i do not find the function I can not put my cursor on the function and press F3. I am sorry, I do not know if I am understanding it incorrectly.


You've posted this code, so you do have the function MC_ProgramSpeedRampMotor1 to place the cursor on

 

void process_command(char *cmd)
{
  if (strncmp(cmd, "SPD", 3) == 0)
  {
    int rpm = atoi(&cmd[3]);
    MC_ProgramSpeedRampMotor1(rpm, 1000);  // Cambia velocidad con rampa de 1s
  }
  else if (strcmp(cmd, "START") == 0)
  {
    MC_StartMotor1();
  }
  else if (strcmp(cmd, "STOP") == 0)
  {
    MC_StopMotor1();
  }
}

 

I was told that if a devices starts to smoke, put the smoke back in. I guess I never got all the smoke because the device never worked afterwards.
Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

Ok I found it it is asking me for MC_ProgramSpeedRampMotor1(int16_t hFinalSpeed, uint16_t hDurationms).

With this i understand that i have to send something like SPEED:1500,2000\n  where 1500 is the speed in rpm and 2000 is the duration of the ramp in miliseconds.

With all this I assume that i should send: 

char tx_buffer[32];
int speed = 1500;
int duration = 2000;

sprintf(tx_buffer, "SPEED:%d,%d\n", speed, duration);
HAL_UART_Transmit(&huart2, (uint8_t*)tx_buffer, strlen(tx_buffer), HAL_MAX_DELAY);

 

And for the receiver:

char rx_buffer[32]; // UART RX buffer
int16_t speed = 0;
uint16_t duration = 0;

void process_uart_command(char* buffer) {
if (sscanf(buffer, "SPEED:%hd,%hu", &speed, &duration) == 2) {
MC_ProgramSpeedRampMotor1(speed, duration);
}
}

 

Do you think it would with the right format for speed and velocity foor the MC_ProgramSpeedRampMotor1() to receive and make the motor spin?

Karl Yamashita
Principal

Instead of worrying about the communication part, first test that by calling MC_ProgramSpeedRampMotor1 works.

Before your main while loop, just call MC_ProgramSpeedRampMotor1 with some test arguments. 

I was told that if a devices starts to smoke, put the smoke back in. I guess I never got all the smoke because the device never worked afterwards.
Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

Ok, I will try that as fast as I can take the university computer and test it.

I will keep you updated, thank you.

Hello @Karl Yamashita , today I could use the computer and test what you said.

If i write for example MC_ProgramSpeedRampMotor1(1500,2000) it works good.

The problem that I have is that I try to send this from the transmiter board:

char tx_buff[32];

int velocidad = 1500;

while (1)

{

   int len = sprintf(tx_buff, "SPD%d\n", velocidad);

   HAL_UART_Transmit(&huart2, (uint8_t*)tx_buff, len, HAL_MAX_DELAY);

   HAL_Delay(1000);

}

 

And the receiver has this in the main:

 

char rx_buff[32];

int duration = 5000;

while (1)

{

HAL_UART_Receive(&huart2, (uint8_t*)rx_buff, 8, HAL_MAX_DELAY);

char *ptr = strstr(rx_buff, "SPD");

if (ptr != NULL)

{

int velocidad = atoi(ptr + 3);

MC_StartMotor1();

MC_ProgramSpeedRampMotor1(velocidad, duration);

}

 

I was trying for it to receive "SPD1500\n" inside the rx_buff, to make the motor move. The strange thing is that while I was trying to receive it, it actually worked once, but the motor didn't move, so when I tried it again it didn't receive anything, even with the same code. I have heard that it could have been only luck that the transmiter and receiver were sincronized at the same moment, but I could not do it again.

Do you think that I should change something in the code to receive the speed and make the motor move using the MC_ProgramSpeedRampMotor(speed,time) as you said?

 

 

 

So you know that MC_ProgramSpeedRampMotor1(1500,2000) works. You're using a duration of 2000.

You're speed of 1500 looks like it should parse correctly.

So now when you receive a string, you're sending MC_ProgramSpeedRampMotor1(1500,5000). So hard code for 2000, instead of 5000 since 2000 seems to work. 

 

 

I was told that if a devices starts to smoke, put the smoke back in. I guess I never got all the smoke because the device never worked afterwards.
Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

The problem is that it is not receiving the 1500 correctly. It is receiving a buffer of random stuff instead of a buffer with "SPD1500\n". As I said it is all the time receiving a buffer with random things and one time it received the right buffer but did not work anyways as the motor was not spinning, but only one time and it has not happened again. How would you send this string and receive it without the SPD part?