Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Control motor using arduino PID and processing

Status
Not open for further replies.

satya82

Newbie level 6
Joined
Dec 29, 2013
Messages
14
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
82
Hi Forum

I had done PID code using arduino and hardware with feedback opto sensor.I just dont understand why my output shows 0 value or constant value 255.Can you advice please thank you.
 

can you provide any more details? What your Opto reads 0? is it going to a analog input?
 

Here is my arduino code.The Ao pin connect to the opto sensor and pwm pin 13 connect to output dc motor.

Code:
#include <PID_v1.h>
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
int inputPin=0, outputPin=3;
unsigned long serialTime;
//LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
#include <SoftwareSerial.h>
int ActPos = A1;    // select the input pin for feedback signal
int DesPos = A0;    // select the input pin for control signal

byte PWMOutput;
long Error[10];
long Accumulator;
long PID;
int PTerm;
int ITerm;
int DTerm;
byte Divider;
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(inputPin);
Setpoint = 100;
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
 myPID.SetMode(AUTOMATIC);
}
    
  
void GetError(void)
{
  byte i = 0;
  word ActualPosition = analogRead(ActPos);  
   word DesiredPosition = analogRead(DesPos);
    for(i=0;i<10;i++)
    Error[i+1] = Error[i];
    Error[0] = (long)DesiredPosition-(long)ActualPosition;
}
void CalculatePID(void)
{
   PTerm = 2000;
  ITerm = 25;
  DTerm = 0;
  Divider = 10;

// Calculate the PID  
  PID = Error[0]*PTerm;     // start with proportional gain
  Accumulator += Error[0];  // accumulator is sum of errors
  PID += ITerm*Accumulator; // add integral gain and error accumulation
  PID += DTerm*(Error[0]-Error[9]); // differential gain comes next
  PID = PID>>Divider; // scale PID down with divider
   if(PID>=127)
    PID = 127;
  if(PID<=-126)
    PID = -126;
 PWMOutput = PID + 127;
}
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(inputPin);
  myPID.Compute();
  analogWrite(outputPin,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++;
}
 

Dear Forum
Need your help regarding PID code using arduino and hardware with feedback opto sensor.I just dont understand why my output shows 0 value or constant value 255.Can you advice please thank you.
I already attach code .Hopefully you can help me please.Thank you.

Here is my arduino code.The Ao pin connect to the opto sensor and pwm pin 13 connect to output dc motor.

Code:
#include <PID_v1.h>
double Setpoint, Input, Output;
const double Kp=10;
const double Ki=0;
const double Kd=0;
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++;
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top