J-M-L:
Made a small mistake in the constraining, as ∆pwm will actually be a signed number so you need to constrain the resulting value keeping the sign.
Assume you have N1 steps for Motor1 and N2 steps for Motor2
If the error is written as (N2 - N1) then when the error is positive it means N2 is greater than N1 which translates into Motor2 has done more steps than Motor1 in a given time and thus you need to slow Motor2 and accelerate Motor1.
The PID formulas will mess around with the error but the resulting ∆pwm will still represent a correction that will respect this idea of minimizing the error through accelerating one and slowing down the other one.
==> So the way you calculate the error gives you which one gets the + (∆pwm / 2) and which one gets the - (∆pwm / 2)
makes sense ?
Yes, I think I understood.
I've written a code, but it didn't show any result.
Here is the code:
#include <Arduino.h>
#include <PID_v1.h>
//#include <analogWrite.h>
//#include <EnableInterrupt.h>
const int pinA = 14;//23;//14
const int pinB = 4;//22;//4
int N1 = 0, sumN1 = 0;
int N2 = 0, sumN2 = 0;
//PID stuff
double error = 0, desired = 0, dPWM = 0;
int kp = 7;
int ki = 0;
int kd = 0;
PID speed_PID(&error, &dPWM, &desired, kp, ki, kd, DIRECT);
//Motor A
int enA = 16;//32;
int in1 = 13;//33;
int in2 = 15;//25;
//Motor B
int enB = 12;//13;
int in3 = 5;//26;
int in4 = 0;//27;
int speed = 400;
//Reading the rising edges
void IRAM_ATTR cntA() {
N1++;
//Serial.print("N1:");
//Serial.println(N1);
}
void IRAM_ATTR cntB() {
N2++;
//Serial.print("N2:");
//Serial.println(N2);
}
//Stop function
void Stop(){
analogWrite(enA, 0);
analogWrite(enB, 0);
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
sumN1 += N1; //store the taken ticks
sumN2 += N2;
N1 = 0; // reset counter A to zero
N2 = 0; // reset counter B to zero
}
//PID
void myPID(){
error = sumN2 - sumN1;
speed_PID.Compute();
}
void Print(){
Serial.println("dPWM: ");
Serial.println(dPWM);
Serial.println("error: ");
Serial.println(error);
Serial.println("sumN1: ");
Serial.println(sumN1);
Serial.println("sumN2: ");
Serial.println(sumN2);
Serial.println();
Serial.println();
}
//Forvard function
void Forward(int steps,int mspeed){
N1 = 0; // reset counter A to zero
N2 = 0; // reset counter B to zero
// Set Motor A forward
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set Motor B forward
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Go forward until step value is reached
while (steps > N1 && steps > N2) {
myPID();
//slow M2, accelerate M1 speed
if (error >= 0){
if (steps > N1) {
analogWrite(enA, mspeed+(dPWM/2));
} else {
analogWrite(enA, 0);
}
if (steps > N2) {
analogWrite(enB, mspeed-(dPWM/2));
} else {
analogWrite(enB, 0);
}
}
//slow M1, accelerate M2 speed
if (error < 0){
if (steps > N1) {
analogWrite(enA, mspeed-(dPWM/2));
} else {
analogWrite(enA, 0);
}
if (steps > N2) {
analogWrite(enB, mspeed+(dPWM/2));
} else {
analogWrite(enB, 0);
}
}
delay(0);
}
// Stop when done
Stop();
}
//Backward function
void Backward (int steps, int mspeed) {
N1 = 0; // reset counter A to zero
N2 = 0; // reset counter B to zero
// Set Motor A forward
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// Set Motor B forward
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
while (steps > N1 && steps > N2){
myPID();
//slow M2, accelerate M1 speed
if (error >= 0){
if (steps > N1) {
analogWrite(enA, mspeed+(dPWM/2));
} else {
analogWrite(enA, 0);
}
if (steps > N2) {
analogWrite(enB, mspeed-(dPWM/2));
} else {
analogWrite(enB, 0);
}
}
//slow M1, accelerate M2 speed
if (error < 0){
if (steps > N1) {
analogWrite(enA, mspeed-(dPWM/2));
} else {
analogWrite(enA, 0);
}
if (steps > N2) {
analogWrite(enB, mspeed+(dPWM/2));
} else {
analogWrite(enB, 0);
}
}
delay(0);
}
// Stop when done
Stop();
}
void setup()
{
Serial.begin(115200);
pinMode(in1,OUTPUT);
pinMode(in2,OUTPUT);
pinMode(enA,OUTPUT);
pinMode(in3,OUTPUT);
pinMode(in4,OUTPUT);
pinMode(enB,OUTPUT);
//Interrupts
attachInterrupt(digitalPinToInterrupt (pinA), cntA, RISING);
attachInterrupt(digitalPinToInterrupt (pinB), cntB, RISING);
//PID
speed_PID.SetOutputLimits(-50, 1023);
speed_PID.SetMode(AUTOMATIC);
}
void loop()
{
Forward(120,speed);
Print();
delay(2000);
Backward(120,speed);
Print();
delay(2000);
}
I'd like to know that if the code is correct, and the only problem is the PID tuning.