I have a little confused with how I can correctly set up haptic feedback. I am using a torque controller with dc current. When I use a PID controller with a pretty low P and 0 for I and D I get a soft force at the attract angles which is preferred. The issues im having is that the motor bounces back and forth.
I tried setting torque to 0 when the velocity is too high (during debugging I saw that the velocity reading is maxing out at about 12). If I use a treshold closer to the limit, it does nothing to stop the bouncing. If I set the threshold to a lower value, then the velocity reading just when I am physically moving the motor, surpases that limit and then I lose the haptic feedback.
I tried multiplying the target value by a percentage of the velocity relative to the max velocity. Basically If its spinning fast, then dont apply torque.
This approach almost works, it does reduce wobbles, sometime completely stopping them, but again I feel no feedback if I move too fast, and the reductions in wobbles is not successful when I use higher torque (a higher P value in the controller)
Can anyone point me in the right direction of how I should go about this?
This is my code:
#include <Arduino.h>
#include "./my_functions.h"
#include "Adafruit_GC9A01A.h"
#include "Wire.h"
#include <Adafruit_INA219.h>
#include <SimpleFOC.h>
/*-----------------------------------------------
Current Sensor
-----------------------------------------------*/
// the current sensor
#define ma_sensor_addr_red_C (0x40) // Red motor wirie - Phase C
#define ma_sensor_addr_yellow_A (0x41) // Yellow motor wire - Phase A
#define ma_sensor_addr_blue_B (0x44) // Blue motor wire - phase B
TwoWire currentSenseI2C(0);
Adafruit_INA219 current_sense_yellow_A(ma_sensor_addr_yellow_A);
Adafruit_INA219 current_sense_blue_B(ma_sensor_addr_blue_B);
Adafruit_INA219 current_sense_red_C(ma_sensor_addr_red_C);
#define cur_SDA_PIN 2
#define cur_SCL_PIN 1
float current_mA = 0;
// current sensor (custom modification to work work i2c current sensing instead of analog)
InlineCurrentSense current_sense = InlineCurrentSense(¤t_sense_red_C, ¤t_sense_blue_B, ¤t_sense_yellow_A);
/*-----------------------------------------------
Motor Driver
-----------------------------------------------*/
#define UL 14 // red motor wire
#define UH 13 // red motor wire - phase C
#define VL 12 // Blue motor wire
#define VH 21 // Blue motor wire - pahse B
#define WL 47 // yellow motor wire
#define WH 48 // yellow motor wire - phase A
BLDCDriver6PWM driver = BLDCDriver6PWM(WH, WL, VH, VL, UH, UL);
BLDCMotor motor = BLDCMotor(7); //, 7.8, 270);
/*-----------------------------------------------
Position Sensor
-----------------------------------------------*/
MagneticSensorI2C as5600 = MagneticSensorI2C(AS5600_I2C);
TwoWire positionSensorI2C(1);
#define pos_SDA_PIN 17
#define pos_SCL_PIN 16
/*
Haptic controller and variables
*/
PIDController P_haptic(0.25, 0, 0, 100000, 5);
// attractor angle variable
float attract_angle = 0;
// distance between attraction points
float attractor_distance = (45 * 3.14159265359f) / 180.0; // dimp each 45 degrees
float findAttractor(float current_angle)
{
return round(current_angle / attractor_distance) * attractor_distance;
}
void setup()
{
Serial.begin(115200);
/*
initialize and connect the position sensor
*/
positionSensorI2C.begin(pos_SDA_PIN, pos_SCL_PIN);
as5600.init(&positionSensorI2C);
motor.linkSensor(&as5600);
/*
initialize the current sensors
*/
currentSenseI2C.begin(cur_SDA_PIN, cur_SCL_PIN); // SDA - SCL
//Driver setup
driver.voltage_power_supply = 5;
driver.init();
motor.linkDriver(&driver);
motor.voltage_sensor_align = 5;
motor.phase_resistance = 7.8; // [Ohm]
motor.current_limit = 1.2; // [Amps] - if phase resistance defined
motor.voltage_limit = 5; // [V] - if phase resistance not defined
motor.velocity_limit = 20; // [rad/s] cca 50rpm
motor.torque_controller = TorqueControlType::dc_current; // TorqueControlType::voltage;
motor.controller = MotionControlType::torque;
current_sense.linkDriver(&driver);
current_sense.init();
motor.linkCurrentSense(¤t_sense);
motor.init();
motor.initFOC();
motor.target = 0;
Serial.println("Motor ready!");
Serial.println("Set target velocity [rad/s]");
_delay(1000);
}
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
float maxVelocity = 0;
float targetTorque = 0;
void loop()
{
motor.loopFOC();
maxVelocity = 13; //I noticed when using a P of 0.25, the max veltocity was about 13
//if the velocity is at 0, apply full torque, if the velocity is at the max I saw, apply no torque
targetTorque = mapFloat((fabsf(motor.shaft_velocity) / maxVelocity), 0, 1, 1, 0) *
P_haptic(attract_angle - motor.shaft_angle);
motor.move(targetTorque);
attract_angle = findAttractor(motor.shaft_angle);
}