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

如何解决步进电机不能正确/精确地旋转

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

硬件: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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-