步进电机不能正确/精确地旋转

问题描述

我想控制一个托盘在多个位置之间自动来回移动。

硬件:arduino nano / mega,TMC2209TB6600步进电机驱动器,步进电机23HS84830

电源:12V / 5A

问题::我编写了代码,并注意到,尽管位置之间的间隔是固定的,但每次移动托盘都会多一点,因此会丢失位置。在最后一个位置,它实际上会处于关闭位置。

尝试的解决方:为解决此问题,我决定编写一个串行命令草图,该草图可让我模拟此行为,定义间隔,位置数,周期,圈数,微步距,请参见下面的代码

enter image description here

我刚刚运行了一个序列,并将其返回到主菜单。这些都是可以配置的选项。

进行了一些试验,发现我的草图正以正确的方式输出我正确配置的内容(请参见下面的逻辑分析仪图片)。

image description here

在这张照片中发生的是:

    步进电机旋转5圈(8000步)并等待0.5秒,然后再次旋转。重复5次。
  1. 改变方向
  2. 与步骤1相同

到目前为止,我为解决问题所做的工作:

  • 在TMC2209和TB6600之间进行了切换,以查看问题是否出在驱动程序上:这不是两个驱动程序都发生的
  • 与逻辑分析器一起检查问题是否出在代码上:不是,代码输出是一致的并且易于测量
  • 回顾了步进电机线圈的连接。没问题,根据电动机数据表/步进电动机驱动器数据表。

此刻,我不明白为什么电动机不能正确地运动,并且我将感谢经验丰富的支持解决此问题,因为这似乎微不足道,但我找不到错误

谢谢!

int PUL=4; //define pulse pin
int DIR=3; //define Direction pin
int ENA=2; //define Enable Pin

#define left 1
#define right 0
#define LEFT 1
#define RIGHT 0

int steps_per_revolution = 200;
int minutes = 60;
long int input_value = 0;
long int _speed = 0;
long int temp_speed_rpm = 0;
long int speed_rpm = 0;
long int steps = 0;
int cycles = 0;
int positions = 0;
long int laps = 0;
long int rpm = 0;
int microstepping = 0;
long int total_laps = 0;

// Serial Commands
String command;
String inString = "";

// control flag to show the menu
boolean refresh_commands = false;

// DIRECTION LOW - MOVES RIGHT
// DIRECTION HIGH - MOVES LEFT

