Skip to content

Commit ea15ea5

Browse files
committed
Basic expo curve implementation
1 parent 32fcf36 commit ea15ea5

File tree

6 files changed

+99
-8
lines changed

6 files changed

+99
-8
lines changed

Firmware/FFBoard/Inc/Axis.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct AxisFlashAddrs
5959
uint16_t encoderRatio = ADR_AXIS1_ENC_RATIO;
6060

6161
uint16_t speedAccelFilter = ADR_AXIS1_SPEEDACCEL_FILTER;
62+
uint16_t postprocess1 = ADR_AXIS1_POSTPROCESS1;
6263
};
6364

6465
struct AxisConfig
@@ -92,7 +93,8 @@ struct GearRatio_t{
9293
enum class Axis_commands : uint32_t{
9394
power=0x00,degrees=0x01,esgain,zeroenc,invert,idlespring,axisdamper,enctype,drvtype,
9495
pos,maxspeed,maxtorquerate,fxratio,curtorque,curpos,curspd,curaccel,reductionScaler,
95-
filterSpeed, filterAccel, filterProfileId,cpr,axisfriction,axisinertia
96+
filterSpeed, filterAccel, filterProfileId,cpr,axisfriction,axisinertia,
97+
expo,exposcale
9698
};
9799

98100
class Axis : public PersistentStorage, public CommandHandler, public ErrorHandler
@@ -159,13 +161,16 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
159161
int32_t getTorque(); // current torque scaled as a 32 bit signed value
160162
int16_t updateEndstop();
161163

164+
int32_t calculateExpoTorque(int32_t torque);
165+
162166
void startForceFadeIn(float start = 0,float fadeTime = 0.5);
163167

164168
metric_t* getMetrics();
165169

166170
void setEffectTorque(int32_t torque);
167171
bool updateTorque(int32_t* totalTorque);
168172

173+
169174
void setGearRatio(uint8_t numerator,uint8_t denominator);
170175

171176
static const std::vector<class_entry<MotorDriver>> axis1_drivers;
@@ -271,9 +276,15 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
271276
void setFxRatio(uint8_t val);
272277
void updateTorqueScaler();
273278

279+
void setExpo(int val);
280+
274281

275282
GearRatio_t gearRatio;
276283

284+
int expoValInt = 0; // expo v = val*2 => v<0 ? 1/-v : v
285+
float expo = 1;
286+
float expoScaler = 50; // 0.28 to 3.54
287+
277288
};
278289

279290
#endif /* SRC_AXIS_H_ */

Firmware/FFBoard/Inc/constants.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* For more settings see target_constants.h in a target specific folder
99
*/
1010

11-
static const uint8_t SW_VERSION_INT[3] = {1,16,3}; // Version as array. 8 bit each!
11+
static const uint8_t SW_VERSION_INT[3] = {1,16,4}; // Version as array. 8 bit each!
1212
#ifndef MAX_AXIS
1313
#define MAX_AXIS 2 // ONLY USE 2 for now else screws HID Reports
1414
#endif

