Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shifters in Stand-alone ERG mode #390

Closed
Flo100 opened this issue Oct 23, 2022 · 25 comments
Closed

Shifters in Stand-alone ERG mode #390

Flo100 opened this issue Oct 23, 2022 · 25 comments
Labels
enhancement New feature or request

Comments

@Flo100
Copy link
Contributor

Flo100 commented Oct 23, 2022

I just found your SmartSpin2k project, build it, adapted it to my already made (and older) hardware setup and I really like it. :)

Is your feature request related to a problem? Please describe.
There's not really a problem, it;'s more inconvenience.
Sometimes I use my spinning bike stand-alone and choose the ERG mode from the webserver and set ERG target Watts. But during my excercise I would like to change this target using the shifters, because using the webinterface is annoying during a workout.

Describe the solution you'd like
Let the shifters increase and decrease the ERG target Watts in ERG mode. For example in 10Watt steps or so.
Also it would be great that the Watts go to minimum Watts when the shift down button is held for 1,5s. That way you don't have to push the button that many times to release the resistance. (Could also work for gears in SIM mode to switch back faster).

Describe alternatives you've considered
Using my phone on the handlebar to change the slider in de webinterface.

I noticed that I can't switch on ERG mode when connected to RGT or Zwift. Would it be possible that the webinterface ERG setting overrides the incline data from RGT so I can ride any event on targeted Watts instead of incline (but still sending all cadence, hr and powerdata to RGT)?

@doudar
Copy link
Owner

doudar commented Oct 24, 2022

I just found your SmartSpin2k project, build it, adapted it to my already made (and older) hardware setup and I really like it. :)

Awesome! Glad to have you here!!!

Is your feature request related to a problem? Please describe. There's not really a problem, it;'s more inconvenience. Sometimes I use my spinning bike stand-alone and choose the ERG mode from the webserver and set ERG target Watts. But during my excercise I would like to change this target using the shifters, because using the webinterface is annoying during a workout.

Describe the solution you'd like Let the shifters increase and decrease the ERG target Watts in ERG mode. For example in 10Watt steps or so. Also it would be great that the Watts go to minimum Watts when the shift down button is held for 1,5s. That way you don't have to push the button that many times to release the resistance. (Could also work for gears in SIM mode to switch back faster).

Holding down the shifters - I like it! That's a pretty cool idea. I'll definitely put it on my todo list. Changing target watts in ERG mode is interesting as well. I think it's something that could be done.

Describe alternatives you've considered Using my phone on the handlebar to change the slider in de webinterface.

I noticed that I can't switch on ERG mode when connected to RGT or Zwift. Would it be possible that the webinterface ERG setting overrides the incline data from RGT so I can ride any event on targeted Watts instead of incline (but still sending all cadence, hr and powerdata to RGT)?

This one might be a little bit harder to implement correctly, but I'll think about it and look into it. In the meantime with Zwift, you could work around this by only connecting SS2k as a power meter and not a controllable trainer.

@Flo100
Copy link
Contributor Author

Flo100 commented Oct 24, 2022

I made a simple version a few years ago with a stepper motor and an A4988 and it works like Smartspin2k when not connected to Zwift, so only changing the resistance by pressing the shifters. I quickly got tired of pushing multiple times to get a large increase or decrease and so I implemented big steps when holding down the button for 1,5s.

It also has a hardware switch and let the stepper "zero" itself when powering on.
I noticed with SmartSpin2k that when I start on a hill the motor keeps spinning backwards until it is mechanical limited and crashes. (Unless I switch up at the same time offcourse)
How do I tell SmartSpin2k that the stepper is already at minimum steps when I power up? Or do I always have to start with the stepper like halfway my resistance?
Perhaps it should only decrease in SIM mode if the measured power > min_watts? Or does that break something else / do I do something wrong here?

This one might be a little bit harder to implement correctly, but I'll think about it and look into it. In the meantime with Zwift, you could work around this by only connecting SS2k as a power meter and not a controllable trainer.

That is a possibility offcourse. I mostly start a course in sim mode and when I'm done I tend to keep riding on the same course to do my cooling down. During the cooldown I don't like the automatic resistance change and would rather stay at a (manually) set power level.

@doudar
Copy link
Owner

doudar commented Oct 26, 2022

