

비상 정지 후 급발진 방지 코드 개선
@cd73cc3653047d79860cc9ff188a3fa84bd51938
--- 2Motor_CTRL.ino
... | ... | @@ -1,213 +0,0 @@ |
1 | -// July 30th 10:17 Updated | |
2 | - | |
3 | -// === 1번 모터 핀 정의 === | |
4 | -#define DIR_1 8 // DIR1 (드라이버 갈색 2번, 점퍼선 주황색) | |
5 | -#define ST_1 9 // START/STOP1 (드라이버 핑크 4번, 점퍼선 초록색) | |
6 | -#define PWM_1 45 // SPEED_IN1 (드라이버 주황색 6번, 점퍼선 노란색) | |
7 | -#define ENCA_1 2 // A상 (드라이버 보라색, 점퍼선 파란색) | |
8 | -#define ENCB_1 3 // B상 (드라이버 회색, 점퍼선 흰색) | |
9 | - | |
10 | -// === 2번 모터 핀 정의 === | |
11 | -#define DIR_2 22 // DIR2 (드라이버 갈색 16번, 점퍼선 주황색) | |
12 | -#define ST_2 24 // START/STOP2 (드라이버 핑크 17번, 점퍼선 초록색) | |
13 | -#define PWM_2 44 // SPEED_IN2 (드라이버 주황색 8번, 점퍼선 노란색) | |
14 | -#define ENCA_2 18 // A상 (드라이버 보라색, 점퍼선 파란색) | |
15 | -#define ENCB_2 19 // B상 (드라이버 회색, 점퍼선 흰색) | |
16 | - | |
17 | -// === 목표 RPM (부호 포함) === | |
18 | -int setRPM1 = 100; | |
19 | -int setRPM2 = 0; | |
20 | - | |
21 | -// === PID 계수 (모터별 개별 설정) === | |
22 | -double kp1 = 0.5, ki1 = 3.0, kd1 = 0.085; | |
23 | -double kp2 = 0.0, ki2 = 0.0, kd2 = 0.0; | |
24 | - | |
25 | -// === 모터 상태 변수 === | |
26 | -// 모터 1 | |
27 | -volatile long encoderPos1 = 0; | |
28 | -double rpm1 = 0; | |
29 | -int calPWM1 = 0; | |
30 | -double error1 = 0, prevError1 = 0, integral1 = 0, derivative1 = 0; | |
31 | - | |
32 | -// 모터 2 | |
33 | -volatile long encoderPos2 = 0; | |
34 | -double rpm2 = 0; | |
35 | -int calPWM2 = 0; | |
36 | -double error2 = 0, prevError2 = 0, integral2 = 0, derivative2 = 0; | |
37 | - | |
38 | -// 제어 주기 | |
39 | -const unsigned long interval = 100; // 단위: ms | |
40 | -unsigned long prevTime = 0; | |
41 | -double dt = interval / 1000.0; // ms → 초(s) 단위로 변경 | |
42 | - | |
43 | -// === 인터럽트 핸들러 === | |
44 | -// 모터 1 | |
45 | -void doEncoderA1() { | |
46 | - if (digitalRead(ENCB_1) == LOW) encoderPos1++; | |
47 | - else encoderPos1--; | |
48 | -} | |
49 | -void doEncoderB1() { | |
50 | - if (digitalRead(ENCA_1) == HIGH) encoderPos1++; | |
51 | - else encoderPos1--; | |
52 | -} | |
53 | - | |
54 | -// 모터 2 | |
55 | -void doEncoderA2() { | |
56 | - if (digitalRead(ENCB_2) == LOW) encoderPos2--; | |
57 | - else encoderPos2++; | |
58 | -} | |
59 | -void doEncoderB2() { | |
60 | - if (digitalRead(ENCA_2) == HIGH) encoderPos2--; | |
61 | - else encoderPos2++; | |
62 | -} | |
63 | - | |
64 | -// === RPM 계산 함수 === | |
65 | -double calculateRPM(long counts) { | |
66 | - return ((double)counts / (4096.0 * 2)) * (60.0 / dt); | |
67 | -} | |
68 | - | |
69 | -// === PID 계산 함수 (모터별 계수 전달) === | |
70 | -int computePID(double currentRPM, double &error, double &prevError, | |
71 | - double &integral, double &derivative, int targetRPM, | |
72 | - double kp, double ki, double kd) { | |
73 | - error = targetRPM - currentRPM; | |
74 | - integral += (error * dt); | |
75 | - derivative = (error - prevError) / dt; | |
76 | - | |
77 | - double output = (kp * error) + (ki * integral) + (kd * derivative); | |
78 | - prevError = error; | |
79 | - return (int)output; | |
80 | -} | |
81 | - | |
82 | -// === 실시간 입력 (R숫자 L숫자 형식으로 입력, 음수 가능) === | |
83 | -void serialSetRPM() { | |
84 | - if (Serial.available()) { | |
85 | - String input = Serial.readStringUntil('\n'); | |
86 | - input.trim(); | |
87 | - | |
88 | - int rIndex = input.indexOf('R'); | |
89 | - int lIndex = input.indexOf('L'); | |
90 | - | |
91 | - if (rIndex == -1 && lIndex == -1) { | |
92 | - Serial.println("입력 오류: 'R' 또는 'L'이 포함되어야 합니다. 예: R100 L-80"); | |
93 | - return; | |
94 | - } | |
95 | - | |
96 | - bool validInput = false; | |
97 | - | |
98 | - // === R 처리 === | |
99 | - if (rIndex != -1) { | |
100 | - int end = (lIndex != -1 && lIndex > rIndex) ? lIndex : input.length(); | |
101 | - String rValStr = input.substring(rIndex + 1, end); | |
102 | - rValStr.trim(); | |
103 | - | |
104 | - if (rValStr.length() == 0) { | |
105 | - Serial.println("오류: R 뒤에 숫자가 없습니다. 예: R100"); | |
106 | - } else { | |
107 | - int rpmVal = rValStr.toInt(); | |
108 | - if (String(rpmVal) != rValStr) { | |
109 | - Serial.print("오류: R에 잘못된 숫자 형식 → "); Serial.println(rValStr); | |
110 | - } else if (abs(rpmVal) > 400) { | |
111 | - Serial.println("오류: R 값은 -400 ~ 400 사이여야 합니다."); | |
112 | - } else { | |
113 | - setRPM1 = rpmVal; | |
114 | - Serial.print("모터1 (R) 목표 RPM → "); Serial.println(setRPM1); | |
115 | - validInput = true; | |
116 | - } | |
117 | - } | |
118 | - } | |
119 | - | |
120 | - // === L 처리 === | |
121 | - if (lIndex != -1) { | |
122 | - int end = (rIndex != -1 && rIndex > lIndex) ? rIndex : input.length(); | |
123 | - String lValStr = input.substring(lIndex + 1, end); | |
124 | - lValStr.trim(); | |
125 | - | |
126 | - if (lValStr.length() == 0) { | |
127 | - Serial.println("오류: L 뒤에 숫자가 없습니다. 예: L-80"); | |
128 | - } else { | |
129 | - int rpmVal = lValStr.toInt(); | |
130 | - if (String(rpmVal) != lValStr) { | |
131 | - Serial.print("오류: L에 잘못된 숫자 형식 → "); Serial.println(lValStr); | |
132 | - } else if (abs(rpmVal) > 400) { | |
133 | - Serial.println("오류: L 값은 -400 ~ 400 사이여야 합니다."); | |
134 | - } else { | |
135 | - setRPM2 = rpmVal; | |
136 | - Serial.print("모터2 (L) 목표 RPM → "); Serial.println(setRPM2); | |
137 | - validInput = true; | |
138 | - } | |
139 | - } | |
140 | - } | |
141 | - | |
142 | - if (!validInput) { | |
143 | - Serial.println("R숫자 L숫자 형식으로 입력해주세요. 예: R100 L-80"); | |
144 | - } | |
145 | - } | |
146 | -} | |
147 | - | |
148 | - | |
149 | -void setup() { | |
150 | - Serial.begin(57600); | |
151 | - | |
152 | - // 모터 1 핀 설정 | |
153 | - pinMode(DIR_1, OUTPUT); pinMode(PWM_1, OUTPUT); pinMode(ST_1, OUTPUT); | |
154 | - pinMode(ENCA_1, INPUT_PULLUP); pinMode(ENCB_1, INPUT_PULLUP); | |
155 | - attachInterrupt(digitalPinToInterrupt(ENCA_1), doEncoderA1, RISING); | |
156 | - attachInterrupt(digitalPinToInterrupt(ENCB_1), doEncoderB1, RISING); | |
157 | - | |
158 | - // 모터 2 핀 설정 | |
159 | - pinMode(DIR_2, OUTPUT); pinMode(PWM_2, OUTPUT); pinMode(ST_2, OUTPUT); | |
160 | - pinMode(ENCA_2, INPUT_PULLUP); pinMode(ENCB_2, INPUT_PULLUP); | |
161 | - attachInterrupt(digitalPinToInterrupt(ENCA_2), doEncoderA2, RISING); | |
162 | - attachInterrupt(digitalPinToInterrupt(ENCB_2), doEncoderB2, RISING); | |
163 | - | |
164 | - // 브레이크 해제 | |
165 | - digitalWrite(ST_1, LOW); | |
166 | - digitalWrite(ST_2, LOW); | |
167 | - | |
168 | - prevTime = millis(); | |
169 | - | |
170 | - Serial.println("R±RPM | L±RPM 입력"); | |
171 | -} | |
172 | - | |
173 | -void loop() { | |
174 | - unsigned long now = millis(); | |
175 | - | |
176 | - if (now - prevTime >= interval) { | |
177 | - prevTime += interval; | |
178 | - | |
179 | - // 모터 1 | |
180 | - noInterrupts(); long currentPos1 = encoderPos1; encoderPos1 = 0; interrupts(); | |
181 | - rpm1 = calculateRPM(currentPos1); | |
182 | - calPWM1 = computePID(rpm1, error1, prevError1, integral1, derivative1, abs(setRPM1), kp1, ki1, kd1); | |
183 | - digitalWrite(DIR_1, setRPM1 >= 0 ? HIGH : LOW); | |
184 | - calPWM1 = constrain(abs(calPWM1), 0, 255); | |
185 | - analogWrite(PWM_1, calPWM1); | |
186 | - | |
187 | - // 모터 2 | |
188 | - noInterrupts(); long currentPos2 = encoderPos2; encoderPos2 = 0; interrupts(); | |
189 | - rpm2 = calculateRPM(currentPos2); | |
190 | - calPWM2 = computePID(rpm2, error2, prevError2, integral2, derivative2, abs(setRPM2), kp2, ki2, kd2); | |
191 | - digitalWrite(DIR_2, setRPM2 >= 0 ? HIGH : LOW); | |
192 | - calPWM2 = constrain(abs(calPWM2), 0, 255); | |
193 | - analogWrite(PWM_2, calPWM2); | |
194 | - | |
195 | - // 시리얼 출력 | |
196 | - // Serial.print("R:"); Serial.println(setRPM1); | |
197 | - // Serial.print("RPM:"); Serial.println(rpm1, 2); | |
198 | - // Serial.print("PWM:"); Serial.println(calPWM1); | |
199 | - // Serial.println(" "); | |
200 | - // Serial.print("L:"); Serial.println(setRPM2); | |
201 | - // Serial.print("RPM:"); Serial.println(rpm2, 2); | |
202 | - // Serial.print("PWM:"); Serial.println(calPWM2); | |
203 | - // Serial.println("--------------------"); | |
204 | - | |
205 | - // Serial Plotter용 출력 (탭으로 구분) | |
206 | - Serial.print(setRPM1); Serial.print('\t'); | |
207 | - Serial.println(rpm1, 2); | |
208 | - // Serial.print(setRPM2); Serial.print('\t'); | |
209 | - // Serial.println(rpm2, 2); | |
210 | - } | |
211 | - | |
212 | - serialSetRPM(); | |
213 | -} |
--- TEST
... | ... | @@ -1,75 +0,0 @@ |
1 | -//test motor with arduino, check hallsensor | |
2 | - | |
3 | -// test run motor with arduino | |
4 | - | |
5 | -const int PWM = 10; // MD200T 6번 (SPEED_IN2) 노랑 | |
6 | -const int DIR = 8; // MD200T 2번 (DIR2) 주황 | |
7 | -const int ST = 9; // MD200T 4번 (START/STOP2) 초록 | |
8 | - | |
9 | -void setup() { | |
10 | - Serial.begin(9600); | |
11 | - | |
12 | - pinMode(PWM, OUTPUT); | |
13 | - pinMode(DIR, OUTPUT); // 회전 방향 (시계 방향 = HIGH) | |
14 | - pinMode(ST, OUTPUT); // 브레이크 (해제 = LOW) | |
15 | - | |
16 | - digitalWrite(ST, HIGH); | |
17 | - delay(2000); // 전원 안정화 | |
18 | -} | |
19 | - | |
20 | -void loop() { | |
21 | - | |
22 | - digitalWrite(ST, LOW); // 브레이크 해제 | |
23 | - digitalWrite(DIR, LOW); // 반시계 회전 | |
24 | - analogWrite(PWM, 0); | |
25 | - // delay(10000); | |
26 | - // digitalWrite(ST, HIGH); // 멈춤 | |
27 | - // delay(4000); | |
28 | - | |
29 | - // digitalWrite(ST, LOW); | |
30 | - // digitalWrite(DIR, HIGH); // 시계 회전 | |
31 | - // analogWrite(PWM, 125); | |
32 | - // delay(10000); | |
33 | - // digitalWrite(ST, HIGH); | |
34 | - // delay(4000); | |
35 | -} | |
36 | - | |
37 | - | |
38 | -// check hallsensor | |
39 | - | |
40 | - | |
41 | -// 홀센서 핀 번호 | |
42 | -const int Hu = 4; | |
43 | -const int Hv = 3; | |
44 | -const int Hw = 2; | |
45 | - | |
46 | -const int PWM = 10; // MD200T 6번 (SPEED_IN2) 노랑 | |
47 | -const int DIR = 8; // MD200T 2번 (DIR2) 주황 | |
48 | -const int ST = 9; // MD200T 4번 (START/STOP2) 초록 | |
49 | - | |
50 | -void setup() { | |
51 | - Serial.begin(9600); | |
52 | - | |
53 | - pinMode(Hu, INPUT); | |
54 | - pinMode(Hv, INPUT); | |
55 | - pinMode(Hw, INPUT); | |
56 | - | |
57 | - pinMode(PWM, OUTPUT); | |
58 | - pinMode(DIR, OUTPUT); // 회전 방향 (시계 방향 = HIGH) | |
59 | - pinMode(ST, OUTPUT); | |
60 | - digitalWrite(ST, HIGH); // 브레이크 (해제 = LOW) | |
61 | - delay(2000); // 전원 안정화 | |
62 | -} | |
63 | - | |
64 | -//모터를 직접 손으로 돌리면서 체크 | |
65 | -void loop() { | |
66 | - int hu = digitalRead(Hu); | |
67 | - int hv = digitalRead(Hv); | |
68 | - int hw = digitalRead(Hw); | |
69 | - | |
70 | - Serial.print("Hu: "); Serial.print(hu); | |
71 | - Serial.print(" | Hv: "); Serial.print(hv); | |
72 | - Serial.print(" | Hw: "); Serial.println(hw); | |
73 | - | |
74 | - delay(200); // 0.2초 간격 출력 | |
75 | -}(파일 끝에 줄바꿈 문자 없음) |
+++ vdwd3.0.ino
... | ... | @@ -0,0 +1,194 @@ |
1 | +// Ch1 : Left | |
2 | +#define DIR_1 8 | |
3 | +#define ST_1 9 | |
4 | +#define PWM_1 45 | |
5 | +#define ENCA_1 2 | |
6 | +#define ENCB_1 3 | |
7 | + | |
8 | +// Ch2 : Right | |
9 | +#define DIR_2 22 | |
10 | +#define ST_2 24 | |
11 | +#define PWM_2 44 | |
12 | +#define ENCA_2 18 | |
13 | +#define ENCB_2 19 | |
14 | + | |
15 | +int setRPM1 = 0; | |
16 | +int setRPM2 = 0; | |
17 | + | |
18 | +double kp1 = 0.5, ki1 = 3.0, kd1 = 0.085; | |
19 | +double kp2 = 0.5, ki2 = 3.0, kd2 = 0.085; | |
20 | +double kb1 = 3, kb2 = 3; | |
21 | +double alpha = 0.3; | |
22 | + | |
23 | +volatile long encoderPos1 = 0, encoderPos2 = 0; | |
24 | +double v = 0, w = 0; | |
25 | +double rpm1 = 0, rpm2 = 0; | |
26 | +int calPWM1 = 0, calPWM2 = 0; | |
27 | +double error1 = 0, prevError1 = 0, integral1 = 0, derivative1 = 0; | |
28 | +double error2 = 0, prevError2 = 0, integral2 = 0, derivative2 = 0; | |
29 | +double prevRPM1 = 0, prevRPM2 = 0; | |
30 | +double backError1 = 0, backError2 = 0; | |
31 | + | |
32 | +const unsigned long interval = 30; | |
33 | +unsigned long prevTime = 0; | |
34 | +double dt = interval / 1000.0; | |
35 | + | |
36 | +const double WHEEL_RADIUS = 0.065; // 65mm | |
37 | +const double WHEEL_DISTANCE = 0.437; // 437mm | |
38 | + | |
39 | +void doEncoderA1() { if (digitalRead(ENCB_1) == LOW) encoderPos1--; else encoderPos1++; } | |
40 | +void doEncoderB1() { if (digitalRead(ENCA_1) == HIGH) encoderPos1--; else encoderPos1++; } | |
41 | +void doEncoderA2() { if (digitalRead(ENCB_2) == LOW) encoderPos2++; else encoderPos2--; } | |
42 | +void doEncoderB2() { if (digitalRead(ENCA_2) == HIGH) encoderPos2++; else encoderPos2--; } | |
43 | + | |
44 | +double calculateRPM(long counts) { | |
45 | + return ((double)counts / (4096.0 * 2)) * (60.0 / dt); | |
46 | +} | |
47 | + | |
48 | +int computePID(double currentRPM, double &error, double &prevError, | |
49 | + double &integral, double &derivative, int targetRPM, | |
50 | + double kp, double ki, double kd, bool isMotor1) { | |
51 | + double absTarget = abs(targetRPM); | |
52 | + double absCurrent = abs(currentRPM); | |
53 | + error = absTarget - absCurrent; | |
54 | + integral += error * dt; | |
55 | + | |
56 | + double rawDerivative = -(absCurrent - (isMotor1 ? prevRPM1 : prevRPM2)) / dt; | |
57 | + double filteredDeriv = alpha * rawDerivative + (1 - alpha) * (isMotor1 ? derivative1 : derivative2); | |
58 | + if (isMotor1) prevRPM1 = absCurrent; else prevRPM2 = absCurrent; | |
59 | + | |
60 | + double P = kp * error; | |
61 | + double I = ki * integral; | |
62 | + double D = kd * filteredDeriv; | |
63 | + double output = P + I + D; | |
64 | + double outputSat = constrain(output, 0, 255); | |
65 | + double backError = outputSat - output; | |
66 | + integral += (isMotor1 ? kb1 : kb2) * backError * dt; | |
67 | + | |
68 | + Serial.print(abs(targetRPM)); Serial.print('\t'); | |
69 | + Serial.print(currentRPM, 2); Serial.print('\t'); | |
70 | + if (isMotor1) { | |
71 | + Serial.print("P1 : "); Serial.print(P, 2); Serial.print('\t'); | |
72 | + Serial.print("I1 : "); Serial.print(I, 2); Serial.print('\t'); | |
73 | + Serial.print("D1 : "); Serial.print(D, 2); Serial.println('\t'); | |
74 | + } else { | |
75 | + Serial.print("P2 : "); Serial.print(P, 2); Serial.print('\t'); | |
76 | + Serial.print("I2 : "); Serial.print(I, 2); Serial.print('\t'); | |
77 | + Serial.print("D2 : "); Serial.print(D, 2); Serial.println('\t'); | |
78 | + Serial.println("---------------------------------------------------------"); | |
79 | + } | |
80 | + | |
81 | + return (int)(P + I + D); | |
82 | +} | |
83 | + | |
84 | +void serialSetTwist() { | |
85 | + if (Serial.available()) { | |
86 | + String input = Serial.readStringUntil('\n'); | |
87 | + input.trim(); | |
88 | + | |
89 | + int vIndex = input.indexOf('V'); | |
90 | + int wIndex = input.indexOf('W'); | |
91 | + | |
92 | + bool vUpdated = false; | |
93 | + bool wUpdated = false; | |
94 | + | |
95 | + if (vIndex != -1) { | |
96 | + int end = (wIndex != -1 && wIndex > vIndex) ? wIndex : input.length(); | |
97 | + String vStr = input.substring(vIndex + 1, end); | |
98 | + vStr.trim(); | |
99 | + double parsedV = vStr.toFloat(); | |
100 | + if (String(parsedV) == vStr || vStr.length() > 0) { | |
101 | + v = parsedV; | |
102 | + vUpdated = true; | |
103 | + } | |
104 | + } | |
105 | + | |
106 | + if (wIndex != -1) { | |
107 | + int end = (vIndex != -1 && vIndex > wIndex) ? vIndex : input.length(); | |
108 | + String wStr = input.substring(wIndex + 1, end); | |
109 | + wStr.trim(); | |
110 | + double parsedW = wStr.toFloat(); | |
111 | + if (String(parsedW) == wStr || wStr.length() > 0) { | |
112 | + w = parsedW; | |
113 | + wUpdated = true; | |
114 | + } | |
115 | + } | |
116 | + | |
117 | + if (vUpdated || wUpdated) { | |
118 | + double pkjR = 1; | |
119 | + double pkjL = 1; | |
120 | + double rpm_r = (v + (WHEEL_DISTANCE / 2.0) * w) / WHEEL_RADIUS * 60.0 / (2 * PI); | |
121 | + double rpm_l = (v - (WHEEL_DISTANCE / 2.0) * w) / WHEEL_RADIUS * 60.0 / (2 * PI); | |
122 | + setRPM1 = (int)(rpm_r * pkjR); | |
123 | + setRPM2 = (int)(rpm_l * pkjL); | |
124 | + | |
125 | +// Serial.print("Target Updated → "); | |
126 | +// Serial.print("V: "); Serial.print(v, 3); | |
127 | +// Serial.print(" W: "); Serial.print(w, 3); | |
128 | +// Serial.print(" R: "); Serial.print(setRPM1); | |
129 | +// Serial.print(" L: "); Serial.println(setRPM2); | |
130 | +// } else { | |
131 | +// Serial.println("Error : Enter in V0.3 or W-0.2 format."); | |
132 | + } | |
133 | + } | |
134 | +} | |
135 | + | |
136 | +void setup() { | |
137 | + Serial.begin(115200); | |
138 | + pinMode(DIR_1, OUTPUT); pinMode(PWM_1, OUTPUT); pinMode(ST_1, OUTPUT); | |
139 | + pinMode(ENCA_1, INPUT_PULLUP); pinMode(ENCB_1, INPUT_PULLUP); | |
140 | + attachInterrupt(digitalPinToInterrupt(ENCA_1), doEncoderA1, RISING); | |
141 | + attachInterrupt(digitalPinToInterrupt(ENCB_1), doEncoderB1, RISING); | |
142 | + | |
143 | + pinMode(DIR_2, OUTPUT); pinMode(PWM_2, OUTPUT); pinMode(ST_2, OUTPUT); | |
144 | + pinMode(ENCA_2, INPUT_PULLUP); pinMode(ENCB_2, INPUT_PULLUP); | |
145 | + attachInterrupt(digitalPinToInterrupt(ENCA_2), doEncoderA2, RISING); | |
146 | + attachInterrupt(digitalPinToInterrupt(ENCB_2), doEncoderB2, RISING); | |
147 | + | |
148 | + digitalWrite(ST_1, LOW); digitalWrite(ST_2, LOW); | |
149 | + prevTime = millis(); | |
150 | +} | |
151 | + | |
152 | +void loop() { | |
153 | + unsigned long now = millis(); | |
154 | + if (now - prevTime >= interval) { | |
155 | + prevTime += interval; | |
156 | + | |
157 | + noInterrupts(); long cnt1 = encoderPos1; encoderPos1 = 0; | |
158 | + long cnt2 = encoderPos2; encoderPos2 = 0; interrupts(); | |
159 | + rpm1 = calculateRPM(cnt1); | |
160 | + rpm2 = calculateRPM(cnt2); | |
161 | + | |
162 | + static int zeroRPMCount = 0; | |
163 | + const int maxZeroRPMCount = 10; // 10*30ms = 300ms | |
164 | + | |
165 | + if (rpm1 == 0 && rpm2 == 0 && (setRPM1 != 0 || setRPM2 != 0)) { | |
166 | + zeroRPMCount++; | |
167 | + } else if (rpm1 == 0 && rpm2 == 0 && setRPM1 == 0 && setRPM2 == 0) { | |
168 | + if (integral1 != 0 || integral2 != 0) { | |
169 | + integral1 = 0; | |
170 | + integral2 = 0; | |
171 | + } | |
172 | + } else { | |
173 | + zeroRPMCount = 0; | |
174 | + } | |
175 | + | |
176 | + if (zeroRPMCount > maxZeroRPMCount) { | |
177 | + setRPM1 = 0; | |
178 | + setRPM2 = 0; | |
179 | + integral1 = 0; | |
180 | + integral2 = 0; | |
181 | + calPWM1 = 0; | |
182 | + calPWM2 = 0; | |
183 | + } | |
184 | + | |
185 | + calPWM1 = computePID(rpm1, error1, prevError1, integral1, derivative1, setRPM1, kp1, ki1, kd1, true); | |
186 | + calPWM2 = computePID(rpm2, error2, prevError2, integral2, derivative2, setRPM2, kp2, ki2, kd2, false); | |
187 | + | |
188 | + digitalWrite(DIR_1, setRPM1 >= 0 ? LOW : HIGH); | |
189 | + digitalWrite(DIR_2, setRPM2 >= 0 ? LOW : HIGH); | |
190 | + analogWrite(PWM_1, constrain(abs(calPWM1), 0, 255)); | |
191 | + analogWrite(PWM_2, constrain(abs(calPWM2), 0, 255)); | |
192 | + } | |
193 | + serialSetTwist(); | |
194 | +}(파일 끝에 줄바꿈 문자 없음) |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?