Skip to content

Commit

Permalink
Merge pull request #420 from doudar/FTMS_Resistance
Browse files Browse the repository at this point in the history
  • Loading branch information
doudar authored Jan 22, 2023
2 parents 53d3798 + 9478b0f commit aa51ef6
Show file tree
Hide file tree
Showing 38 changed files with 854 additions and 515 deletions.
21 changes: 20 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,25 @@
},
"C_Cpp.errorSquiggles": "Disabled",
"cSpell.words": [
"endianness"
"Appender",
"Baranick",
"BINFILE",
"Doud",
"endianness",
"IRAM",
"LOGW",
"MDNS",
"millis",
"Peloton",
"POWERTABLE",
"PWCFILENAME",
"RUNTIMECONFIG",
"ssid",
"STEALTHCHOP",
"UPDATEURL",
"Upgrader",
"userconfig",
"VERSIONFILE",
"WEBSERVER"
]
}
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added power scaler for new board.
- Added Main Index link to develop.html.
- Added feature to automatically reconnect BLE devices if both are specified.
- Added ftms passthrough. FTMS messages from the client app are now passed to a connected FTMS device.
- Added resistance capture to Echelon.
- Added Resistance capture to Flywheel.
- Added Resistance Capture to Peloton.
- Added Resistance capture to FTMS.
- Added scanning when devices are not connected.
- Added ability to set travel limits based on resistance feedback from a bike.
- Added shifting in ERG mode (changes watt target).
- Added shifting in resistance mode (changes resistance target.)

### Changed
- PowerTable values are now adjusted to 90 RPM cad on input.
Expand All @@ -22,6 +31,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Moved serial checking to own function.
- Reduced verbosity of ERG logging.
- Fixed instance of BLE PM dropdown not being saved correctly.
- Moved post connect handling to the ble communication loop. (improves startup stability)
- Fixed bug submitted by @flo100 where MIN_WATTS in ERG should have been userConfig.getMinWatts();
- FTMS resistance mode now changes the attached bike resistance with feedback. (i.e. setting resistance to 50 with a Peloton attached will set 50 on the Peloton)
- Refactored rtConfig to use more measurement class.
- Increased stepper speed when a Peloton is connected. (very light resistance)
- Updated libraries to latest

### Hardware
- Removed duplicate directory in direct mount folder.
Expand Down Expand Up @@ -364,7 +379,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* WiFi Fallback to AP mode is now 10 seconds.
* WiFi AP mode Fallback SSID is now device name (MDNS name), and the password is whatever you have set.
* ERG Mode slightly more aggressive.
* Stealthchop 2 now selectable in settings.
* StealthChop 2 now selectable in settings.
* Holding both shifters at boot resets the unit to defaults and erases filesystem. (firmware remains intact)
* Holding both shifters for 3 seconds after boot preforms a BLE device scan/reconnect.

Expand Down
4 changes: 2 additions & 2 deletions CustomCharacteristic.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ From BLE_common.h
|BLE_deviceName |0x07 | |Not Implemented |
|BLE_shiftStep |0x08 |int |Stepper steps per shifter button press |
|BLE_stepperPower |0x09 |int |Stepper power in ma |
|BLE_stealthchop |0x0A |bool |Stepper stealthchop on/off |
|BLE_stealthChop |0x0A |bool |Stepper stealthChop on/off |
|BLE_inclineMultiplier |0x0B |float|- multiplied by incline to get steps per % gradient|
|BLE_powerCorrectionFactor |0x0C |float|.5 - 2.0 to calibrate power output |
|BLE_simulateHr |0x0D |bool | |
|BLE_simulateWatts |0x0E |bool | |
|BLE_simulateCad |0x0F |bool | |
|BLE_ERGMode |0x10 |bool | |
|BLE_FTMSMode |0x10 |bool | |
|BLE_autoUpdate |0x11 |bool |updates on (01) or off (00) |
|BLE_ssid |0x12 | |Not Implemented |
|BLE_password |0x13 | |Not Implemented |
Expand Down
43 changes: 23 additions & 20 deletions data/btsimulator.html
Original file line number Diff line number Diff line change
Expand Up @@ -238,29 +238,32 @@ <h2>ERG Target Watts</h2>
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var obj = JSON.parse(this.responseText);
document.getElementById("wattsValue").innerHTML = obj.simulatedWatts + " Watts";
document.getElementById("wattsSlider").value = obj.simulatedWatts;
document.getElementById("wattsOutput").checked = obj.simulateWatts;
document.getElementById("wattsInputContainer").hidden = !obj.simulateWatts;