If you’re using a new version of SS2K and have some type of power meter attached, it will generate travel limits as you’re pedaling. These are base off min brake watts and max brake watts (settings) and SS2K won’t let you go above or below those respectively.

@Flo100
Copy link
Contributor Author

Flo100 commented Dec 25, 2022

It does that only in ERG mode right? Not in simulation mode?
When I start on top of a hill in simulation mode, my stepper rotates back beyond it's mechanical limit.

Also I think that MIN_WATTS needs to be replaced by userConfig.getMinwatts() in ERG_Mode.cpp?
// set minimum SetPoint to MIN_WATTS if app sends setpoints lower than MIN_WATTS. if (newSetPoint < userConfig.getMinWatts()) { SS2K_LOG(ERG_MODE_LOG_TAG, "ERG Target Below Minumum Value."); newSetPoint = userConfig.getMinWatts(); }

@doudar
Copy link
Owner

doudar commented Dec 25, 2022

It does that only in ERG mode right? Not in simulation mode?

When I start on top of a hill in simulation mode, my stepper rotates back beyond it's mechanical limit.

Also I think that MIN_WATTS needs to be replaced by userConfig.getMinwatts() in ERG_Mode.cpp?

` // set minimum SetPoint to MIN_WATTS if app sends setpoints lower than MIN_WATTS.

if (newSetPoint < userConfig.getMinWatts()) {

SS2K_LOG(ERG_MODE_LOG_TAG, "ERG Target Below Minumum Value.");

newSetPoint = userConfig.getMinWatts();

}`

Good catch! Yes, it should be.

Right now, the power table isn't persistent so it takes a few minutes of pedaling at various watt levels before the min and max positions are calculated. Prior to that, the limits are very large and the knob could crash.

What I'd like to do is have the offsets for the table saved and then the table regenerated once a known position is found. That should give you protection after just a few seconds of pedaling.

The only time in sim mode that shifting is blocked is if you are up against a calculated limit.

@doudar
Copy link
Owner

doudar commented Dec 25, 2022

It does that only in ERG mode right? Not in simulation mode? When I start on top of a hill in simulation mode, my stepper rotates back beyond it's mechanical limit.

Also I think that MIN_WATTS needs to be replaced by userConfig.getMinwatts() in ERG_Mode.cpp? // set minimum SetPoint to MIN_WATTS if app sends setpoints lower than MIN_WATTS. if (newSetPoint < userConfig.getMinWatts()) { SS2K_LOG(ERG_MODE_LOG_TAG, "ERG Target Below Minumum Value."); newSetPoint = userConfig.getMinWatts(); }

Current changes (you suggested) are going into the FTMS_Resistance branch, as that is currently undergoing testing for merging into develop. If you're interested in working on a persistent power table, I'd absolutely love the help. No pressure of course.

@Flo100
Copy link
Contributor Author

Flo100 commented Dec 27, 2022

This one might be a little bit harder to implement correctly, but I'll think about it and look into it. In the meantime with Zwift, you could work around this by only connecting SS2k as a power meter and not a controllable trainer.