void setup() {
  pinMode (PUL,OUTPUT);
  pinMode (DIR,OUTPUT);
  pinMode (ENA,OUTPUT);

  Serial.begin(115200);

  menu_print();
}
void loop()
{
  if(Serial.available()){
        command = Serial.readStringUntil('\n');
        if(command.equals("p")){

            variable_print();
            
            refresh_commands = true;
        }
        if(command.equals("ss")){
            Serial.println("0");
            _speed = input_data();
            Serial.print(_speed);
            Serial.println(" uS");
            refresh_commands = true;
        }
        if(command.equals("ssr")){
            Serial.println("ssr");
            temp_speed_rpm = input_data();
            _speed = calculate_speed(temp_speed_rpm);
                        
            refresh_commands = true;
        }
        if(command.equals("sd")){                   // checks if one direction is set,changes and then changes back again
            if(digitalRead(DIR) == HIGH)
            {
              change_direction(right);
              Serial.println("Direction changed to: RIGHT");
            }
            else
            {
              if(digitalRead(DIR) == LOW)
              {
                change_direction(left);
                Serial.println("Direction changed to: LEFT");
              }
            }
        
            refresh_commands = true;
        }
        if(command.equals("sst")){
            Serial.println("sst");
            steps = input_data();
            Serial.println(" ");
            Serial.print(steps);
            Serial.println(" - steps configured");
            refresh_commands = true;
        }
        if(command.equals("sm")){
            Serial.println("sm");
            Serial.println("sm --> how many microsteps?");
            microstepping = input_data();
            Serial.println(microstepping);
            refresh_commands = true;
        }
        if(command.equals("sp")){
            Serial.println("sp");
            positions = input_data();
            Serial.println("sp --> Configure Positions");
            Serial.println(positions);
            refresh_commands = true;
        }
        if(command.equals("sc")){
            Serial.println("sc");
            cycles = input_data();
            Serial.println("sc --> Configure Cycles");
            Serial.println(cycles);
            refresh_commands = true;
        }
        if(command.equals("sl")){
            Serial.println("sl");
            Serial.println("sl --> how many laps?");
            laps = input_data();
            Serial.print(laps);
            refresh_commands = true;
        }
        if(command.equals("1")){
            Serial.println("1");
            change_direction(left);
            steps = input_data();       // Asks before for how many steps to rotate and changes the value.
            rotate_motor(steps);
            refresh_commands = true;
        }
        if(command.equals("2")){
            Serial.println("2");
            change_direction(right);
            steps = input_data();       // Asks before for how many steps to rotate and changes the value.
            rotate_motor(steps);
            refresh_commands = true;
        }
        if(command.equals("3")){
            Serial.println("3");
            change_direction(left);
            rotate_motor(steps);
            refresh_commands = true;
        }
        if(command.equals("4")){
            Serial.println("4");
            change_direction(right);
            rotate_motor(steps);
            refresh_commands = true;
        }
        if(command.equals("rs")){
            Serial.println("rs --> Run Sequence");
            variable_print();
            delay(3000);
            total_laps = laps * steps_per_revolution * microstepping;
            // run the planned sequence
            run_sequence(cycles,positions);
            refresh_commands = true;
        }
        if(command.equals("rl")){
            Serial.println("rl");
            Serial.println("rl --> how any laps? ");
            variable_print();
            delay(3000);
            total_laps = laps * steps_per_revolution * microstepping;
            // calculate laps and activate motor
            run_laps();
            refresh_commands = true;
        }
        else{
           Serial.println("Invalid command");
           refresh_commands = true;
        }        
        refresh_commands = true;            // added here to remove from all other commands
    }
    if (refresh_commands == true){
      menu_print();
      refresh_commands = false;
    }
}

void run_sequence(int cycles,int positions){
  int j = 0;
  
  
  for(j=0; j<cycles; j++)
  {
    Serial.print("Cycle:      ");
    Serial.println(j);
    // Start always moving to LEFT
    change_direction(left);
    Serial.println("Direction changed to: LEFT");
    
    for(int i=0; i<positions; i++)
    {
      Serial.print("FWD Pos.: ");
      Serial.println(i);
      rotate_motor(total_laps);
      delay(500);
    }
    delay(1000);
    //change_direction(right);
    change_direction(right);
    Serial.println("Direction changed to: RIGHT");
    delay(100);
    
    for(int i=0; i<positions; i++)
    {
      Serial.print("BWD Pos.: ");
      Serial.println(i);
      rotate_motor(total_laps);
      delay(500);
    }
  }
}

void run_laps(){
//  long int total_laps = 0;
//  total_laps = laps * steps_per_revolution * microstepping;
//  moved to the main cycle and changed run_sequence to include the laps
  Serial.print("Total Laps Steps: ");         // to be tested.
  Serial.println(total_laps);

  Serial.print("Laps: ");         // to be tested.
  Serial.println(laps);

  Serial.print("Steps/rev: ");         // to be tested.
  Serial.println(steps_per_revolution);

  Serial.print("MicroStepping: ");         // to be tested.
  Serial.println(microstepping);

  // change direction
  change_direction(left);

  // rotate motor
  rotate_motor(total_laps);              // variables must be long otherwise we cannot do the same number of steps as others

  delay(1000);

  // change direction
  change_direction(right);

  // rotate motor
  rotate_motor(total_laps);

  Serial.print(laps);
  Serial.println(" - Laps completed.");
}

int input_data(){
  int inChar = 0;
  boolean flag = false;
  
  Serial.println("How many?");
  Serial.println(" ");

  do{
     while (Serial.available() > 0) {
        inChar = Serial.read();
        if (isDigit(inChar)) {
          // convert the incoming byte to a char and add it to the string:
          inString += (char)inChar;
        }
        // if you get a newline,print the string,then the string's value:
        if (inChar == '\n') {
          input_value = inString.toInt();
          
          // clear the string for new input:
          inString = "";
          flag = true;
        }
//        // if the received char is an 'Z',then it triggers a flag to leave the menu
//        if(inChar == 'Z')
//        {
//          flag = true;
//        }
      }
  }while(!flag);
  
  return input_value;
}

