如何使用PID控制和超声波传感器控制步进电机的速度?

如何解决如何使用PID控制和超声波传感器控制步进电机的速度?

小故事: 我目前正在做这个项目,涉及使用两辆汽车,分别称为A块和B块,B块必须使用PID,PD,PI或P与A块保持10厘米的距离。我正在使用PID 。 B块使用Arduino,而A块则由用户手动控制。模块B使用单极步进电机作为执行器,并使用超声波传感器来感应距离。我的教授希望电动机沿两个方向移动并具有不同的速度(慢速,中速和快速)。我一直在使用brett的PID,因为我以前在以前的实验室中都使用过它。

问题: 我对于如何为B块创建不同的速度存在问题,就像直观地知道,我想让B块移动,例如,如果汽车大于20厘米,则;如果汽车大于20 cm,则 medium汽车在20厘米至14厘米之间,如果在14厘米至10厘米之间则慢。但是我只是不能直接使用从传感器获取的输入值来控制电动机,因为这会使它成为开放系统。因此,我使用了从Brett的PID代码中检索到的错误来控制步进电机。到目前为止,我已经通过设置myPID.SetOutputLimits(-800,800);得到了工作指导。但是,当它试图使用误差来控制速度时,这是不可能的,因为误差总是在特定距离处波动。例如,在12厘米处,我会得到800或300左右。目前,我对如何通过PID实现对步进电机速度的控制感到困惑,对此问题的任何帮助将不胜感激。

代码: 代码是通过Arduino IDE进行的。

#include "SR04.h"
#include <Stepper.h>
#include <PID_v1.h>

#define TRIG_PIN 7
#define ECHO_PIN 6

//intialization of Ultrasonic sensor
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
long s; 

//intializing motor variables
int stepsPerRevolution = 2048;
int motorSpeed = 6;
Stepper myStepper (stepsPerRevolution,8,10,9,11);

//Declared PID variables
double Setpoint = 10; //desired temp value
double Input;    //thermsitor
double Output;   //DC motor
double Error;

//defined variables for PID parameters
double Kp=100,Ki=10,Kd=1;

//PID equation
PID myPID(&Input,&Output,&Setpoint,Kp,Kd,Ki,REVERSE);


void setup(){
  Serial.begin(9600);

  //setting PID
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-800,800);

  //speed intialized
  myStepper.setSpeed(motorSpeed);
 

}

void loop(){
  s=sr04.Distance();
  Input = s;
  myPID.Compute();
  Error = Input - Setpoint;
  //Serial.print(Input);
  //Serial.print(",");
  //Serial.println(Setpoint);
  Serial.println(Output);
  //Serial.print(",");
  //Serial.println(Error);
  Error = Output; 
  
//Away from Block B
 if (0<Error<800){
    myStepper.setSpeed(motorSpeed);
    myStepper.step(-300);
  } //slow speed
  
   if (Error>=800){
    myStepper.setSpeed(motorSpeed*2);
    myStepper.step(-128);
  } //fast speed

//Towards Block B
  if (-800<Error<0) {
    myStepper.setSpeed(motorSpeed);
    myStepper.step(128);
  } //slow speed
  
  if (Error<=-800) {
    myStepper.setSpeed(motorSpeed*2);
    myStepper.step(128);
  }//Fast speed
 }
  

解决方法

您需要做的是计算需要多少更改当前速度以最小化距离误差。

您的错误计算方法不正确。

