속도 테스트3 No class, Use pid - suakii/oddMotorStudy GitHub Wiki

이번에는 속도를 PID 제어를 통해 테스팅 해봅니다.

이를 통해 원하는 속도에 보다 빠르게 근접하는 것을 확인할 수 있습니다.

/*
 * Speed Test wit PID
 * class를 사용하지 않는 형태임 
 * 다음 작업에서는 클래스를 사용한 형태로 변환
 * [email protected]
 * 아래 코드 중 pid 제어부분과 switch 부분은
 * [canDynamix] 모터 속도 테스트  (광주로봇동호회_[깡통로봇연구소]) |작성자 Baram
*  코드를 참고하여 작성하였음을 밝힙니다.
 */
//arduino pid library
//https://playground.arduino.cc/Code/PIDLibrary
#include "src/PID_v1.h"

int pulses, currentPulses;
int motorSpeed;
    
int encoderA = 2;//아두이노2번핀 -- 모터의 3번핀 Encoder A Phase
int encoderB = 4;//아두이노4번핀 --- 모터의 4번핀 Encoder B Phase
int motorPlus = 5;//아두이노5번핀 -- 모터 드라이버의 A-1A                      
int motorMinus = 6;//아두이노 6번핀 --모터 드라이버의 A-1B  

int state = 0;
unsigned long pre_time = millis();
unsigned long pre_time_log = millis();
unsigned long pre_time_delay = millis();
int  pwm = 0;//motor pwm valuf for control

double enc_speed, goal_speed, pwm_output;
double Kp=30, Ki=20, Kd=0;
//PID(&Input, &Output, &Setpoint, Kp, Ki, Kd, Direction)
PID motorPID(&enc_speed, &pwm_output, &goal_speed, Kp, Ki, Kd, DIRECT);




void setup() {
  pinMode(encoderA, INPUT_PULLUP);//인코더 값을 읽기 위하여 내부 풀업 저항 사용 
  pinMode(encoderB, INPUT_PULLUP);
 
  
  attachInterrupt(0, A_CHANGE, CHANGE);//
   
  analogWrite(motorPlus, 0);//초기 모터 정지
  analogWrite(motorMinus, 0);
 
  Serial.begin(115200);//시리얼로 값을 보내기 위한 작업
  motorPID.SetSampleTime(10);
  motorPID.SetOutputLimits(0, 255);
  motorPID.SetMode(AUTOMATIC);
  goal_speed = 0;

}
bool pulsesChanged = false;

void loop() {

  /*
  2초마다 goal speed 를 증가시키고 있음.
  */
   switch(state)
  {
    case 0:
      if (millis()-pre_time_delay >= 2000)
      {
        pre_time_delay = millis();
        state = 1;
        goal_speed = 5;
      }
      break;

    case 1:
      if (millis()-pre_time_delay >= 2000)
      {
        pre_time_delay = millis();
        state = 2;
        goal_speed = 10;
      }
      break;

    case 2:
      if (millis()-pre_time_delay >= 2000)
      {
        pre_time_delay = millis();
        state = 3;
        goal_speed = 15;
      }
      break;
    case 3:
      if (millis()-pre_time_delay >= 2000)
      {
        pre_time_delay = millis();
        state = 4;
        goal_speed = 20;
      }
      break;
    case 4:
     if (millis()-pre_time_delay >= 2000)
      {
        pre_time_delay = millis();
        state = 5;
       goal_speed = 25;
      }
      break;
       case 5:
      if (millis()-pre_time_delay >= 2000)
      {
        pre_time_delay = millis();
        state = 0;
        goal_speed = 0;  
      }
      break;    
  }
  //pid input value 
  //현재 속도가 다시 pid로 들어감.
  enc_speed = motorSpeed;
  
  //pip에서 연산 후 ouput 값을 가지고 실제 모터 컨트롤
  if (motorPID.Compute() == true)
  {
    pwm = constrain(pwm_output, 0, 255);
    analogWrite(motorPlus, pwm);//계산된 값을 적용
  }
	//이전과 다르게 10ms 당 속도를 측정하고 있음.
  // pid의 계산시간 역시 10ms로 맞추어져 있음.
	if (millis()-pre_time >= 10)
  {
    pre_time = millis();
	  motorSpeed = pulses - currentPulses;//속도의 정의를 100ms당 회전수로 정의
	  currentPulses = pulses;    
  }

   //pwm 적용된 결과를 보기 위하여 100ms 마다 시리얼로 값을 전송
  if (millis()-pre_time_log >= 100)
  {
    pre_time_log = millis();
    Serial.print(goal_speed);
    Serial.print("  ");
    Serial.println(motorSpeed);
  }
  
}

void A_CHANGE() {                                     
  if ( digitalRead(encoderB) == 0 ) {
    if ( digitalRead(encoderA) == 0 ) {
      // A fall, B is low
      pulses--; // Moving forward
    } else {
      // A rise, B is high
      pulses++; // Moving reverse
    }
  } else {
    if ( digitalRead(encoderA) == 0 ) {
      pulses++; // Moving reverse
    } else {
      // A rise, B is low
      pulses--; // Moving forward
    }
  }
  pulsesChanged = true;

}

ALT TEXT

여기서 주목해야할 부분은 코드에서 셋팅된 목표치의 최대값 25가 의미하는 수치입니다.

여기서의 수치는 앞서 언급한되로 25회전/10ms 입니다.

25펄스/10ms = 2500펄스/s 가 되며

모터의 스펙상 2100펄스가 1회전이므로

1.785회전/s

가 되고 분당 RPM은

107.14/m

이 되어 모터의 Micro Metal Geared motor w/Encoder - 6V 105RPM 150:1

스펙의 한꼐치를 넘어가게 되므로 끝까지 올라가지 못하는 것을 볼 수 있습니다.

해당 코드는 https://github.com/suakii/oddMotorStudy/tree/master/Chapter5_SpeedTestNoClassPID/SpeedTestPID_ino

에서 확인할 수 있습니다.