고급 개발자로 가는 길

Firmware/모터 제어

[Firmware-모터 제어] 모터 PID 제어

다크엔지니어 2022. 2. 10. 21:02
반응형

PID 제어란

비례 / 적분 / 미분  제어로서 P I D 의미를 갖는다.

자동제어로 센서로부터 I/O 신호를 읽고 목표치와 비교하며, 운전 등 조작량을 제어하므로써

목표 값에 근사하게 유지하는 방식이다.

즉, 조작량을 비례 한 크기로 제어하는 방식이다.

PID 제어를 증명하려면 사실 어렵긴하지만, 이 글에서는 PD제어에 대하여 설명 할 것이다.

 

PD 제어

PD 제어는 Proportional Derivative 제어 (비례 미분 제어) 로서, 아래의 수식을 갖는다.

별칭으로는 폭주하는 제어를 잠재우기 위한 미분제 라고도 하며,

실제로 모터 사용 시 아래와 같이 모듈레이션이 좋지 않은걸 스코프로 측정 할 수 있다.

이러한 경우 모터 구동 시 RPM 이 일정하지 않으며, 소음 등이 정상 제어가 되지 않는다.

이럴때 바로, PID 제어 중 PD 제어가 필요한 것이다.

 

PID 제어로 PID 및 Target 값은 상수로 사용된다.

MotorOutput.RPM.->En0 = (60/(((float)MotorOutput.RPM->TargetRPM)*0x000004)) - (60/(((float)MotorOutput.RPM->CurrentRPM)*0x000004));
MotorOutput.RPM.->En0 = MotorOutput.RPM.->En0>>4;

if(SpeedControl == SPDCTL_ON)
	xQ = PAR_PID_END;
else
	xQ = PAR_PID_AN;

MotorOutput.RPM.->OffsetDuty = ((float)((((xQ * MotorOutput.RPM.->En0 - MotorOutput.RPM.->En1 + MotorOutput.RPM.->En2)/8)*16)/183 * 128) - 0x4000);

if(MotorOutput.RPM.->En0 >= 250){
	MotorOutput.RPM.->En0 = 250;
}else if(MotorOutput.RPM.->En0 =< -250){
	MotorOutput.RPM.->En0 = -250;
}

//---------------------------------------------------------------------
// 이전 에러량 비교
//---------------------------------------------------------------------
MotorOutput.RPM.->En2 = MotorOutput.RPM.->En1;
MotorOutput.RPM.->En1 = MotorOutput.RPM.->En0;

//---------------------------------------------------------------------
// 현재 에러량 계산
//---------------------------------------------------------------------
MotorOutput.RPM.->En0 = (float)((float)MotorOutput.RPM->CurrentRPM - (float)MotorOutput.RPM->TargetRPM);

//---------------------------------------------------------------------
// p 계산
//---------------------------------------------------------------------
fTerm_p = Kp * MotorOutput.RPM->En0;

if(fTerm_p <= -1024){
	fTerm_p = -1024;
}else if(fTerm_p >= 1024){
	fTerm_p = 1024;
}

//---------------------------------------------------------------------
// i 계산
//---------------------------------------------------------------------
fTerm_i = Ki * ((MotorOutput.RPM->En0 + MotorOutput.RPM->En1 + MotorOutput.RPM->En2)/3);

if(fTerm_i <= -512){
	fTerm_i = -512;
}else if(fTerm_i >= 512){
	fTerm_i = 512;
}

//---------------------------------------------------------------------
// d 계산
//---------------------------------------------------------------------
fTerm_d = ((MotorOutput.RPM->En0 - MotorOutput.RPM->En1 - (MotorOutput.RPM->En1 - MotorOutput.RPM->En2));
fTerm_d = Kd * fTerm_d;

if(fTerm_d <= -512){
	fTerm_d = -512;
}else if(fTerm_d >= 512){
	fTerm_d = 512;
}

//---------------------------------------------------------------------
// PID 계산
//---------------------------------------------------------------------
if(Kp != 0))
{
	MotorOutput.RPM.->OffsetDuty = (float)MotorOutput.RPM.->OffsetDuty + (fTerm_p + fTerm_i + fTerm_d);
}


tempDuty = 0x4000;
tempDuty = tempDuty + MotorOutput.RPM->OffsetDuty;

if(tempDuty >= 0x8000){
	tempDuty = 0x8000;
}else if(tempDuty <= 0){
	tempDuty = 0;
}

PWM_Set_Duty((int)tempDuty);

 


목표 값 : 3000 rpm

아래는 위의 코드를 통해 실제 펌웨어에 적용하였을때의 측정 결과이다.

3000 RPM 으로 목표 값에 거의 수렴하는 것을 볼 수 있다.

 

이로서 원하는 RPM 제어를 하기 위해 PD 제어 하는 것을 볼 수 있었다.

실제 모터를 구동하는 펌웨어에서 자주 사용되며, 모터에 따라 사양도 다르고

많은 테스트를 거쳐야 한다.

 

이것으로 PD 제어 방식을 마치겠다.

반응형