使用旋转编码器控制直流减速电机

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是一个控制器,可帮助您的电机在尽可能最短的时间内以尽可能低的过冲(错误)运行到所需的位置。需要一个控制过程来学习所有这些。您基本上需要一个采用“所需角度”的反馈回路,将其提供给移动电机的控制器。然后,您将获得电机的当前位置,该位置将反馈到系统的原点。您的“所需角度”减去“当前角度”将是每次微控制器越过回路时电机应移动的程度。以下是反馈循环的样子:enter image description here

这里是学习控制的链接。祝好运! Control Tutorials

编辑2:我应该给你介绍一下PID是什么。 PID控制器由三个不同的组件组成:

  1. 成比例的
  2. 积分
  3. 衍生物

每次你得到你想要的角度 - “实际角度”或“e”,如图所示,你将按Kp计算它。找到它相对于前一个e的导数并用Kd计算它,并找到误差的积分并用Ki计算它的时间。您可以先忽略Ki和积分,然后在以后需要时添加它。获得Kpe + Kdd(e)/ dt后,此值是您输出到电机的功率百分比。 Kp和Kd和Ki是真正的工程发挥作用的地方。您应该使用系统的传递函数找到它们,并在MatLab或类似软件中对它们进行微调。这些值通常很低(小于1)。这真的取决于你的系统。对于我的运动,它们是Kp = 0.001和Kd = 0.02

以上是关于使用旋转编码器控制直流减速电机的主要内容,如果未能解决你的问题,请参考以下文章

Arduino PID直流电机位置控制

电机控制2---带光电编码器式直流电动机模型及控制

使用 H-Bridge 和 neopixel 以及 Arduino UNO 控制直流电机

Verilog直流电机的pwm控制设计

pcl怎样控制伺服电机回到零点

基于锁相环的直流电机控制系统simulink仿真