我想做什么: 使用 2 个直流电机、电机驱动器、电线、2 个光学编码器磁盘和连接到直流电机的速度传感器以及 Arduino UNO 设计汽车的硬件模型。硬件模型(即 2 个直流电机)应该使其速度等于代码中预先提供的某个设定点(目标)。为此,我设计了一个闭环反馈控制,其中速度传感器充当反馈。根据此反馈和目标计算误差项,然后将其输入 PID 控制器。该 PID 控制器将控制信号(在我的代码中称为“u”)馈入系统(直流电机)。
注意:PID 值未调整。
硬件设置如下:
使用 l298n 电机驱动器。 2个直流电机连接到它。
与直流电机相连的光学编码器,使用附在光学编码器盘上的速度传感器找到电机的速度。当磁盘旋转时,传感器检测到输出。然后使用代码中使用的 ISR 将其用于计算 RPM。
有一个 arduino UNO 连接到电机驱动器和速度传感器。这有管理整个设置的代码。
我有什么问题? 我真的不知道为什么这段代码没有给出正确的结果。此外,我的直流电机并不总是能正常运行。有时,当我重置 arduino 时,电机会发出噪音,但不会以所需的速度旋转。代码进入循环()后,直流电机速度达到 0。这不应该发生。
代码:
#include "TimerOne.h"
// defining the Enabler / speed control pins for Motors 1 and 2.
const byte PWM1 = 9; // motor1
const byte PWM2 = 10; // motor2
//defining the setpoint for my control system
const int target = 80;
//defining variable for maxspeed
const int maxSpeed= 100;
// defining the direction control pins for Motors 1
const byte IN1 = 11; // colour = brown
const byte IN2 = 12; // colour = orange
// defining the direction control pins for Motors 2
const byte IN3 = 5; // colour = red
const byte IN4 = 6; // colour = yellow
// defining the output pins for the 2 speed sensors attached, which also work as INTERRUPT pins in this code
const byte Motor1 = 2; // Motor 1 Interrupt Pin - INT 0
const byte Motor2 = 3; // Motor 2 Interrupt Pin - INT 1
// Integers for pulse counters
unsigned int counter1 = 0;
unsigned int counter2 = 0;
// Float for number of slots in encoder disk
float diskslots = 20; // Change to match value of encoder disk
//declaring the motor speed variables globally
float rotation1=0;
float rotation2=0;
//The PID controller variables
long prevT = 0;
float eprev=0;
float eintegral = 0;
float max_speed = 100; // set the maximum motor speed
// Interrupt Service Routines
// Motor 1 pulse count ISR
void ISR_count1()
{
counter1++; // increment Motor 1 counter value
}
// Motor 2 pulse count ISR
void ISR_count2()
{
counter2++; // increment Motor 2 counter value
}
void ISR_timerone()
{
Timer1.detachInterrupt(); // Stop the timer
Serial.print(micros()); // print current time
Serial.print("Rotation1: ");
Serial.print(rotation1);
Serial.print(" RPM");
Serial.print("\tRotation2: ");
Serial.print(rotation2);
Serial.print(" RPM");
Serial.print("\tTarget: ");
Serial.print(target);
Serial.print(" RPM");
Serial.println(); // print newline
rotation1 = (counter1 / diskslots) * 60.00; // calculate RPM for Motor 1
counter1 = 0; // reset counter to zero
rotation2 = (counter2 / diskslots) * 60.00; // calculate RPM for Motor 2
counter2 = 0; // reset counter to zero
Timer1.attachInterrupt( ISR_timerone ); // Enable the timer
}
void setMotor(float speed1, float speed2)
{
// Motor1
int pwm1= (int)fabs(((speed1*1.0)/maxSpeed) * 255);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
analogWrite(PWM1, pwm1);
// Motor2
int pwm2= (int)fabs(((speed2*1.0)/maxSpeed) * 255);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(PWM2, pwm2);
}
//the PID controller loop
float controller(int speed)
{
float kp = 1;
float kd = 0; // increase derivative gain
float ki = 0;
// the target variable is 'target'
// time diff
long currT = micros(); // current time in micro secs
float deltaT = ((float)(currT - prevT)) / 1.0e6; // find the delta T in seconds
prevT = currT;
// error
int e = target - speed;
// derivative
float dedt = (e - eprev) / deltaT;
// integral
eintegral = eintegral + e * deltaT;
eintegral = constrain(eintegral, -100.0, 100.0); // limit integral term
// control signal
float u = kp * e + kd * dedt + ki * eintegral;
// motor power
float pwr = fabs(u);
if (pwr > 255)
pwr = 255;
return pwr;
}
void setup() {
pinMode(PWM1, OUTPUT);
pinMode(PWM2, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(Motor1, INPUT);
pinMode(Motor2, INPUT);
Serial.begin(9600); // initialize the serial communication at 9600 bits per second
// the RPM calculator
Timer1.initialize(1000000); // set timer for 1sec
attachInterrupt(digitalPinToInterrupt (Motor1), ISR_count1, RISING); // Increase counter 1 when speed sensor pin goes High
attachInterrupt(digitalPinToInterrupt (Motor2), ISR_count2, RISING); // Increase counter 2 when speed sensor pin goes High
Timer1.attachInterrupt( ISR_timerone );
// set the initial PWM values
setMotor(100, 100);
delay(3000);
}
void loop() {
// read feedback values
int speed1 = rotation1;
int speed2 = rotation2;
// calculate control signal
float control_signal1 = controller(speed1);
float control_signal2 = controller(speed2);
// set motor speed using control signal
setMotor(control_signal1, control_signal2);
// wait for a short period of time
delay(100);
}
我希望直流电机以我的目标速度运行。但是相反,电机要么根本不运行,要么只在线路运行期间运行:setMotor(100, 100);在 setup() 中,它被放在那里只是为了让他们开始。在这一脚之后,它进入循环()并完全停止运行。