项目中的问题使用反馈控制来控制两个直流电机的速度!代码看起来没问题,但电机没有以目标速度运行

问题描述 投票:0回答:0

我想做什么: 使用 2 个直流电机、电机驱动器、电线、2 个光学编码器磁盘和连接到直流电机的速度传感器以及 Arduino UNO 设计汽车的硬件模型。硬件模型(即 2 个直流电机)应该使其速度等于代码中预先提供的某个设定点(目标)。为此,我设计了一个闭环反馈控制,其中速度传感器充当反馈。根据此反馈和目标计算误差项,然后将其输入 PID 控制器。该 PID 控制器将控制信号(在我的代码中称为“u”)馈入系统(直流电机)。

注意:PID 值未调整。

硬件设置如下:

  1. 使用 l298n 电机驱动器。 2个直流电机连接到它。

  2. 与直流电机相连的光学编码器,使用附在光学编码器盘上的速度传感器找到电机的速度。当磁盘旋转时,传感器检测到输出。然后使用代码中使用的 ISR 将其用于计算 RPM。

  3. 有一个 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() 中,它被放在那里只是为了让他们开始。在这一脚之后,它进入循环()并完全停止运行。

c++ arduino sensors arduino-uno control-theory
© www.soinside.com 2019 - 2024. All rights reserved.