Firmware/FFBoard/Src/Axis.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,22 @@ Axis::Axis(char axis,volatile Control_t* control) :CommandHandler("axis", CLSID_
9595
setInstance(0);
9696
this->flashAddrs = AxisFlashAddrs({ADR_AXIS1_CONFIG, ADR_AXIS1_MAX_SPEED, ADR_AXIS1_MAX_ACCEL,
9797
ADR_AXIS1_ENDSTOP, ADR_AXIS1_POWER, ADR_AXIS1_DEGREES,ADR_AXIS1_EFFECTS1,ADR_AXIS1_EFFECTS2,ADR_AXIS1_ENC_RATIO,
98-
ADR_AXIS1_SPEEDACCEL_FILTER});
98+
ADR_AXIS1_SPEEDACCEL_FILTER,ADR_AXIS1_POSTPROCESS1});
9999
}
100100
else if (axis == 'Y')
101101
{
102102
drv_chooser = ClassChooser<MotorDriver>(axis2_drivers);
103103
setInstance(1);
104104
this->flashAddrs = AxisFlashAddrs({ADR_AXIS2_CONFIG, ADR_AXIS2_MAX_SPEED, ADR_AXIS2_MAX_ACCEL,
105105
ADR_AXIS2_ENDSTOP, ADR_AXIS2_POWER, ADR_AXIS2_DEGREES,ADR_AXIS2_EFFECTS1,ADR_AXIS2_EFFECTS2, ADR_AXIS2_ENC_RATIO,
106-
ADR_AXIS2_SPEEDACCEL_FILTER});
106+
ADR_AXIS2_SPEEDACCEL_FILTER,ADR_AXIS2_POSTPROCESS1});
107107
}
108108
else if (axis == 'Z')
109109
{
110110
setInstance(2);
111111
this->flashAddrs = AxisFlashAddrs({ADR_AXIS3_CONFIG, ADR_AXIS3_MAX_SPEED, ADR_AXIS3_MAX_ACCEL,
112112
ADR_AXIS3_ENDSTOP, ADR_AXIS3_POWER, ADR_AXIS3_DEGREES,ADR_AXIS3_EFFECTS1,ADR_AXIS3_EFFECTS2,ADR_AXIS3_ENC_RATIO,
113-
ADR_AXIS3_SPEEDACCEL_FILTER});
113+
ADR_AXIS3_SPEEDACCEL_FILTER,ADR_AXIS3_POSTPROCESS1});
114114
}
115115

116116

@@ -157,6 +157,8 @@ void Axis::registerCommands(){
157157
registerCommand("filterAccel", Axis_commands::filterAccel, "Biquad filter freq and q*100 for accel", CMDFLAG_GET);
158158

159159
registerCommand("cpr", Axis_commands::cpr, "Reported encoder CPR",CMDFLAG_GET);
160+
registerCommand("expo", Axis_commands::expo, "Exponential curve correction (x^(val/exposcale)+1)", CMDFLAG_GET | CMDFLAG_SET);
161+
registerCommand("exposcale", Axis_commands::exposcale, "Scaler constant for expo", CMDFLAG_GET);
160162
}
161163

