jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
楼主  发表于: 2024-12-22 20:41
图片:
一圈360度,分为12个段点,每个段点30度,每个段点都有一个开关。
当开关打开的区间,步进电机以正常速度旋转,并在段点停留0.5秒,没有打开段点的区间,以快于正常速度进行旋转,且不做停留。

以下例,1、2,5、6,9,10这几个区间是正常速度,其它区间是快速通过。
偿了下几种方式,效果都不好,大多都是快速时跑过了头,把正常区间都越过了。
PLC是三菱FX3U

希望老师们能指点下思路,感谢。

jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
1楼  发表于: 2024-12-23 20:56
引用
引用第3楼木林森于2024-12-23 09:03发表的  :
轴旋转前检查开关状态,ON 则直接旋转 30° 后停留 0.5S,OFF 则继续检查下一个节点开关状态并进行角度累加直到开关为 ON 后进行旋转停留


先用你的思路试一下,感谢。
jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
2楼  发表于: 2024-12-23 21:05
引用
引用第2楼二手工控电器于2024-12-23 08:58发表的  :
重赏之下必有勇夫!!!这个看似逻辑简单,实则梯形图有些复杂!!!


有兴趣和上班有空闲的朋友可以偿试下,开关用中间继电器代替,成功了的话个人发红包200感谢,重赏谈不上,只是一个为知识付费的态度。
jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
3楼  发表于: 2024-12-24 07:55
引用
引用第10楼dingzyi于2024-12-23 21:32发表的  :
步进电机速度能快多少。步进速度快了容易丢步。。停顿也要有时间的,为啥不用伺服。       

这个转速不高,其实在快速通过的点位,按三楼说的,增加转动的脉冲数,就可以了,最后一个点位是原点,每个循环的最后动作是回原点。
电机驱动前有个点动开关,点动一次,电机就一个循环动作,没什么丢步的问题。
jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
4楼  发表于: 2024-12-24 21:05
引用
引用第14楼梦雨天涯于2024-12-24 15:07发表的  :
大概这个样子,你觉得呢??


有点这个意思。
jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
5楼  发表于: 2024-12-24 21:15
引用
引用第16楼红云123于2024-12-24 17:05发表的  :
这个能不能实现


我目前的方法同你的方法有点类似,用电机的脉冲数来判断区间,效果不是很好,如果前面全部是开,后面全部是断,还可以,间隔开断的反应不过来。
jony7788
级别: 工控侠客
精华主题: 0
发帖数量: 50 个
工控威望: 2003 点
下载积分: 1083 分
在线时间: 237(小时)
注册时间: 2023-02-25
最后登录: 2025-03-27
查看jony7788的 主题 / 回贴
6楼  发表于: 33天前
请豆包帮忙写的,调整几次之后,可以正常运行,用的是Arduino板子,豆包写梯形图的能力还不强,写这种编程语言厉害些。
// 定义步进电机控制引脚
const int stepPin = 2;
const int dirPin = 3;

// 定义启动按键引脚
const int startButtonPin = 4;

// 定义 12 个开关引脚
const int switchPins[12] = {5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1, A2};

// 定义原点感应点位引脚
const int originPin = A3;

// 定义料件感应点位引脚
const int materialSensorPin = A4;

// 定义振动盘点位引脚
const int vibrationDiskPin = A5;

// 定义步进电机参数
const int stepsPerRevolution = 1000;  // 步进电机每转脉冲数

// 定义速度参数(毫秒)
const unsigned long normalSpeedDelay = 1;  // 正常速度延迟
const unsigned long fastSpeedDelay = 0.2;  // 快速速度延迟
const unsigned long returnSpeedDelay = 0.5; // 返回原点速度延迟

// 定义停留时间(毫秒)
const unsigned long pauseTime = 500;

// 定义变量
bool startButtonState = false;
bool lastStartButtonState = false;
bool isRunning = false;
bool isReturning = false;
int currentSegment = 0;
int remainingSteps = stepsPerRevolution;
unsigned long lastStepTime = 0;
unsigned long lastPauseTime = 0;
bool isPausing = false;

void setup() {
  // 初始化步进电机控制引脚为输出模式
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  // 初始化启动按键引脚为输入模式,并启用上拉电阻
  pinMode(startButtonPin, INPUT_PULLUP);

  // 初始化 12 个开关引脚为输入模式,并启用上拉电阻
  for (int i = 0; i < 12; i++) {
    pinMode(switchPins, INPUT_PULLUP);
  }

  // 初始化原点感应点位引脚为输入模式,并启用上拉电阻
  pinMode(originPin, INPUT_PULLUP);

  // 初始化料件感应点位引脚为输入模式,并启用上拉电阻
  pinMode(materialSensorPin, INPUT_PULLUP);

  // 初始化振动盘点位引脚为输出模式
  pinMode(vibrationDiskPin, OUTPUT);

  // 设置初始方向
  digitalWrite(dirPin, HIGH);
}

void loop() {
  // 读取启动按键状态
  startButtonState = digitalRead(startButtonPin);

  // 检测启动按键按下事件
  if (startButtonState == LOW && lastStartButtonState == HIGH) {
    isRunning = true;
    currentSegment = 0;
    remainingSteps = stepsPerRevolution;
    isReturning = false;
  }

  // 保存上一次启动按键状态
  lastStartButtonState = startButtonState;

  // 控制振动盘
  bool materialDetected = digitalRead(materialSensorPin) == LOW;
  digitalWrite(vibrationDiskPin, !materialDetected);

  // 如果电机正在运行
  if (isRunning) {
    if (isReturning) {
      unsigned long currentTime = millis();
      if (currentTime - lastStepTime >= returnSpeedDelay) {
        digitalWrite(dirPin, LOW); // 设置返回方向
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(10);  // 确保脉冲宽度
        digitalWrite(stepPin, LOW);
        lastStepTime = currentTime;

        if (digitalRead(originPin) == LOW) {
          isRunning = false;
          isReturning = false;
          digitalWrite(dirPin, HIGH); // 恢复正向
        }
      }
    } else {
      if (isPausing) {
        if (millis() - lastPauseTime >= pauseTime) {
          isPausing = false;
        }
      } else {
        unsigned long currentTime = millis();
        bool switchState = digitalRead(switchPins[currentSegment]);
        unsigned long speedDelay = switchState ? normalSpeedDelay : fastSpeedDelay;

        if (currentTime - lastStepTime >= speedDelay) {
          if (remainingSteps > 0) {
            digitalWrite(stepPin, HIGH);
            delayMicroseconds(10);  // 确保脉冲宽度
            digitalWrite(stepPin, LOW);
            remainingSteps--;
            lastStepTime = currentTime;
          }
          if (remainingSteps * 12 <= (11 - currentSegment) * stepsPerRevolution) {
            if (switchState) {
              isPausing = true;
              lastPauseTime = currentTime;
            }
            currentSegment++;
          }
          if (currentSegment >= 12) {
            isReturning = true;
          }
        }
      }
    }
  }

  // 短暂延迟以减少 CPU 负载
  delay(1);
}