document.getElementById("hrValue").innerHTML = obj.simulatedHr + " BPM";
document.getElementById("hrSlider").value = obj.simulatedHr;
document.getElementById("hrOutput").checked = obj.simulateHr;
document.getElementById("hrSlider").hidden = !obj.simulateHr;
document.getElementById("hrValue").hidden = !obj.simulateHr;

document.getElementById("cadValue").innerHTML = obj.simulatedCad + " RPM";
document.getElementById("cadSlider").value = obj.simulatedCad;
document.getElementById("cadOutput").checked = obj.simulateCad;
document.getElementById("cadInputContainer").hidden = !obj.simulateCad;

document.getElementById("enableErgCheckbox").checked = obj.ERGMode;
document.getElementById("wattsValue").innerHTML = obj.watts + " Watts";
document.getElementById("wattsSlider").value = obj.watts;
document.getElementById("wattsOutput").checked = obj.simWatts;
document.getElementById("wattsInputContainer").hidden = !obj.simWatts;

document.getElementById("hrValue").innerHTML = obj.hr + " BPM";
document.getElementById("hrSlider").value = obj.hr;
document.getElementById("hrOutput").checked = obj.simHr;
document.getElementById("hrSlider").hidden = !obj.simHr;
document.getElementById("hrValue").hidden = !obj.simHr;

document.getElementById("cadValue").innerHTML = obj.cad + " RPM";
document.getElementById("cadSlider").value = obj.cad;
document.getElementById("cadOutput").checked = obj.simCad;
document.getElementById("cadInputContainer").hidden = !obj.simCad;
var ergMode = false;
if (obj.FTMSMode == "0x05"){
ergMode = true;
}
document.getElementById("enableErgCheckbox").checked = ergMode;

document.getElementById("targetWattsValue").innerHTML = obj.targetWatts + " Watts";
document.getElementById("targetWattsSlider").value = obj.targetWatts == null ? 0 : obj.targetWatts;
document.getElementById("targetWattsOutput").checked = obj.simulateTargetWatts;
document.getElementById("targetWattsSlider").hidden = !obj.simulateTargetWatts;
document.getElementById("targetWattsValue").hidden = !obj.simulateTargetWatts;
document.getElementById("targetWattsOutput").checked = obj.simTargetWatts;
document.getElementById("targetWattsSlider").hidden = !obj.simTargetWatts;
document.getElementById("targetWattsValue").hidden = !obj.simTargetWatts;

