给大家分享一个项目案例,结合 ESP32 开发板、LN298N 电机驱动模块以及带有编码器(霍尔编码器)的推杆,实现对推杆运动的精准控制。实现了推杆的前进、后退、速度控制,还添加了根据目标行程自动控制的功能函数,并能实时反馈电机当前的行程位置。
1.电推杆参数
下图:带霍尔编码器的电推杆
具有六根线:
LN298N
LN298N参数如下图所示;
ESP32
ESP32用的是S2系列,这里就不再出图了。
接线
具体接线步骤
1. 电源连接
外部电源与 LN298N:
将外部电源(如 12V 或 24V 直流电源,需根据推杆电机的额定电压选择)的正极连接到 LN298N 模块的 +12V 或相应的电源输入引脚(确保电源电压在 LN298N 的工作范围内),负极连接到 GND 引脚。这为 LN298N 模块和推杆电机提供电力。
LN298N 与推杆电机:
把 LN298N 模块的输出引脚 OUT1 和 OUT2 连接到推杆电机的两个接线端(电机的正负极)。若电机需要反转功能,可通过控制 OUT1 和 OUT2 的电平来实现。
ESP32 电源:ESP32 可通过 USB 线连接到电脑或使用合适的电源模块供电。同时,将 ESP32 的 GND 引脚与 LN298N 模块的 GND 引脚相连,确保共地。
2. 控制信号连接
ESP32 与 LN298N:
方向控制:将 ESP32 的 GPIO 引脚(如 GPIO18 和 GPIO19)分别连接到 LN298N 模块的 IN1 和 IN2 引脚。通过控制这两个引脚的电平高低,可以改变电机的转动方向。
速度控制:把 ESP32 具有 PWM 功能的引脚(如 GPIO25)连接到 LN298N 模块的 ENA 引脚。通过调整 PWM 信号的占空比,可以控制电机的转速。
ESP32 与编码器:
编码器信号 A:将编码器的信号线 A(通常为蓝色线)连接到 ESP32 的 GPIO16 引脚。该信号用于检测电机的旋转状态和方向。
编码器信号 B:把编码器的信号线 B(通常为白色线)连接到 ESP32 的 GPIO17 引脚。与信号 A 配合,可实现更精确的位置检测和速度计算。
编码器电源:编码器的电源正极(通常为黄色线)连接到 ESP32 的 3.3V 引脚(若编码器工作电压兼容 3.3V),负极(通常为绿色线)连接到 ESP32 的 GND 引脚。
关于行程的计算
参考官方文档
BMMINI系列推杆采用双通道AB相增量式磁编码器。输出为两路正交90°方波(如下图所示),分辨率7线即电机旋转一圈输出7个脉冲。如果想知道每个脉冲位移多少,那么就用丝杠的导程÷(编码器线数×减速比),就可以得到每脉冲位移是多少毫米;编码器使用非接触磁感应技术,不存在机械磨损,从而具有超长的使用寿命和稳定性,可靠性极强。
关于速度
若输入电源电压为 12V,PWM 信号占空比为 78.4%,那么电机两端的平均电压约为 0.784×12V=9.408V,电机转速与平均电压的关系,直流电机的转速和其两端的电压大致成正比。在其他条件不变的情况下,电机两端的平均电压越高,电机的转速就越快;反之,平均电压越低,转速越慢。所以,通过调整 ESP32 输出的 PWM 信号的占空比,就能改变 LN298N 输出到电机的平均电压,进而实现对电机转速的控制。
总结:最大速度8mm/s,如果占空比是78.4%,那么实际速度是V=8X78.4%
代码
// 定义LN298N控制引脚
const int in1 = 18;
const int in2 = 19;
const int enA = 25;
// 定义编码器引脚
const int encoderA = 16;
const int encoderB = 17;
// 编码器脉冲计数
volatile long encoderCount = 0;
// 每脉冲对应的位移,需根据实际参数调整
// 假设获取到的丝杠导程为L毫米,减速比为R
// 需替换为实际的丝杠导程和减速比
const float lead = 2; // 示例丝杠导程,单位:毫米
const float reductionRatio = 100; // 示例减速比
// 根据公式计算每脉冲对应的位移
const float displacementPerPulse = lead / (7 * reductionRatio);
// 中断服务函数
void IRAM_ATTR handleEncoder() {
int stateA = digitalRead(encoderA);
int stateB = digitalRead(encoderB);
if (stateA == stateB) {
encoderCount++;
} else {
encoderCount--;
}
}
// 功能函数,控制推杆移动到目标行程
void movePusher(int speed, float targetDistance) {
long targetPulses = targetDistance / displacementPerPulse;
long initialCount = encoderCount;
long currentPulses;
int direction;
if (targetPulses > 0) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
direction = 1;
} else {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
direction = -1;
targetPulses = -targetPulses;
}
analogWrite(enA, speed);
while (1) {
currentPulses = abs(encoderCount - initialCount);
float currentDistance = currentPulses * displacementPerPulse;
Serial.print("Current position: ");
Serial.print(currentDistance);
Serial.println(" mm");
float initialDistance = initialCount * displacementPerPulse;
Serial.print("Initial position: ");
Serial.print(initialDistance);
Serial.println(" mm");
if (currentPulses >= targetPulses) {
break;
}
delay(10);
}
// 停止电机
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
analogWrite(enA, 0);
}
void setup() {
Serial.begin(115200);
// 设置LN298N控制引脚为输出模式
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(enA, OUTPUT);
// 初始化电机停止
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
analogWrite(enA, 0);
// 设置编码器引脚为输入模式
pinMode(encoderA, INPUT_PULLUP);
pinMode(encoderB, INPUT_PULLUP);
// 附加中断服务函数
attachInterrupt(digitalPinToInterrupt(encoderA), handleEncoder, CHANGE);
}
void loop() {
// 推杆后退,速度200,目标行程 -50mm
movePusher(200, 50);
delay(5000);
// // 推杆前进,速度200,目标行程 50mm
movePusher(200, -50);
delay(5000);
}
以上就可以实现带霍尔编码器的电推杆的控制了!如有疑问可以发邮件联系我
dnddn@foxmail.com