【simpleFOC-项目】一个电机如何模拟不同旋钮的手感反馈?

原文链接:https://mp.weixin.qq.com/s?__biz=MzU1NjEwMTY0Mw==&mid=2247597033&idx=2&sn=e92f8f1dec8b363aa209788354f8fa64&chksm=fad1130bfafd0b9af53b0f110e354d8772f6c5a0d98735690d1c0c75d0c3c75785ea1041ea1a&scene=27

 

概述

simpleFOC可以实现对各种电机的精确控制,并且提供闭环扭矩反馈控制。那我们是否可以利用这种特性,用一个电机来模拟不同旋钮的手感反馈呢,答案是,当然可以!!而且网上也有不少开源的案例,例如最开始的smartknob,还有国内各种适配,修改的版本,这里就不一一列举了。

 

而本篇将使用2808电机,arduino和simplefocshielf,模拟不同旋钮的旋转手感,而不会将目光放在旋钮的交互上。

 

图片

 

 

初始化设置

 

再开始之前,我们需要在arduino的初始化函数当中设置一些电机和驱动的参数。

 

配置位置传感器,使用i2c与arduino进行通信:

MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

 

配置电机和驱动:

BLDCMotor motor = BLDCMotor(7);BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

 

设置驱动输入电压为24v,并初始化驱动:

driver.voltage_power_supply = 24;driver.init();

 

设置控制模式(这里我们使用力矩控制模式)

motor.controller = MotionControlType::torque;

 

完整初始化代码如下:

void setup() {
  // 设置串口波特率  Serial.begin(9600);  // enable more verbose output for debugging  // comment out if not needed  SimpleFOCDebug::enable(&Serial);
  // initialise magnetic sensor hardware  sensor.init();  // link the motor to the sensor  motor.linkSensor(&sensor);
  // 设置驱动输入电压为24v  driver.voltage_power_supply = 24;  driver.init();  motor.linkDriver(&driver);
  // aligning voltage   motor.voltage_sensor_align = 3;  // motor.voltage_limit = 5;  // choose FOC modulation (optional)  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;  // set motion control loop to be used  motor.controller = MotionControlType::torque;
  // comment out if not needed  motor.useMonitoring(Serial);
  // initialize motor  motor.init();  // align sensor and start FOC  motor.initFOC();
  // add target command T  Serial.println(F("Motor ready."));  Serial.println(F("Set the target voltage using serial terminal:"));  _delay(1000);}

 

 

一、无阻力手感

 

在力矩控制模式下,只要将期望力矩设置为0,即可实现无阻力手感,该模式下,电机模块相当于一个数值传感器,无任何手感反馈,这里就不做演示了

 

 

二、阻尼手感

 

在许多应用中,比如高端音响设备、工业控制面板或者游戏控制器,阻尼手感旋钮提供了一种直观且具有反馈感的用户交互方式。这种旋钮通常会给人一种平滑而有阻力的感觉,使用户在操作时能够更加精准地控制。通俗解释,就是有一股作用力来阻止我们旋转电机。这实际上是一种负反馈控制,我们使用电机速度作为反馈信号,其公式如下:

 

图片

写成代码就是:

tau = Kd * sensor.getVelocity()

 

接下来就是调kd了,kd越大,给的阻力就越大,我们先给个0.05,

过大的KD会导致电机疯狂抖动,建议从一个较小的值开始尝试

float Kd = 0.1;void loop() {  motor.loopFOC();  float tau = -Kd * sensor.getVelocity();  motor.move(tau);}

 

效果演示:

 

图片

 

 

三、顺滑手感

 

顺滑手感旋钮的关键在于实现旋钮在转动时的平滑响应。这意味着旋钮在转动过程中不会有任何卡顿或突兀的感觉。与上一章相反,要电机顺滑转动,需要正反馈,同样使用电机速度作为反馈信号,有以下:

 

图片

 

其中Kd需要是一个很小的值。

float tau = Kd * sensor.getVelocity();motor.move(tau);

 

因为是正反馈,如果Kd过大,会造成电机一致转下去。

float Kd = 0.04;void loop() {  motor.loopFOC();  float tau = -Kd * sensor.getVelocity();  motor.move(tau);}

 

效果如下:

 

图片

 

 

四、档位手感

还有一种旋钮是具有档位的,一圈会成好几个小段,每旋转过一段会产生顿挫感。而这种顿挫感,我们同样可以利用foc来实现。实际上,与上两节不一样,该手感是来自位置反馈,参考灯哥开源里面的原理解释。

 

图片

 

主循环代码如下,设置Kp为5,档位数量为4:

float Kp = 5;void loop() {    motor.loopFOC();  float num = 4; // 档位数量  float attractor_distance = 360/num * 3.1415926 / 180.0; // 转换为弧度制  float target = round(sensor.getAngle() / attractor_distance) * attractor_distance;  motor.move(Kp * (target - sensor.getAngle()));}

 

Kd值越大,档位的顿挫感就越强,效果如下:

 

图片

 

 

总结

根据力的反馈,我们可以利用电机来模拟各种各样的旋钮反馈手感,如果加上一些底层交互逻辑,我们就可以实现智能旋钮,用来控制智能家居等设备。

posted @ 2025-09-15 00:01  FBshark  阅读(54)  评论(0)    收藏  举报