How to Control the Speed and Direction for Alternat Current Servo Motor in STM 32 nucleo F746ZG

How to Control the Speed and Direction for Alternat Current Servo Motor in STM 32 nucleo F746ZG.

I have Inovance SV660P Series Servo Drive and Servo Motor .
how i will Control the Speed and Direction in PWM Signal.

                            #include "mbed.h"
                            PwmOut Pwm_pins(PC_8)
                            int main()
                            {
                                while(1)
                                {
                                Pwm_Pins.period_ms(0.005);//5 micro Seconds for ,200KHZ Frequency;
                                Pwm_Pins.plusewidth_ms(2.5);// ton ,50%of Duty cycle
                                Pwm_Pins.write(0.5);
                                }
                            }
1 Like

Hello,

First:
The PWM is a timer module of MCU what is able to run without any asistence of MCU. So the code should be out of loop.

         #include "mbed.h"
          PwmOut Pwm_pins(PC_8)
          int main()
          {
             // set 5us period
             Pwm_Pins.period_us(5);  
             // set 50% Duty cycle
             Pwm_Pins.write(0.5);  
             
             while(1)
             {
                thread_sleep_for(500);
                // do something else
             }
          }

Second:
All drivers are probably similar. Two pins, one for direction for steps or speed.
How Jojo wrote in previous topic - the PWM is good for continuous rotation with variable speed. For stepping you need just pulses, one pulce for every step.

Then you need something like this (just example, not tested code)

DigitalOut dir(D8);
DigitalOut step(D7);

void DoSomeSteps(int steps, int time_us, bool direction) {
   //set direction
   dir.write(direction); 
   //do specified number of steps
   for(int i = 0; i > steps; i++) {
      step.write(1);
      wait_us(time_us); // time is same for both states = 50% Duty Cycle
      step.write(0);
      wait_us(time_us);
   }
}

BR, Jan

Hi JohnnyK thanks for your Response
i want Start with Negative(-ve)PWM pluse with 200KHZ with Time Delay(50%duty Cycle)
note- Alternate Current Servo Motor Speed 3000 RPM when i will give 200KHz Negative Pluse (Pluse-),can you pls Help

I modified code above.
We already discussed about negative PWM. From where you got this terminology and why you think you need this? Can you explain pls.

How I already written in previous topic the MCU is not able to generate negative value it can switching between GND and Vin. For that you need an additional circuit. For example - Negative voltage PWM? - Electrical Engineering Stack Exchange

BR, Jan

hi johnny

I am New for this domain(embedded systems), Currently i am doing robotics for some Motors(stepper, DC Servo, pumps and DC geared Motor), Now i started to writing the code for Alternate current servo motor. Herewith i have attached the reference of motor and driver,

I am using this type of servo is lifting up and down motion. whenever i run this servo motor at same stepper motor is also not working, but one by one working fine, These codes i have modified from the stepper motor code. The stepper motor is controlled by working in half mode. The servo motor is controlled by working in full mode.

Please find the attached main file, CPP file and main file.

Kindly help me on this issue. Sorry for the inconvenience,

I appreciate your support on this issue.

AC_Servo Servo_Motor(PC_8,PC_9); // AC Servo (Pluse+,Pluse-)
DigitalOut Linear_Up_Motion(PE_9); // AC Servo up
DigitalOut Linear_Down_Motion(PG_15); // AC Servo Down
DigitalOut AC_Servo_Enable_Relay(PF_2); // AC Servo Enable(-24vdc)


void AC_Sero(int step,int direction)
{
int steps=0;
//steps =(step10000);
steps =(step
1000);
wait_ms(1);
AC_Servo_Enable_Relay=1;
wait_ms(1);
Linear_Up_Motion=0;
wait_ms(1);
Linear_Down_Motion=0;
wait_ms(1);
printf(“\n\n AC Servo Enable”);
if(direction==1)
{
printf(“\n UP direction”);
Linear_Up_Motion=1;
}
else
{
printf(“\n Down direction”);
Linear_Down_Motion=1;
}
Servo_Motor.stepp(steps);
wait_ms(1);
AC_Servo_Enable_Relay=0;
wait_ms(1);
Linear_Up_Motion=0;
wait_ms(1);
Linear_Down_Motion=0;
wait_ms(1);
}
int main()

          printf("\n\n AC_Servo");
          printf("\n\nEnter steps:");
          scanf("%d",&Steps);
          printf("\n\nEnter direction:");
          scanf("%d",&Dir);
          AC_Sero(Steps,Dir);
          printf("Steps:%d \t,Direction:%d\t",Steps,Dir);

//-------------------------------------------------------------------------------------
Servo.cpp
#include “AC_Servo.h”
#include “mbed.h”

AC_Servo::AC_Servo(PinName A0, PinName A1) : _A0(A0), _A1(A1), _A2(A2), _A3(A3) { // Defenition of motor pins
_A0=0;
_A1=0;
_A2=0;
_A3=0;
}

