Control Systems - Part 3

Extracting Transfer Function of DC Motor

The Code and Data Acquisition 

The complete code is available on my Github

Now because we need different sets of input and output data, we need to see the response of motor over various values of voltage. We do this by varying PWM and measure the corresponding voltage.


PWM
Voltage (V)
255
10.4
100
7.56
75
6              
50
3.68

The table above shows the corresponding values of voltage measured when different values of output were given. Using this data, a simple ratio formula is deduced to calculate the voltage at PWM which can be any value from 50-255.

As you can observe that its not linear, and hence the formula only tells us the approximate voltage and not the actual voltage

float volts(int num1) {
   /* local variable declaration */
   float result;
   float num2;
   num2=num1;
   if(num2>=100){
    result=(num2-100)*0.01806;
    result=result+7.6;
   }
   else if(num2<100 && num2>75){
    result=(num2-75)*0.06;
    result=result+6; 
   }
   else{
    result=(num2-50)*0.0928;
    result=result+3.68;
   }
   return result;

The function volts will allow us to calculate the corresponding value of voltage for the PWM,

As the motor uses quadrature encoder, there are 2 outputs from the motor that gives pulses. These pulses are counted and converted to revolutions/second and radians/second.

void EncoderInit()
{
  Direction = true;//default -> Forward  
  pinMode(encoder0pinB,INPUT);  
  attachInterrupt(0, wheelSpeed, CHANGE);
}
void wheelSpeed()
{
  int Lstate = digitalRead(encoder0pinA);
  if((encoder0PinALast == LOW) && Lstate==HIGH)
  {
    int val = digitalRead(encoder0pinB);
    if(val == LOW && Direction)
    {
      Direction = false; //Reverse
    }
    else if(val == HIGH && !Direction)
    {
      Direction = true;  //Forward
    }
  }
  encoder0PinALast = Lstate;
  if(!Direction)  duration++;
  else  duration--;

An interrupt service routine is called every time an impulse is received which allows us to measure impulses for the desired time.

 long rpm1(unsigned long d){

  long result1;
  
  result1 = (duration/2)*600;
  result1 = result1/1440;

  return result1;
}

float rad(long a){

  float result2;

  result2 = a*0.1047;

  return result2;

}

The above two functions converts impulses to rpm and rpm to rad/s. 

The latest commit in the code gives steps of 2 volts. For other inputs refer to the commit history on github

 for(int pwm=100; pwm<256;pwm++){
    analogWrite(speedPinA, pwm);//Sets speed variable via PWM 
    delay(100);
    time = millis();
    }

for(int pwm=255; pwm >99;pwm--){
    analogWrite(speedPinA, pwm);//Sets speed variable via PWM 
    delay(100);
    time = millis();
    }

Above two blocks, allow us to give ramp input and see the corresponding. All the different data sets I acquired are also uploaded on Github.




The figure above shows the data we have acquired. We can see how motor behaves to the step and ramp input. 
    

Comments