BASIC4MCU | 질문게시판 | DC모터 PID 제어
페이지 정보
작성자 호구마 작성일2023-11-17 14:47 조회411회 댓글1건
https://www.basic4mcu.com/bbs/board.php?bo_table=gac&wr_id=23402
본문
엔코더(1/150) 달린 DC모터 PID 제어를 하려고하는데 시리얼모니터에 각도 값을 넣으면 계속 회전만 하네요 어떻게 해야할까요?
//MCU timeruint16_t MCU_TIMER_start;#define MCU_CONTROL_RATE 10void timer_loop(unsigned int mcu_ms){while((uint16_t)millis()-MCU_TIMER_start <= mcu_ms);MCU_TIMER_start = (uint16_t)millis();}//Pin defineconst int motorPWMPin = 6;const int motorDirPin1 = 8;const int motorDirPin2 = 9;const int encoderPinA = 2;const int encoderPinB = 3;//Dedine constint encoderPos = 0;const float ratio = 360./150./12.;//PID control variablefloat Kp = 1;float Ki = 0;float Kd = 0;float Ltime = 0.01;float targetDeg = 0;float motorDeg;float error;float P_control, I_control, D_control;float control;float error_previous;//Set encoderint flag = 0;void doEncoderA() { encoderPos += (digitalRead(encoderPinA) == digitalRead(encoderPinB)) ? 1: -1;}void doEncoderB() { encoderPos += (digitalRead(encoderPinA) == digitalRead(encoderPinB)) ? -1: 1;}String gainData;float Target;//set motorvoid doMotor(bool dir, int vel){digitalWrite(motorDirPin1, !(dir));digitalWrite(motorDirPin2, dir);digitalWrite(motorPWMPin, min(vel, 255));}void setup(){pinMode(encoderPinA, INPUT_PULLUP);attachInterrupt(0, doEncoderA, CHANGE);pinMode(encoderPinB, INPUT_PULLUP);attachInterrupt(1, doEncoderB, CHANGE);pinMode(motorDirPin1, OUTPUT);pinMode(motorDirPin2, OUTPUT);Serial.begin(115200);}void loop(){timer_loop(MCU_CONTROL_RATE);if(Serial.available()){gainData = Serial.readStringUntil('\r');unsigned int gainDataLength = gainData.length();unsigned int index[3];String temp;index[0] = gainData.indexOf("*");index[1] = gainData.indexOf(",");temp = gainData.substring(index[0] + 1, index[1]);flag = temp.toInt();temp = gainData.substring(index[1] + 1, gainDataLength);Target = temp.toFloat();switch (flag){case 1: Kp = Target; encoderPos = 0; break;case 2: Ki = Target; encoderPos = 0; break;case 3: Kd = Target; encoderPos = 0; break;case 4: targetDeg = Target; encoderPos = 0; break;default: Target = 0; break;}}motorDeg = float(encoderPos)*ratio;error = targetDeg - motorDeg;P_control = (Kp*error);I_control += (Ki*error*Ltime);D_control = Kd * (error - error_previous)/(Ltime);control = P_control + I_control + D_control;error_previous = error;doMotor( (control>=0)?HIGH:LOW, min(abs(control), 255));Serial.print("encoderPos : ");Serial.print(encoderPos);Serial.print(" motorDeg : ");Serial.print(float(encoderPos)*ratio);Serial.print(" error : ");Serial.print(error);Serial.print(" control : ");Serial.print(control);Serial.print(" motorVel : ");Serial.print(min(abs(control), 255));Serial.print(" Kp : ");Serial.print(Kp);Serial.print(" Ki : ");Serial.print(Ki);Serial.print(" Kd : ");Serial.println(Kd);}
댓글 1
조회수 411master님의 댓글
master 작성일
시리얼모니터에 출력되는 값을 잘 보고서
변수값을 설정하는 것들이 제대로 입력되는지 체크하시고
I,D 제어는 하지말고 P제어만 우선 해보세요