#include
// Define the input, output, and setpoint variables
double Setpoint, Input, Output;
// Specify the PID tuning parameters
double Kp = 2.0, Ki = 5.0, Kd = 1.0;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
// Motor control pins
const int motorPin1 = 18;
const int motorPin2 = 19;
// Encoder input pins
const int encoderPin1 = 34;
const int encoderPin2 = 35;
// Variables for encoder
volatile int encoderPos = 0;
int encoderPosLast = 0;
// Timer for PID sampling
unsigned long lastTime = 0;
unsigned long sampleTime = 100; // 100ms
void setup() {
// Set motor control pins as outputs
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
// Set encoder pins as inputs
pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);
// Attach interrupts for encoder
attachInterrupt(digitalPinToInterrupt(encoderPin1), readEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPin2), readEncoder, CHANGE);
// Initialize PID controller
Setpoint = 200; // Desired RPM
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(-255, 255);
Serial.begin(115200);
}
void loop() {
// Read the current speed from the encoder
Input = readRPM();
// Run the PID computation if sample time has passed
if (millis() - lastTime >= sampleTime) {
lastTime = millis();
myPID.Compute();
// Control the motor based on PID output
if (Output > 0) {
analogWrite(motorPin1, Output);
analogWrite(motorPin2, 0);
} else {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, -Output);
}
Serial.print("RPM: ");
Serial.println(Input);
}
}
// Encoder reading function
void readEncoder() {
int state1 = digitalRead(encoderPin1);
int state2 = digitalRead(encoderPin2);
if (state1 == state2) {
encoderPos++;
} else {
encoderPos--;
}
}
// Function to calculate RPM
double readRPM() {
int deltaPos = encoderPos - encoderPosLast;
encoderPosLast = encoderPos;
return (deltaPos / 20.0) * 60.0; // Convert to RPM
}