|
|
本帖最后由 liangquan 于 2014-9-28 16:15 编辑
配置:
Arduino UNO
L298N
MPU6050
直流电机12V,无反馈,150r/min
采用PID_v1库对直流电机进行速度控制,希望小车不倒,可是无论怎样调整参数,最好的效果是小车大幅震荡,无法直立。
代码
- #include<Wire.h>
- #include "gyro_accel.h"
- #include "PID_v1.h"
- // Defining constants
- #define dt 1 // time difference in milli seconds
- #define rad2degree 57.3 // radian to degree conversion
- #define Filter_gain 0.95 // e.g. angle = angle_gyro*Filter_gain + angle_accel*(1-Filter_gain)
- // Global Variables
- unsigned long t = 0; // Time Variables
- float angle_x_gyro=0, angle_y_gyro=0, angle_z_gyro=0, angle_x_accel=0, angle_y_accel=0, angle_z_accel=0, angle_x=0, angle_y=0, angle_z=0;
- // DC motor driver with L298N
- const int motor1PWMPin = 5; // PWM Pin of Motor 1
- const int motor1Polarity1 = 4; // Polarity 1 Pin of Motor 1
- const int motor1Polarity2 = 7; // Polarity 2 Pin of Motor 1
- const int motor2PWMPin = 6; // PWM Pin of Motor 2
- const int motor2Polarity1 = 8; // Polarity 1 Pin of Motor 2
- const int motor2Polarity2 = 12; // Polarity 2 Pin of Motor 2
- int ValM1 = 255; // Initial Value for PWM Motor 1
- int ValM2 = 255; // Initial Value for PWM Motor 2
- double Setpoint, Input, Output;
- PID myPID(&Input, &Output, &Setpoint, 10, 0, 1, DIRECT);
- void setup()
- {
- // MPU-6050
- Serial.begin(115200);
- Wire.begin();
- MPU6050_ResetWake();
- MPU6050_SetGains(0,1); // Setting the lows scale
- MPU6050_SetDLPF(0); // Setting the DLPF to inf Bandwidth for calibration
- MPU6050_OffsetCal(); // very important
- MPU6050_SetDLPF(6); // Setting the DLPF to lowest Bandwidth
-
- t = millis();
-
- // DC motor
- pinMode(motor1PWMPin, OUTPUT);
- pinMode(motor1Polarity1, OUTPUT);
- pinMode(motor1Polarity2, OUTPUT);
-
- pinMode(motor2PWMPin, OUTPUT);
- pinMode(motor2Polarity1, OUTPUT);
- pinMode(motor2Polarity2, OUTPUT);
-
- // set enablePin of motor 1 high so that motor 1 can turn on
- digitalWrite(motor1PWMPin, HIGH);
- digitalWrite(motor1Polarity1, HIGH);
- digitalWrite(motor1Polarity2, LOW);
- // set enablePin of motor 2 high so that motor 2 can turn on
- digitalWrite(motor2PWMPin, HIGH);
- digitalWrite(motor2Polarity1, HIGH);
- digitalWrite(motor2Polarity2, LOW);
-
- Input = 0.0;
- Setpoint = 0.0;
-
- myPID.SetMode(AUTOMATIC);
- myPID.SetSampleTime(1);
- }
- void loop()
- {
- t = millis();
-
- MPU6050_ReadData();
-
- angle_x_gyro = (gyro_x_scalled*((float)dt/1000)+angle_x);
- angle_y_gyro = (gyro_y_scalled*((float)dt/1000)+angle_y);
- angle_z_gyro = (gyro_z_scalled*((float)dt/1000)+angle_z);
- angle_z_accel = atan(accel_z_scalled/(sqrt(accel_y_scalled*accel_y_scalled+accel_x_scalled*accel_x_scalled)))*(float)rad2degree;
- angle_y_accel = -atan(accel_x_scalled/(sqrt(accel_y_scalled*accel_y_scalled+accel_z_scalled*accel_z_scalled)))*(float)rad2degree;
- angle_x_accel = atan(accel_y_scalled/(sqrt(accel_x_scalled*accel_x_scalled+accel_z_scalled*accel_z_scalled)))*(float)rad2degree;
- angle_x = Filter_gain*angle_x_gyro+(1-Filter_gain)*angle_x_accel;
- angle_y = Filter_gain*angle_y_gyro+(1-Filter_gain)*angle_y_accel;
- angle_z = Filter_gain*angle_z_gyro+(1-Filter_gain)*angle_z_accel;
-
- digitalWrite(motor1PWMPin, HIGH);
- digitalWrite(motor2PWMPin, HIGH);
-
- Serial.print(angle_x);
- Serial.print("\t");
-
- // change direction is very important
- if(angle_x>0)
- {
- myPID.SetControllerDirection(REVERSE);
-
- // set enablePin of motor 1 high so that motor 1 can turn on
- digitalWrite(motor1Polarity1, HIGH);
- digitalWrite(motor1Polarity2, LOW);
- // set enablePin of motor 2 high so that motor 2 can turn on
- digitalWrite(motor2Polarity1, HIGH);
- digitalWrite(motor2Polarity2, LOW);
- }
- else
- {
- myPID.SetControllerDirection(DIRECT);
- // set enablePin of motor 1 high so that motor 1 can turn on
- digitalWrite(motor1Polarity1, LOW);
- digitalWrite(motor1Polarity2, HIGH);
- // set enablePin of motor 2 high so that motor 2 can turn on
- digitalWrite(motor2Polarity1, LOW);
- digitalWrite(motor2Polarity2, HIGH);
- }
-
- Input = angle_x;
- Serial.print(Input);
- Serial.print("\t");
-
- myPID.Compute();
- Serial.print(Output);
- Serial.print("\n");
-
- analogWrite(motor1PWMPin, Output);
- analogWrite(motor2PWMPin, Output);
-
- while((millis()-t) < dt) // Maing sure the cycle time is equal to dt
- {
- // Do nothing
- }
- }
复制代码
视频中的试验是通过USB线为Arduino供电,USB线起到了辅助支撑的作用,如果撤掉USB线,小车将震荡的更加厉害,最终无法稳定直立。
可能是什么原因呢?
1. MPU6050放置的不平?
2. 小车的电机最高转速太慢或太快?
3. PID参数还不对?
视频
|
|