162164
/*
@@ -235,6 +237,11 @@ void Axis::restoreFlash(){
235237
accelFilter.setQ(filterAccelCst[this->filterProfileId].q / 100.0);
236238
}
237239

240+
uint16_t pp1;
241+
if(Flash_Read(flashAddrs.postprocess1, &pp1)){
242+
setExpo(pp1 & 0xff);
243+
}
244+
238245
}
239246
// Saves parameters to flash.
240247
void Axis::saveFlash(){
@@ -253,6 +260,10 @@ void Axis::saveFlash(){
253260
// save CF biquad
254261
uint16_t filterStorage = (uint16_t)this->filterProfileId & 0xFF;
255262
Flash_Write(flashAddrs.speedAccelFilter, filterStorage);
263+
264+
// Postprocessing
265+
Flash_Write(flashAddrs.postprocess1, expoValInt & 0xff);
266+
256267
}
257268

258269

@@ -598,7 +609,7 @@ void Axis::calculateAxisEffects(bool ffb_on){
598609
float speed = metric.current.speed * INTERNAL_SCALER_FRICTION;
599610
float speedRampupCeil = 4096;
600611
float rampupFactor = 1.0;
601-
if (fabs (speed) < speedRampupCeil) { // if speed in the range to rampup we apply a sinus curbe to ramup
612+
if (fabs (speed) < speedRampupCeil) { // if speed in the range to rampup we apply a sine curve
602613
float phaseRad = M_PI * ((fabs (speed) / speedRampupCeil) - 0.5);// we start to compute the normalized angle (speed / normalizedSpeed@5%) and translate it of -1/2PI to translate sin on 1/2 periode
603614
rampupFactor = ( 1 + sin(phaseRad ) ) / 2; // sin value is -1..1 range, we translate it to 0..2 and we scale it by 2
604615
}
@@ -655,6 +666,18 @@ uint16_t Axis::getPower(){
655666
return power;
656667
}
657668

669+
/**
670+
* Calculates an exponential torque correction curve
671+
*/
672+
int32_t Axis::calculateExpoTorque(int32_t torque){
673+
float torquef = (float)torque / (float)0x7fff; // This down and upscaling may introduce float artifacts. Do this before scaling down.
674+
if(torquef < 0){
675+
return -powf(-torquef,expo) * 0x7fff;
676+
}else{
677+
return powf(torquef,expo) * 0x7fff;
678+
}
679+
}
680+
658681
void Axis::updateTorqueScaler() {
659682
effect_margin_scaler = ((float)fx_ratio_i/255.0);
660683
torqueScaler = ((float)power / (float)0x7fff);
@@ -702,11 +725,15 @@ bool Axis::updateTorque(int32_t* totalTorque) {
702725

703726
// Scale effect torque
704727
int32_t torque = effectTorque; // Game effects
728+
if(expo != 1){
729+
torque = calculateExpoTorque(torque);
730+
}
705731
torque *= effect_margin_scaler;
706732
torque += axisEffectTorque; // Independent effects
707733
torque += updateEndstop();
708734
torque *= torqueScaler; // Scale to power
709735

736+
710737
// TODO speed and accel limiters
711738
if(maxSpeedDegS > 0){
712739

@@ -785,6 +812,21 @@ void Axis::setDegrees(uint16_t degrees){
785812
}
786813

787814

815+
void Axis::setExpo(int val){
816+
val = clip(val, -127, 127);
817+
expoValInt = val;
818+
if(val == 0){
819+
expo = 1; // Explicitly force expo off
820+
return;
821+
}
822+
float valF = abs((float)val / expoScaler);
823+
if(val < 0){
824+
expo = 1.0f/(1.0f+valF);
825+
}else{
826+
expo = 1+valF;
827+
}
828+
}
829+
788830
CommandStatus Axis::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
789831

790832
switch(static_cast<Axis_commands>(cmd.cmdId)){
@@ -998,6 +1040,14 @@ CommandStatus Axis::command(const ParsedCommand& cmd,std::vector<CommandReply>&
9981040
}
9991041
break;
10001042

1043+
case Axis_commands::expo:
1044+
handleGetSetFunc(cmd, replies, expoValInt, &Axis::setExpo, this); // need to also provide the expoScaler constant
1045+
break;
1046+
1047+
case Axis_commands::exposcale:
1048+
handleGetSet(cmd, replies, expoScaler); // need to also provide the expoScaler constant
1049+
break;
1050+
10011051
default:
10021052
return CommandStatus::NOT_FOUND;
10031053
}

Firmware/FFBoard/UserExtensions/Inc/eeprom_addresses.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313

1414
#include "main.h"
1515
// Change this to the amount of currently registered variables
16-
#define NB_OF_VAR 161
16+
#define NB_OF_VAR 164
1717
extern const uint16_t VirtAddVarTab[NB_OF_VAR];
1818

1919
// Amount of variables in exportable list
20-
#define NB_EXPORTABLE_ADR 146
20+
#define NB_EXPORTABLE_ADR 149
2121
extern const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR];
2222

2323

@@ -103,6 +103,7 @@ uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data) will return 1 if
103103
#define ADR_AXIS1_SPEEDACCEL_FILTER 0x309 // Speed/Accel filter Lowpass profile
104104
#define ADR_AXIS1_ENC_RATIO 0x30A // Accel filter Lowpass
105105
#define ADR_AXIS1_EFFECTS2 0x30B // 0-7 Friction, 8-15 Inertia
106+
#define ADR_AXIS1_POSTPROCESS1 0x30C // 0-7 expo curve
106107
// TMC1
107108
#define ADR_TMC1_MOTCONF 0x320 // 0-2: MotType 3-5: PhiE source 6-15: Poles
108109
#define ADR_TMC1_CPR 0x321
@@ -128,6 +129,7 @@ uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data) will return 1 if
128129
#define ADR_AXIS2_SPEEDACCEL_FILTER 0x349 // Speed/Accel filter Lowpass profile
129130
#define ADR_AXIS2_ENC_RATIO 0x34A // Store the encoder ratio for an axis
130131
#define ADR_AXIS2_EFFECTS2 0x34B // 0-7 Friction, 8-15 Inertia
132+
#define ADR_AXIS2_POSTPROCESS1 0x34C // 0-7 expo curve
131133
// TMC2
132134
#define ADR_TMC2_MOTCONF 0x360 // 0-2: MotType 3-5: PhiE source 6-15: Poles
133135
#define ADR_TMC2_CPR 0x361
@@ -153,6 +155,7 @@ uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data) will return 1 if
153155
#define ADR_AXIS3_SPEEDACCEL_FILTER 0x389 // Speed/Accel filter Lowpass profile
154156
#define ADR_AXIS3_ENC_RATIO 0x38A // Store the encoder ratio for an axis
155157
#define ADR_AXIS3_EFFECTS2 0x38B // 0-7 Friction, 8-15 Inertia
158+
#define ADR_AXIS3_POSTPROCESS1 0x38C // 0-7 expo curve
156159
// TMC3
157160
#define ADR_TMC3_MOTCONF 0x3A0 // 0-2: MotType 3-5: PhiE source 6-15: Poles
158161
#define ADR_TMC3_CPR 0x3A1
@@ -216,6 +219,7 @@ uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data) will return 1 if
216219
#define ADR_LOCALANALOG_MAX_6 0x50D
217220
#define ADR_LOCALANALOG_MIN_7 0x50E
218221
#define ADR_LOCALANALOG_MAX_7 0x50F
222+
// ADS111X
219223
#define ADR_ADS111X_MIN_0 0x510
220224
#define ADR_ADS111X_MAX_0 0x511
221225
#define ADR_ADS111X_MIN_1 0x512

