【问题标题】:How to control the motor using the rotary encoder如何使用旋转编码器控制电机
【发布时间】:2021-01-09 08:44:16
【问题描述】:

我想用旋转编码器控制电机的精度。

例如,我想将电机移动到任意一侧,例如 70 度,并使用旋转编码器返回其原始位置。我写了一个代码,但是这个代码电机不会移动,除非旋转编码器被移动。

二手零件

  • 带齿轮箱的直流电机
  • arduino mega
  • bts 7960
  • 编码器旋转

代码:

// Rotary Encoder Inputs
#define inputCLK 3
#define inputDT 2
int LPWM = 6; //   
int LEN = 9; // 
int RPWM =5; // 
int REN = 8; // 
int counter = 0; 
int currentStateCLK;
int previousStateCLK; 

String encdir ="";
 void setup() { 
  
  // Set encoder pins as inputs  
 pinMode (inputCLK,INPUT);
 pinMode (inputDT,INPUT);
 pinMode(LPWM, OUTPUT); 
 pinMode(RPWM, OUTPUT); 
 pinMode(LEN, OUTPUT);
 pinMode(REN, OUTPUT);

 digitalWrite(LEN, HIGH);
 digitalWrite(REN, HIGH);
    // Setup Serial Monitor
  Serial.begin (9600);
  
  // Read the initial state of inputCLK
  // Assign to previousStateCLK variable
  previousStateCLK = digitalRead(inputCLK);

} 

void loop() 
{ 
 
 // Read the current state of inputCLK
  currentStateCLK = digitalRead(inputCLK);
   
  // If the previous and the current state of the inputCLK are different then a pulse has occured
  if (currentStateCLK != previousStateCLK){ 
      
    // If the inputDT state is different than the inputCLK state then 
    // the encoder is rotating counterclockwise
    if (digitalRead(inputDT) != currentStateCLK) { 
      counter --;
      encdir ="CCW";
        digitalWrite(RPWM,HIGH);   //move forward and backward
        digitalWrite(LPWM, LOW);
    
    } else {
      // Encoder is rotating clockwise
      counter ++;
      encdir ="CW";
        digitalWrite(RPWM,LOW);
        digitalWrite(LPWM, HIGH);
            
    }
    Serial.print("Direction: ");
    Serial.print(encdir);
    Serial.print(" -- Value: ");
    Serial.println(counter);
  } 
  // Update previousStateCLK with the current state
  previousStateCLK = currentStateCLK; 




} 

【问题讨论】:

    标签: griddb


    【解决方案1】:
    1. 需要用 PWM 信号驱动 H 桥 PWM 引脚,将 PWM 引脚拉高会导致电机全速旋转,不适合位置控制。
    2. 您需要将编码器引脚连接到硬件定时器(在计数器模式下)以提高控制性能,否则您可能无法在高电机速度下获得编码器值。当然,编码器信号经过特殊编码,因此您可能需要先对其进行解码,然后再对其进行计数。请谷歌它以获取更多信息。
    3. 您需要使用 P、PI 或 PID 控制器(在软件中)来有效控制电机位置。我将举一个 P 控制的例子,一旦你开始工作,你可以检查更高级的(PI 或 PID)。
    4. 避免在高速循环中调用 Serial.print 内容,这会降低性能。

    您可以找到以下代码作为起点(虽然它没有经过测试)。

    // Rotary Encoder Inputs
    #define inputCLK 3
    #define inputDT 2
    int LPWM = 6; //   
    int LEN = 9; // 
    int RPWM =5; // 
    int REN = 8; // 
    int currentStateCLK;
    int previousStateCLK; 
    
    int counter = 0; // the actual place where the motor stand
    int setPoint = 500; // The encoder counter value where you want the motor to go
    float kp = 0.5; // proportional control gain
    
    void doPControl(int set, int current) {
        int error = set - current;
        int level = (int)(kp * error);
        
        if (level < 0) {
            analogWrite(RPWM, 0); // need to use PWM signal instead of digital HIGH/LOW
            analogWrite(LPWM, -level);
        } else {
            analogWrite(LPWM, 0);
            analogWrite(RPWM, level);
        }
    }
    
    void setup() { 
        // Set encoder pins as inputs
        pinMode (inputCLK,INPUT);
        pinMode (inputDT,INPUT);
        pinMode(LPWM, OUTPUT); 
        pinMode(RPWM, OUTPUT); 
        pinMode(LEN, OUTPUT);
        pinMode(REN, OUTPUT);
    
        analogWrite(LPWM, 0);
        analogWrite(RPWM, 0);
        digitalWrite(LEN, HIGH);
        digitalWrite(REN, HIGH);
      
        // Read the initial state of inputCLK
        // Assign to previousStateCLK variable
        previousStateCLK = digitalRead(inputCLK);
    } 
    
    void loop() 
    { 
        // Read the current state of inputCLK
        currentStateCLK = digitalRead(inputCLK);
    
        // If the previous and the current state of the inputCLK are different then a pulse has occured
        if (currentStateCLK != previousStateCLK && currentStateCLK == 1){ // this block is a task updating the encoder counter
            // If the inputDT state is different than the inputCLK state then 
            // the encoder is rotating counterclockwise
            if (digitalRead(inputDT) != currentStateCLK) { 
                counter --;
            } else {
                // Encoder is rotating clockwise
                counter ++;
            }
        }
    
        doPControl(setPoint, counter); // this line needs to get executed regardless of the encoder reading task
        
        // Update previousStateCLK with the current state
        previousStateCLK = currentStateCLK; 
    }
    

    【讨论】:

    • 我不明白,如果你解释一下,因为我是初学者,我尝试了代码,它没有工作
    • 我没有你的硬件,所以我无法验证它是否有效。虽然编译成功。我已经更新了代码,请再试一次。还有一个问题:您可能需要更改电机的极性,即将其连接到 H 桥的电源线反转。 (不是编码器线!)一旦你让它工作,你可能还需要调整 kp 值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多