赞
踩
【Arduino 101】五分钟搞懂PID控制算法
Arduino Uno x 1
超声波模块(HC-SR04)x 1
舵机(Tower Pro MG996R)x 1
舵机供电: 5V 稳压管(LM7805) x 1 , 滤波电容 (0.33uF, 0.1uF) x 2, 9V 电池 x 1
滑轨:泡沫板
支架:乐高
滚动物体:胶带(Up试过网球,但是测距模块的表现不理想)
设计缺陷:
1: 测距模块读数不稳定,存在+/-5mm 的浮动。
2: 整体制作比较粗糙,轨道摩擦不均匀。对稳态误差的出现原因仅仅是个猜测,所以视频中用了“可能”两个字。
/* PID control Demo, PID 控制算法演示 * Last Edited: March.12th.2021 by Mun Kim * Contact: Robotix.Kim@gmail.com */ #include <Servo.h> Servo servo; int angle = 0; //舵机角度 #define echo 2 //HC-SR04的Echo接 Arduino D2 #define trig 3 //HC-SR04的Trig接 Arduino D3 float time, duration, distance; //PID constants**************************************************************** float setPoint=19; //滑轨中心与测距模块的距离 float error; //当前误差 float previous_error; //上一时刻误差,用来计算D float kp=0; //10 float ki=0; //0.05 float kd=0; //200 int dt=50; //每50毫秒进行一次计算 float P,I,D, PID; //***************************************************************************** void setup() { Serial.begin(9600); pinMode(trig, OUTPUT); pinMode(echo, INPUT); servo.attach(9); time = millis(); } void loop() { if (millis() > time + dt) { time = millis(); // HC-SR04 Distance Measuremnt, 通过超声波模块测量胶带的位置******************* digitalWrite(trig, LOW); delayMicroseconds(2); digitalWrite(trig, HIGH); delayMicroseconds(10); digitalWrite(trig, LOW); duration = pulseIn(echo, HIGH); //读取反射信号 distance = (duration*0.0343)/2; //测距公式,单位为cm // PID Calculation, PID计算************************************************* error = distance-setPoint; //计算误差 P = kp*error; //P项 if(-4 < error && error < 4){ I += ki*error; } //I项 else{ I = 0; } D = kd*((error - previous_error)/dt); //D项, PID=P + I + D ; //PID if (PID>200){PID=200;} //限幅 if (PID<-200){PID=-200;} //限幅 previous_error=error; //更新上一时刻误差 // Serial Display,在串口监视器显示每个项,有助于调试***************************** Serial.print("Distance: "); Serial.print(distance); Serial.print(" cm "); Serial.print("Error: "); Serial.print(error); Serial.print(" cm "); Serial.print(" P: "); Serial.print(P); Serial.print(" D: "); Serial.print(D); Serial.print(" I: "); Serial.print(I); Serial.print(" PID: "); Serial.println(PID); // Servo Control,用计算结果控制舵机******************************************* angle = map(PID, -200,200,150,20); servo.write(angle); } }
Up只是把上面有关PID计算的代码块搬到上期的项目中,替代了起停式控制的那一部分。dt=1s。详细的接线以及代码请大家参考这个博文:
【Arduino 101】霍尔编码器(增量,正交)与起停式闭环控制
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。