机器人平台设计8章:https://blog.csdn.net/qq_52537255/article/details/119350982
机器人平台设计8章 8-1 概述:https://blog.csdn.net/qq_52537255/article/details/119351229
机器人平台设计8章8.2 机器人平台设计之arduino基础:https://blog.csdn.net/qq_52537255/article/details/119351360?spm=1001.2014.3001.5501
机器人平台设计8章8.3 机器人平台设计之arduino与电机驱动:https://blog.csdn.net/qq_52537255/article/details/119352154?spm=1001.2014.3001.5501

8.3 机器人平台设计之arduino与电机驱动

对于构建轮式机器人而言,电机驱动是一重要实现环节。

场景:在机器人架构中,如果要实现机器人移动,其中一种实现策略是:控制系统会先发布预期的车辆速度信息,然后驱动系统订阅到该信息,控制电机转速至预期速度,调速过程中需要时时测速用于计算实际速度与预期速度的差值,作为调速算法的输入数据,获取的实际速度还要反馈给控制系统,控制系统会计算实际位移并生成里程计信息。

在上述流程中,控制系统(ROS端)其实就是典型的发布和订阅实现,不再赘述,具体到驱动系统(Arduino)层面,需要解决的问题有如下几点:

一个周期伊始,Arduino 如何订阅控制系统发布的速度信息?一个周期结束,Arduino 如何发布实际速度信息到控制系统?一个周期之中,Arduino 如何驱动电机(正传、反转)?一个周期之中,Arduino 如何实现电机测速?一个周期之中,Arduino 如何实现电机调速?

前两个问题涉及到驱动系统与控制系统的通信,在下一节中单独讲解,本节主要介绍电机基本控制、电机测速以及调速实现,主要内容如下:

硬件:主要介绍电机类型与结构,还会介绍常用电机驱动板;电机转向控制与电机转速的控制;电机测速实现;电机调速实现。

8.3.1 硬件_电机与电机驱动板

如果要通过Arduino实现电机相关操作(比如:转向控制、转速控制、测速等),那么必须先要具备两点前提知识:

需要简单了解电机类型、机械结构以及各项参数,这些是和机器人的负载、极限速度、测速结果等休戚相关的;
还需要选配合适的电机驱动板,因为Arduino的输出电流不足以直接驱动电机,需要通过电机驱动板放大电机控制信号。

当前我们的机器人平台使用的电机为直流减速电机,电机驱动板为L298P电机驱动板。接下来就分别介绍这两个模块:
1.直流减速电机

如图所示,相当一部分ROS智能车中使用的直流减速电机与之类似,只要构成由三部分构成:

头部:减速箱
中间:电机主体
尾部:编码器电机主体通过输入轴与减速箱相连接,通过减速箱的减速效果,最终外端的输出轴会按照比例(取决于减速箱减速比)降低电机输入轴的转速,当然速度降低之后,将提升电机的力矩。尾部是AB相霍尔编码器,通过AB编码器输出的波形图,可以判断电机的转向以及计算电机转速

另外,即便电机外观相同,具体参数也可能存在差异,参数需要商家提供,需要了解的参数如下:

额定电压
额定电流
额定功率
额定扭矩
减速比
减速前转速
减速后转速
编码器精度主要参数:额定扭矩:额定扭矩和机器人质量以及有效负荷相关,二者正比例相关,额定扭矩越大,可支持的机器人质量以及有效负荷越高;减速比:电机输入轴与输出轴的减速比例,比如: 减速比为60,意味着电机主体旋转60圈,输出轴旋转1圈。减速后转速:与减速比相关,是电机减速箱输出轴的转速,单位是 rpm(转/分),减速后转速与减速前转速存在转换关系: 减速后转速 = 减速前转速 / 减速比。另外,可以根据官方给定的额定功率下的减速后转速结合车轮参数来确定小车最大速度。编码器精度:是指编码器旋转一圈单相(当前编码器有AB两相)输出的脉冲数,注意:电机输入轴旋转一圈的同时,编码器旋转一圈,如果输出轴旋转一圈,那么编码器的旋转圈数和减速比一致(比如减速比是60,那么输出轴旋转一圈,编码器旋转60圈),而编码器输出的脉冲数计算公式则是: 输出轴旋转一圈产生的脉冲数 = 减速比 * 编码器旋转一圈发送的脉冲数(比如:减速比为60,编码器旋转一圈输出13个脉冲,那么输出轴旋转一圈总共产生 13 * 60 也即780个脉冲)。

