BLDC motor with L6234

Hey,

I'm trying to control a brushless gimbal motor with a l6234 three phase motor driver and my arduino.
It is important to note that gimbal motors are not like normal brushless motors. In contrast to the normal brushless motors, they use thin wire and many winding for the coils giving them high impedance and high torque. Therefore no feedback (sensors/back emf) is needed as the motor will be used more like an actuator.

So I did a lot of research about BLDC (and I couldn't find much information), but eventually I found out, that those motors are normally driven by three sine waves shifted by 120°.

In order to do this I generated an array with 256 entries containing the values which are depicted in the image above as "Phase A". The other two phases are simply the first phase shifted by 85 and 170 steps, respectively.

The L6234 has three IN pins and three EN pins. The IN pins controls whether the upper or the lower DMOS of the corresponding half bridge is activated and the EN pin turns the whole phase on or off. So to archieve the waveform shown in the diagram above, I need to use a pwm signal with the current value from the array on the EN pins and turn the IN pins on when the graph is above zero and off when it is below zero.

int stepA = 0;
int stepB = 85;
int stepC = 170;

void loop(){

  if(sin_array[stepA] < 0){                    //if current value is below zero 
    digitalWrite(L6234_IN1, LOW);              //turn lower DMOS on (upper off)
    analogWrite(L6234_EN1, -sin_array[stepA]); //pwm, but with positive value
  }
  if(sin_array[stepA] > 0){                    //if current value is greater than zero 
    digitalWrite(L6234_IN1, HIGH);             //turn upper DMOS on
    analogWrite(L6234_EN1, sin_array[stepA]);  //pwm
  }
  if(sin_array[stepB] < 0){                    //if current value is below zero 
    digitalWrite(L6234_IN2, LOW);              //turn lower DMOS on (upper off)
    analogWrite(L6234_EN2, -sin_array[stepB]); //pwm, but with positive value
  }
  if(sin_array[stepB] > 0){                    //if current value is greater than zero 
    digitalWrite(L6234_IN2, HIGH);             //turn upperDMOS on
    analogWrite(L6234_EN2, sin_array[stepB]);  //pwm
  }
  if(sin_array[stepC] < 0){                    //if current value is below zero 
    digitalWrite(L6234_IN2, LOW);              //turn lower DMOS on (upper off)
    analogWrite(L6234_EN2, -sin_array[stepC]); //pwm, but with positive value
  }
  if(sin_array[stepC] > 0){                    //if current value is greater than zero 
    digitalWrite(L6234_IN3, HIGH);             //turn upperDMOS on
    analogWrite(L6234_EN3, sin_array[stepC]);  //pwm
  }

  int value= analogRead(A0)/4;
  
  stepA= value;
  stepB= value+ 85;
  stepC= value+ 170;
  
  if(stepB >= 256) mstep_b -= 256;
  if(stepC >= 256) mstep_c -= 256;
}

This is the main loop of a sketch I wrote to control the motor with a poti. When I start turning the poti the motor turns proportionally, but after like 20 steps it stops turning for a while (like 40 steps) and then start turning again. This behaviour continues all the way to the end.

My problem is that I have no idea where this behaviour is coming from, but I really need to move the motor in a linear way. I tried to use a trapezoidal waveform instead of a sinusoidal one. This seems to increase the torque of the motor, but is doesn't help concerning my problem.

What am I doing wrong?

Hoping for answers,
Josua

You need to sense position to commutate a brushless motor, whether by hall sensors or backEMF sensing, or some other method (like periodically measuring winding inductance).

backEMF sensing cannot work at standstill and thus cannot be used for a servo-motor
application such as a gimbal motor. Does you motor have hall sensors?

If I wanted to make the motor spin, I'd agree with you, but since I only need do adjust the angle it's different.

Let me explain it like this: When I turn the motor on with any valid step of the commutation sequence it will snap in place. Now, imagine I had a button connected to the Arduino and every time I press this button it will go one step forward. So far, this works flawless (I tested it) and the motor turns around once in 42 steps (7 electrical rotation with each 6 steps -> 42 steps).

Of course, I need much more resolution (i.e. accuracy). So I took the regular commutation sequence and added "intermediate steps". The result are three trapezoidal shaped curves, which look a bit like the sine waves...


First diagram with the regular commutation sequence


Second diagram with modified sequence

This works basically pretty well except it is not linear. When the graph is inclined, PWM is used. The PWM value starts at 255 and goes to zero. At this point the IN pin switches (from 0 to 1 if the graph is increasing, otherwise from 1 to 0). Then the PWM values go up to 255 again.

The problem is that the motor only moves for the values 130-255 and not all the way from 0 to 255.

I have no idea what causes this problem, but I'm pretty sure timing is not the problem since this way of controlling a motor has little to do with the traditional way (I think it's called vector control).

I repeat does you motor have hall sensors? More to the point please give us information
about the motor.

BLDCs are not driven open-loop, which is what you are describing, because the performance
is v. poor. For that you need a stepper motor.

I use the GB54-1 sensors from T-Motors (Link) and they don't have hall sensors.

I think you'll find the drivers for gimbal motors use the IMU input to perform commutation
and sense winding inductance or current to self-calibrate - ie some sophisticated software
techniques are employed to save on the cost of hall sensors. Given the setup involves
sensing orientation already in gimbal systems that information is utilised to do the commutation.

So I guess the simplest approach is to add a shaft encoder to the motor to sense position
and use that to commutate?

I found a way to solve my problem. I left out the pwm values which didn't affect the motor. Now I can turn it to a certain position with a potentiometer.

The next step is to calculate the position of the camera using an IMU and correct its position. So the feed back of my IMU will basically provide all the information I need.

I don't plan on using shaft encoder right now, but maybe I'll add some when it comes to the tuning. Could you explain to me, how I would use such a sensor in respect of commutation?

Commutation requires knowledge of the rotor position so that the right
windings are energised.

Servo motor operation requires PWM to provide a linearly controlled torque
as output of the PID loop - as I said its quite complicated as you'll be using
the position information both for commutation and for calculating the input
error value into the PID loop.

Hi Josuaj,

first thank You for sharing Your findings. I'm looking for the same solution - I need to operate two gimbal motors, but not to stabilize camera. I need them to aim platform at desired direction. So I need shaft position encoders as other guys suggested (I plan to use magnetic ones), but stabilization systems with IMU doesn't need them.
Stabilization systems works by getting IMU readings and rotating camera to desired position. If camera is offsetted off desired value by some measured value, then uCU commands to rotate motor back to compensate this offset, and it rotates motor till acceptable position (reported by IMU) is reached.

No hall and shaft encoders are used. Also in theory no back-EMF can be measured because of very low/no speeds. I can guess just that they experimentally found what sine-wave frequency works best for chosen motor and using it without any magic sensing techniques.

My questions for You is - what about current on "stalled" direct drive motor ? Most of the time, opposing traditional motor function it has to be powered, but not rotating (holding load) and not burned by continuous current. How it is achieved ? By current limiting ? But commercially available gimbal controllers can accept very different motors (windings and resistances differs a lot), how do they know what current is acceptable for holding load, but yet not burning windings ?

Than You!

OK, thats what I came up to:

Take a look, maybe You'll find something usefull.