原文链接: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值越大,档位的顿挫感就越强,效果如下:
总结
根据力的反馈,我们可以利用电机来模拟各种各样的旋钮反馈手感,如果加上一些底层交互逻辑,我们就可以实现智能旋钮,用来控制智能家居等设备。