static void push_tran_motor_relative_angle_control(Gimbal_Control_t *push_tran_motor,uint8_t Mode)//push点金控制 { if (push_tran_motor == NULL) { return; } switch(Mode) { case 1: { //角度环PID for (int i=0;i<2;i++) { push_tran_motor->shoot_push_motor[i].motor_speed_set = PID_Calc(&push_location_pid, push_tran_motor->shoot_push_motor[i].relative_angle, push_tran_motor->shoot_push_motor[i].relative_angle_set); //push_tran的速度环PID push_tran_motor->shoot_push_motor[i].current_set= PID_Calc(&push_speed_pid, push_tran_motor->shoot_push_motor[i].motor_speed, push_tran_motor->shoot_push_motor[i].motor_speed_set); //控制电流赋值 push_tran_motor->shoot_push_motor[i].given_current = (int16_t)(push_tran_motor->shoot_push_motor[i].current_set); } break; } case 2: { debugcase2++; push_tran_motor->shoot_translate_motor.motor_speed_set =PID_Calc(&translate_location_pid, push_tran_motor->shoot_translate_motor.relative_angle, push_tran_motor->shoot_translate_motor.relative_angle_set); push_tran_motor->shoot_translate_motor.current_set = PID_Calc(&translate_speed_pid, push_tran_motor->shoot_translate_motor.motor_speed, push_tran_motor->shoot_translate_motor.motor_speed_set); push_tran_motor->shoot_translate_motor.given_current = (int16_t)(push_tran_motor->shoot_translate_motor.current_set); break; } } } static void gimbal_motor_raw_angle_control(Gimbal_Motor_t *gimbal_motor) { if (gimbal_motor == NULL) { return; } gimbal_motor->current_set = gimbal_motor->raw_cmd_current; gimbal_motor->given_current = (int16_t)(gimbal_motor->current_set); }我如果要实现push电机持续转动,我到底该怎么做啊
时间: 2025-03-09 13:08:51 浏览: 36
<think>好的,用户想实现push电机的持续转动,但不太清楚该怎么做。让我先看看他提供的代码。
首先,他有两个函数:push_tran_motor_relative_angle_control和gimbal_motor_raw_angle_control。看起来push_tran函数处理两种模式,模式1和模式2,分别控制不同的电机。模式1里有两个电机,可能是推进和发射相关的,而模式2处理平移电机。这些模式都是通过PID控制位置和速度,最终设置电流值。而gimbal_motor_raw_angle_control函数似乎直接设置电流,没有使用PID,可能是开环控制。
用户的问题是想让push电机持续转动。现在,当前的代码中,无论是模式1还是模式2,都是基于相对角度的PID控制,也就是位置闭环。这种情况下,电机会转动到目标角度后停止。要实现持续转动,需要让目标角度不断变化,或者切换到速度控制模式,或者直接控制电流。
首先,检查现有代码中的控制结构。在push_tran的case 1中,使用的是位置环(relative_angle到motor_speed_set),然后再用速度环得到current_set。这样其实是位置和速度的双闭环控制。要让电机持续转动,可能需要不断更新relative_angle_set,使其一直递增或递减,比如在每次循环中增加一定角度,这样电机会不断追踪这个变化的目标,从而持续旋转。但这种方法可能不够高效,且需要频繁更新目标值。
另一种方法是修改控制模式,直接使用速度环,设置目标速度而不是位置。例如,在现有代码中,如果有一个模式可以绕过位置环,直接设置motor_speed_set为一个固定值,然后速度环PID计算电流。但当前代码中case 1和case 2都是基于位置环的,可能需要新增一个模式,或者修改现有模式。
或者,参考gimbal_motor_raw_angle_control函数,它是直接设置current_set为raw_cmd_current,也就是开环控制,直接给电流。这样,如果用户设置一个固定的电流值,电机就会持续转动,直到遇到阻力或达到限幅。但这种方法可能不够稳定,因为没有速度或位置的反馈,容易出现过流或堵转。
所以可能的解决方案是:
1. 在现有的push_tran函数中新增一个模式(比如case 3),在这个模式下直接设置目标速度为固定值,从而让速度环控制电流,使电机持续转动。或者修改现有模式,但需要确保不干扰原有功能。
2. 或者,在现有模式中,不断更新relative_angle_set的值,让目标位置持续增加,这样位置环会让电机一直转动。例如,在每次调用函数时,将relative_angle_set递增一个步长,模拟连续旋转。但这种方法需要确保更新频率足够高,否则可能会有顿挫感。
3. 使用gimbal_motor_raw_angle_control的方式,直接设置电流,绕过PID控制。但需要确认push电机是否支持这种控制方式,以及是否有电流限制,避免损坏电机。
用户可能需要检查他们的电机控制架构,是否有速度环可以直接使用。例如,如果在case 1中,他们原本是位置环,那么如果想持续转动,可能需要将位置环的目标设置为无限递增,或者切换到速度控制模式,直接设置速度目标。
另外,代码中的PID参数是否正确,例如push_speed_pid是否配置为速度环的PID,这样当设置motor_speed_set为一个固定速度时,速度环就会调整电流以维持该速度,从而实现持续转动。
可能的步骤:
- 添加一个新的控制模式,比如case 3,直接设置motor_speed_set为某个固定值,然后仅运行速度环PID,而不需要位置环。或者,在现有的模式中,如果能够绕过位置环,直接设置速度目标。
- 或者,在调用push_tran函数时,将Mode设置为一个新模式,比如在case 3中,直接给current_set一个固定值,类似gimbal_motor_raw_angle_control的做法,但这样可能没有速度闭环,只是开环控制。
需要确保电机控制器的模式切换正确,并且PID参数适合速度控制。例如,在速度环中,PID参数需要调整到能够维持稳定的转速,而不是位置环的参数。
总结来说,用户需要确定是要用闭环速度控制还是开环电流控制。闭环更稳定,但需要正确配置PID;开环简单,但可能不够精确。根据代码结构,可能更适合在现有框架下新增一个模式,或者在现有模式中修改目标值的设置方式,让目标位置持续变化,从而驱动电机转动。</think>要实现push电机的持续转动,需要根据代码结构选择以下两种方案之一:
---
### **方案一:位置环动态更新目标角度(闭环控制)**
#### 适用场景
- 需要精确控制电机转动速度
- 系统已配置位置环PID参数
#### 实现步骤
1. **修改目标角度设置逻辑**
在调用`push_tran_motor_relative_angle_control`函数前,持续递增目标角度:
```c
// 示例:每次控制周期增加360度(持续旋转)
for (int i = 0; i < 2; i++) {
push_tran_motor->shoot_push_motor[i].relative_angle_set += 360.0f; // 单位:度
}
push_tran_motor_relative_angle_control(push_tran_motor, 1); // Mode=1
```
2. **注意事项**
- 需保证目标角度更新频率 $\geq$ PID计算频率
- 角度值溢出需处理(如用`fmod`取模)
---
### **方案二:速度环直接控制(推荐)**
#### 适用场景
- 需要简单稳定的持续转动
- 系统已配置速度环PID参数
#### 代码修改
1. **新增控制模式(如Mode=3)**
```c
case 3: // 速度环直接控制
{
for (int i = 0; i < 2; i++) {
// 直接设置目标转速(单位:RPM或度/秒)
float target_speed = 1000.0f; // 根据需求调整
push_tran_motor->shoot_push_motor[i].current_set =
PID_Calc(&push_speed_pid,
push_tran_motor->shoot_push_motor[i].motor_speed,
target_speed);
push_tran_motor->shoot_push_motor[i].given_current =
(int16_t)(push_tran_motor->shoot_push_motor[i].current_set);
}
break;
}
```
---
### **方案三:开环电流控制**
#### 适用场景
- 调试阶段快速验证
- 无速度/位置精度要求
#### 代码修改
```c
// 直接给固定电流值(示例给最大电流的50%)
#define SUSTAIN_CURRENT 15000 // 根据电机规格调整
push_tran_motor->shoot_push_motor[0].given_current = SUSTAIN_CURRENT;
push_tran_motor->shoot_push_motor[1].given_current = SUSTAIN_CURRENT;
```
---
### **关键差异对比**
| 方案 | 控制类型 | 精度 | 稳定性 | 代码改动量 |
|------|----------|------|--------|------------|
| 位置环动态更新 | 闭环 | 高 | 高 | 中 |
| 速度环直接控制 | 闭环 | 中 | 高 | 小 |
| 开环电流控制 | 开环 | 低 | 低 | 最小 |
---
### **补充建议**
1. **PID参数调试**
- 速度环需单独调参,典型公式:
$$ u(t) = K_p e(t) + K_i \int_0^t e(\tau)d\tau + K_d \frac{de(t)}{dt} $$
- 建议先用阶跃响应法粗调
2. **安全保护**
```c
// 添加电流钳位
#define MAX_CURRENT 30000 // 根据电机规格定义
given_current = (given_current > MAX_CURRENT) ? MAX_CURRENT :
((given_current < -MAX_CURRENT) ? -MAX_CURRENT : given_current);
```
3. **反馈信号验证**
- 检查`motor_speed`反馈信号是否正常
- 确认编码器分辨率配置正确:
$$ \text{实际转速} = \frac{\text{编码器脉冲数} \times 60}{\text{分辨率} \times \text{控制周期}} $$
根据实际需求选择合适的实现方案,建议优先采用**速度环直接控制**方案。
阅读全文
相关推荐
















