Skip to content

Commit

Permalink
Merge pull request #385 from doudar/Min_Max_fix
Browse files Browse the repository at this point in the history
Min max fix
  • Loading branch information
doudar authored Oct 22, 2022
2 parents 7e6f89b + 70ed7ee commit 5ad002c
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 19 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Added blocking for shifts above or below min/max setpoints.

### Changed
- PowerTable values are now adjusted to 90 RPM cad on input.
- PowerTable entries are now validated against previous entries.
- changes to default settings for better rideability. raised incline multiplier and erg sensitivity, increased incline multiplier and max brake watts.

### Hardware
Expand Down
4 changes: 4 additions & 0 deletions include/ERG_Mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class PowerTable {

// Display power table in log
void toLog();

private:
// Adjust Watts For Cadence
int _adjustWattsForCadence(int watts, int cad);
};

class ErgMode {
Expand Down
7 changes: 5 additions & 2 deletions include/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@

//////////// Defines for hardware Revision 1 ////////////

//Board Name
// Board Name
#define r1_NAME "Revision One"

// ID Voltage on pin 34. Values are 0-4095 (0-3.3v)
Expand Down Expand Up @@ -125,7 +125,7 @@
////////////////////////////////////////////////////////
//////////// Defines for hardware Revision 2 ////////////

//Board Name
// Board Name
#define r2_NAME "Revision Two"

// ID Voltage on pin 34. Values are 0-4095 (0-3.3v)
Expand Down Expand Up @@ -227,6 +227,9 @@
// Number of similar power samples to take before writing to the Power Table
#define POWER_SAMPLES 5

// Normal cadence value (used in power table and other areas)
#define NORMAL_CAD 90

// Temperature of the ESP32 at which to start reducing the power output of the stepper motor driver.
#define THROTTLE_TEMP 85

Expand Down
2 changes: 1 addition & 1 deletion src/BLE_Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ void calculateInstPwrFromHR() {

#ifndef DEBUG_HR_TO_PWR
rtConfig.setSimulatedWatts(avgP);
rtConfig.setSimulatedCad(90);
rtConfig.setSimulatedCad(NORMAL_CAD);
#endif // DEBUG_HR_TO_PWR

SS2K_LOG(BLE_SERVER_LOG_TAG, "Power From HR: %d", avgP);
Expand Down
65 changes: 54 additions & 11 deletions src/ERG_Mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ void PowerBuffer::reset() {
}

void PowerTable::processPowerValue(PowerBuffer& powerBuffer, int cadence, Measurement watts) {
if ((cadence > 70) && (cadence < 100) && (watts.value > 10) && (watts.value < POWERTABLE_SIZE * POWERTABLE_INCREMENT)) {
if ((cadence >= (NORMAL_CAD - 20)) && (cadence <= (NORMAL_CAD + 20)) && (watts.value > 10) && (watts.value < (POWERTABLE_SIZE * POWERTABLE_INCREMENT))) {
if (powerBuffer.powerEntry[0].readings == 0) {
powerBuffer.set(0); // Take Initial reading
// Take Initial reading
powerBuffer.set(0);
// Check that reading is within 25w of the initial reading
} else if (abs(powerBuffer.powerEntry[0].watts - watts.value) < (POWERTABLE_INCREMENT / 2)) {
for (int i = 1; i < POWER_SAMPLES; i++) {
if (powerBuffer.powerEntry[i].readings == 0) {
Expand All @@ -114,17 +116,25 @@ void PowerTable::setStepperMinMax() {

int minBreakWatts = userConfig.getMinWatts();
if (minBreakWatts > 0) {
_return = this->lookup(minBreakWatts, 90);
_return = this->lookup(minBreakWatts, NORMAL_CAD);
if (_return != RETURN_ERROR) {
// never set less than one shift bewlow current incline.
if ((_return >= rtConfig.getCurrentIncline()) && (rtConfig.getSimulatedWatts().value > userConfig.getMinWatts())) {
_return = rtConfig.getCurrentIncline() - userConfig.getShiftStep();
}
rtConfig.setMinStep(_return);
SS2K_LOG(ERG_MODE_LOG_TAG, "Min Position Set: %d", _return);
}
}

int maxBreakWatts = userConfig.getMaxWatts();
if (maxBreakWatts > 0) {
_return = this->lookup(maxBreakWatts, 90);
_return = this->lookup(maxBreakWatts, NORMAL_CAD);
if (_return != RETURN_ERROR) {
// never set less than one shift above current incline.
if ((_return <= rtConfig.getCurrentIncline()) && (rtConfig.getSimulatedWatts().value < userConfig.getMaxWatts())) {
_return = rtConfig.getCurrentIncline() + userConfig.getShiftStep();
}
rtConfig.setMaxStep(_return);
SS2K_LOG(ERG_MODE_LOG_TAG, "Max Position Set: %d", _return);
}
Expand All @@ -139,10 +149,14 @@ void PowerTable::newEntry(PowerBuffer& powerBuffer) {

for (int i = 0; i < POWER_SAMPLES; i++) {
if (powerBuffer.powerEntry[i].readings == 0) {
// break if powerEntry is not set
// break if powerEntry is not set. This should never happen.
break;
}

// Adjust input watts to an cadence of NORMAL_CAD
powerBuffer.powerEntry[i].watts = _adjustWattsForCadence(powerBuffer.powerEntry[i].watts, powerBuffer.powerEntry[i].cad);
powerBuffer.powerEntry[i].cad = NORMAL_CAD;

if (i == 0) { // first loop -> assign values
watts = powerBuffer.powerEntry[i].watts;
targetPosition = powerBuffer.powerEntry[i].targetPosition;
Expand All @@ -155,11 +169,28 @@ void PowerTable::newEntry(PowerBuffer& powerBuffer) {
targetPosition = (targetPosition + powerBuffer.powerEntry[i].targetPosition) / 2;
cad = (cad + powerBuffer.powerEntry[i].cad) / 2;
}
// Done with powerBuffer

// To start working on the PowerTable, we need to calculate position in the table for the new entry
int i = round(watts / POWERTABLE_INCREMENT);

if (i == 1) { // set the minimum resistance level of the trainer.
rtConfig.setMinStep(this->powerEntry[i].targetPosition);
// Prohibit entries that are less than the number to the left
if (i > 0) {
for (int j = i - 1; j > 0; j--) {
if ((this->powerEntry[j].targetPosition != 0) && (this->powerEntry[j].targetPosition >= targetPosition)) {
SS2K_LOG(POWERTABLE_LOG_TAG, "Target Slot (%dw)(%d)(%d) was less than previous (%d)(%d)", watts, i, targetPosition, j, this->powerEntry[j].targetPosition);
return;
}
}
}
// Prohibit entries that are greater than the number to the right
if (i < POWERTABLE_SIZE) {
for (int j = i + 1; j < POWERTABLE_SIZE; j++) {
if ((this->powerEntry[j].targetPosition != 0) && (targetPosition >= this->powerEntry[j].targetPosition)) {
SS2K_LOG(POWERTABLE_LOG_TAG, "Target Slot (%dw)(%d)(%d) was greater than next (%d)(%d)", watts, i, targetPosition, j, this->powerEntry[j].targetPosition);
return;
}
}
}

if (this->powerEntry[i].readings == 0) { // if first reading in this entry
Expand Down Expand Up @@ -187,6 +218,12 @@ int32_t PowerTable::lookup(int watts, int cad) {
float cad;
};

watts = _adjustWattsForCadence(watts, cad);
if (watts <= 0) {
return -99;
}
cad = NORMAL_CAD;

int i = round(watts / POWERTABLE_INCREMENT); // find the closest entry
float scale = watts / POWERTABLE_INCREMENT - i; // Should we look at the next higher or next lower index for comparison?
int indexPair = -1; // The next closest index with data for interpolation // The next closest index
Expand Down Expand Up @@ -279,15 +316,21 @@ int32_t PowerTable::lookup(int watts, int cad) {
return (RETURN_ERROR);
}

// Cadence Adjustment
float averageCAD = (below.cad + above.cad) / 2;
watts = ((watts * 2) * (averageCAD / (cad + 1)) / 2);
// actual interpolation
int32_t rTargetPosition = below.targetPosition + ((watts - below.power) / (above.power - below.power)) * (above.targetPosition - below.targetPosition);

return rTargetPosition;
}

int PowerTable::_adjustWattsForCadence(int watts, int cad) {
if (cad > 0) {
watts = (watts * (NORMAL_CAD / cad));
return watts;
} else {
return 0;
}
}

bool PowerTable::load() {
// load power table from littlefs
return false; // return unsuccessful
Expand Down Expand Up @@ -359,7 +402,7 @@ void ErgMode::computErg() {
// SetPoint changed
if (this->setPoint != newSetPoint) {
_setPointChangeState(newSetPoint, newCadence, newWatts, currentIncline);
SS2K_LOG(ERG_MODE_LOG_TAG, "SetPoint changed");
SS2K_LOG(ERG_MODE_LOG_TAG, "SetPoint changed: %dw", newSetPoint);
return;
}

Expand Down
16 changes: 11 additions & 5 deletions src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void setup() {
Serial.begin(512000);
SS2K_LOG(MAIN_LOG_TAG, "Compiled %s%s", __DATE__, __TIME__);
pinMode(REV_PIN, INPUT);
int actualVoltage = analogRead(REV_PIN);
int actualVoltage = analogRead(REV_PIN);
if (actualVoltage - boards.rev1.versionVoltage >= boards.rev2.versionVoltage - actualVoltage) {
currentBoard = boards.rev2;
} else {
Expand Down Expand Up @@ -170,12 +170,18 @@ void SS2K::maintenanceLoop(void *pvParameters) {
while (true) {
vTaskDelay(200 / portTICK_RATE_MS);
if (rtConfig.getShifterPosition() > ss2k.lastShifterPosition) {
SS2K_LOG(MAIN_LOG_TAG, "Shift UP: %l", rtConfig.getShifterPosition());
Serial.println(ss2k.targetPosition);
SS2K_LOG(MAIN_LOG_TAG, "Shift UP: %d tgt: %d min %d max %d", rtConfig.getShifterPosition(), ss2k.targetPosition, rtConfig.getMinStep(), rtConfig.getMaxStep());
if (ss2k.targetPosition > rtConfig.getMaxStep()) {
SS2K_LOG(MAIN_LOG_TAG, "Shift Blocked By MaxStep");
rtConfig.setShifterPosition(ss2k.lastShifterPosition);
}
spinBLEServer.notifyShift();
} else if (rtConfig.getShifterPosition() < ss2k.lastShifterPosition) {
SS2K_LOG(MAIN_LOG_TAG, "Shift DOWN: %l", rtConfig.getShifterPosition());
Serial.println(ss2k.targetPosition);
SS2K_LOG(MAIN_LOG_TAG, "Shift DOWN: %d tgt: %d min %d max %d", rtConfig.getShifterPosition(), ss2k.targetPosition, rtConfig.getMinStep(), rtConfig.getMaxStep());
if (ss2k.targetPosition < rtConfig.getMinStep()) {
SS2K_LOG(MAIN_LOG_TAG, "Shift Blocked By MinStep");
rtConfig.setShifterPosition(ss2k.lastShifterPosition);
}
spinBLEServer.notifyShift();
}
ss2k.lastShifterPosition = rtConfig.getShifterPosition();
Expand Down

0 comments on commit 5ad002c

Please sign in to comment.