I implemented a simple 'solution' to this one.
In SmartSpin_parameters.h change getERGMode() to:
bool getERGMode() { return ERGMode || simulateTargetWatts; }
And in BLE_Server.cpp change case FitnessMachineControlPointProcedure::SetIndoorBikeSimulationParameters: { to:
...
port = bytes_to_u16(buf[1], buf[0]);
rtConfig.setERGMode(false);
if(!rtConfig.getERGMode()){
rtConfig.setTargetIncline(port);
logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Sim Mode Incline %2f", rtConfig.getTargetIncline() / 100);
}
ftmsStatus = ....

This way you can "Override" the simulation mode using the webinterface and ride with a fixed Powersetting. I use this when cooling down, because then I don't like the shifting up and down anymore.
Also when RGT (or Zwift) is set to ERG mode RGT is still leading and the Set Power can't be altered during the workout using SmartSpin2k.

Holding down the shifters - I like it! That's a pretty cool idea. I'll definitely put it on my todo list. Changing target watts in ERG mode is interesting as well. I think it's something that could be done.

I also made changes to the Interrupt Functions of Main.cpp to get this working.
///////////// Interrupt Functions /////////////
void IRAM_ATTR SS2K::shiftUp() { // Handle the shift up interrupt IRAM_ATTR is to keep the interrput code in ram always
if (ss2k.deBounce()){
if (!digitalRead(currentBoard.shiftUpPin)) { // double checking to make sure the interrupt wasn't triggered by emf
if(!rtConfig.getERGMode()) {
rtConfig.setShifterPosition(rtConfig.getShifterPosition() - 1 + userConfig.getShifterDir() * 2);
} else { // -> rtConfig.getERGMode()
int newSetPoint = rtConfig.getTargetWatts() +10;
if (newSetPoint > userConfig.getMaxWatts()) {
newSetPoint = userConfig.getMaxWatts();
}
rtConfig.setTargetWatts(newSetPoint);
}
}// Probably Triggered by EMF, reset the debounce
}
}

void IRAM_ATTR SS2K::shiftDown() { // Handle the shift down interrupt
if (ss2k.deBounce()){
if (!digitalRead(currentBoard.shiftDownPin)) { // double checking to make sure the interrupt wasn't triggered by emf
if(!rtConfig.getERGMode()) {
rtConfig.setShifterPosition(rtConfig.getShifterPosition() + 1 - userConfig.getShifterDir() * 2);
} else { // -> rtConfig.getERGMode()
int newSetPoint = rtConfig.getTargetWatts() -10;
if (newSetPoint < userConfig.getMinWatts()) {
newSetPoint = userConfig.getMinWatts();
}
rtConfig.setTargetWatts(newSetPoint);
}
}// Probably Triggered by EMF, reset the debounce
}
}

void SS2K::scanIfShiftersHeld() {
if ((digitalRead(currentBoard.shiftUpPin) == LOW) && (digitalRead(currentBoard.shiftDownPin) == LOW)) { // are both shifters held?
....
} else if(digitalRead(currentBoard.shiftDownPin) == LOW) { // left shifter held?
SS2K_LOG(MAIN_LOG_TAG, "Left shifter Held %d", shiftersHoldForScan);
if (shiftersHoldForScan < 2) { // have they been held for enough loops?
SS2K_LOG(MAIN_LOG_TAG, "Left shifter Held < 2 %d", shiftersHoldForScan);
if(!rtConfig.getERGMode()) { //In Simulation mode?
rtConfig.setShifterPosition(0);
SS2K_LOG(MAIN_LOG_TAG, "Decrease shifters to '0'");
} else { //No, must be in ERG mode
rtConfig.setTargetWatts(userConfig.getMinWatts());
SS2K_LOG(MAIN_LOG_TAG, "Decrease Watts to MinWatts");
}
shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN;
} else {
shiftersHoldForScan--;
}
} else {
shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN;
}
}

I posted this, so perhaps anyone can also benefit from this.

@doudar
Copy link
Owner

doudar commented Jan 5, 2023

Implemented in #420

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 5, 2023

Implemented in #420

That was quick! :)

There is a bug with the above solution for the ERG mode when switched off again. (I never use it, but it should work offcourse).
When ERG mode is turned off the min and max positions needs to be set to default again otherwise the shifters won't shift as far as they should.

In settings.h I added three lines:
// Default Min and Max step in Simulation mode. Will be recalculated in ERG mode.
#define DEFAULT_MIN_STEP -200000000
#define DEFAULT_MAX_STEP 200000000

In smartSpin_parameters.h I changed line 44 & 45 to:
int minStep = DEFAULT_MIN_STEP;
int maxStep = DEFAULT_MAX_STEP;

And the void in line 75 to:
void setSimulateTargetWatts(bool swt)
{
simulateTargetWatts = swt;
if (!swt)
{
minStep = DEFAULT_MIN_STEP; //reset minStep
maxStep = DEFAULT_MAX_STEP; //reset maxStep
targetIncline = 0; //reset targetIncline to avoid big stepper increase when switching from ERG to Simulation or Stand-alone mode
shifterPosition = 0; //not really necessary, but should give a fixed starting point when turning ERG mode off.
}
}

@doudar
Copy link
Owner

doudar commented Jan 5, 2023

Implemented in #420

That was quick! :)

There is a bug with the above solution for the ERG mode when switched off again. (I never use it, but it should work offcourse). When ERG mode is turned off the min and max positions needs to be set to default again otherwise the shifters won't shift as far as they should.

In settings.h I added three lines: // Default Min and Max step in Simulation mode. Will be recalculated in ERG mode. #define DEFAULT_MIN_STEP -200000000 #define DEFAULT_MAX_STEP 200000000

