我需要编写一个程序来使用 atmega328P 和 A4988 芯片来控制步进电机。 我一直在寻找合适的库,但到目前为止我还没有找到合适的。
我需要一个转盘来转为绝对位置的预教。我认为有问题的电机每转 20000 步,1/16 微步。当位置计数器达到 20000 时,它必须重新设置为 0,反之亦然。所以从 19999 到 1 的旅行可以双向进行。
我希望步进电机线性加速和减速。这是我不完全知道该怎么做的一件事。
我想使用 arduino IDE 的 micros() 定时器功能来对步进引脚上的脉冲进行计时。
我可以计算我必须移动多少脉冲,我可以以固定的间隔增加/减少速度,但我很难计算何时开始减速。
如果我调整速度,每走一步,加速度就不是线性的。我尝试使用以下公式计算制动距离:pulses = VV / 2。这是我从基本运动和行程公式得出的。 S(t) = S0 + V0 * t - 0.5A*t^2。我为 A 取 1,为 T 取 1。每次我用 1 加/减速度。所以我得到 S(1) = V^2 - 0.5 * V^2 = 0。* V^2 或 V^2 / 2.
增加速度与脉冲不同步,我不知道如何解决这个问题。
我可以使用一些指针。
背景: 步进器将控制模型铁路转盘。转盘将正确连接到电机轴。 控制器将有 4 个按钮。
- 手动/自动按钮。
- 连续波
- 逆时针
- 店铺位置
在自动模式下,电机可以通过按 CW 和 CCW 从一个示教位置转换到另一个位置。当转盘仍在转动时,也必须能够接受新的位置。
在手动模式下,我可以使用相同的 CW 和 CCW 按钮手动巡航转盘。当我按住按钮时,电机需要加速到预设的最大速度,当我松开按钮时,电机需要减速到 0。
使用存储按钮,我可以将当前位置保存在 20 个预留位置之一中。
控制器第一次上电时,会将电机当前的物理位置作为虚拟零点。每次转盘停止时,它的当前位置都会存储在 EEPROM 中。很明显,当控制器关闭时,转盘不会因外力而移动。
编辑评论+回答
我没有使用任何库来控制步进器,我目前使用 micros() 计时器来设置步长。
宏 REPEAT_MS 和 END_REPEAT 之间的所有代码都以我们给定的间隔运行
void setSteps()
{
uint8_t speedVar = 255 - speed ;
REPEAT_US( speedVar ) ;
if( enabled )
{
if( !digitalRead( dirPin ) )
{
if( ++position == maxPos+1 ) position = 1 ; // verify this code if positions work well
digitalWrite( stepPin,HIGH ) ;
digitalWrite( stepPin,LOW ) ; // slow enough for mininum pulse duration
}
else
{
//if( --position == 0 ) position = maxPos ; // currently run 1 direction
}
}
Serial.print("position: ");
Serial.println( position ) ;
else
{
digitalWrite( stepPin,state ) ;// may become port manipulated
return ;
}
END_REPEAT
}
控制速度:
void manageSpeed()
{
REPEAT_MS( accELERATION_FactOR ) ; // separate fixed timing for constant acceleration and deceleration
static uint8_t speedPrev = 255 ;
if( speedSetpoint > speed ) speed ++ ;
if( speedSetpoint < speed ) speed -- ;
if( speed == 0 ) enabled = false ; // if speed reaches 0,stop sending pulses
if( speedPrev != speed ) {
speedPrev = speed ;
Serial.print("SPEED :") ;
Serial.println( speed ) ;
}
END_REPEAT
}
以及不太重要的使用宏(它们工作正常,经过良好测试)
#define REPEAT_MS(x) { \
static uint32_t previousTime ;\
uint32_t currentTime = millis() ;\
if( currentTime - previousTime >= x ) {\
previousTime = currentTime ;
// code to be repeated goes between these 2 macros
#define REPEAT_US(x) { \
static uint32_t previousTime ;\
uint32_t currentTime = micros() ;\
if( currentTime - previousTime >= x ) {\
previousTime = currentTime ;
// code to be repeated goes between these 2 macros
#define END_REPEAT } \
}
我将仔细研究并尝试实现梯形控制器并尝试实现建议的公式。
第二次编辑: 我目前有一些可以工作的代码,但有一点我无法理解。
目前我每 100 毫秒调整一次速度,1。1 是加速因子。总加速时间是3500ms,因为35是我的最大速度。
这是加速期间的输出。我不得不稍微调整一下步距。 速度:34 上次:100 总时间:3400 距离:6853 总位置:1147
SPEED :35
Last Time: 100 total time: 3500
distanceToGo: 6784
total position: 1216
cruising
这个 1216 应该是 1225。 P(t) = 0.5 * 1 * 35^2 = 1225 个脉冲。然而,它已经足够接近了。
比减速:
braking
SPEED :34
Last Time: 27 total time: 11400
distanceToGo: 1207
total position: 6793
SPEED :33
Last Time: 100 total time: 11500
distanceToGo: 1137
total position: 6863
...
SPEED :0
Last Time: 100 total time: 14800
distanceToGo: -8
total position: 8008
Last Time: 1 total time: 14801
distanceToGo: -8
total position: 8008
我的超调为 8,这是可以接受的。但是,我没有得到以下内容。现在步时间间隔的计算是
REPEAT_US( 47950 / speed ) ;
47950 除了不完美之外,也是不可计算的。我通过反复试验找到了它,无法解释为什么会这样。
位置控制器方法大致如何工作?