wokwi
程序
#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
// This defines the analog input pin for reading the control voltage
// Tested with a 10k linear pot between 5v and GND
const byte PositionPot = A0;
const byte AccelerationPot = A1;
void setup()
{
stepper.setMaxSpeed(1000);
stepper.setAcceleration(35);
}
void loop()
{
// Read new position
int analog_in = analogRead(PositionPot);
stepper.setAcceleration(analogRead(AccelerationPot));
stepper.moveTo(analog_in);
stepper.run();
}
仿真
频率控制步进电机转速。
实践项目名称
基于Arduino的步进电机速度与位置控制实践
实践目的
通过实践掌握使用Arduino和AccelStepper库控制步进电机的基本方法,实现根据模拟输入(电位器)动态调整电机的目标位置和加速度,进一步理解步进电机的工作原理及其在开环控制系统中的应用。
实践设备
- Arduino开发板(如Arduino Uno)
- 步进电机及驱动器
- 电位器(2个,用于位置和加速度控制)
- 面包板和连接线
- 电脑及Arduino IDE软件
- AccelStepper库
实践原理
本实践利用Arduino读取两个电位器的模拟信号,分别作为步进电机的目标位置和加速度的控制输入。通过AccelStepper库,可以方便地设置步进电机的最大速度、加速度,并根据输入信号动态调整电机的运行状态。电位器的阻值变化被转换为0-1023的数字信号(Arduino的模拟输入分辨率),用于控制电机的不同参数。
实践内容
- 组装电路:将步进电机驱动器与Arduino、步进电机以及电位器正确连接。确保电位器的中心端接Arduino的模拟输入引脚(A0和A1),另一端分别接5V和GND,形成电压分压电路。
- 编写并上传代码:在Arduino IDE中编写控制程序,设置步进电机的最大速度和初始加速度,然后在循环中读取电位器的值来调整电机的目标位置和加速度,并执行电机的运行。
- 测试与调试:运行程序,观察步进电机根据电位器调节的反应,验证电机的位置控制和加速度调整是否准确、平滑。
思考题及作答
思考题:
- 如果将电位器的连接改为使用数字引脚而不是模拟引脚,程序应该如何修改以实现对步进电机的控制?
- 程序中
stepper.setAcceleration(analogRead(AccelerationPot));
一行直接使用了模拟读数值作为加速度,这样做有何潜在问题?如何改进?
作答:
-
如果将电位器连接到数字引脚,由于数字引脚只能读取高低电平(0或1),无法直接获取连续的模拟值,因此无法直接使用电位器来调节控制参数。一种替代方案是使用PWM(脉冲宽度调制)输出,虽然它本质上是数字信号,但可以通过调整占空比来模拟不同的控制级别。另一种方法是使用外部ADC(模拟数字转换器)模块来将电位器的模拟信号转换为数字信号,再由Arduino读取。
-
直接使用
analogRead()
的返回值作为加速度值存在几个潜在问题:首先,analogRead()
的返回值范围是0-1023,而加速度的合理范围可能远小于这个值,导致加速度设置过大或过小,不易控制;其次,模拟信号可能受到噪声干扰,导致加速度值不稳定。改进的方法是先将analogRead()
的值映射到一个更合适的加速度范围内,例如使用map()
函数,同时可以增加一些平滑处理(如滑动平均)来减少噪声的影响。示例代码修改如下:int rawAcceleration = analogRead(AccelerationPot); int mappedAcceleration = map(rawAcceleration, 0, 1023, 0, 100); // 假设合适的加速度范围是0-100 stepper.setAcceleration(mappedAcceleration);
cpp复制代码
int rawAcceleration = analogRead(AccelerationPot);
int mappedAcceleration = map(rawAcceleration, 0, 1023, 0, 100); // 假设合适的加速度范围是0-100
stepper.setAcceleration(mappedAcceleration);
这样,加速度值就被限制在了一个更合理的范围内,且更容易通过电位器进行精细调整。
云课五分钟-Arduino wokwi和步进电机实验报告快速撰写
详细介绍
代码概述:
提供的代码是一个基于Arduino平台的简单示例,用于控制步进电机的位置和加速度。它使用了AccelStepper
库,这是一个专为步进电机设计的Arduino库,支持多种步进模式(如单步、双步、半步和微步)以及加速和减速功能。
硬件连接:
- 步进电机通过驱动器与Arduino的2、3、4、5号数字引脚相连,这些引脚默认被
AccelStepper
库用作FULL4WIRE模式的控制引脚。 - 两个电位器分别连接到A0和A1模拟输入引脚,用于控制步进电机的目标位置和加速度。
代码解析:
AccelStepper stepper;
:声明一个AccelStepper
对象,默认使用FULL4WIRE模式和2, 3, 4, 5引脚。const byte PositionPot = A0;
和const byte AccelerationPot = A1;
:定义电位器连接的模拟输入引脚。setup()
函数中设置了步进电机的最大速度(setMaxSpeed(1000)
)和初始加速度(setAcceleration(35)
)。loop()
函数是一个无限循环,用于不断读取电位器的值并更新步进电机的目标位置和加速度。
潜在问题:
- 直接使用
analogRead()
的返回值作为加速度可能导致加速度值过大或过小,因为analogRead()
的返回值范围是0-1023。通常,需要将这个值映射到一个更合适的加速度范围内。 - 加速度值的变化可能过于频繁,导致电机运行不稳定。可以通过增加一些平滑处理(如滑动平均)来减少噪声的影响。
更多示例
示例1:映射加速度值
在这个示例中,我们将analogRead()
的返回值映射到一个更合适的加速度范围内(例如0-100):
#include <AccelStepper.h>
AccelStepper stepper;
const byte PositionPot = A0;
const byte AccelerationPot = A1;
void setup() {
stepper.setMaxSpeed(1000);
stepper.setAcceleration(35);
}
void loop() {
int position = analogRead(PositionPot);
int rawAcceleration = analogRead(AccelerationPot);
int mappedAcceleration = map(rawAcceleration, 0, 1023, 0, 100); // 映射到0-100范围
stepper.setAcceleration(mappedAcceleration);
stepper.moveTo(position);
stepper.run();
}
cpp复制代码
#include <AccelStepper.h> | |
AccelStepper stepper; | |
const byte PositionPot = A0; | |
const byte AccelerationPot = A1; | |
void setup() { | |
stepper.setMaxSpeed(1000); | |
stepper.setAcceleration(35); | |
} | |
void loop() { | |
int position = analogRead(PositionPot); | |
int rawAcceleration = analogRead(AccelerationPot); | |
int mappedAcceleration = map(rawAcceleration, 0, 1023, 0, 100); // 映射到0-100范围 | |
stepper.setAcceleration(mappedAcceleration); | |
stepper.moveTo(position); | |
stepper.run(); | |
} |
示例2:增加平滑处理
在这个示例中,我们使用滑动平均来减少加速度值变化中的噪声:
#include <AccelStepper.h>
AccelStepper stepper;
const byte PositionPot = A0;
const byte AccelerationPot = A1;
const int smoothFactor = 10; // 平滑因子,越大越平滑
int accelerationValues[smoothFactor];
int accelerationIndex = 0;
int smoothAcceleration = 0;
void setup() {
stepper.setMaxSpeed(1000);
stepper.setAcceleration(35);
// 初始化加速度值数组
for (int i = 0; i < smoothFactor; i++) {
accelerationValues[i] = 0;
}
}
void loop() {
int position = analogRead(PositionPot);
int rawAcceleration = analogRead(AccelerationPot);
// 更新加速度值数组并计算滑动平均
accelerationValues[accelerationIndex] = rawAcceleration;
smoothAcceleration = 0;
for (int i = 0; i < smoothFactor; i++) {
smoothAcceleration += accelerationValues[i];
}
smoothAcceleration /= smoothFactor;
// 映射平滑后的加速度值到合适范围
int mappedAcceleration = map(smoothAcceleration, 0, 1023, 0, 100);
stepper.setAcceleration(mappedAcceleration);
stepper.moveTo(position);
stepper.run();
// 更新加速度值数组索引
accelerationIndex = (accelerationIndex + 1) % smoothFactor;
}
cpp复制代码
#include <AccelStepper.h> | |
AccelStepper stepper; | |
const byte PositionPot = A0; | |
const byte AccelerationPot = A1; | |
const int smoothFactor = 10; // 平滑因子,越大越平滑 | |
int accelerationValues[smoothFactor]; | |
int accelerationIndex = 0; | |
int smoothAcceleration = 0; | |
void setup() { | |
stepper.setMaxSpeed(1000); | |
stepper.setAcceleration(35); | |
// 初始化加速度值数组 | |
for (int i = 0; i < smoothFactor; i++) { | |
accelerationValues[i] = 0; | |
} | |
} | |
void loop() { | |
int position = analogRead(PositionPot); | |
int rawAcceleration = analogRead(AccelerationPot); | |
// 更新加速度值数组并计算滑动平均 | |
accelerationValues[accelerationIndex] = rawAcceleration; | |
smoothAcceleration = 0; | |
for (int i = 0; i < smoothFactor; i++) { | |
smoothAcceleration += accelerationValues[i]; | |
} | |
smoothAcceleration /= smoothFactor; | |
// 映射平滑后的加速度值到合适范围 | |
int mappedAcceleration = map(smoothAcceleration, 0, 1023, 0, 100); | |
stepper.setAcceleration(mappedAcceleration); | |
stepper.moveTo(position); | |
stepper.run(); | |
// 更新加速度值数组索引 | |
accelerationIndex = (accelerationIndex + 1) % smoothFactor; | |
} |
在这个示例中,我们使用了一个数组来存储最近的smoothFactor
个加速度值,并计算它们的平均值作为当前的加速度值。这样可以有效减少由于电位器读数不稳定引起的加速度变化。
实践项目名称
基于Arduino的步进电机速度与位置控制实践
实践目的
通过实践掌握使用Arduino和AccelStepper库控制步进电机的基本方法,实现根据模拟输入(电位器)动态调整电机的目标位置和加速度,进一步理解步进电机的工作原理及其在开环控制系统中的应用。
实践设备
Arduino开发板(如Arduino Uno)
步进电机及驱动器
电位器(2个,用于位置和加速度控制)
面包板和连接线
电脑及Arduino IDE软件
AccelStepper库
实践原理
本实践利用Arduino读取两个电位器的模拟信号,分别作为步进电机的目标位置和加速度的控制输入。通过AccelStepper库,可以方便地设置步进电机的最大速度、加速度,并根据输入信号动态调整电机的运行状态。电位器的阻值变化被转换为0-1023的数字信号(Arduino的模拟输入分辨率),用于控制电机的不同参数。
实践内容
组装电路:将步进电机驱动器与Arduino、步进电机以及电位器正确连接。确保电位器的中心端接Arduino的模拟输入引脚(A0和A1),另一端分别接5V和GND,形成电压分压电路。
编写并上传代码:在Arduino IDE中编写控制程序,设置步进电机的最大速度和初始加速度,然后在循环中读取电位器的值来调整电机的目标位置和加速度,并执行电机的运行。
测试与调试:运行程序,观察步进电机根据电位器调节的反应,验证电机的位置控制和加速度调整是否准确、平滑。
思考题及作答
思考题:
如果将电位器的连接改为使用数字引脚而不是模拟引脚,程序应该如何修改以实现对步进电机的控制?
程序中stepper.setAcceleration(analogRead(AccelerationPot));一行直接使用了模拟读数值作为加速度,这样做有何潜在问题?如何改进?
作答:
如果将电位器连接到数字引脚,由于数字引脚只能读取高低电平(0或1),无法直接获取连续的模拟值,因此无法直接使用电位器来调节控制参数。一种替代方案是使用PWM(脉冲宽度调制)输出,虽然它本质上是数字信号,但可以通过调整占空比来模拟不同的控制级别。另一种方法是使用外部ADC(模拟数字转换器)模块来将电位器的模拟信号转换为数字信号,再由Arduino读取。
直接使用analogRead()的返回值作为加速度值存在几个潜在问题:首先,analogRead()的返回值范围是0-1023,而加速度的合理范围可能远小于这个值,导致加速度设置过大或过小,不易控制;其次,模拟信号可能受到噪声干扰,导致加速度值不稳定。改进的方法是先将analogRead()的值映射到一个更合适的加速度范围内,例如使用map()函数,同时可以增加一些平滑处理(如滑动平均)来减少噪声的影响。示例代码修改如下:
cpp
int rawAcceleration = analogRead(AccelerationPot);
int mappedAcceleration = map(rawAcceleration, 0, 1023, 0, 100); // 假设合适的加速度范围是0-100
stepper.setAcceleration(mappedAcceleration);
这样,加速度值就被限制在了一个更合理的范围内,且更容易通过电位器进行精细调整。