Example: Position Control Of A Brushless Motor With Arduino Uno [code example]

Here an example of position control of a Brushless DC or Permanent Magnet Synchronous Motor.

The goal will be to have an infinite loop with:

  • A spin of the motor from 0 to +50000 pulses with 5000 RPM plus a short wait time
  • Turning back the Motor into -32559 pulses with 1500 RPM of speed plus a short wait time

For this example I’m using:

  • Arduino Uno
  • Brushless Motor as teknic m-2310P-LN-04K This Motor has 8 Poles with an internal Encoder with 1000 physical lines pre-quad, meaning that in 1 turn rotation the motor controller will read 4000 pulses generated by this motor’s encoder in quadrature manner ( 4 times more)
  • Solo Uno as motor controller used as servo drive.

To make it work, I also use the Library for communication between Arduino and the motor controller, more info here.

The schematic:

  • The piano switch for the motor controller is from pin 1 to 5: Up, Up, Up, Up, Down.
  • Correctly calibrated the Encoder with correct connection of the Motor’s windings to ABC outputs of the motor controller

The code:

#include <SOLOMotorController.h>


//pointer of SOLO object:
SOLOMotorController *SOLO_Obj1; 

//the device address of SOLO:
unsigned char SOLO_address1=0; 

//Desired Switching or PWM Frequency at Output
long pwmFrequency=70; 

//Motor's Number of Poles
long numberOfPoles = 8; 

//Motor's Number of Encoder Lines (PPR pre-quad)
long numberOfEncoderLines = 1000; 

//Select the Normal BLDC_PMSM motor type
long motorType= 1; 

//Speed controller Kp
float speedControllerKp = 0.15; 

//Speed controller Ki
float speedControllerKi = 0.03; 

//Position controller Kp
float positionControllerKp = 0.12;

//Position controller Ki
float positionControllerKi = 0.02; 

// Current Limit of the Motor
float currentLimit= 15.0; 

// Battery or Bus Voltage
float busVoltage = 0; 

// Desired Speed Limit[RPM]
long desiredSpeedLimit =3000; 

// Desired Position Reference 
long desiredPositionReference =0; 

// Motor speed feedback
long actualMotorSpeed = 0; 

// Motor position feedback
long actualMotorPosition = 0; 

void setup() {
  Serial.begin(115200); 

  //Initialize the SOLO object
  SOLO_Obj1 = new SOLOMotorController(SOLO_address1); 
  delay(2000);
  
  busVoltage = SOLO_Obj1->GetBusVoltage();
  while(busVoltage <=0){
      busVoltage = SOLO_Obj1->GetBusVoltage();
      //wait here till communication is established
      Serial.println("\n Trying to Connect To SOLO");
      delay(1000);
      }
      
  Serial.println("\n Communication Established succuessfully!");
  
  //dummy read after Serial.println to open the UART line
  SOLO_Obj1->GetBusVoltage();
  // Initial Configurations
  SOLO_Obj1->SetPWMFrequency(pwmFrequency);
  SOLO_Obj1->SetCurrentLimit(currentLimit);
  SOLO_Obj1->SetEncoderLines(numberOfEncoderLines);

  //select Digital Mode
  SOLO_Obj1->SetCommandMode(1);

  SOLO_Obj1->SetMotorType(motorType);

  //run the motor identification
  //run ID. always after selecting the Motor Type!
  SOLO_Obj1->SetIdentification(1);

  Serial.println("\n Identifying the Motor");

  //wait at least for 2sec till ID. is done
  delay(2000); 
  
  //dummy read after Serial.println to open the UART line
  SOLO_Obj1->GetBusVoltage();
  
  //Operate while using Quadrature Encoder
  SOLO_Obj1->SetSpeedControlMode(1);

  //Control The Position
  SOLO_Obj1->SetControlMode(2);

  //Speed Controller Tunings
  SOLO_Obj1->SetSpeedControllerKp(speedControllerKp);
  SOLO_Obj1->SetSpeedControllerKi(speedControllerKi);

  //Position Controller Tunings
  SOLO_Obj1->SetPositionControllerKp(positionControllerKp);
  SOLO_Obj1->SetPositionControllerKi(positionControllerKi);
  
}

void loop() {

  //set a desired Speed Limit for trajectory in RPM
  desiredSpeedLimit = 5000;
  SOLO_Obj1->SetSpeedLimit(desiredSpeedLimit);
  
  // set a positive desired Position Reference 
  desiredPositionReference =+500000;
  SOLO_Obj1->SetDesiredPosition(desiredPositionReference);

  // wait till motor reaches to the reference 
  delay(3000); 

  actualMotorPosition = SOLO_Obj1->GetEncoderPosition();
  Serial.println("\n Number of Pulses passed: ");
  Serial.println(actualMotorPosition);

  //dummy read after Serial.println to open the UART line
  SOLO_Obj1->GetBusVoltage();

    //set a desired Speed Limit for trajectory in RPM
  desiredSpeedLimit = 1500;
  SOLO_Obj1->SetSpeedLimit(desiredSpeedLimit);
  
  // set a negative desired Position Reference 
  desiredPositionReference =-32559;
  SOLO_Obj1->SetDesiredPosition(desiredPositionReference);

  // wait till motor reaches to the reference 
  delay(6000); 

  actualMotorPosition = SOLO_Obj1->GetEncoderPosition();
  Serial.println("\n Number of Pulses passed: ");
  Serial.println(actualMotorPosition);

  //dummy read after Serial.println to open the UART line
  SOLO_Obj1->GetBusVoltage();
  
}

So, after setting up the essential parameters like the Motor’s number or Poles, Encoder lines and others, in the loop the main code of this example.

It worth mentioning that when the motor controller is in Position Mode, it counts the pulses in a quadrature manner, so the feedbacks and the references are all in quadrature form, for instance in this example when we ask the motor controller to traverse the shaft of the motor into +50000 pulses, if we consider the initial starting point is at zero, we are spinning the motor for (+50000 / ( 10000 * 4)) = 12.5 turns or 4500.0 degrees, so it is possible to calculate the exact end point and provide desired reference to Solo Uno to reach a different goal.

This looks pretty interesting. Does the Solo motor controller work with motors like this one: link?

Do not forget to power the UNO, it will not operate with the USB disconnected as your fuzzy thing does not show power and ground connections as a schematic would.

Hi Power_Broker, I took a look at your link and a brief search on the internet, but I had a hard time finding the real wiring pinout for the mentioned motor to check how the Motor operates, based on the comments on Amazon link, it seems this motor is a Brushless Motor and as the wiring suggests, there are 3 wires that are thicker that probably are for power of the motor, and there are 5 other wires that are probably for either Hall sensors or Encoders, but I couldn’t find which exactly.

The motor controller supports DC brushed, BLDC, PMSM and ACIM motors, so if it’s any of these there is a good chance that you can control it.

If you have any further information or technical data about this motor I will try my best to help you. :grinning_face_with_smiling_eyes:

To know more about the specs of this motor controller you can read also here

yeah, you are right, so to power up Arduino you have two options using the USB cable or using the +5V/1A output from the motor controler.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.