Example: Torque control of a Brushless Motor with Hall Sensors

I like to show an example on how to handle Torque control of a Brushless Motor with Hall Sensors using Arduino UNO, a Brushless DC Motor with the part number of “DB56C036030-A” and Solo UNO as motor controller.
To make it work, I also use the Library for communication between Arduino and Solo here .

The idea of this example is to lock the shaft of the motor by hand and by code increase the torque of the motor gradually in order to feel how the force is increasing every time.

The schematic is here:

  • The piano switch for Solo UNO is from pin 1 to 5: Down, Up, Up, Up, Down.
  • the pin “~3” of Arduino UNO is connected to “S/T” input of SOLO, which in our configuration will define the Torque reference, this reference is calculated based on the maximum current that SOLO can feed into the Motor.
  • pin “~9” of Arduino in which will define for SOLO the current limit and it’s connected to “P/F” input of SOLO for protection purposes.
  • correctly calibrated the Hall sensors windings to ABC outputs of Solo

And this is the code:

#include <SOLOMotorController.h>

#define AnalogueCommandMode 0
#define PMSM_BLDC_Normal 1
#define UsingHallSensors 2
#define DigitalCommandMode 1
#define ControlType_Torque 1
#define ControlType_Speed 0
 
//instanciate a SOLO object:
SOLOMotorController *SOLO_Obj1; 

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

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

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

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

// Define Desired Torque referrrence
float desiredTorque_Iq = 1.5;

// Converted value to PWM duty cycle for Iq
int desiredDutyCycle_Iq = 0;

// Converted value to PWM duty cycle for currentLimit 
int desiredDutyCycle_CurrentLimit = 0;

// Define the Max Measurable current in SOLO UNO for 100% duty Cycle
float MaxMeasurableCurrent_SOLO_UNO = 32.0;

// Battery or Bus Voltage
float busVoltage = 0; 

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

// Motor speed feedback
long actualMotorSpeed = 0; 

// Motor Iq (torque) feedback
float actualMotorTorque_Iq = 0; 

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

  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);
  
  //select Digital Mode
  SOLO_Obj1->SetCommandMode(DigitalCommandMode);
  SOLO_Obj1->SetMotorType(PMSM_BLDC_Normal);

  //Operate while using Hall sensors
  SOLO_Obj1->SetSpeedControlMode(UsingHallSensors);

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

  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();

  //Go back to Analogue Mode to accept PWM as Reference for Torque and Speed
  SOLO_Obj1->SetCommandMode(AnalogueCommandMode);
  //Enable PWM pins of Arduiono with Fixed frequency greater than 5kHz
  
  pinMode(3, OUTPUT); //torque adjuster connected to "S/T" on SOLO UNO
  pinMode(9, OUTPUT);//current Limit adjuster connected to "P/F" on SOLO UNO
  
  pinMode(2,OUTPUT); //Direction Control Pin
    
  // declare pin 3 to be a PWM enabled output with 31kHz of fixed Frequency
  TCCR2B = TCCR2B & 0b11111000 | 0x01;
  // declare pin 9 to be a PWM enabled output 31kHz of fixed Frequency
  TCCR1B = TCCR1B & 0b11111000 | 0x01;
}

void loop() {
  
  // Converted value to PWM duty cycle for desired current Limit on 8 bit PWM of Arduino
  desiredDutyCycle_CurrentLimit = (int)(255 - (255*( currentLimit/ MaxMeasurableCurrent_SOLO_UNO)));
  //Set the right Duty cycle on Pin ~9 for current Limit
  analogWrite(9, desiredDutyCycle_CurrentLimit);

  //Define the desired torque in Amps
  desiredTorque_Iq = 1.5;

  //Define the Direction of Rotation
  digitalWrite(2,LOW);
  
  // Converted value to PWM duty cycle for desired Iq on 8 bit PWM of Arduino
  desiredDutyCycle_Iq = (int)(255*(desiredTorque_Iq / MaxMeasurableCurrent_SOLO_UNO));

  //Set the right Duty cycle on Pin ~3 for Torque
  analogWrite(3, desiredDutyCycle_Iq);

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

  actualMotorTorque_Iq= SOLO_Obj1->GetQuadratureCurrent();
  Serial.println("\n Torque (Iq): ");
  Serial.print(actualMotorTorque_Iq , 7);
  
  //dummy read after Serial.println to open the UART line
  SOLO_Obj1->GetBusVoltage();

  
 // wait for user to read
  delay(3000);
  
  //Define the desired torque in Amps
  desiredTorque_Iq = 2.5;

  //Define the Direction of Rotation
  digitalWrite(2,HIGH);
  
  // Converted value to PWM duty cycle for desired Iq on 8 bit PWM of Arduino
  desiredDutyCycle_Iq = (int)(255*(desiredTorque_Iq / MaxMeasurableCurrent_SOLO_UNO));

  //Set the right Duty cycle on Pin ~3 for Torque
  analogWrite(3, desiredDutyCycle_Iq);

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

  actualMotorTorque_Iq= SOLO_Obj1->GetQuadratureCurrent();
  Serial.println("\n Torque (Iq): ");
  Serial.print(actualMotorTorque_Iq , 7);
  
  //dummy read after Serial.println to open the UART line
  SOLO_Obj1->GetBusVoltage();
 
  // wait for user to read
  delay(3000);
  
}

So the thing that is happening is, in the code is hardcoded desired torque in Amps, then it will convert it to a PWM duty cycle on pin “~3” for each reference, the PWM duty cycle will remain constant as long as the reference has not been changed. In Arduino UNO, the PWM section has a 8 bits counter and this means to go from 0% to 100% duty cycle we have 255 steps, which will define the resolution of Torque control, the frequency of PWM pulses is not important and anything above 5kHz it’s ok, both pin ~3 and ~9 are on 31kHz.

1 Like

Improved schematic:

1 Like