我将使用两个步进电机,两个简易驱动器,一个arduino uno。每个步进电机都有前后旋转的齿轮。首先,我想为每个步进器分配多个旋转提示。如
int step1cue1 = 329
int step1cue2 = 582
int step1cue3 = 1038
int step1 cue4 = 1790
...
int step2cue1 = 568
int step2cue2 = 1004
int step2cue3 = 1928
int step2cue4 = 3592
...
and each stepper needs minimum 0 and maximum value, such as,
int step1maxcue = 8372
int step2maxcue = 8421
each rotation speed and acceleration need to be set and controllable as well.
I would like to use rotation speed = 0 to make the stepper stopped at the cue.
**操作
两个步进器都从 0 开始,首先,stepper1 从其 step1cues 中旋转到随机选择的提示,当它几乎到达所选提示时,stepper2 开始旋转到从 step2cues 中随机选择的提示。(步进器1在提示处停止,速度=0),当步骤2几乎到达其提示时,步进器1开始旋转到另一个随机选择的步骤1cue(不是当前提示)。(步进器2停止,速度=0)。并在两个步进器之间重复此转换。
你能帮我写这段代码吗?
我想使用下面的代码,
#include <AccelStepper.h>
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
int pos1 = 3600;
int pos2 = 5678;
void setup()
{
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(2000);
stepper2.setAcceleration(800);
}
void loop()
{
if (stepper1.distanceToGo() == 0)
{
pos1 = -pos1;
stepper1.moveTo(pos1);
}
if (stepper2.distanceToGo() == 0)
{
pos2 = -pos2;
stepper2.moveTo(pos2);
}
stepper1.run();
stepper2.run();
}
AccelStepper 库,所以我可能是错的,但这应该按照您的要求:
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = { 329, 582, 1038, 1790 ...};
const int step2cues[] = { 568, 1004, 1928, 3592 ...};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
movingStepper = 1;
}
}
stepper1.run();
stepper2.run();
}
THRESHOLD
是句子中的"几乎":当它接近此值时,它将开始移动另一个电机。注意:提示应该是模式距离另一个的两倍,而不是阈值的两倍,这样您就不会有混合条件(我的意思是,在这个阈值下,一个提示和任何其他提示的最小距离应该是 40)。
顺便说一下,您无需将速度设置为 0:当步进器到达该位置时,它将自行停止。
编辑:
OP 还要求另外三个功能(选择时打印下一个提示,串行打印当前位置,在电机到达提示时设置开关),所以它们就在这里。
首先,为了清楚起见,我将第二个和第三个功能与以前的代码分开。我选择仅在位置更改时才运行该代码,但这可以很容易地更改为
- 仅在
- 固定数量的更改后打印该代码(例如,仅在更改 50 或更多之后)
- 在固定时间(例如 0.5 秒)打印该代码
无论如何,这是代码:
int currentPos1 = -1;
int currentPos2 = -1;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if (currentPos1 != stepper1.currentPosition())
{ // Stepper 1 has moved
currentPos1 = stepper1.currentPosition()
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
Serial.print("Motor 1 pos: ");
Serial.println(currentPos1);
}
if (currentPos2 != stepper2.currentPosition())
{ // Stepper 2 has moved
currentPos2 = stepper2.currentPosition()
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
Serial.print("Motor 2 pos: ");
Serial.println(currentPos2);
}
stepper1.run();
stepper2.run();
}
如果您选择修改它以不接收频繁的电机更新(例如,每半秒显示一次消息),则应将Stepper X has reached the final position
块移到控件之外,以便每次迭代都可以执行它:
unsigned long lastShownMessages = 0;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if ((millis() - lastShownMessages) > 500)
{ // More than 500 ms passed since last update:
Serial.print("Motor 1 pos: ");
Serial.println(stepper1.currentPosition());
Serial.print("Motor 2 pos: ");
Serial.println(stepper2.currentPosition());
lastShownMessages += 500;
}
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
stepper1.run();
stepper2.run();
}
另外,出于校准目的,我可以在服务器监视器上看到步进器的旋转值(增量)吗?我可以将速度设置得很低并让它滚动,然后我可以知道我需要设置的阶梯的提示值。
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
const int step2cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 4, 3);
AccelStepper stepper2(1, 7, 6);
int switch1 = 12;
int switch2 = 13;
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
Serial.begin(9600);
pinMode(switch1, OUTPUT);
pinMode(switch2, OUTPUT);
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.println("2");
Serial.println(nextpos);
movingStepper = 2;
if ( nextpos = stepper2.targetPosition() ){
digitalWrite(switch1, HIGH);
}
else {
digitalWrite(switch1, LOW);
}
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.println("1");
Serial.println(nextpos);
movingStepper = 1;
if ( nextpos = stepper1.targetPosition() ){
digitalWrite(switch2, HIGH);
}
else {
digitalWrite(switch2, LOW);
}
}
}
stepper1.run();
stepper2.run();
}