Buenos tardes. Amigos estoy tratando de hacer el control PID de dos motores polulos usando un encoder magnético dentro de un mismo archivo.
El control PID lo estoy haciendo mediante la librería, el caso es que me ha funcionado correctamente para un polulo, pero ahora no sé como hacer para tener dos controladores PID independientes (para cada motor) en mi mismo código.
Si alguien sabe por favor me puede decir como se hace, gracias!.
Crea un segundo objeto con la Clase PID
Este es el ejemplo Basic de la librería PID v1.0
#include <PID_v1.h>
#define PIN_INPUT 0
#define PIN_OUTPUT 3
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
Asi tendrás dos PID
#include <PID_v1.h>
#define PIN_INPUT1 0
#define PIN_OUTPUT1 3
#define PIN_INPUT2 4 // Est
#define PIN_OUTPUT2 5
//Define Variables we'll be connecting to
double Setpoint1, Input1, Output1;
double Setpoint2, Input2, Output2;
//Specify the links and initial tuning parameters
double Kp1=2, Ki1=5, Kd1=1;
double Kp2=5, Ki2=2, Kd2=0.5;
PID myPID1(&Input1, &Output1, &Setpoint1, Kp1, Ki1, Kd1, DIRECT);
PID myPID2(&Input2, &Output2, &Setpoint2, Kp2, Ki2, Kd2, DIRECT);
void setup()
{
//initialize the variables we're linked to
Input1 = analogRead(PIN_INPUT1);
Input2 = analogRead(PIN_INPUT2);
Setpoint1 = 100;
Setpoint2 = 50;
//turn the PID1 on
myPID1.SetMode(AUTOMATIC);
//turn the PID2 on
myPID2.SetMode(AUTOMATIC);
}
void loop()
{
// PID 1
Input = analogRead(PIN_INPUT1);
myPID1.Compute();
analogWrite(PIN_OUTPUT1, Output1);
// PID 2
Input2 = analogRead(PIN_INPUT2);
myPID2.Compute();
analogWrite(PIN_OUTPUT2, Output2);
}
Muchas gracias por responder, hice lo que me ha sugerido y con eso pude hacer dos PID (myPID1 y myPID2), pero el my.PID2 no esta controlando el motor.
El motor conectado para los pines del PID1 esta funcionando correctamente y aclarar que ambos motores son el mismo tipo, por ello estoy usando los mismos parámetros para el PID.
El motor del PID1 responde de acuerdo a la entrada, en cambio el motor del PID2 se mantiene en constante movimiento hacia una sola dirección, ya probé el encoder y esta funcionando. también hice el cambio de motores, es decir, pasé el motor del PID1 al PID2 y viceversa aún así el PID1 funciona y el segundo sigue sin funcionar bien.
Aquí le muestro mi programa el cual estoy usando, no puse la parte del encoder porque no quería que fuera muy largo, además no creo que sea el problema.
#include <PID_v1.h>
#define EnableM1 3 //Enable motor 1 PWM
#define DirecionM1 1 // Motor Forward/Reverse pin 1
#define SleepM1 2
#define EnableM2 4 //Enable motor 2 PWM
#define DirecionM2 5 // Motor Forward/Reverse pin 5
#define SleepM2 6
#define sensor1 A0
#define sensor2 A1
int PPR = 1800; // Encoder Pulse per revolution. 360 grados -> 600 pulsos
int Referencia1 = 0; // Set point REQUIRED ENCODER VALUE 1
int Referencia2 = 0; // Set point REQUIRED ENCODER VALUE 2
int Val_Sensor1 = 0;
int Val_Sensor2 = 0;
double kp_uno = 1.1 , ki_uno = 0.19 , kd_uno = 0.001;
double input_uno = 0, output_uno = 0, setpoint_uno = 0;
PID myPID1(&input_uno, &output_uno, &setpoint_uno, kp_uno, ki_uno, kd_uno, DIRECT);
double kp_dos = 1.1 , ki_dos = 0.19 , kd_dos = 0.001;
double input_dos = 0, output_dos = 0, setpoint_dos = 0;
PID myPID2(&input_dos, &output_dos, &setpoint_dos, kp_dos, ki_dos, kd_dos, DIRECT);
void setup() {
//here, I put the code for the encoder and OUTPUTS Setup.
myPID1.SetMode(AUTOMATIC); //set PID in Auto mode
myPID1.SetSampleTime(1); // refresh rate of PID controller
myPID1.SetOutputLimits(-255, 225); // this is the MAX PWM value to move motor.
myPID2.SetMode(AUTOMATIC); //set PID in Auto mode
myPID2.SetSampleTime(1); // refresh rate of PID controller
myPID2.SetOutputLimits(-255, 225); // this is the MAX PWM value to move motor.
}
void loop(){
//PID1
Val_Sensor1 = analogRead(sensor1);
Referencia1 = map (Val_Sensor1, 0, 1023, 0, PPR);
setpoint_uno = Referencia1;
input_uno = encoderValue1;
myPID1.Compute(); // calculate new output
pwmOut_uno();
//PID2
Val_Sensor2 = analogRead(sensor2);
Referencia2 = map (Val_Sensor2, 0, 1023, 0, PPR);
setpoint_dos = Referencia2;
input_dos = encoderValue2;
myPID2.Compute(); // calculate new output
pwmOut_dos();
}
void pwmOut_uno() {
if (output_uno > 0) { // if Referencia > encoderValue1 motor move in forward direction.
analogWrite(EnableM1, output_uno); // Enabling motor PWM pin to reach the desire angle
forward_uno(); // calling motor to move forward
}
else {
analogWrite(EnableM1, abs(output_uno)); // if Referencia < encoderValue1 motor move in reverse.
reverse_uno(); // calling motor to move reverse
}
}
void pwmOut_dos() {
if (output_dos > 0) { // if Referencia > encoderValue2 motor move in forward direction.
analogWrite(EnableM2, output_dos); // Enabling motor enable pin to reach the desire angle
forward_dos(); // calling motor to move forward
}
else {
analogWrite(EnableM2, abs(output_dos)); // if Referencia < encoderValue12 motor move in reverse direction.
reverse_dos(); // calling motor to move reverse
}
}
void forward_uno () {
digitalWrite(SleepM1, HIGH);
digitalWrite(DirecionM1, LOW);
}
void reverse_uno () {
digitalWrite(SleepM1, HIGH);
digitalWrite(DirecionM1, HIGH);
}
void forward_dos () {
digitalWrite(SleepM2, HIGH);
digitalWrite(DirecionM2, LOW);
}
void reverse_dos () {
digitalWrite(SleepM2, HIGH);
digitalWrite(DirecionM2, HIGH);
}
void finish () {
digitalWrite(SleepM1, LOW);
digitalWrite(SleepM2, LOW);
}
Que Arduino usas ? porque si es Arduino UNO no puedes usar el pin D4 ya que no es PWM.
#define EnableM2 4 //Enable motor 2 PWM
PD: Los pines PWM son: 3, 5, 6, 9, 10 y 11.
Estoy usando el Teensy 3.2 en el cual todos los pines digitales se pueden usar para interrupción y los pines PWM son 3, 4, 5, 6, 9, 10, 20, 21, 22 y 23.
El PID que estoy haciendo para dos motores es solo el comienzo al final lo haré para 4 motores, a su vez usaré 4 encoders por lo cual necesitaré 8 pines de interrupción, es por eso que estoy usando el teensy 3.2.
Muchas gracias por sus respuestas, me funcionó bien con el código tal como esta en mi anterior comentario donde puse el programa.
Revisé todo nuevamente y me di cuenta que el problema era un jumper erl cual estaba en corto.
Estoy muy agradecido, ya que logré hacer dos PID haciendo dos objetos con la clase PID tal como me lo sugirió en el primer comentario.