void rotate_motor(long int motor_steps){
  Serial.print("Starting Rotation -->  ");
  Serial.println(motor_steps);

  long int i=0;
  
  digitalWrite(ENA,LOW);
  for (i=0; i<motor_steps; i++)
  {
    digitalWrite(PUL,HIGH);
    delayMicroseconds(_speed);
    digitalWrite(PUL,LOW);
    delayMicroseconds(_speed);
  }
  Serial.print("i -->  ");
  Serial.print(i);
  digitalWrite(ENA,HIGH);
  Serial.println("Finished rotation!");
}

void change_direction(bool direction){
  delayMicroseconds(500);
    digitalWrite(ENA,HIGH);
  delayMicroseconds(100);
    digitalWrite(DIR,direction);
  delayMicroseconds(500);
    digitalWrite(ENA,LOW);
  delayMicroseconds(100);
    Serial.print("Read Dir: ");
    Serial.println(digitalRead(DIR));
}

void menu_print(){
  Serial.println(" ");
  Serial.println("p --> display Parameters");
  Serial.println("ss --> Set Speed (tON/tOFF)");
  Serial.println("ssr --> Set Speed (RPM)");
  Serial.println("sd --> Configure direction");
  Serial.println("sst --> Set Steps");
  Serial.println("sm --> Set MicroStepping (default = 1)");
  Serial.println("sp --> Set Positions");
  Serial.println("sc --> Set Cycles");
  Serial.println("sl --> Set Laps");
  Serial.println("1 --> Move LEFT x steps");
  Serial.println("2 --> Move RIGHT x steps");
  Serial.println("3 --> Move LEFT 1 position");
  Serial.println("4 --> Move RIGHT 1 position");
  Serial.println("rs --> Run Sequence");
  Serial.println("rl --> Run Laps");
  Serial.println(" ");
}

void variable_print(){
  Serial.print("Speed:         ");
  Serial.print(_speed); 
  Serial.println(" us");
  Serial.print("Speed:         ");
  Serial.print(temp_speed_rpm); 
  Serial.println(" RPM");
  Serial.print("Steps:         ");
  Serial.println(steps);
  Serial.print("Microstepping: ");
  Serial.println(microstepping);
  Serial.print("Positions:     ");
  Serial.println(positions);
  Serial.print("Cycles:        ");
  Serial.println(cycles);
  Serial.print("Laps:          ");
  Serial.println(laps);
  Serial.print("Direction:     ");
  read_direction();                    
}

bool read_direction(){
  //bool dir_state = 0;
  
  if(digitalRead(DIR) == HIGH)
  {
    Serial.println("LEFT");
  }
  else
  {
    if(digitalRead(DIR) == LOW)
    {
      Serial.println("RIGHT");
    }
  }
  return digitalRead(DIR);
}

long int calculate_speed(long int _speed){
  
  float steps_per_second = 0;         // truncating a float to int -> error chance here
  float temp_speed = 0;
  

  Serial.print("FUNCTION: Calculate_speed: ");
  Serial.print(_speed);
  Serial.println(" RPM");

  steps_per_second = (_speed * steps_per_revolution) / minutes;
  
  Serial.print("FUNCTION: steps_per_second: ");
  Serial.println(steps_per_second);

  temp_speed = (1 / steps_per_second);

  temp_speed = temp_speed / 2;        // to find Ton and Toff
  temp_speed = temp_speed / 0.000001; // to convert to microseconds (input to delayMicroseconds() function)

  temp_speed = (int) temp_speed;

//  Serial.print("FUNCTION: _speed in microseconds:  ");
//  Serial.print(temp_speed,5);
//  Serial.println(" uS");

  Serial.print("FUNCTION: _speed in microseconds:  ");
  Serial.print(temp_speed);
  Serial.println(" uS");
    
  return temp_speed;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)