How do I implement PI control into my DC motor speed controller?

Hi guys,

I am working on a project where I need to control the speed on my DC Motor using PI control, I am using an Arduino Uno, shield and an Opto Sensor to sense the speed from the motor:

I would like to know how to implement the PI control into the program I have previously written which currently allows for the potentiometer in my Arduino shield to control the speed, however what I need to achieve is controlling the speed on the motor when a load is applied, so that the program senses the load an adjusts the speed accordingly (using PI control).

Please help me as much as possible please.

// A Opto sensor to pin 2
#define OptoSen 2
#define RedLED 6
#define WhiteLED 5 
#define POT 2

// PI Parameters
float kp = 0.1; // proportional gain
float Output = 0; // motorVal

//count needs to be a global variable. It is modified in the interrupt service
// procedure, so needs to be qualified as volitile.
volatile unsigned int count=0;
int potPin = A2;
int motorPin = 9;
int potVal = 0;
int motorVal = 0;



void setup() {
 // put your setup code here, to run once:
pinMode(OptoSen, INPUT); // Used here to sense motor
pinMode(RedLED, OUTPUT);
pinMode(WhiteLED, OUTPUT);
attachInterrupt(0, countup, RISING); // Make a rising signal from the opto-sensor
                                     // trigger a count up
interrupts(); // Enable the interrupts
Serial.begin(9600); // Set up serial for monitoring
}
/* This is the interrupt service procedure. It increments a counter, that's
  pretty well all! Deciding what to do with the value is done in the main
  loop.
  */
void countup() {
 count++;
}

void loop() {
 // put your main code here, to run repeatedly:

 boolean red=0;
 unsigned int c=0;
 unsigned int rpm=0;
 unsigned int oneSecondCount=0;
 unsigned int val=0;
 long int startTime,nowTime,elapsedTime; // For timing the loop
 int setrpm;
 signed int error; 

 
while (c>2000){
  startTime=millis();
  digitalWrite(RedLED,red); // flash this to show life
  red=!red;
  
  // Wait till one second has elapsed
  elapsedTime=0; // reset
  while (elapsedTime <1000){
    // This bit happens for exactly 1 second
     val = analogRead(POT);
     val = val/4;
    analogWrite(WhiteLED,val);
    nowTime=millis();
    elapsedTime = nowTime - startTime;
            } // End of one second loop
  oneSecondCount = count; // Store the counts in the last second
  count = 0;              // reset count
     // Work out the rpm and display
  rpm=(oneSecondCount*60); // Multiply by 60, for pulses per minute
  rpm=((rpm+5)/10)*10; // Round to the nearest 10
  Serial.print(" Speed = ");
  Serial.print(rpm);
  
  c++;


  potVal = analogRead(potPin);
  setrpm = map(potVal, 0, 1023, 0, 3000);
  float Ouput =  kp*error;
  if(Output > 255) Output = 255;
  if(Output < 0) Output = 0;
  analogWrite(motorPin, motorVal);
  Serial.print("rpm, potentiometer = ");
  Serial.print(potVal);
  Serial.print("\t motor = ");
  Serial.println(motorVal);
  delay(2);
  // Keep doing this for 2000 seconds!
}
}
[code]

[/code]

Pcontrol.ino (2.4 KB)

Might I also add that this (below) was my original program which worked and allowed for the RedLED (Pin6) to light up when power, allowed for the WhiteLED (Pin5) to increase and decrease according to the position of the potentiometer, and for my potentiometer (A2) to control the speed of the DC motor.

In the program I am trying to add PI control none of these command work any more and I’m uncertain as to why?

However my Opto sensor still seems okay, which is great.

/* This program is for demo of motor speed measurement.
  */

// A Opto sensor to pin 2
#define OptoSen 2
#define RedLED 6
#define WhiteLED 5
#define POT 2





// count needs to be a global variable. It is modified in the interrupt service
// procedure, so needs to be qualified as volatile.
volatile unsigned int count=0;
int potPin = A2;
int motorPin = 9;
int potValue = 0;
int motorValue = 0;


void setup(){
 pinMode(OptoSen, INPUT); // Used here to sense the wheel
 pinMode(RedLED, OUTPUT);
 pinMode(WhiteLED, OUTPUT);
 attachInterrupt(0, countup, RISING); // Make a rising signal from the opto-sensor
                                      // trigger a count up
 interrupts(); // Enable the interrupts
 Serial.begin(9600);  // Set up serial for monitoring
}

/* This is the interrupt service procedure. It increments a counter, that's
  pretty well all! Deciding what to do with the value is done in the main
  loop.
  */
void countup() {
 count++;
}


void loop(){
 
 boolean red=0;
 unsigned int c=0;
 unsigned int rpm=0;
 unsigned int oneSecondCount=0;
 unsigned int val=0;
 long int startTime,nowTime,elapsedTime; // For timing the loop

 
 while (c<2000){
   startTime=millis();
   digitalWrite(RedLED,red); // flash this to show life
   red=!red;
  
   // Wait till one second has elapsed
   elapsedTime=0; // reset
   while (elapsedTime <1000){
     // This bit happens for exactly 1 second
     val = analogRead(POT);
     val = val/4;
     analogWrite(WhiteLED,val);
     nowTime=millis();
     elapsedTime = nowTime - startTime;
                      } // End of one second loop
   oneSecondCount = count; // Store the counts in the last second
   count = 0;              // Reset count
       // Work out the rpm and display
   rpm=(oneSecondCount*60);   // Multiply by 60, for pulses per minute
   rpm=((rpm+5)/10)*10;   // Round to the nearest 10                             
   Serial.print(" Speed = ");
   Serial.print(rpm);
  
   c++; 
   
   
   potValue = analogRead(potPin);  
motorValue = map(potValue, 0, 1023, 0, 255);
analogWrite(motorPin, motorValue);  
Serial.print("rpm,  potentiometer = " );     
Serial.print(potValue);
Serial.print("\t motor = ");
Serial.println(motorValue);
delay(2);    
 // Keep doing this for 2000 seconds!
 }
}
[code]

I had hoped to learn something here.

Now I am going to Google "Arduino PID" and you may choose to do the same

...R