PID code for controlling speed dc motor.

Dear Forum
Can you please check my code because the ouput value shows 0. I connect pin 3 output for dc motor and pin 2 for the opto sensor.

/*
Adafruit Arduino - Lesson 15. Bi-directional Motor
*/
//#include <LiquidCrystal.h>
#include <PID_v1.h>
double Setpoint, Input, Output;
const double Kp=0.1;
const double Ki=0;
const double Kd=0.3;
PID myPID(&Input, & Output, &Setpoint, Kp, Ki, Kd, DIRECT);
int inputPin=0, outputPin=3;
unsigned long serialTime;
//LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;
int enablePin = 11;
int in1Pin = 10;
int in2Pin = 9;
int switchPin = 8;
int potPin = 1;


void setup()
{
  Serial.begin(9600);
pinMode(in1Pin, OUTPUT);
pinMode(in2Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
//lcd.begin(16, 2);
//lcd.print("rpm!");
Serial.begin(9600); 
Input = analogRead(0);
Setpoint = 100;
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
 myPID.SetMode(AUTOMATIC);
//}
    
//union {                // This Data structure lets
  //byte asBytes[24];    // us take the byte array
  //float asFloat[6];    // sent from processing and
//}                      // easily convert it to a
//foo;                   // float array
}
void SerialReceive()
{

   //read the bytes sent from Processing
  int index=0;
  byte Auto_Man = -1;
  byte Direct_Reverse = -1;
  while(Serial.available()&&index<26)
  {
    if(index==0) Auto_Man = Serial.read();
    else if(index==1) Direct_Reverse = Serial.read();
    //else foo.asBytes[index-2] = Serial.read();
    index++;
   
}
}
  
  // if the information we got was in the correct format, 
  // read it into the system
  //if(index==26  && (Auto_Man==0 || Auto_Man==1)&& (Direct_Reverse==0 || Direct_Reverse==1))
 // {
   // Setpoint=double(foo.asFloat[0]);
    //Input=double(foo.asFloat[1]);       // * the user has the ability to send the 
                                          //   value of "Input"  in most cases (as 
                                          //   in this one) this is not needed.
   // if(Auto_Man==0)                       // * only change the output if we are in 
   // {                                     //   manual mode.  otherwise we'll get an
   //   Output=double(foo.asFloat[2]);      //   output blip, then the controller will 
   // /}                                     //   overwrite.
     
void loop()
{
  Input = analogRead(0);
  myPID.Compute();
  analogWrite(3,Output);
int speed = analogRead(potPin) / 4;
myPID.Compute();
boolean reverse = digitalRead(switchPin);
setMotor(speed, reverse);

 if (millis() - lastmillis >= 1000){  //Uptade every one second, this will be equal to reading frecuency (Hz).
 detachInterrupt(0);    //Disable interrupt when calculating
 
 
 rpm = rpmcount * 60;  // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.
 
 Serial.print("RPM =\t"); //print the word "RPM" and tab.
 Serial.print(rpm); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount); //print revolutions per second or Hz. And print new line or enter.
 
 rpmcount = 0; // Restart the RPM counter
 lastmillis = millis(); // Uptade lasmillis
 attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
 if(millis()>serialTime)
  {
    SerialReceive();
    SerialSend();
   serialTime+=500;
  }
  }
                         
}
void SerialSend()
{
  Serial.print("PID ");
  Serial.print(Setpoint);   
  Serial.print(" ");
  Serial.print(Input);   
  Serial.print(" ");
  Serial.print(Output);   
  Serial.print(" ");
  Serial.print(myPID.GetKp());   
  Serial.print(" ");
  Serial.print(myPID.GetKi());   
  Serial.print(" ");
  Serial.print(myPID.GetKd());   
  Serial.print(" ");
  if(myPID.GetMode()==AUTOMATIC) Serial.print("Automatic");
  else Serial.print("Manual");  
  Serial.print(" ");
  if(myPID.GetDirection()==DIRECT) Serial.println("Direct");
  else Serial.println("Reverse");
}


void setMotor(int speed, boolean reverse)
{
analogWrite(enablePin, speed);
digitalWrite(in1Pin, ! reverse);
digitalWrite(in2Pin, reverse);
}

void rpm_fan(){ // this code will be executed every time the interrupt 0 (pin2) gets low.
  rpmcount++;
}

I connect pin 3 output for dc motor

Does this mean that the Arduino's pin 3 is controlling the motor speed?