Firmware/FFBoard/UserExtensions/Src/eeprom_addresses.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const uint16_t VirtAddVarTab[NB_OF_VAR] =
2929
ADR_FFBWHEEL_BUTTONCONF,
3030
ADR_FFBWHEEL_ANALOGCONF,
3131
ADR_FFBWHEEL_CONF1,
32+
// CAN remote
33+
ADR_CANREMOTE_CONF1,
34+
ADR_CANREMOTE_CONF2,
3235
// Button Sources:
3336
ADR_SPI_BTN_1_CONF,
3437
ADR_SHIFTERANALOG_CONF,
@@ -82,6 +85,7 @@ const uint16_t VirtAddVarTab[NB_OF_VAR] =
8285
ADR_AXIS1_SPEEDACCEL_FILTER, // Speed/Accel filter Lowpass profile
8386
ADR_AXIS1_ENC_RATIO, // Accel filter Lowpass
8487
ADR_AXIS1_EFFECTS2, // 0-7 Friction, 8-15 Inertia
88+
ADR_AXIS1_POSTPROCESS1, // 0-7 expo curve
8589
// TMC1
8690
ADR_TMC1_MOTCONF, // 0-2: MotType 3-5: PhiE source 6-15: Poles
8791
ADR_TMC1_CPR,
@@ -107,6 +111,7 @@ const uint16_t VirtAddVarTab[NB_OF_VAR] =
107111
ADR_AXIS2_SPEEDACCEL_FILTER, // Speed/Accel filter Lowpass profile
108112
ADR_AXIS2_ENC_RATIO, // Store the encoder ratio for an axis
109113
ADR_AXIS2_EFFECTS2, // 0-7 Friction, 8-15 Inertia
114+
ADR_AXIS2_POSTPROCESS1, // 0-7 expo curve
110115
// TMC2
111116
ADR_TMC2_MOTCONF, // 0-2: MotType 3-5: PhiE source 6-15: Poles
112117
ADR_TMC2_CPR,
@@ -132,6 +137,7 @@ const uint16_t VirtAddVarTab[NB_OF_VAR] =
132137
ADR_AXIS3_SPEEDACCEL_FILTER, // Speed/Accel filter Lowpass profile
133138
ADR_AXIS3_ENC_RATIO, // Store the encoder ratio for an axis
134139
ADR_AXIS3_EFFECTS2, // 0-7 Friction, 8-15 Inertia
140+
ADR_AXIS3_POSTPROCESS1, // 0-7 expo curve
135141
// TMC3
136142
ADR_TMC3_MOTCONF, // 0-2: MotType 3-5: PhiE source 6-15: Poles
137143
ADR_TMC3_CPR,
@@ -195,6 +201,7 @@ const uint16_t VirtAddVarTab[NB_OF_VAR] =
195201
ADR_LOCALANALOG_MAX_6,
196202
ADR_LOCALANALOG_MIN_7,
197203
ADR_LOCALANALOG_MAX_7,
204+
// ADS111X
198205
ADR_ADS111X_MIN_0,
199206
ADR_ADS111X_MAX_0,
200207
ADR_ADS111X_MIN_1,
@@ -222,6 +229,9 @@ const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR] =
222229
ADR_FFBWHEEL_BUTTONCONF,
223230
ADR_FFBWHEEL_ANALOGCONF,
224231
ADR_FFBWHEEL_CONF1,
232+
// CAN remote
233+
ADR_CANREMOTE_CONF1,
234+
ADR_CANREMOTE_CONF2,
225235
// Button Sources:
226236
ADR_SPI_BTN_1_CONF,
227237
ADR_SHIFTERANALOG_CONF,
@@ -275,6 +285,7 @@ const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR] =
275285
ADR_AXIS1_SPEEDACCEL_FILTER, // Speed/Accel filter Lowpass profile
276286
ADR_AXIS1_ENC_RATIO, // Accel filter Lowpass
277287
ADR_AXIS1_EFFECTS2, // 0-7 Friction, 8-15 Inertia
288+
ADR_AXIS1_POSTPROCESS1, // 0-7 expo curve
278289
// TMC1
279290
ADR_TMC1_MOTCONF, // 0-2: MotType 3-5: PhiE source 6-15: Poles
280291
ADR_TMC1_CPR,
@@ -300,6 +311,7 @@ const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR] =
300311
ADR_AXIS2_SPEEDACCEL_FILTER, // Speed/Accel filter Lowpass profile
301312
ADR_AXIS2_ENC_RATIO, // Store the encoder ratio for an axis
302313
ADR_AXIS2_EFFECTS2, // 0-7 Friction, 8-15 Inertia
314+
ADR_AXIS2_POSTPROCESS1, // 0-7 expo curve
303315
// TMC2
304316
ADR_TMC2_MOTCONF, // 0-2: MotType 3-5: PhiE source 6-15: Poles
305317
ADR_TMC2_CPR,
@@ -325,6 +337,7 @@ const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR] =
325337
ADR_AXIS3_SPEEDACCEL_FILTER, // Speed/Accel filter Lowpass profile
326338
ADR_AXIS3_ENC_RATIO, // Store the encoder ratio for an axis
327339
ADR_AXIS3_EFFECTS2, // 0-7 Friction, 8-15 Inertia
340+
ADR_AXIS3_POSTPROCESS1, // 0-7 expo curve
328341
// TMC3
329342
ADR_TMC3_MOTCONF, // 0-2: MotType 3-5: PhiE source 6-15: Poles
330343
ADR_TMC3_CPR,
@@ -388,6 +401,7 @@ const uint16_t exportableFlashAddresses[NB_EXPORTABLE_ADR] =
388401
ADR_LOCALANALOG_MAX_6,
389402
ADR_LOCALANALOG_MIN_7,
390403
ADR_LOCALANALOG_MAX_7,
404+
// ADS111X
391405
ADR_ADS111X_MIN_0,
392406
ADR_ADS111X_MAX_0,
393407
ADR_ADS111X_MIN_1,

