Skip to main content
Explorer II
April 24, 2024
Solved

How to control delays in non-blocking ways?

  • April 24, 2024
  • 3 replies
  • 4377 views

I am using H563ZI to develop a motor control project. I have several motors in my project. Motor control commands will be sent to the board with ethernet cable(I have finished this part). Once the board get the command, it should then make the motor with given index run for given period of time, and then stop the motor. I created a function that toggles the GPIO pins and calls HAL_Delay to control the period. After the delay, the function then toggle the GPIO pins back. The problem is that when one motor is in the HAL_Delay, the whole process is blocked. Is there any way that I can turn on several motors and stop them after their given period individually? For example, if [200, 300] is given, motor0 and motor1 should be turned on at (at least nearly) the same time. Motor0 should be turned off after 200ms, and motor1 should be turned off after 300ms.

I guess one idea is to use ThreadX, which I also used for the Ethernet part (https://github.com/STMicroelectronics/STM32CubeH5/tree/main/Projects/NUCLEO-H563ZI/Applications/NetXDuo/Nx_UDP_Echo_Client). However, I have at least 14 motors, should I create a thread for each motor? Or is there a better way to implement this?

Here is my function to control the motors now, which leads to blocking issue.

 

void stopMotor(int motor_idx) {
HAL_GPIO_WritePin(motors[motor_idx].IN1.GPIO_Port,
motors[motor_idx].IN1.GPIO_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(motors[motor_idx].IN2.GPIO_Port,
motors[motor_idx].IN2.GPIO_Pin, GPIO_PIN_RESET);
}
void controlMotor(int motor_idx, uint32_t duration, int direction) {
GPIO_PinState in1_state = direction == 0 ? GPIO_PIN_RESET : GPIO_PIN_SET;
GPIO_PinState in2_state = direction == 0 ? GPIO_PIN_SET : GPIO_PIN_RESET;
HAL_GPIO_WritePin(motors[motor_idx].IN1.GPIO_Port,
motors[motor_idx].IN1.GPIO_Pin, in1_state);
HAL_GPIO_WritePin(motors[motor_idx].IN2.GPIO_Port,
motors[motor_idx].IN2.GPIO_Pin, in2_state);
HAL_Delay(duration);
stopMotor(motor_idx);
}
    This topic has been closed for replies.
    Best answer by LCE

    Why so complicated?

    Add a counter variable to your motor struct, and use an STM timer set to required resolution, with interrupt.

    When start command is received, start the motors and set .counter = time.

    In timer interrupt: for( i++ until < number of motors ) if( motor[i].counter ) { motor[i].counter--; if( 0 == motor[i].counter ) set motor[i].stopflag }

    In main (or some OS thread): for( i++ until < number of motors ) if motor[i].stopflag then stop motor

     

    Great C code! ;)

    3 replies

    Graduate II
    April 24, 2024

    >>Or is there a better way to implement this?

    Make a queued list of things to change/manage with time stamps, and advance through it at every 1ms SysTick ?

    Graduate II
    April 24, 2024

    Say a linked list, with a ms target time, and a 32-bit vector one for Motor On events, and another for Motor Off events. Search list for existing events, and either insert a new one, in order, or tag the on/off motor flags.

    Graduate II
    April 24, 2024

    Hi,

    You could use OTP timers to control the motor(s)... Either in hardware, or firmware...

    I hope that helps.

    Kind regards
    Pedro

     

     

    LCEAnswer
    Graduate II
    April 24, 2024

    Why so complicated?

    Add a counter variable to your motor struct, and use an STM timer set to required resolution, with interrupt.

    When start command is received, start the motors and set .counter = time.

    In timer interrupt: for( i++ until < number of motors ) if( motor[i].counter ) { motor[i].counter--; if( 0 == motor[i].counter ) set motor[i].stopflag }

    In main (or some OS thread): for( i++ until < number of motors ) if motor[i].stopflag then stop motor

     

    Great C code! ;)

    hchientiAuthor
    Explorer II
    April 24, 2024

    Hi @LCE ,

    Thanks for providing this cool idea. I just implemented it and the result is just what I needed!

    Thanks a lot!