setTimeout(function () {
const watermark = document.getElementById("loadingWatermark");
Expand Down
6 changes: 3 additions & 3 deletions data/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,14 @@ <h2>
</tr>
<tr>
<td>
<p class="tooltip">Stepper Stealthchop
<p class="tooltip">Stepper StealthChop
<span class="tooltiptext">
Make stepper silent at expense of torque
</span>
</p>
</td>
<td>
<label class="switch"><input type="checkbox" name="stealthchop" id="stealthchop"><span
<label class="switch"><input type="checkbox" name="stealthChop" id="stealthChop"><span
class="slider"></span></label>
</td>
</tr>
Expand Down Expand Up @@ -319,7 +319,7 @@ <h2>
document.getElementById("stepperPower").value = obj.stepperPower;
document.getElementById("minWatts").value = obj.minWatts;
document.getElementById("maxWatts").value = obj.maxWatts;
document.getElementById("stealthchop").checked = obj.stealthchop;
document.getElementById("stealthChop").checked = obj.stealthChop;
document.getElementById("autoUpdate").checked = obj.autoUpdate;
document.getElementById("stepperDir").checked = obj.stepperDir;
document.getElementById("shifterDir").checked = obj.shifterDir;
Expand Down
6 changes: 3 additions & 3 deletions data/status.html
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ <h2>
var obj = JSON.parse(this.responseText);
document.getElementById("currentIncline").value = obj.currentIncline;
document.getElementById("targetIncline").value = obj.targetIncline;
document.getElementById("simulatedHr").value = obj.simulatedHr;
document.getElementById("simulatedWatts").value = obj.simulatedWatts;
document.getElementById("simulatedHr").value = obj.hr;
document.getElementById("simulatedWatts").value = obj.watts;
document.getElementById("targetWatts").value = obj.targetWatts;
document.getElementById("simulatedCad").value = obj.simulatedCad;
document.getElementById("simulatedCad").value = obj.cad;
}
}
};
Expand Down
13 changes: 8 additions & 5 deletions include/BLE_Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,21 @@
#define BLE_deviceName 0x07
#define BLE_shiftStep 0x08
#define BLE_stepperPower 0x09
#define BLE_stealthchop 0x0A
#define BLE_stealthChop 0x0A
#define BLE_inclineMultiplier 0x0B
#define BLE_powerCorrectionFactor 0x0C
#define BLE_simulateHr 0x0D
#define BLE_simulateWatts 0x0E
#define BLE_simulateCad 0x0F
#define BLE_ERGMode 0x10
#define BLE_FTMSMode 0x10
#define BLE_autoUpdate 0x11
#define BLE_ssid 0x12
#define BLE_password 0x13
#define BLE_foundDevices 0x14
#define BLE_connectedPowerMeter 0x15
#define BLE_connectedHeartMonitor 0x16
#define BLE_shifterPosition 0x17
#define BLE_saveToLittleFS 0x18
#define BLE_saveToLittleFS 0x18
#define BLE_targetPosition 0x19
#define BLE_externalControl 0x1A
#define BLE_syncMode 0x1B
Expand Down Expand Up @@ -158,6 +158,7 @@ class SpinBLEAdvertisedDevice {
bool userSelectedCSC = false;
bool userSelectedCT = false;
bool doConnect = false;
bool postConnected = false;

void set(BLEAdvertisedDevice *device, int id = BLE_HS_CONN_HANDLE_NONE, BLEUUID inserviceUUID = (uint16_t)0x0000, BLEUUID incharUUID = (uint16_t)0x0000) {
advertisedDevice = device;
Expand All @@ -179,8 +180,9 @@ class SpinBLEAdvertisedDevice {
userSelectedCSC = false; // Cycling Speed/Cadence
userSelectedCT = false; // Controllable Trainer
doConnect = false; // Initiate connection flag
postConnected = false; // Has Cost Connect Been Run?
if (dataBufferQueue != nullptr) {
Serial.println("Resetting queue");
//Serial.println("Resetting queue");
xQueueReset(dataBufferQueue);
}
}
Expand Down Expand Up @@ -220,7 +222,8 @@ class SpinBLEClient {
// Reset devices in myBLEDevices[]. Bool All (true) or only connected ones
// (false)
void resetDevices();
void postConnect(NimBLEClient *pClient);
void postConnect();
void FTMSControlPointWrite(const uint8_t *pData, int length);
};
class MyAdvertisedDeviceCallback : public NimBLEAdvertisedDeviceCallbacks {
public:
Expand Down
16 changes: 9 additions & 7 deletions include/ERG_Mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,29 +75,31 @@ class PowerTable {
class ErgMode {
public:
ErgMode(PowerTable* powerTable) { this->powerTable = powerTable; }
void computErg();
void computeErg();
void computeResistance();
void _writeLogHeader();
void _writeLog(int cycles, float currentIncline, float newIncline, int currentSetPoint, int newSetPoint, int currentWatts, int newWatts, int currentCadence, int newCadence);
void _writeLog(float currentIncline, float newIncline, int currentSetPoint, int newSetPoint, int currentWatts, int newWatts, int currentCadence, int newCadence);

private:
bool engineStopped = false;
bool initialized = false;
int setPoint = 0;
int cycle = 0;
int offsetMultiplier = 0;
Measurement watts = Measurement(0);
int resistance = 0;
int cadence = 0;

Measurement watts;
PowerTable* powerTable;

// check if user is spinning, reset incline if user stops spinning
bool _userIsSpinning(int cadence, float incline);

// calculate incline if setpoint (from Zwift) changes
void _setPointChangeState(int newSetPoint, int newCadence, Measurement& newWatts, float currentIncline);
void _setPointChangeState(int newCadence, Measurement& newWatts);

// calculate incline if setpoint is unchanged
void _inSetpointState(int newSetPoint, int newCadence, Measurement& newWatts, float currentIncline);
void _inSetpointState(int newCadence, Measurement& newWatts);

// update localvalues + incline, creates a log
void _updateValues(int newSetPoint, int newCadence, Measurement& newWatts, float currentIncline, float newIncline);
void _updateValues(int newCadence, Measurement& newWatts, float newIncline);
};
22 changes: 13 additions & 9 deletions include/Main.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SS2K {
bool stepperIsRunning;
bool externalControl;
bool syncMode;
int txCheck;

bool IRAM_ATTR deBounce();
static void IRAM_ATTR moveStepper(void* pvParameters);
Expand All @@ -47,11 +48,14 @@ class SS2K {
void restartWifi();
void setupTMCStepperDriver();
void updateStepperPower();
void updateStealthchop();
void updateStealthChop();
void checkDriverTemperature();
void motorStop(bool releaseTension = false);
void checkSerial();
void checkBLEReconnect();
void FTMSModeShiftModifier();
static void rxSerial(void);
void txSerial();
void pelotonConnected();

SS2K() {
targetPosition = 0;
Expand All @@ -65,12 +69,13 @@ class SS2K {
shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN;
scanDelayTime = 10000;
scanDelayStart = 0;
txCheck = TX_CHECK_INTERVAL;
}
};

class AuxSerialBuffer {
public:
uint8_t data[20];
uint8_t data[AUX_BUF_SIZE];
size_t len;

AuxSerialBuffer() {
Expand All @@ -81,7 +86,7 @@ class AuxSerialBuffer {
}
};

// Users Physical Working Capacity Calculation Parameters (heartrate to Power
// Users Physical Working Capacity Calculation Parameters (heart rate to Power
// calculation)
extern physicalWorkingCapacity userPWC;
extern SS2K ss2k;
Expand All @@ -90,8 +95,7 @@ extern SS2K ss2k;
extern userParameters userConfig;
extern RuntimeParameters rtConfig;

//Peloton Specific Parameters
#define PELOTON_RQ_SIZE 4
const uint8_t peloton_rq_watts[]{0xF5, 0x44, 0x39, 0xF6};
const uint8_t peloton_rq_cad[]{0xF5, 0x41, 0x36, 0xF6};
const uint8_t peloton_rq_res[]{0xF5, 0x4A, 0x3F, 0xF6};
// Peloton Specific Parameters
// const uint8_t peloton_rq_watts[]{0xF5, 0x44, 0x39, 0xF6};
// const uint8_t peloton_rq_cad[]{0xF5, 0x41, 0x36, 0xF6};
// const uint8_t peloton_rq_res[]{0xF5, 0x49, 0x3F, 0xF6};
Loading

0 comments on commit aa51ef6

Please sign in to comment.