In smartSpin_parameters.h I changed line 44 & 45 to: int minStep = DEFAULT_MIN_STEP; int maxStep = DEFAULT_MAX_STEP;

And the void in line 75 to: void setSimulateTargetWatts(bool swt) { simulateTargetWatts = swt; if (!swt) { minStep = DEFAULT_MIN_STEP; //reset minStep maxStep = DEFAULT_MAX_STEP; //reset maxStep targetIncline = 0; //reset targetIncline to avoid big stepper increase when switching from ERG to Simulation or Stand-alone mode shifterPosition = 0; //not really necessary, but should give a fixed starting point when turning ERG mode off. } }

Here's how I've done it in #420

I don't like adding much to ISR's so I instead created a new function that is run in the maintenance loop which checks for shifts in the ISR and then applies them depending on what the current FTMS mode is. That way, customized shifting can be easily implemented in every FTMS mode. Also, if you read this code, I started a refactor on the rtConfig class which you might notice. Watts, Resistance, Cadence and Heartrate were added to "Measurements".

SmartSpin2k/src/Main.cpp

Lines 236 to 283 in fbc9ef9

void SS2K::FTMSModeShiftModifier() {
int shiftDelta = rtConfig.getShifterPosition() - ss2k.lastShifterPosition;
if (shiftDelta) {
switch (rtConfig.getFTMSMode()) {
case FitnessMachineControlPointProcedure::SetTargetPower:
rtConfig.setShifterPosition(ss2k.lastShifterPosition); // reset shifter position because we're remapping it to ERG target
if ((rtConfig.watts.getTarget() + (shiftDelta * ERG_PER_SHIFT) < userConfig.getMinWatts()) ||
(rtConfig.watts.getTarget() + (shiftDelta * ERG_PER_SHIFT) > userConfig.getMaxWatts())) {
SS2K_LOG(MAIN_LOG_TAG, "Shift to %dw blocked", rtConfig.watts.getTarget() + shiftDelta);
break;
}
rtConfig.watts.setTarget(rtConfig.watts.getTarget() + (ERG_PER_SHIFT * shiftDelta));
SS2K_LOG(MAIN_LOG_TAG, "ERG Shift. New Target: %dw", rtConfig.watts.getTarget());
break;
case FitnessMachineControlPointProcedure::SetTargetResistanceLevel:
if (rtConfig.getMaxResistance() != DEFAULT_RESISTANCE_RANGE) {
if ((rtConfig.resistance.getTarget() + shiftDelta < rtConfig.getMinResistance()) || (rtConfig.resistance.getTarget() + shiftDelta > rtConfig.getMaxResistance())) {
SS2K_LOG(MAIN_LOG_TAG, "Shift to %d blocked", rtConfig.resistance.getTarget() + shiftDelta);
break;
}
rtConfig.setShifterPosition(ss2k.lastShifterPosition); // reset shifter position because we're remapping it to resistance target
rtConfig.resistance.setTarget(rtConfig.resistance.getTarget() + shiftDelta);
SS2K_LOG(MAIN_LOG_TAG, "Resistance Shift. New Target: %d", rtConfig.resistance.getTarget());
break;
}
default:
SS2K_LOG(MAIN_LOG_TAG, "Shift %+d pos %d tgt %d min %d max %d r_min %d r_max %d", shiftDelta, rtConfig.getShifterPosition(), ss2k.targetPosition, rtConfig.getMinStep(),
rtConfig.getMaxStep(), rtConfig.getMinResistance(), rtConfig.getMaxResistance());
if ((ss2k.targetPosition > rtConfig.getMaxStep()) || (rtConfig.resistance.getTarget() > rtConfig.getMaxResistance()) || (ss2k.targetPosition < rtConfig.getMinStep()) ||
(rtConfig.resistance.getTarget() < rtConfig.getMinResistance())) {
SS2K_LOG(MAIN_LOG_TAG, "Shift Blocked by limits.");
rtConfig.setShifterPosition(ss2k.lastShifterPosition);
spinBLEServer.notifyShift();
}
}
ss2k.lastShifterPosition = rtConfig.getShifterPosition();
}
}

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 8, 2023

Nice :)
I flashed the resistance branch to my setup and it took me a while to get it working. Seemed like my Wi-Fi passphrase was too long and I ended up with no free space left in the filesystem. After I increased that it worked like a charm. :)

