0

I'm writing a PID program for a simple DC Motor. This motor has an encoder at the bottom which allows me to read motor speed. The goal of the project is to provide a constant speed if there is light friction applied to the motor. Although speed may vary slightly, I can still graph the PWM signal and show the duty cycle increases in response to friction. I've gotten the motor speed and potentiometer to function perfectly, now I'm just stuck on the actual PID part.

The issue I'm having is that whenever I set my SET pin high, the motor completely shuts off. I don't understand why because I'm sending it values in that while loop which should be sufficient to initiate the compensation

Here is my code:

#include "TimerOne.h"
#include <PID_v1.h>

int counter=0;
//Polarity
const int IN1 = 11;
const int IN2 = 10;

volatile float pot=0;
//PWM Signal and Analog from the Potentiometer
const int POT = 0;
const int ENA = 6;

const int SET = 12;

int rotation;

double Setpoint, Input, Output;
double Kp=1, Ki=1, Kd=1;

PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


void docount()  // counts from the speed sensor
{
  counter++;  // increase +1 the counter value
} 

//This takes the docout() counter and calculates how many holes its read to give rotations per second
void timerIsr()
{
  Timer1.detachInterrupt();  //stop the timer
  Serial.print("Motor Speed: "); 
  rotation = (counter / 31);  // divide by number of holes in Disc
  Serial.print(rotation,DEC); 


  Serial.println(" Rotation per second"); 
  counter=0;  //  reset counter to zero
  Timer1.attachInterrupt( timerIsr );  //enable the timer
  Serial.print("pot = ");
  Serial.print(pot);

  Serial.print("\n");


}

void setup() 
{
  Serial.begin(9600);

  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT); 
  pinMode(SET, INPUT);
  Timer1.initialize(1000000); // set timer for 1sec
  attachInterrupt(0, docount, FALLING);  // increase counter when speed sensor pin goes High
  Timer1.attachInterrupt( timerIsr ); // enable the timer

  myPID.SetMode(AUTOMATIC);
  myPID.SetSampleTime(10);
} 

void loop()
{
  // This bit is how you convert the pot values to manually control the fan
  pot=analogRead(POT)/4.01569;
  analogWrite(ENA, pot);

  // This basically acts as a push button. If the SET pin is HIGH it initiates the PID and whatever
  // the current rotation and pot setting are, they're used to send to the myPID function above to 
  // maintain current operating values
  while (digitalRead(SET) == HIGH)
  {

      Setpoint = rotation;
      Input = pot;
      myPID.Compute();
      analogWrite(ENA, Output);
      digitalWrite(10, HIGH);  // set rotation of motor to Clockwise
      digitalWrite(11, LOW);

  }
  digitalWrite(10, HIGH);  // set rotation of motor to Clockwise
  digitalWrite(11, LOW);



  delay (50);
}
  • 1
    1. You haven't implemented any of the suggestions, that I gave in my answer to your previous question. Did you find them not fitting? Or were something unclear? Then please comment on my answer, so that it can be approved. – chrisl Apr 29 at 16:15
  • 2. Your logic seems garbled. I thought you use the pot (which is constant while SET is HIGH, since you don't read it there) to control the setpoint, but currently you use it for input of the PID, which should instead be the current speed value. – chrisl Apr 29 at 16:18
  • And most likely your while loop runs so fast, that the PWM wave gets restarted again and again, effectively chopping it up to zero, which means no speed – chrisl Apr 29 at 16:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.