2.电机驱动板

电机驱动板可选型号较多,比如:TB6612、L298N、L298P…

TB6612:

L298N:

L298P:

在此我们选用 L298P,可以在Arduino上直接插拔,使用更为方便,另外请注意:为了保护电路板,使用之前,请先剔除L298P电机驱动板Vin引脚背后的锡焊或者也可以将对应的排针直接折断。至于更详细使用方式,后续有详细介绍。

8.3.2 电机基本控制实现

在ROS智能车中,控制车辆的前进、后退以及速度调节,那么就涉及到电机的转向与转速控制,本节主要就是介绍相关知识点。

需求:控制电机转动,先控制电机以某个速率正向转动N秒,再让电机停止N秒,再控制电机以某个速率逆向转动N秒,最后让电机停止N秒,如此循环。

实现流程:

接线,需要先集成电池、Arduino、电机驱动板与电机(可以使用杜邦线接线);
编写Arduino程序,setup中设置引脚模式,loop中控制电机运动;
上传并查看运行结果。

1.接线

先将电机驱动板与Arduino集成(注意:请先剔除L298P电机驱动板Vin引脚背后的锡焊或者也可以将对应的排针直接折断);

然后将电池的正负极使用杜邦线(公对公)分别接入L298P电机驱动模块的VIN与GND(注意:正负极不可接反,正=VIN,负=GND);

最后将电机编码器的电机线+和电机线-使用杜邦线(公对母)分别接入L298P电机驱动模块的A+与A-(无强制对应关系)。

接线效果图如下:

不同的编码器排针顺序可能有差异,请注意区分,当前的编码器电机线+与电机线-是最外围两个排针。
2.编码

前提知识点:

L298P电机驱动板的 A+ 与 A- 输出对应的是引脚4(DIRA)和引脚5(PWMA),引脚4控制转向,引脚5输出PWM。B+ 与 B- 输出对应的是引脚6(PWMB)和引脚7(DIRB),引脚7控制转向,引脚6输出PWM。
可以通过PWM控制电机转速。

代码:

 * 电机转动控制* 1.定义接线中电机对应的引脚* 2.setup 中设置引脚为输出模式* 3.loop中控制电机转动int DIRA = 4;
int PWMA = 5;void setup() {//两个引脚都设置为 OUTPUTpinMode(DIRA,OUTPUT);pinMode(PWMA,OUTPUT);
}void loop() {//先正向转动3秒digitalWrite(DIRA,HIGH);analogWrite(PWMA,100);delay(3000);//停止3秒digitalWrite(DIRA,HIGH);analogWrite(PWMA,0);delay(3000);//再反向转动3秒digitalWrite(DIRA,LOW);analogWrite(PWMA,100);delay(3000);//停止3秒digitalWrite(DIRA,LOW);analogWrite(PWMA,0);delay(3000);
  • 注意:
  • 1.可以通过将DIRA设置为HIGH或LOW来控制电机转向,但是哪个标志位正转或反转需要根据需求判断,转向是相对的。
  • 2.PWM的取值为 [0,255],该值可自己设置。

3.运行

程序上传到Arduino上,如无异常,电机开始转动,转动结果与需求描述类似。

8.3.3 电机测速01_理论

测速实现是调速实现的前提,8.3.3-8.3.N会循序渐进的介绍测速的完整实现,本节主要介绍AB相增量式编码器测速原理。
1.概念

百度百科关于编码器介绍如下:
编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换成电信号,前者称为码盘,后者称为码尺。按照读出方式编码器可以分为接触式和非接触式两种;按照工作原理编码器可分为增量式和绝对式两类。增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。

2.测速原理

关于编码器相关概念简单了解即可,在此需要着重介绍的是 AB相增量式编码器测速原理:

AB相编码器主要构成为A相与B相,每一相每转过单位的角度就发出一个脉冲信号(一圈可以发出N个脉冲信号),A相、B相为相互延迟1/4周期的脉冲输出,根据延迟关系可以区别正反转,而且通过取A相、B相的上升和下降沿可以进行单频或2倍频或4倍频测速。
3.测速举例

假设编码器旋转1圈输出13个脉冲,减速比为 60。伪代码如下:

单频计数://设置一个计数器
int count = 0;
//当A为上升沿时
if(B为高电平){count++;
}else {count--;
}
//....
//速度=单位时间内统计的脉冲的个数 / (13*60) / 单位时间2倍频计数://设置一个计数器
int count = 0;
//当A为上升沿时
if(B为高电平){count++;
}else {count--;
}
//当A为下降沿时
if(B为低电平){count++;
}else {count--;
}//....
//速度=单位时间内统计的脉冲的个数 / (13*2*60) / 单位时间4倍频计数://设置一个计数器
int count = 0;
//当A为上升沿时
if(B为高电平){count++;
}else {count--;
}
//当A为下降沿时
if(B为低电平){count++;
}else {count--;
}
//当B为上升沿时
if(A为低电平){count++;
} else {count--;
}
//当B为下降沿时
if(A为高电平){count++;
} else {count--;
}
//....
//速度=单位时间内统计的脉冲的个数 / (13*4*60) / 单位时间

8.3.4 电机测速02_实现

需求:统计并输出电机转速。
思路:先统计单位时间内以单频或2倍频或4倍频的方式统计脉冲数,再除以一圈对应的脉冲数,最后再除以时间所得即为电机转速。
核心:计数时,需要在A相或B相的上升沿或下降沿触发时,实现计数,在此需要使用中断引脚与中断函数。

Arduino Mega 2560 的中断引脚:2 (interrupt 0), 3 (interrupt 1),18 (interrupt 5), 19 (interrupt 4), 20 (interrupt 3), 21 (interrupt 2)

实现流程:

接线:将Arduino与电机驱动模块集成,使用杜邦线将电机编码器连接到Arduino的相关引脚;
编写Arduino程序先实现脉冲数统计;
编写Arduino程序再实现转速计算相关实现;
上传到Arduino并测试。

1.接线

先将Arduino与电机驱动模块集成(以实现);

然后使用杜邦线(公对母)将编码器5V与编码器GND分别连接到Arduino或电机驱动板的5V和GND;

最后使用杜邦线(公对母)将编码器A相和编码器B相分别连接中断引脚(比如:A相连接18,B相连接19)。

注意:当前只是测速案例,没必要必须连接电池以及为电机供电,精简期间,当前只连接编码器。

**接线效果图如下:

2.编码实现脉冲统计**

核心知识点:attachInterrupt()函数

描述:当发生外部中断时,调用一个指定函数。当中断发生时,该函数会取代正在执行的程序。大多数的Arduino板有两个外部中断:0(数字引脚2)和1(数字引脚3)。arduino Mege有四个外部中断:数字2(引脚21),3(引脚20),4(引脚19),5(引脚18)。语法:attachInterrupt(interrupt, function, mode)interrupt:中断引脚数function:中断发生时调用的函数,此函数必须不带参数和不返回任何值。该函数有时被称为中断服务程序。mode:定义何时发生中断以下四个contstants预定有效值:LOW 当引脚为低电平时,触发中断CHANGE 当引脚电平发生改变时,触发中断RISING 当引脚由低电平变为高电平时,触发中断FALLING 当引脚由高电平变为低电平时,触发中断.返回:无注意事项:当中断函数发生时,delay()和millis()的数值将不会继续变化。当中断发生时,串口收到的数据可能会丢失。你应该声明一个变量来在未发生中断时储存变量。

代码:

  • 测速实现:

  • 阶段1:脉冲数统计

  • 阶段2:速度计算

  • 阶段1:

  • 1.定义所使用的中断引脚,以及计数器(使用 volatile 修饰)

  • 2.setup 中设置波特率,将引脚设置为输入模式

  • 3.使用 attachInterupt() 函数为引脚添加中断出发时机以及中断函数

  • 4.中断函数编写计算算法,并打印

  • A.单频统计只需要统计单相上升沿或下降沿

  • B.2倍频统计需要统计单相的上升沿和下降沿

  • C.4倍频统计需要统计两相的上升沿和下降沿

  • 5.上传并查看结果

int motor_A = 18;//中端口是5
int motor_B = 19;//中断口是4
volatile int count = 0;//如果是正转,那么每计数一次自增1,如果是反转,那么每计数一次自减1 void count_A(){//单频计数实现//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比/*if(digitalRead(motor_A) == HIGH){if(digitalRead(motor_B) == LOW){//A 高 B 低count++;  } else {//A 高 B 高count--;  }}*///2倍频计数实现//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2if(digitalRead(motor_A) == HIGH){if(digitalRead(motor_B) == HIGH){//A 高 B 高count++;  } else {//A 高 B 低count--;  }} else {if(digitalRead(motor_B) == LOW){//A 低 B 低count++;  } else {//A 低 B 高count--;  }  }}//与A实现类似
//4倍频计数实现
//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 4
void count_B(){if(digitalRead(motor_B) == HIGH){if(digitalRead(motor_A) == LOW){//B 高 A 低count++;} else {//B 高 A 高count--;}} else {if(digitalRead(motor_A) == HIGH){//B 低 A 高count++;} else {//B 低 A 低count--;}}}void setup() {Serial.begin(57600);//设置波特率  pinMode(18,INPUT);pinMode(19,INPUT);attachInterrupt(5,count_A,CHANGE);//当电平发生改变时触发中断函数//四倍频统计需要为B相也添加中断attachInterrupt(4,count_B,CHANGE);
}void loop() {//测试计数器输出delay(3000);Serial.println(count);}

3.转速计算

思路:需要定义一个开始时间(用于记录每个测速周期的开始时刻),还需要定义一个时间区间(比如50毫秒),时时获取当前时刻,当当前时刻 - 上传结束时刻 >= 时间区间时,就获取当前计数并根据测速公式计算时时速度,计算完毕,计数器归零,重置开始时间

核心知识点:当使用中断函数中的变量时,需要先禁止中断noInterrupts(),调用完毕,再重启中断interrupts()

代码(核心):

2中代码除了 loop 实现,无需修改。

int reducation = 60;//减速比,根据电机参数设置,比如 15 | 30 | 60
int pulse = 13; //编码器旋转一圈产生的脉冲数该值需要参考商家电机参数
int per_round = pulse * reducation * 4;//车轮旋转一圈产生的脉冲数
long start_time = millis();//一个计算周期的开始时刻,初始值为 millis();
long interval_time = 50;//一个计算周期 50ms
double current_vel;//获取当前转速的函数
void get_current_vel(){long right_now = millis();  long past_time = right_now - start_time;//计算逝去的时间if(past_time >= interval_time){//如果逝去时间大于等于一个计算周期//1.禁止中断noInterrupts();//2.计算转速 转速单位可以是秒,也可以是分钟... 自定义即可current_vel = (double)count / per_round / past_time * 1000 * 60;//3.重置计数器count = 0;//4.重置开始时间start_time = right_now;//5.重启中断interrupts();Serial.println(current_vel);}
}void loop() {//测试计数器输出//delay(3000);//Serial.println(count);delay(10);get_current_vel();}

4.测试

将代码上传至Arduino,打开出口监视器,手动旋转电机,可以查看到转速信息。

8.3.5 电机调速01_PID控制理论

场景:

速度信息可以以m/s为单位,或者也可以转换成转速 r/s,而电机的转速是由PWM脉冲宽度来控制的,如何根据速度信息量化成合适的PWM至呢?
比如:现有一辆行驶中的无人车,要求将车速调整至100KM/h,那么应该如何向电机输出PWM值?或换言之,如何控制油门?

调速实现策略由多种,PID其中较为常用。
PID简介

PID算法是一种经典、简单、高效的动态速度调节方式,P代表比例,I代表积分,D代表微分。

PID公式如下:

  e(t)作为 PID 控制的输入;u(t)作为 PID 控制器的输出和被控对象的输入;Kp 控制器的比例系数;Ki控制器的积分时间,也称积分系数;Kd控制器的微分时间,也称微分系数。

上述公式稍显晦涩,PID控制原理框架图更有助于理解:

1.P

如果实现上述场景中的车速控制,一种简单的实现方式是: 确定目标速度,获取当前速度,使用(目标速度-当前速度)*某一系数 计算结果为输出的PWM,再获取当前速度,使用(目标速度-当前速度)*某一系数 计算结果累加上次的PWM并输出…如此循环

比如:

目标速度为100KM/h,系数为0.5
初始状态为静止0KM/h,差值为100,差值*系数计算输出结果为50,当前速度可达 60KM/h
初始速度为60KM/h,差值为40,差值*系数计算结果为20,累加之后为70,当前速度可达84KM/h
初始速度为84KM/h,差值为16,差值*系数计算结果为8,累加之后为78,当前速度可达93.6KM/h
.... 以此类推,最终达成目标速度。

在上述模型中,调速实现是一个闭环,每一次循环都会根据当前时速与目标时速的差值,再乘以以固定系数,计算出需要增长的PWM值,这其中的系数,称之为比例,也是PID中的P。
2.I

上述模型是理想状态实现,当PWM按照比例增长时,时速也是等比例增长的,但是实际状态下,可能由于内部外部因素的影响(摩擦力、风阻等),时速不能等比例增长,每次循环中实际速度与预期速度存在稳态误差,这意味着最终结果可能永远无法达成预期,解决的方法就是使用积分I。

每次调速时,输出除了要累加计算的PWM之外,还要累加根据积分I计算的结果,以消除静态误差。
3.D

仍然以模型1为例,当比例设置的过大时,可能会出先"超速"的情况,超速之后可能需要多次调整,产生系统震荡,具体到电机上表现,可能会出现抖动,解决这种情况可以使用D微分,当速度越是接近目标速度时,D就会越施加反方向力,减弱P的控制,起到类似”阻尼“的作用。通过D的使用可以减小系统震荡。

综上,PID闭环控制实现是结合了比例、积分和微分的一种控制机制,通过P可以以增量的方式计算输出,通过I可以消除稳态误差,通过D可以减小系统震荡,三者相结合,最终是要快速、精准且稳定的达成预期结果,而要实现该结果,还需要对这三个数值反复测试、调整…下一节将介绍在 Arduino 中PID控制的具体实现,其中就包括PID库的调用,以及PID调试的具体方式。

8.3.6 电机调速02_PID控制实现

了解了PID原理以及计算公式之后,我们可以在程序中自实现PID相关算法实现,不过,在Arduino中该算法已经被封装了,直接整合调用即可,从而提高程序的安全性与开发效率。该库是:Arduino-PID-Library,接下来通过一个案例演示该库的使用。

需求:通过PID控制电机转速,预期转速为 120r/m。

实现流程:

添加Arduino-PID-Library;
接线——Arduino集成电机驱动模块、电池、电机;
编写Arduino程序直接调用相关实现;
使用串口绘图器调试PID值。

1.添加Arduino-PID-Library

首先在 GitHub 下载 PID 库: git clone https://github.com/br3ttb/Arduino-PID-Library

然后将该文件夹移动到 arduino 的安装目录的 libraries下: sudo cp -r Arduino-PID-Library /usr/share/arduino/libraries

还要重命名文件夹: sudo mv Arduino-PID-Library ArduinoPIDLibrary

最后重启 ArduinoIDE
2.接线

需要按照8.3.2中的接线模式集成电机驱动模块、电池与电机线;

需要按照8.3.4中的接线模式集成Arduino与电机编码器。

接线效果图如下:

3.编码

PID调速中,测速是实现闭环的关键实现,所以需要复制之前的电机控制代码以及测速代码。

完整代码实现:

  • PID 调速实现:
  • 1.代码准备,复制并修改电机控制以及测速代码
  • 2.包含PID头文件
  • 3.创建PID对象
  • 4.在setup中启用自动调试
  • 5.调试并更新PWM
#include <PID_v1.h> int DIRA = 4;
int PWMA = 5;int motor_A = 18;//中端口是5
int motor_B = 19;//中断口是4
volatile int count = 0;//如果是正转,那么每计数一次自增1,如果是反转,那么每计数一次自减1 void count_A(){//单频计数实现//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比/*if(digitalRead(motor_A) == HIGH){if(digitalRead(motor_B) == LOW){//A 高 B 低count++;  } else {//A 高 B 高count--;  }}*///2倍频计数实现//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2if(digitalRead(motor_A) == HIGH){if(digitalRead(motor_B) == HIGH){//A 高 B 高count++;  } else {//A 高 B 低count--;  }} else {if(digitalRead(motor_B) == LOW){//A 低 B 低count++;  } else {//A 低 B 高count--;  }  }}//与A实现类似
//4倍频计数实现
//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 4
void count_B(){if(digitalRead(motor_B) == HIGH){if(digitalRead(motor_A) == LOW){//B 高 A 低count++;} else {//B 高 A 高count--;}} else {if(digitalRead(motor_A) == HIGH){//B 低 A 高count++;} else {//B 低 A 低count--;}}}int reducation = 60;//减速比,根据电机参数设置,比如 15 | 30 | 60
int pulse = 13; //编码器旋转一圈产生的脉冲数该值需要参考商家电机参数
int per_round = pulse * reducation * 4;//车轮旋转一圈产生的脉冲数
long start_time = millis();//一个计算周期的开始时刻,初始值为 millis();
long interval_time = 50;//一个计算周期 50ms
double current_vel;//获取当前转速的函数
void get_current_vel(){long right_now = millis();  long past_time = right_now - start_time;//计算逝去的时间if(past_time >= interval_time){//如果逝去时间大于等于一个计算周期//1.禁止中断noInterrupts();//2.计算转速 转速单位可以是秒,也可以是分钟... 自定义即可current_vel = (double)count / per_round / past_time * 1000 * 60;//3.重置计数器count = 0;//4.重置开始时间start_time = right_now;//5.重启中断interrupts();Serial.println(current_vel);}
}//-------------------------------------PID-------------------------------------------
//创建 PID 对象
//1.当前转速 2.计算输出的pwm 3.目标转速 4.kp 5.ki 6.kd 7.当输入与目标值出现偏差时,向哪个方向控制
double pwm;//电机驱动的PWM值
double target = 120;
double kp=1.5, ki=3.0, kd=0.1;
PID pid(&current_vel,&pwm,&target,kp,ki,kd,DIRECT);//速度更新函数
void update_vel(){//获取当前速度get_current_vel();pid.Compute();//计算需要输出的PWMdigitalWrite(DIRA,HIGH);analogWrite(PWMA,pwm);}void setup() {Serial.begin(57600);//设置波特率  pinMode(18,INPUT);pinMode(19,INPUT);//两个电机驱动引脚都设置为 OUTPUTpinMode(DIRA,OUTPUT);pinMode(PWMA,OUTPUT);attachInterrupt(5,count_A,CHANGE);//当电平发生改变时触发中断函数//四倍频统计需要为B相也添加中断attachInterrupt(4,count_B,CHANGE);pid.SetMode(AUTOMATIC);
}void loop() {delay(10);//digitalWrite(DIRA,HIGH);//analogWrite(PWMA,150);//get_current_vel();update_vel();}

核心代码解释:

1.包含PID头文件

#include <PID_v1.h>

2.创建PID对象

//创建 PID 对象
//1.当前转速 2.计算输出的pwm 3.目标转速 4.kp 5.ki 6.kd 7.当输入与目标值出现偏差时,向哪个方向控制

double pwm;//电机驱动的PWM值
double target = 120;
double kp=1.5, ki=3.0, kd=0.1;
PID pid(&current_vel,&pwm,&target,kp,ki,kd,DIRECT);

3.setup中启用PID自动控制

pid.SetMode(AUTOMATIC);

4.计算输出值

pid.Compute();

4.调试

PID控制的最终预期结果,是要快速、精准、稳定的达成预期结果,P主要用于控制响应速度,I主要用于控制精度,D主要用于减小震荡增强系统稳定性,三者的取值是需要反复调试的,调试过程中需要查看系统的响应曲线,根据响应曲线以确定合适的PID值。

在 Arduino 中响应曲线的查看可以借助于 Serial.println() 将结果输出,然后再选择菜单栏的工具下串口绘图器以图形化的方式显示响应结果:

PID调试技巧:

参数整定找最佳,从小到大顺序查
先是比例后积分,最后再专把微分加
曲线振属荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢。微分时间应加长
理想曲线两个波,前高后低4比1
一看二调多分析,调节质量不会低

后面发现了一个骚操作: 呜呜呜,没有之前那么麻烦的Ծ‸Ծ,链接惊喜:http://www.autolabor.com.cn/book/ROSTutorials/di-9-zhang-ji-qi-ren-dao-822a28-shi-4f5329.html

有帮助的小伙伴给个赞呗,大家进交流群一起学习。

8.3 机器人平台设计之arduino与电机驱动相关推荐

  1. 【毕业设计_课程设计】基于python的微信公众平台机器人的设计与实现

    文章目录 0 项目说明 项目介绍 项目工程 0 项目说明 基于python的微信公众平台机器人的设计与实现 提示:适合用于课程设计或毕业设计,工作量达标,源码开放 项目介绍 1.NGINX做负载均衡, ...

  2. python笔迹识别_关于机器视觉笔迹识别和Arduino控制机器人的设计

    0 引言 伴随着现在日益高性能的计算机硬件和完善的理论技术,机器视觉技术已开始得到广泛的应用.结合机器视觉技术的智能机器人在现今人工智能趋势下扮演一个重要角色,在智能制造推进.智慧城市建设.家居生活质 ...

  3. 初中计算机教案3D,基于3D 仿真平台的初中机器人 教学设计

    原标题:基于3D 仿真平台的初中机器人 教学设计 本文发表于 <数字教育> 2018年第5期(总第23期)实践案例栏目,页码:71-77.转载请注明出处. 摘 要:本文采用实践教学法,以社 ...

  4. 【实战+源码】基于RGB-D(深度视觉)的具有机械臂抓取功能的自主规划移动服务机器人的设计与实现(一)——准备工作

    目录 一,实物or仿真 1,实物或仿真的利弊 2,从哪些角度去考虑是选择实物还是仿真 二,环境准备 1,首推ROS 2,其他环境 三,理论学习 四,实物搭建 一,实物or仿真 我想这个问题是在开发之前 ...

  5. 5G和AI机器人平台为工业4.0和无人机提供服务

    5G和AI机器人平台为工业4.0和无人机提供服务 Qualcomm 5G and AI robotics platform delivers for Industry 4.0 and drones 高 ...

  6. 5G和AI机器人平台

    5G和AI机器人平台 Qualcomm Launches 5G and AI Robotics Platform 高通技术公司(Qualcomm Technologies)周三推出了一款高级5G和人工 ...

  7. ROS探索总结(十六)(十七)(十八)(十九)——HRMRP机器人的设计 构建完整的机器人应用系统 重读tf 如何配置机器人的导航功能

    ROS探索总结(十六)--HRMRP机器人的设计 1. HRMRP简介         HRMRP(Hybrid Real-time Mobile Robot Platform,混合实时移动机器人平台 ...

  8. 使用机器学习算法在 .NET Core 中运行的 100% C# 开源 AI 聊天机器人平台构建器...

    简介 BotSharp是一个用于 AI Bot 平台构建器的开源机器学习框架.该项目涉及自然语言理解.计算机视觉和音频处理技术,旨在推动智能机器人助手在信息系统中的开发和应用.开箱即用的机器学习算法让 ...

  9. 乐乐勇智能教育机器人有多少型号_【头条】协作机器人平台化趋势将会是柔性自动化的破局之道...

    智能机器人商情微信公众号,关注中国智能机器人行业热点与发展趋势,打造快捷高效的行业资讯交互平台.更多精彩内容,您可以点击标题下方的蓝字关注我们. 导语 艾利特平台级CS系列协作机器人全新发布 9月15 ...

最新文章

  1. hdu 4263(有限制的生成树)
  2. Flask-Login一些使用解释(根据官网和个人查找资料的理解并解释)
  3. 清华张悠慧:AI时代,「图灵完备」之后,「类脑计算完备」如何设计?
  4. Office2019 Word 新建文档豆沙绿背景色失效零时解决方案
  5. python快速编程入门第13章-Python快速编程入门,打牢基础必须知道的11个知识点...
  6. 判断线段相交 + vector. erase迭代指针 的使用 poj 2653 Pick-up sticks
  7. 精馏塔matlab,MATLAB图解精馏塔理论塔板数程序代码
  8. 【Data Cluster】真机环境下MySQL数据库集群搭建
  9. 评分系统 java_C自动评分系统
  10. 实现安卓里边下边播的播放器(源码公开)
  11. Leetcode--461. 汉明距离
  12. Linux开机启动过程(4):切换到64位模式-长模式(直到内核解压缩之前)
  13. 股东其实对公司情况一无所知,唯一办法是追责
  14. Studio One5新版一键下载安装教程
  15. 自相关法谱估计matlab,自相关法估计功率谱密度
  16. ZZUOJ 公主与骑士 (BFS)
  17. 绘制3d散点图报错ax = fig.gca(projection = ‘3d‘)TypeError: gca() got an unexpected keyword argument
  18. Unity Shader 学习记录(3) —— CG语言和Shader文件
  19. SpringBoot发生404跳转404页面
  20. PPT造电池,特斯拉电池日画一张“十年保质期”的大饼

热门文章

  1. 河北省会计证年检流程
  2. 服务器10的系统杀毒怎么关,Win10自带杀毒软件怎么关闭?彻底关闭Windows Defender方法...
  3. iOS 13.x获取通讯录信息时的注意事项
  4. 基于Edge浏览器的沙拉划词插件使用教程(好用的翻译插件)
  5. 完美解决小米随身wifi创建网络失败
  6. git使用进阶(一)
  7. 点阵、基元和晶体结构之间的关系
  8. 清北学堂2019.8.9
  9. 【Excel】用excel生成矩阵
  10. 电脑无法修改ip地址