Firmware/scripts/memory_map.csv

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Section comment,Name,Value,Comment on key,VirtAddVarTab,exportableFlashAddresses
6767
,ADR_AXIS1_SPEEDACCEL_FILTER,0x309,// Speed/Accel filter Lowpass profile,1,1
6868
,ADR_AXIS1_ENC_RATIO,0x30A,// Accel filter Lowpass,1,1
6969
,ADR_AXIS1_EFFECTS2,0x30B,"// 0-7 Friction, 8-15 Inertia",1,1
70+
,ADR_AXIS1_POSTPROCESS1,0x30C,// 0-7 expo curve,1,1
7071
// TMC1,,,,,
7172
,ADR_TMC1_MOTCONF,0x320,// 0-2: MotType 3-5: PhiE source 6-15: Poles,1,1
7273
,ADR_TMC1_CPR,0x321,,1,1
@@ -92,6 +93,13 @@ Section comment,Name,Value,Comment on key,VirtAddVarTab,exportableFlashAddresses
9293
,ADR_AXIS2_SPEEDACCEL_FILTER,0x349,// Speed/Accel filter Lowpass profile,1,1
9394
,ADR_AXIS2_ENC_RATIO,0x34A,// Store the encoder ratio for an axis,1,1
9495
,ADR_AXIS2_EFFECTS2,0x34B,"// 0-7 Friction, 8-15 Inertia",1,1
96+
,ADR_AXIS2_POSTPROCESS1,0x34C,// 0-7 expo curve,1,1
97+
,,,,,
98+
,,,,,
99+
,,,,,
100+
,,,,,
101+
,,,,,
102+
,,,,,
95103
// TMC2,,,,,
96104
,ADR_TMC2_MOTCONF,0x360,// 0-2: MotType 3-5: PhiE source 6-15: Poles,1,1
97105
,ADR_TMC2_CPR,0x361,,1,1
@@ -117,6 +125,9 @@ Section comment,Name,Value,Comment on key,VirtAddVarTab,exportableFlashAddresses
117125
,ADR_AXIS3_SPEEDACCEL_FILTER,0x389,// Speed/Accel filter Lowpass profile,1,1
118126
,ADR_AXIS3_ENC_RATIO,0x38A,// Store the encoder ratio for an axis,1,1
119127
,ADR_AXIS3_EFFECTS2,0x38B,"// 0-7 Friction, 8-15 Inertia",1,1
128+
,ADR_AXIS3_POSTPROCESS1,0x38C,// 0-7 expo curve,1,1
129+
,,,,,
130+
,,,,,
120131
// TMC3,,,,,
121132
,ADR_TMC3_MOTCONF,0x3A0,// 0-2: MotType 3-5: PhiE source 6-15: Poles,1,1
122133
,ADR_TMC3_CPR,0x3A1,,1,1
@@ -183,6 +194,7 @@ Section comment,Name,Value,Comment on key,VirtAddVarTab,exportableFlashAddresses
183194
,ADR_LOCALANALOG_MAX_6,0x50D,,1,1
184195
,ADR_LOCALANALOG_MIN_7,0x50E,,1,1
185196
,ADR_LOCALANALOG_MAX_7,0x50F,,1,1
197+
// ADS111X,,,,,
186198
,ADR_ADS111X_MIN_0,0x510,,1,1
187199
,ADR_ADS111X_MAX_0,0x511,,1,1
188200
,ADR_ADS111X_MIN_1,0x512,,1,1

0 commit comments

Comments
 (0)