Question of DC motor control using PID control.

Hi, I tried to control a DC-motor using Arduino.
I want to achieve the torque or current control for rotational angle of the DC-motor.
I achieved to obtain rotational angle of the DC-motor using a rotary encoder.
Then, I achieved to freely rotate the motor using motor driver.
However, I don't know a method that the rotational angle of the motor is converged to desired angle by PID control on Arduino.
Can I solve this problem using PID library (PID_v1.h) ?

Since I read the example of this library, I didn't understand that the PID library solves the my problem.
Please give me the advice for solution of this problem.
I show an unfinished code for PID control of the DC-motor.
Best regard.


#define inA_encoder 2 // pinA
#define inB_encoder 3 // pinB
#define in_pwm 5 //for pwm
#define inA_motor 8 // for rotate direction
#define inB_motor 9 // for rotate direction
const float ppr = 500; //pulse per resolution of encoder
const int step_size = 50;
const float kp = 10; //P-gain
const float kd = 0.5; //D-gain
const float th1d = 0.90 [rad] //desired value

volatile long count_encoder = 0; //count of encoder
long p_time = 0;
long c_time = 0;

void setup()
{
Serial.begin(9600);
pinMode(inA_encoder_1, INPUT_PULLUP);
pinMode(inB_encoder_1, INPUT_PULLUP);
pinMode(in_pwm, OUTPUT);
pinMode(inA_motor, OUTPUT);
pinMode(inB_motor, OUTPUT);
attachInterrupt(digitalPinToInterrupt(inA_encoder), Update_encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(inB_encoder), Update_encoder, CHANGE);
p_time = millis();
}

void loop()
{
c_time = millis();
float th1 = count_encoder * 2 * 3.14 / ppr;
float dth1 = (th1 - p_th1) / (c_time-p_time);
p_time = c_time;
p_th1 = th1;
//--- PD control --------------------
tau = -kp1 * (th1 - th1d) - kd1 * dth1;
//--- Calculate pwm output -------------
int pwm = ; //pwm output

//--- Rotate direction ----------
if (tau > 0){
//--- CW -------------------------
digitalWrite(inA_motor, LOW);
digitalWrite(inB_motor, HIGH);
else {
//--- CCW -------------------------
digitalWrite(inA_motor, HIGH);
digitalWrite(inB_motor, LOW);
}
analogWrite(in_pwm, pwm);
}
}

the code you listed is incomplete, there are several undefined variables and functions that make it difficult to figure out what your trying to do

PID can be used to position a motor as well as maintain its' speed. you "mention torque or current control" which suggests speed, but later you say "converged to desired angle"

when PID is used to control position, the proportional term is applied to an error that is the difference between the current and a desired position. your code appears to be doing this (i.e. th1 - th1d).

the actual error, "tau" needs to be mapped to a PWM value. Since PWM is typically between 0-255, tau must be mapped to that range (can't be larger than 255) and use a positive value if negative

the sign of the differential term make sense, but Kp is typically positive. you should calculate the difference "to" the desired position, th1d - th1

tau = Kp * (th1d - th1) - Kd * (th1 - p_th1)

If this a simple DC motor then you can only control it’s speed , you won’t be able to rotate the shaft to a specific angle ( if that is what you are trying to do ).

hammy:
If this a simple DC motor then you can only control it’s speed , you won’t be able to rotate the shaft to a specific angle ( if that is what you are trying to do ).

That is not correct. If you have an encoder and know the motor's properties and how it responds to input, you can position it quite accurately.

I am working with a industrial system right now that does exactly this. A simple brushed DC motor with an encoder and a controller. The motor turns a spindle with a part attached to precise positions for processing, then to a final position for robot unload/load.
The specific controller is a Maxon EPOS2 24/5.

I don't know how capable an Arduino is for this, as I've never looked into it.

Geared or direct drive ?

I could see it being possible with a geared motor .
With a direct drive , acceleration , intertia and the fact you have a small number of commutator positions does not make it a trivial task or one for the long life of the motor (high current )

Most people on here confuse stepper motors with DC motors with Servos - hence my comments

The system we are using is direct drive, although we then do use a third party 50:1 reducer. I am not an expert with this, it isn't something I normally deal with, so I may be missing something.
I just know that, on my desk top without the reducer, with a moderate load, the system is pretty darned accurate.

I'm sure there are other companies out there that make the same kind of thing. This is just the one we used.

Maxon Motor

Controller

Thank you everyone for advice.
I might be able to achieve by converting from Torque to PWM value (0-255).
I try to modify the unfinished code.

The PID has two inputs: Setpoint and Input. Setpoint is the angle you want the motor to go to. Input is the position of the motor that you have read from the encoder. Both MUST be in the same units, like degrees or radians. The Output of the PID is in arbitrary units. The default range is 0 to 255. Since you may need to move the motor in both directions I recommend you change the range to -255 to 255. That way you can use the sign to indicate direction and use the magnitude to use for PWM.