and pin 2 for the opto sensor

What kind of opto sensor? Is the thing being sensed connected to the non-moving motor?

  Input = analogRead(0);

Input should be based on the speed of the motor, shouldn't it? What are you reading from?

  myPID.Compute();
  analogWrite(3,Output);
int speed = analogRead(potPin) / 4;
myPID.Compute();

Why are you calling Compute() twice? What are you reading from the potPin?

If it helps, here’s a piece of code I wrote AGES ago using the same PID library, it was to control a FBW throttle using a manual pot in a completely non safety critical application, and was nothing more than a bare bones functional of the motor driving hardware that later on went to see use in a project with C code written in Atmel Studio on a custom controller.

#include <PID_v1.h>

const int pwm_pin = 6;
const int in_a_pin = 5;
const int in_b_pin = 4;
const int en_a_pin = 9;
const int en_b_pin = 7;
const int current_sense_pin = A0;

const int pps_pin = A3;
const int tps1_pin = A1;
const int tps2_pin = A2;

double duty_cycle = 0;
double current_reading = 0;
double pps = 0;
double tps1 = 0;
double tps2 = 0;
double tps_sum = 0;

float current = 0;

PID throttle_PID(&tps1, &duty_cycle, &pps, 2, 0, 0, 0); // last zero is there, because direction is set in loop

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

  pinMode(pwm_pin, OUTPUT);
  pinMode(in_a_pin, OUTPUT);
  pinMode(in_b_pin, OUTPUT);
  pinMode(en_a_pin, INPUT);
  pinMode(en_b_pin, INPUT);
  pinMode(current_sense_pin, INPUT);

  digitalWrite(in_a_pin, LOW);
  digitalWrite(in_b_pin, LOW);

  throttle_PID.SetMode(AUTOMATIC);
  throttle_PID.SetSampleTime(5);
  throttle_PID.SetOutputLimits(0, 255);

  TCCR0B = TCCR0B & 0b11111000 | 0x03; // set pwm to 976Hz
}

void loop()
{
  tps1 = analogRead(tps1_pin);
  // tps2 = analogRead(tps2_pin);
  // tps_sum = tps1 + tps2;

  // Serial.println(tps1);
  // Serial.println(tps2);

  pps = analogRead(pps_pin);
  // pps = map(pps, 0, 1023, 150, 980);
  // Serial.println(pps);

  if (pps >= tps1)
  {
    digitalWrite(in_a_pin, HIGH);
    digitalWrite(in_b_pin, LOW);

    throttle_PID.SetControllerDirection(DIRECT);

    throttle_PID.Compute();
    analogWrite(pwm_pin, duty_cycle);
  }

  if (pps <= tps1)
  {
    digitalWrite(in_a_pin, LOW);
    digitalWrite(in_b_pin, HIGH);

    throttle_PID.SetControllerDirection(REVERSE);

    throttle_PID.Compute();
    analogWrite(pwm_pin, duty_cycle);
  }

 /*if (pps >= 155 <= 165 && tps1 >= 170 <= 180)
  {
    digitalWrite(in_a_pin, LOW);
    digitalWrite(in_b_pin, LOW);
    analogWrite(pwm_pin, 0);
  }*/

  // current_reading = analogRead(current_sense_pin);
  // Serial.println(current_reading);
}

The whole idea behind PID is that it takes a setpoint and some input value. It computes how much error there is, and determines what adjustment needs to be made to get the input closer to the setpoint.

The setpoint and input need to be related, and the output used to influence the process.

What does your setpoint value represent? What is your input value? Are they, in fact, related?

You have a variable called speed that looks like what should be the input to the PID process, but is in reality some potentiometer reading, which: 1) Seems irrelevant to the PID process 2) You haven't defined WHAT the potentiometer is actually defining

I'm about to give up, since you won't answer questions.

I usually get input 969 value.

From here:

  Input = analogRead(0);

where

Analog A0 pin used as feedback for potientional meter .

You STILL haven't described what moves this potentiometer and how the position of the potentiometer is supposed to reflect the speed of the motor.

Analog AO pin used for potentiometer to control speed of the motor(to increase or decrease speed motor). The opto encoder sensor as the feedback to the PID.

This doesn't make sense. It turning the potentiometer causes the motor speed to change, how can you make the Arduino control the speed? Are you controlling a servo that turns the potentiometer?

You need to be reading the feedback as the input to the PID process, not the potentiometer?