void AC_Servo::AC_Servo_Runn() {
for (int i = 4; i > 0 ; i–) {

    switch (i)
     {
     case 0: {
            _A0=1;
            _A1=1;
            _A2=0;
            _A3=0;
      }
        break;
      case 1: {
         _A0=0;
         _A1=1;
         _A2=1;
         _A3=0;
        }
        break;
     case 2: {
            _A0=0;
            _A1=0;
            _A2=1;
            _A3=1;
       }
        break;
        case 3: {
            _A0=1;
            _A1=0;
            _A2=0;
            _A3=1;
     }
       break;            
    }
    wait_us(0); // wait time defines the speed 
}

}

void AC_Servo::stepp(int num_steps) { // Servo function: number of steps
int count=0; // initalize step count
do {
AC_Servo_Runn();
count++;
} while (count<num_steps); // turn number of steps applied
}
//--------------------------------------------------------------------------------------
Servo.hfile

#include “mbed.h”

class AC_Servo {
public:

AC_Servo(PinName A0,PinName A1); //motor constructor    
void stepp(int num_steps);
void AC_Servo_Runn();

private:

DigitalOut _A0;
DigitalOut _A1;
DigitalOut _A2;
DigitalOut _A3;

};

To control the speed and direction of an Alternating Current (AC) Servo Motor using STM32 Nucleo F746ZG and Inovance SV660P Series Servo Drive, follow these steps:

  1. Connect Hardware: Ensure that your STM32 Nucleo F746ZG is properly connected to the Inovance SV660P Series Servo Drive and Servo Motor.
  2. Configure PWM Pin: Set up a PWM (Pulse Width Modulation) pin on the STM32 Nucleo for signal output. Choose a PWM pin and configure it in your code.
  3. Initialize PWM: In your STM32 code, initialize the PWM module for the chosen pin. Set parameters like frequency and duty cycle.
  4. Link PWM to Servo Drive: Connect the PWM output from the STM32 to the corresponding input on the Inovance SV660P Servo Drive. This will control the speed of the servo motor.
  5. Direction Control: If your servo motor requires a separate signal for direction control, configure another pin for this purpose. Use this pin to control the direction of the motor.
  6. Programming: Write code to adjust the PWM duty cycle to control the speed. Additionally, control the direction pin to set the desired direction.

Here’s a basic example using STM32 HAL library:

cCopy code

#include "stm32f7xx_hal.h"

TIM_HandleTypeDef htim_pwm;

void SystemClock_Config(void);

int main(void) {
  HAL_Init();
  SystemClock_Config();

  __HAL_RCC_GPIOA_CLK_ENABLE();  // Enable GPIOA clock
  __HAL_RCC_TIM1_CLK_ENABLE();   // Enable TIM1 clock

  // Configure PWM Pin
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  // Configure PWM Timer
  htim_pwm.Instance = TIM1;
  htim_pwm.Init.Prescaler = 0;
  htim_pwm.Init.Period = 1000;  // Adjust according to your requirements
  htim_pwm.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim_pwm.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&htim_pwm);

  // Initialize PWM Channel
  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500;  // Adjust duty cycle (0 to Period)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  HAL_TIM_PWM_ConfigChannel(&htim_pwm, &sConfigOC, TIM_CHANNEL_1);

  // Start PWM
  HAL_TIM_PWM_Start(&htim_pwm, TIM_CHANNEL_1);

  while (1) {
    // Adjust speed and direction as needed
  }
}

void SystemClock_Config(void) {
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 360;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    Error_Handler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                              RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
    Error_Handler();
  }
}

This example initializes a PWM signal on Pin PA8 using TIM1. You may need to adapt the code based on your specific requirements and peripherals. Ensure you refer to the datasheets for the STM32 Nucleo F746ZG and Inovance SV660P Series for pin mappings and specifications.

Thanks for your Support
This Program and Deceleration can i use to Arm Keil Studio Software?

Yes, you can use STM32 HALs in Keil Studio becasue Mbed call STM32 HALs via Mbed APIs. But in this code is another clock setting and when is different than in Mbed then it can make a colision. So if you do not know then do not touch.
However the answer above seems to be generated with a chat bot, you will see…

To be honest I do not understand to your description above very much. And in the code see few things what are also strange

  • like constructor with two input parameters (two pins) but inside of the class you fill 4 objects (with 4 pins) and also use 4 objects
    image

  • Also I am not sure how good is using names (I mean names like A0, A1, D0,D1 and so on) for variables what are already used as masks of pins
    image

For you driver you need a manual about how your driver works. When you look inside of that manual to page 111 you will see basic connection. I still see just an optocoupler which needs to be turned on via a basic pulse over a transistor and you just have a choice with which one:

  • NPN - transistor controls Pulse- and Pulse + will be connected to +24V
  • PNP - transistor controls Pulse+ and Pulse - will be connected to GND.

So from my point of view any negative pulse of PWM is not necessary. But I do no know, I am not expert and I do not have experinces with this.

BR, Jan

I really appreciate your efforts for helping me out. Now the i get position Control and Run the Speed 3000 Rpm .
Thanks

That is amazing, good luck.

BR, Jan

thank you johnnyk.