There is a bug with the above solution for the ERG mode when switched off again. (I never use it, but it should work offcourse).
When ERG mode is turned off the min and max positions needs to be set to default again otherwise the shifters won't shift as far as they should.

Still, when switching from ERG to simulation mode the min and max stepperpositions needs to be set wide again (because ERG mode limited these points). This is also the case when you turn off ERG mode in RGT.

I like the webinterface (SimTargetWatts) to overrule the incline data when connected to RGT so I made some changes to BLE_Server.cpp to get that working again. Because of the use of FTMSMode a little more lines were needed than my solution above.

I also added the else back in the scanIfShiftersHeld to switch to '0' if the left shifter is held.

@doudar
Copy link
Owner

doudar commented Jan 8, 2023

Nice :) I flashed the resistance branch to my setup and it took me a while to get it working. Seemed like my Wi-Fi passphrase was too long and I ended up with no free space left in the filesystem. After I increased that it worked like a charm. :)

Did you increase

#define USERCONFIG_JSON_SIZE 1024 + DEBUG_LOG_BUFFER_SIZE
or something else?

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 10, 2023

I tried that first, but made no difference.
It seemed that Config.txt could not be written due to lack of free space. When I entered less password characters it wrote the file without error.
So I ended up making a custom_partition.csv and expanding the filesystem partition by leaving out the coredump.
Perhaps not the nicest way, but it worked.

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 10, 2023

I also noticed that the BLE tries to reconnect from Main while I have a pm connected and hr set to "none"
Should the 'ifs' in checkBLEReconnect() be something like this:
if (((strcmp(userConfig.getConnectedHeartMonitor(), "none") == 0) && (spinBLEClient.connectedPM))) { // Exit if "none" PM and HR is connected
bleCheck = 0;
return;
}
Because of the const char compare?

@doudar
Copy link
Owner

doudar commented Jan 10, 2023

yes, they need to be cast to string type. It's been fixed in FTMS-resistance. I hope to merge this branch into develop soon

SmartSpin2k/src/Main.cpp

Lines 560 to 577 in eaa165a

void SS2K::checkBLEReconnect() {
static int bleCheck = 0;
if ((String(userConfig.getConnectedPowerMeter()) == "none") && ((String(userConfig.getConnectedPowerMeter()) == "none"))) { // Exit immediately if "none" and "none"
bleCheck = 0;
return;
}
if ((spinBLEClient.connectedHR) && (spinBLEClient.connectedPM)) { // Exit if both are connected
bleCheck = 0;
return;
}
if (((String(userConfig.getConnectedPowerMeter()) == "none") && (spinBLEClient.connectedHR))) { // Exit if "none" PM and HR is connected
bleCheck = 0;
return;
}
if (((String(userConfig.getConnectedPowerMeter()) == "none") && (spinBLEClient.connectedPM))) { // Exit if "none" HR and PM is connected
bleCheck = 0;
return;
}

@doudar
Copy link
Owner

doudar commented Jan 10, 2023

I tried that first, but made no difference. It seemed that Config.txt could not be written due to lack of free space. When I entered less password characters it wrote the file without error. So I ended up making a custom_partition.csv and expanding the filesystem partition by leaving out the coredump. Perhaps not the nicest way, but it worked.

What would really help here (freeing up file space) is getting rid of hosting jquery, which we're only using for OTA firmware updates. I see there's this library/example without jQuery which I might try to adapt after FTMS-resistance is merged.

https://github.com/pangodream/ESP2SOTA

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 10, 2023

yes, they need to be cast to string type. It's been fixed in FTMS-resistance. I hope to merge this branch into develop soon

I see now you already fixed this 2 days ago :)
When it's merged I'll flash back to develop and give it a go!
I think we can close this one now.

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 10, 2023

