// Function prototypes
void encoderISR();
int pidControl(int setPoint, float actual);
// Pin definitions
const int motorPin1 = 7; // Motor driver input pin 1
const int motorPin2 = 8; // Motor driver input pin 2
const int enablePin = 9; // Motor driver enable pin (PWM control)
const int encoderPinA = 2; // Encoder signal A pin
const int encoderPinB = 3; // Encoder signal B pin
// Constants and Variables
const int numReadings = 5; // Number of readings for averaging
unsigned long readings[numReadings]; // Array to store pulse durations
int readIndex = 0;
unsigned long total = 0;
int average = 0;
volatile unsigned long lastTime = 0;
volatile unsigned long pulseDuration = 0;
const int PPR = 240; // Pulses Per Revolution (Adjust based on your encoder)
// PID constants
float Kp = 1.0;
float Ki = 0.5;
float Kd = 0.1;
float integral = 0;
float previousError = 0;
const long interval = 100; // Interval in milliseconds for PID calculations
// Desired and current speed
int desiredSpeed = 100; // Desired speed in RPM
float currentSpeed = 0;
void setup() {
// Set motor pins as outputs
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(enablePin, OUTPUT);
// Set encoder pins as inputs
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
// Attach interrupt to encoder pin A
attachInterrupt(digitalPinToInterrupt(encoderPinA), encoderISR, FALLING);
// Start Serial Monitor
Serial.begin(9600);
// Initialize lastTime
lastTime = micros();
}
void loop() {
noInterrupts();
// Update readings
total = total - readings[readIndex];
readings[readIndex] = pulseDuration;
total = total + readings[readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
interrupts();
// Calculate average pulse duration
average = total / numReadings;
// Calculate current speed (RPM)
if (average > 0) {
currentSpeed = (60.0 * 1000000.0) / (average * (float)PPR);
} else {
currentSpeed = 0; // Avoid division by zero
}
Serial.print("Average Pulse Duration: ");
Serial.print(average);
Serial.println(" microseconds");
Serial.print("Current Speed: ");
Serial.print(currentSpeed);
Serial.println(" RPM");
// PID control
int pwmValue = pidControl(desiredSpeed, currentSpeed);
// Set motor speed
analogWrite(enablePin, pwmValue);
// Print PID output and PWM value for debugging
Serial.print("PID Output: ");
Serial.print(pwmValue);
Serial.println(" PWM");
delay(100); // Delay to prevent overwhelming the serial monitor
}
// Encoder ISR
void encoderISR() {
unsigned long currentTime = micros();
pulseDuration = currentTime - lastTime;
lastTime = currentTime;
}
// PID control function
int pidControl(int setPoint, float actual) {
float error = setPoint - actual;
integral += error * interval / 1000.0;
float derivative = (error - previousError) / (interval / 1000.0);
int output = Kp * error + Ki * integral + Kd * derivative;
previousError = error;
// Constrain output to PWM range
return constrain(output, 0, 255);
}
will code work for speed control of a dc motor. I am using l293d motor driver, CH-N20-3 encoded dc motor and arduino uno