void loop()
{

    long s=sr04.Distance();
    Input = s;             // using global variables to pass values to your PID 
                           // is not a good idea.  Use function parameters instead.
                           // You are storing a 32 bit value in a 16 bit variable!!!
                           // That's only the start of your problems.  
    myPID.Compute();
    Error = Input - Setpoint; // 

由于我们从一个主要的设计缺陷开始,所以我必须假设您将解决此问题并更改PID代码以接受和计算长整数,既作为输入值作为函数参数,又作为函数的类型。它的返回值。

您要做的是根据距设定点的距离误差计算PID,然后相应地调节当前速度。直接使用PID时效果最好,可以使用7种速度(1个停止,3个前进/ 3个倒退),但是我认为效果不会更好,我会把练习留给您。

我还没有尝试过,我手边没有任何汽车。这是我如何去做的骨架。调整PID应该是花费您最长的时间。

//...

// speeds are in RPMs.
long curSpeed = 0;
const long MAX_SPEED = XXX;  // whatever you max speed is for your car.
const long MIN_NEG_SPEED = -XXX;  // whatever you max speed is for your car going reverse.
const long MIN_SPEED = XXX;  // below this absolute speed,we're stopped. 
const int SLICE_TIME = 10;   // time between readings and adjustments,in ms.
                             // you'll need to adjust this according to you minimum speed,and steps per turn. 
const long STEPS_PER_TURN = 200;  // change to whatever you steps/turn value is.

// you'll need to limit the output of your PID to match the acceleration your
// motors can handle for your particular car.

// returns the number of steps to run for our slice time.  
long Steps(int speed)
{
    if (-MIN_SPEED <= speed && speed <= MIN_SPEED)
        return 0;

    // compute number of steps for our slice time.
    // choose slice time and minimum speed wisely!!
    long steps = (SLICE_TIME * (speed * STEPS_PER_TURN)) / (60000L);
    
    // for very low speeds.  I've added this,because I'm unsure of the 
    // time domain behaviour of stepper library with less than 2 steps
    if (-1 <= steps && steps <= 1)
    {
        if (speed < 0)
            return -2;
        else
            return 2;
    } 
    return int(steps);
}

void loop() 
{
    // You may want to filter the sr04 readings with a median of 5
    // filter to limit input noise.   

    // You want to keep the car at a distance of 'set_point'
    // from the leading car.  distance_error is the error you want to
    // minimize to zero by using the PID,and that's what should be
    // the PID input.
    //
    // The way this works.  We are rolling at speed curSpeed,we
    // measure the error in distance from our set_point,feed that 
    // to the PID,then accelerate or decelerate by subtracting
    // the output of the PID from the current speed. 
    //    
    // Note: you can add or subtract the PID to/from the current speed,// the sign of the PID depends on you coefficients and sensor. 
    // I've used subtraction here because that's how you express 
    // negative feedback mathematically.  In real life,we'll use what
    // best fits our needs.  Usually it's the operation that makes P
    // positive.

    long distance_error = sr04.Distance() - setPoint;

    long pid_out = myPID.Compute(distance_error);

    // increment or decrement the current speed to try and reduce the error.
    long speed = curSpeed - pid_out;  // As usual,PID coefficients do matter 
                                     // for this to work well.

    if (speed > MAX_SPEED)
        speed = MAX_SPEED;
    if (speed < MIN_NEG_SPEED)
        speed = MIN_NEG_SPEED;

    curSpeed = speed;
    if (speed < 0)
        speed = -speed;

    myStepper.setSpeed(speed);     // modulate speed
    int steps = Steps(curSpeed);
    if (steps)
        myStepper.step(steps);     // keep rolling.
}

我也没有尝试对其进行编译,因此这可能无法按原样进行编译。但是,大多数技巧和陷阱都已涵盖,如果您要使用PID路径,这应该给您一个领先的机会。但是我认为您的教授真的会想知道那个人是从哪里来的:)尽管如此,您还是应该尝试使其运行起来,这很有趣。

反之,没有PID,使用设定的速度要简单得多。它也可能更接近练习所需的内容。当然,汽车之间的距离会有所不同。而且它根本不使用PID。

const int MAX_SPEED = 3;
int speed = 0;    // value range is [-MAX_SPEED,+MAX_SPEED]  

long RPMS[MAX_SPEED + 1] = { 0,200,400,800 }; // in RPMs,assuming average speed will be around 400,in this case.
// For 3 speeds,the difference between speeds cannot be higher than max acceleration.  
// You can add as many speeds as desired.  More speeds = more precision.

const long STEPS_PER_TURN = 200;  // change to whatever you steps/turn value is.  MUST be 200 or more.
const int STEPS = STEPS_PER_TURN / 100;  // 3.6° between speed adjustment.
                                         // it is very small right now,so 
                                         // you will want to play with this value.

// this threshold gives some control over aceleration.
// and 'hardness' of distance tracking.  
const long THRESHOLD = 0;

void loop()
{
    // get the error in distance.
    long distance_error = sr04.Distance() - setPoint;

    // modulate speed.  
    if (distance_error > THRESHOLD) 
        ++speed;
    if (distance_error < -THRESHOLD)
        --speed;

    if (speed > MAX_SPEED)
        speed = MAX_SPEED;
    if (speed < -MAX_SPEED)
        speed = -MAX_SPEED;

    long rpm = RPMS[(speed < 0) : -speed : speed];
    if (rpm)
    {
        myStepper.setSpeed(rpm);
        myStepper.setSpeed((speed < 0) ? -STEPS : STEPS)
    }
}

对于此代码,您必须选择速度和STEPS值,以使您获得加速而不会错过任何步骤。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res