在本文中,我们将向您展示一个简单的示例,说明如何使用旋转编码器实时移动步进电机。这将使用标准的步进电机驱动器完成,但没有任何库。
有几种运动控制器库可供使用,所有这些库都可以实现(Grbl,Smoothieware等)。
脉冲序列的可视化。
我们的目标是每次Arduino从编码器接收到脉冲时,将步进电机移动一定步数。Arduino将产生一个所谓的脉冲序列并将其发送给电机驱动器。
目录
脉冲列参数
此脉冲序列有两个重要参数:
- 脉冲数(上图中的N)
- 每次我们从编码器获得脉冲时,产生并发送给驱动器的脉冲数。
- 这个数字越大,当Arduino获得单个编码器脉冲时,电动机运行的时间就越长。
- 期
- 每个脉冲之间经过的时间。
- 该数字越小,电动机运动越快。太快会导致步骤松动。
- 如果没有适当的加速度曲线,则需要小心,并且不要将此参数设置得太低。
引脚
在我们的情况下,我们需要在Arduino上配置5个引脚。
旋转编码器针脚
- 脉冲–编码器在被操纵时将发送脉冲。
- 方向–此引脚将指示您是顺时针还是逆时针旋转编码器。
步进电机驱动器引脚
- 步骤–这是我们发送脉冲序列的地方。
- 方向–决定电动机旋转的方式。
- 启用–需要将其设置为“打开”电动机驱动器。
代码示例
该代码将具有一个缓冲区,该缓冲区存储将发送给驱动程序的所有步骤。电机将继续向一个方向移动,直到缓冲区为空。只有这样,您才能改变方向。注意,我们使用中断来读取旋转编码器。
#define ENCODER_DIR_PIN 3
#define DRIVER_STEP_PIN 8
#define DRIVER_DIR_PIN 9
#define DRIVER_EN_PIN 10
#define STEPS_PR_ENCODER_PULSE 10
#define DRIVER_PULSE_PERIOD_US 1600
enum Driver_pulse_state_enum {PULSE_IDLE, PULSE_HIGH, PULSE_LOW};
uint8_t dir = LOW;
uint16_t pulse_buffer = 0;
unsigned long time_now = 0;
uint16_t driver_pulse_hold_time_us = DRIVER_PULSE_PERIOD_US/2;
uint8_t driver_pulse_state = PULSE_IDLE;
void setup() {
pinMode(ENCODER_PULSE_PIN, INPUT);
pinMode(ENCODER_DIR_PIN, INPUT);
pinMode(DRIVER_STEP_PIN, OUTPUT);
pinMode(DRIVER_DIR_PIN, OUTPUT);
pinMode(DRIVER_EN_PIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(ENCODER_PULSE_PIN), encoderISR, RISING);
digitalWrite(DRIVER_EN_PIN, HIGH);
}
void loop() {
if((pulse_buffer) && (driver_pulse_state == PULSE_IDLE)){
driver_pulse_state = PULSE_HIGH;
digitalWrite(DRIVER_DIR_PIN, digitalRead(ENCODER_DIR_PIN));
digitalWrite(DRIVER_STEP_PIN, HIGH);
time_now = micros();
}
if((micros() - time_now > driver_pulse_hold_time_us) && (driver_pulse_state == PULSE_LOW)){
driver_pulse_state = PULSE_HIGH;
digitalWrite(DRIVER_STEP_PIN, HIGH);
time_now = micros();
}
if((micros() - time_now > driver_pulse_hold_time_us) && (driver_pulse_state == PULSE_HIGH)){
digitalWrite(DRIVER_STEP_PIN, LOW);
time_now = micros();
pulse_buffer -= 1;
if(pulse_buffer < 0){
pulse_buffer = 0;
}
if(pulse_buffer){
driver_pulse_state = PULSE_LOW;
}
else{
driver_pulse_state = PULSE_IDLE;
}
}
}
void encoderISR(){
pulse_buffer += STEPS_PR_ENCODER_PULSE;
}
该STEPS_PR_ENCODER_PULSE
参数是每次我们从旋转编码器获取读数时发送给驱动器的脉冲数。DRIVER_PULSE_PERIOD_US
确定脉冲序列的每个脉冲之间的时间间隔(以微秒为单位)。
改善功能
使代码更酷的一种方法是清空缓冲区,并在Arduino接收到与电机当前运行方向相反的编码器脉冲时开始向相反方向移动。就像现在一样,系统需要先清空缓冲区,然后电动机才能以相反的方向运行。
我们还可以实现不同的控制模式,例如使用电位计来调节速度,并使用拨动开关来选择方向。
一个更重要的功能是拥有适当的加速度曲线。这样,我们可以在不损失步数的情况下获得更快的速度,并且运动会变得更加流畅。