On the other hand maybe we can't close it yet.
I discovered that I can switch 1 step back when I'm already at minResistance and one step up when already at maxResistance.
And then the stepper slowly steps back to the correct target and keeps repeating over and over because the shifterposition is still to low or to high.
I changed < and > to <= and >= in line 273 and 274 below so it doesn't switch when it is already on min or max resistance.
if ((ss2k.targetPosition > rtConfig.getMaxStep()) || (rtConfig.resistance.getValue() >= rtConfig.getMaxResistance()) || (ss2k.targetPosition < rtConfig.getMinStep()) || (rtConfig.resistance.getValue() <= rtConfig.getMinResistance())) {

SmartSpin2k/src/Main.cpp

Lines 273 to 279 in eaa165a

if ((ss2k.targetPosition > rtConfig.getMaxStep()) || (rtConfig.resistance.getValue() > rtConfig.getMaxResistance()) || (ss2k.targetPosition < rtConfig.getMinStep()) ||
(rtConfig.resistance.getValue() < rtConfig.getMinResistance())) {
SS2K_LOG(MAIN_LOG_TAG, "Shift Blocked by limits.");
rtConfig.setShifterPosition(ss2k.lastShifterPosition);
spinBLEServer.notifyShift();
}

@doudar
Copy link
Owner

doudar commented Jan 10, 2023

Whoa! Resistance numbers? That's experimental in this branch - what bike are you using that you're getting resistance feedback? I could really use another tester if you have a bike with resistance feedback! (Especially an Echelon)

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 11, 2023

No sorry, I don't have an Echelon bike.
I made my own setup a few years ago with a simple spinningbike, stepper and nextion display. I mounted a FSR under the felt pad to measure the resistance. I mainly use this when zeroing the stepper at startup and from that point it was just a matter of counting steps and stop at max resistance. I only had the incline from RGT and Zwift working in simulation mode.

I like the ERG mode you implemented, that's why I ported your software to my setup and since it now has resistance too, I thought I'll give it a go.
If I switch fast enough (and keep the stepper spinning) I can still switch beyond the limits because the resistance hasn't changed enough yet for the shifts to be blocked. It obviously did not reach its destination yet (That's why the stepper is still spinning offcourse).
But I don't know if that's normal behaviour for a resistance bike or that it's just my setup.
I use the nextion for displaying the parameters like power, heartrate and cadence and to switch some settings like ERG mode or turn the fan on or off. And offcourse this way I get all the parameters directly on my bike too in stand-alone mode.

@doudar
Copy link
Owner

doudar commented Jan 11, 2023

Awesome! That sounds pretty cool!
Your setup is spot on - that's an exact duplicate of the last remaining bug (so far) that we've found in testing with the Peloton.

The delay is why we have the Peloton resistance limits at 5&98. The actual bike is 0 and 100 but there needs to be a buffer for overshoot.

@doudar
Copy link
Owner

doudar commented Jan 11, 2023

Here's a new binary (with @Flo100 's oscillation fix) for anyone else that might be watching this thread. Unzip and make sure it's named exactly firmware.bin then use the web interface admin/admin.
firmware.zip
Also, as a reminder, some of the HTML files have also changed in this release so if you manually update, you will have to update those from the FTMS_resistance branch individually as well. You'll find them in the data folder. https://github.com/doudar/SmartSpin2k/tree/FTMS_Resistance/data

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 12, 2023

Awesome! That sounds pretty cool! Your setup is spot on - that's an exact duplicate of the last remaining bug (so far) that we've found in testing with the Peloton.

The delay is why we have the Peloton resistance limits at 5&98. The actual bike is 0 and 100 but there needs to be a buffer for overshoot.

Before I had BLE working I wanted some sort of reproducable resistance level with each workout and that's why I mounted the FSR. After that I used to find the zero point at startup, reset the stepper to zero and use this as stepper minimum. My FSR gets saturated over time because there is more force on the felt pad than expected and I actually need another type. But I counted the steps to maxResistance once and used that as upper limit.

You could probably do something like that too. Find the zero point at startup and after that use minStep() as boundary.
You can also find the maxStep this way, only it takes some time, so perhaps implement a calibration setting in config which stores maxStep?
If you reset the stepper (stepper->clearPulseCounter()) at the found zero point minStep will be 0 and you only have to store the number of steps until maxResistance (maxStep).
Offcourse this interferes with ERG mode... so minStep and maxStep needs to be initialized after switching modes or perhaps add minResistanceStep and maxResistanceStep?

@doudar doudar added the enhancement New feature or request label Jan 14, 2023
@doudar
Copy link
Owner

doudar commented Mar 8, 2023

Merged into develop for testing.

@doudar
Copy link
Owner

doudar commented Dec 18, 2023

Fixed

@doudar doudar closed this as completed Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants