使用旋转编码器控制直流减速电机
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用旋转编码器控制直流减速电机相关的知识,希望对你有一定的参考价值。
我有一个旋转编码器和一个直流减速电机连接到我的Arduino UNO。我想以一定的角度旋转直流电机。就像我现在一样,我编写了一个代码,在旋转它时读取编码器的位置并打印出位置和角度。我还编写了在固定时间内运行直流电机的代码。
我想以一定的角度旋转直流电机。例如,如果我输入90度,我的电机应旋转90度并停止。
- 我使用引脚2和引脚3作为通道A和B(ENCODER)
- 我正在使用引脚9来控制我的直流电机。
我不知道如何处理这个...任何想法?
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int lcd_case = 0;
volatile int timeToRun = 0;
int motorPin = 6;
#define BTN_RIGHT 0
#define BTN_LEFT 1
#define BTN_UP 2
#define BTN_DOWN 3
#define BTN_SELECT 4
#define BTN_NONE 5
#define SELECT 6
#define RESET 7
#define PIN
#define encoderPinA 2
#define encoderPinB 3
#define CPR 256
volatile int counter =0;
volatile boolean flag;
volatile int var_degrees =0;
void setup() {
pinMode(3, OUTPUT);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
Serial.begin (9600);
attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_2, RISING);
lcd.clear();
}
void loop() {
if(flag == true){
var_degrees = ((360/256.0)*counter);
Serial.println(var_degrees);
//lcd.setCursor(0, 1);
//lcd.print("Degrees: ");
//lcd.setCursor(9, 1);
//lcd.print(var_degrees);
flag = false;
}
lcd_case = readButtons();
int read_button = analogRead (0);
//Depending on which button we pressed, we performan action
switch (lcd_case) {
case BTN_RIGHT:
{
break;
}
case BTN_LEFT:
{
break;
}
case BTN_UP:
{
timeToRun = timeToRun +1;
lcd.setCursor(0, 1);
lcd.print("Degrees: ");
lcd.setCursor(9, 1);
lcd.print(timeToRun);
delay(500);
break;
}
case BTN_DOWN:
{
if (timeToRun > 0) {
timeToRun = timeToRun - 1;
lcd.setCursor(0, 1);
lcd.print("Degrees: ");
lcd.setCursor(9, 1);
lcd.print(timeToRun);
delay(500);
break;
}
}
case BTN_SELECT:
{
analogWrite(motorPin, 255);
// I NEED TO ROTATE MOTOR BASED ON ANGLE IN ENCODER
delay(timeToRun * 100); //ONLY ROTATES DC MOTOR IN SECONDS
break;
}
case RESET:
{
break;
}
}
}
//Interrupts
void isr_2(){
flag = true;
if(digitalRead(encoderPinA) == HIGH){
if(digitalRead(encoderPinB) == LOW){
counter = counter -1; //COUNTER CLOCK WISE
}
else{
counter = counter +1; //CLOCK WISE
}
}
else{ //IF PIN A IS LOW
if(digitalRead(encoderPinB) == LOW){
counter = counter +1; //CLOCK WISE
}
else{
counter = counter -1 ; //COUNTER CLOCK WISE
}
}
}
int readButtons() {
int read_button;
read_button = analogRead (0);
if (read_button < 50) {
return BTN_RIGHT;
}
if (read_button < 195) {
return BTN_UP;
}
if (read_button < 400) {
return BTN_DOWN;
}
if (read_button < 600) {
return BTN_LEFT;
}
if (read_button < 800) {
return BTN_SELECT;
}
else
return BTN_NONE;
}
你正确地读取电机电枢的位置是件好事。现在是时候使用PID和闭环了!调谐PID是一个控制器,可帮助您的电机在尽可能最短的时间内以尽可能低的过冲(错误)运行到所需的位置。需要一个控制过程来学习所有这些。您基本上需要一个采用“所需角度”的反馈回路,将其提供给移动电机的控制器。然后,您将获得电机的当前位置,该位置将反馈到系统的原点。您的“所需角度”减去“当前角度”将是每次微控制器越过回路时电机应移动的程度。以下是反馈循环的样子:
这里是学习控制的链接。祝好运! Control Tutorials
编辑2:我应该给你介绍一下PID是什么。 PID控制器由三个不同的组件组成:
- 成比例的
- 积分
- 衍生物
每次你得到你想要的角度 - “实际角度”或“e”,如图所示,你将按Kp计算它。找到它相对于前一个e的导数并用Kd计算它,并找到误差的积分并用Ki计算它的时间。您可以先忽略Ki和积分,然后在以后需要时添加它。获得Kpe + Kdd(e)/ dt后,此值是您输出到电机的功率百分比。 Kp和Kd和Ki是真正的工程发挥作用的地方。您应该使用系统的传递函数找到它们,并在MatLab或类似软件中对它们进行微调。这些值通常很低(小于1)。这真的取决于你的系统。对于我的运动,它们是Kp = 0.001和Kd = 0.02
以上是关于使用旋转编码器控制直流减速电机的主要内容,如果未能解决你的问题,请参考以下文章