I'm using this video from DroneBot Workshop that allows for sensing the DC motor RPM with a rotary encoder(attached to the DC motor). It measures the RPM of the motor, and it reflects the value changing as you physically try to stop the motor from turning.
I've been trying to create a program that works on angle control, similar to this video that uses PID. I'm not necessarily invested in using PID but was wondering what steps I should take if I just want to control the angle (set it to a specific value).
I'd ideally want it to act as a sort of control system in the sense that if I move the DC motor shaft, it would try to return to the original angle set. My current thinking is creating a program that would constantly compare the actual angle value to the set value and if it's less than the set value then increase it (rotate CW), and if it's greater than the set value then decrease it (rotate CCW).
I have attached the setup I have at the moment (from the DroneBot Workshop video).
I would start with the sketch from the video and remove the PID library:
const byte MotEnable = 6; //Motor Enamble pin Runs on PWM signal
const byte MotFwd = 4; // Motor Forward pin
const byte MotRev = 7; // Motor Reverse pin
int User_Input = 0; // This while convert input string into integer
const byte encoderPin1 = 2; //Encoder Output 'A' must connected with intreput pin of arduino.
const byte encoderPin2 = 3; //Encoder Otput 'B' must connected with intreput pin of arduino.
volatile int lastEncoded = 0; // Here updated value of encoder store.
volatile long encoderValue = 0; // Raw encoder value
const int PPR = 1600; // Encoder Pulse per revolution.
int angle = 360; // Maximum degree of motion.
int REV = 0; // Set point REQUIRED ENCODER VALUE
int lastMSB = 0;
int lastLSB = 0;
// double kp = 5 , ki = 1 , kd = 0.01; // modify for optimal performance
// double input = 0, output = 0, setpoint = 0;
int input = 0, output = 0, setpoint = 0;
void setup()
{
pinMode(MotEnable, OUTPUT);
pinMode(MotFwd, OUTPUT);
pinMode(MotRev, OUTPUT);
Serial.begin(9600); //initialize serial comunication
pinMode(encoderPin1, INPUT_PULLUP);
pinMode(encoderPin2, INPUT_PULLUP);
//call updateEncoder() when either pin changes
attachInterrupt(digitalPinToInterrupt(encoderPin1), updateEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPin2), updateEncoder, CHANGE);
TCCR1B = (TCCR1B & 0b11111000) | 1; // set 31KHz PWM to prevent motor noise
}
void loop()
{
if (Serial.available()) //Check if the serial data is available.
{
User_Input = Serial.parseInt();
while (Serial.available())
Serial.read(); // Empty the remainder of the input buffer
REV = map (User_Input, 0, 360, 0, PPR); // mapping degree into pulse
Serial.print("this is REV - ");
Serial.println(REV); // printing REV value
}
setpoint = REV; // PID while work to achive this value consider as SET value
Serial.print("encoderValue - ");
Serial.println(encoderValue);
input = encoderValue; // data from encoder consider as a Process value
// Simple proportional control
output = constrain(setpoint - input, -255, 255);
if (output == 0)
{
finish(); // Stop
}
else if (output > 0) // if setpoint > input, move in forward direction.
{
analogWrite(MotEnable, output);
forward();
}
else // if setpoint < input, move in reverse direction.
{
analogWrite(MotEnable, -output);
reverse();
}
}
void updateEncoder()
{
int MSB = digitalRead(encoderPin1); //MSB = most significant bit
int LSB = digitalRead(encoderPin2); //LSB = least significant bit
int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
lastEncoded = encoded; //store this value for next time
}
void forward ()
{
digitalWrite(MotFwd, HIGH);
digitalWrite(MotRev, LOW);
}
void reverse ()
{
digitalWrite(MotFwd, LOW);
digitalWrite(MotRev, HIGH);
}
void finish ()
{
digitalWrite(MotFwd, LOW);
digitalWrite(MotRev, LOW);
}