From 5c8640327b89e2ac135c577f765c5eee9b0e7728 Mon Sep 17 00:00:00 2001 From: Markus Schneider Date: Sat, 4 Dec 2021 11:00:31 +0100 Subject: [PATCH 01/42] Moved ERG to seperate task --- include/BLE_Common.h | 2 +- include/ERG_Mode.h | 16 +++++++ include/SmartSpin_parameters.h | 3 ++ src/BLE_Common.cpp | 2 +- src/BLE_Server.cpp | 70 +++------------------------- src/ERG_Mode.cpp | 84 ++++++++++++++++++++++++++++++++++ src/Main.cpp | 3 ++ 7 files changed, 115 insertions(+), 65 deletions(-) create mode 100644 include/ERG_Mode.h create mode 100644 src/ERG_Mode.cpp diff --git a/include/BLE_Common.h b/include/BLE_Common.h index c3f34290..c6d93149 100644 --- a/include/BLE_Common.h +++ b/include/BLE_Common.h @@ -77,7 +77,7 @@ extern SpinBLEServer spinBLEServer; void startBLEServer(); bool spinDown(); -void computeERG(int = 0); +// void computeERG(int = 0); void computeCSC(); void logCharacteristic(char *buffer, const size_t bufferCapacity, const byte *data, const size_t dataLength, const NimBLEUUID serviceUUID, const NimBLEUUID charUUID, const char *format, ...); diff --git a/include/ERG_Mode.h b/include/ERG_Mode.h new file mode 100644 index 00000000..b304a0de --- /dev/null +++ b/include/ERG_Mode.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#define ERG_MODE_LOG_TAG "ERG_Mode" +#define ERG_MODE_DELAY 1000 + +class ErgMode { + public: + static void setupERG(); + + private: + static TaskHandle_t _ergTask; + static void loop(void *pvParameters); + static void computErg(int newSetpoint); +}; \ No newline at end of file diff --git a/include/SmartSpin_parameters.h b/include/SmartSpin_parameters.h index a770bf35..433e5909 100644 --- a/include/SmartSpin_parameters.h +++ b/include/SmartSpin_parameters.h @@ -15,6 +15,7 @@ class userParameters { private: String firmwareUpdateURL; float incline; + int targetWatts; int simulatedWatts; int simulatedHr; int simulatedCad; @@ -41,6 +42,7 @@ class userParameters { public: const char* getFirmwareUpdateURL() { return firmwareUpdateURL.c_str(); } float getIncline() { return incline; } + int getTargetWatts() { return targetWatts; } int getSimulatedWatts() { return simulatedWatts; } int getSimulatedHr() { return simulatedHr; } int getSimulatedCad() { return simulatedCad; } @@ -67,6 +69,7 @@ class userParameters { void setDefaults(); void setFirmwareUpdateURL(String fURL) { firmwareUpdateURL = fURL; } void setIncline(float inc) { incline = inc; } + void setTargetWatts(int w) { targetWatts = w; } void setSimulatedWatts(int w) { simulatedWatts = w; } void setSimulatedHr(int hr) { simulatedHr = hr; } void setSimulatedCad(float cad) { simulatedCad = cad; } diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index 164f8020..e7bac585 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -142,7 +142,7 @@ void BLECommunications(void *pvParameters) { } processFTMSWrite(); - computeERG(); + // computeERG(); if (updateConnParametersFlag) { vTaskDelay(100 / portTICK_PERIOD_MS); diff --git a/src/BLE_Server.cpp b/src/BLE_Server.cpp index 3f454f6f..6b79bc94 100644 --- a/src/BLE_Server.cpp +++ b/src/BLE_Server.cpp @@ -206,62 +206,6 @@ bool spinDown() { return true; } -// as a note, Trainer Road sends 50w target whenever the app is connected. -void computeERG(int newSetPoint) { - // SS2K_LOG(BLE_SERVER_LOG_TAG, "ComputeERG. Setpoint: %d", newSetPoint); - if (userConfig.getERGMode() && spinBLEClient.connectedPM) { - // continue - } else { - // SS2K_LOG(BLE_SERVER_LOG_TAG, "ERG request but ERG off or no connected PM"); - return; - } - static bool userIsPedaling = true; - static int setPoint = 0; - float incline = userConfig.getIncline(); - float newIncline = incline; - int amountToChangeIncline = 0; - int wattChange = userConfig.getSimulatedWatts() - setPoint; - - if (newSetPoint > 0) { // only update the value if new value is sent - setPoint = newSetPoint; - } - if (setPoint < 50) { // minumum setPoint - setPoint = 50; - } - - if (userConfig.getSimulatedCad() <= 20) { - if (!userIsPedaling) { // Test so motor stop command only happens once. - motorStop(); // release tension - return; - } - userIsPedaling = false; - userConfig.setIncline(incline-userConfig.getShiftStep()*2); - // Cadence too low, nothing to do here - return; - } - userIsPedaling = true; - - amountToChangeIncline = wattChange * userConfig.getERGSensitivity(); - if (abs(wattChange) < WATTS_PER_SHIFT) { - // As the desired value gets closer, make smaller changes for a smoother experience - amountToChangeIncline *= SUB_SHIFT_SCALE; - } - // limit to 10 shifts at a time - if (abs(amountToChangeIncline) > userConfig.getShiftStep() * 2) { - if (amountToChangeIncline > 5) { - amountToChangeIncline = userConfig.getShiftStep() * 2; - } - if (amountToChangeIncline < -5) { - amountToChangeIncline = -(userConfig.getShiftStep() * 2); - } - } - - // Reduce the amount per loop (don't try to oneshot it) and scale the movement the higher the watt target is as higher wattages require less knob movement. - // amountToChangeIncline = amountToChangeIncline / ((userConfig.getSimulatedWatts() / 100) + .1); // +.1 to eliminate possible divide by zero. - newIncline = incline - amountToChangeIncline; - userConfig.setIncline(newIncline); - // SS2K_LOG(BLE_SERVER_LOG_TAG, "newincline: %f", newIncline); -} void updateIndoorBikeDataChar() { float cadRaw = userConfig.getSimulatedCad(); @@ -321,7 +265,7 @@ void updateCyclingPowerMeasurementChar() { remainder = spinBLEClient.cscLastCrankEvtTime % 256; cyclingPowerMeasurement[7] = remainder; cyclingPowerMeasurement[8] = quotient; - } + } cyclingPowerMeasurementCharacteristic->notify(); @@ -366,9 +310,7 @@ void MyServerCallbacks::onDisconnect(BLEServer *pServer) { BLEDevice::startAdvertising(); } -void MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { - FTMSWrite = pCharacteristic->getValue(); - } +void MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { FTMSWrite = pCharacteristic->getValue(); } void processFTMSWrite() { if (FTMSWrite == "") { @@ -394,7 +336,7 @@ void processFTMSWrite() { case 0x00: // request control logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> Control Request"); returnValue[2] = 0x01; - //userConfig.setERGMode(false); + // userConfig.setERGMode(false); pCharacteristic->setValue(returnValue, 3); ftmsTrainingStatus[1] = 0x01; fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2); @@ -435,7 +377,9 @@ void processFTMSWrite() { if (spinBLEClient.connectedPM || userConfig.getSimulateWatts()) { int targetWatts = bytes_to_u16(rxValue[2], rxValue[1]); userConfig.setERGMode(true); - computeERG(targetWatts); + userConfig.setTargetWatts(targetWatts); + + // computeERG(targetWatts); logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, "-> ERG Mode Target: %d Current: %d Incline: %2f", targetWatts, userConfig.getSimulatedWatts(), userConfig.getIncline() / 100); returnValue[2] = 0x01; @@ -501,7 +445,7 @@ void processFTMSWrite() { SS2K_LOG(BLE_SERVER_LOG_TAG, "App wrote nothing "); SS2K_LOG(BLE_SERVER_LOG_TAG, "assuming it's a Control request"); uint8_t controlPoint[3] = {0x80, 0x00, 0x01}; - //userConfig.setERGMode(true); + // userConfig.setERGMode(true); pCharacteristic->setValue(controlPoint, 3); ftmsTrainingStatus[1] = 0x01; fitnessMachineTrainingStatus->setValue(ftmsTrainingStatus, 2); diff --git a/src/ERG_Mode.cpp b/src/ERG_Mode.cpp new file mode 100644 index 00000000..eca9a4b3 --- /dev/null +++ b/src/ERG_Mode.cpp @@ -0,0 +1,84 @@ +#include "ERG_Mode.h" +#include "SS2KLog.h" +#include "Main.h" + +TaskHandle_t ErgMode::_ergTask; + +void ErgMode::setupERG() { + SS2K_LOG(ERG_MODE_LOG_TAG, "Starting ERG Mode task..."); + xTaskCreatePinnedToCore(loop, /* Task function. */ + "ERGModeTask", /* name of task. */ + 1800, /* Stack size of task*/ + NULL, /* parameter of the task */ + 1, /* priority of the task*/ + &_ergTask, /* Task handle to keep track of created task */ + 1); /* pin task to core 0 */ + + SS2K_LOG(ERG_MODE_LOG_TAG, "ERG Mode task started"); +} + +void ErgMode::loop(void *pvParameters) { + vTaskDelay(ERG_MODE_DELAY / portTICK_PERIOD_MS); + + // int newSetPoint = userConfig.getTargetWatts(); + // bool isInErgMode = userConfig.getERGMode(); + // bool hasConnectedPowerMeter = spinBLEClient.connectedPM; + + // if (isInErgMode && hasConnectedPowerMeter) { + // SS2K_LOG(ERG_MODE_LOG_TAG, "ComputeERG. Setpoint: %d", newSetPoint); + // ErgMode::computErg(newSetPoint); + // } else { + // SS2K_LOG(ERG_MODE_LOG_TAG, "ERG request but ERG off or no connected PM"); + // } +} + +// as a note, Trainer Road sends 50w target whenever the app is connected. +void ErgMode::computErg(int newSetPoint) { + static bool userIsPedaling = true; + static int setPoint = 0; + float incline = userConfig.getIncline(); + float newIncline = incline; + int amountToChangeIncline = 0; + int wattChange = userConfig.getSimulatedWatts() - setPoint; + int cadance = userConfig.getSimulatedCad(); + + if (newSetPoint > 0) { // only update the value if new value is sent + setPoint = newSetPoint; + } + if (setPoint < 50) { // minumum setPoint + setPoint = 50; + } + + if (cadance <= 20) { + if (!userIsPedaling) { // Test so motor stop command only happens once. + motorStop(); // release tension + return; + } + userIsPedaling = false; + userConfig.setIncline(incline - userConfig.getShiftStep() * 2); + // Cadence too low, nothing to do here + return; + } + userIsPedaling = true; + + amountToChangeIncline = wattChange * userConfig.getERGSensitivity() * (75.0 / (double)cadance); + if (abs(wattChange) < WATTS_PER_SHIFT) { + // As the desired value gets closer, make smaller changes for a smoother experience + amountToChangeIncline *= SUB_SHIFT_SCALE; + } + // limit to 10 shifts at a time + if (abs(amountToChangeIncline) > userConfig.getShiftStep() * 2) { + if (amountToChangeIncline > 5) { + amountToChangeIncline = userConfig.getShiftStep() * 2; + } + if (amountToChangeIncline < -5) { + amountToChangeIncline = -(userConfig.getShiftStep() * 2); + } + } + + // Reduce the amount per loop (don't try to oneshot it) and scale the movement the higher the watt target is as higher wattages require less knob movement. + // amountToChangeIncline = amountToChangeIncline / ((userConfig.getSimulatedWatts() / 100) + .1); // +.1 to eliminate possible divide by zero. + newIncline = incline - amountToChangeIncline; + userConfig.setIncline(newIncline); + SS2K_LOG(ERG_MODE_LOG_TAG, "newincline: %f", newIncline); +} diff --git a/src/Main.cpp b/src/Main.cpp index 6ee7ac90..302e4861 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -12,6 +12,7 @@ #include #include #include "FastAccelStepper.h" +#include "ERG_Mode.h" bool lastDir = true; // Stepper Last Direction @@ -109,6 +110,8 @@ void setup() { setupBLE(); startHttpServer(); + ErgMode::setupERG(); + resetIfShiftersHeld(); SS2K_LOG(MAIN_LOG_TAG, "Creating Shifter Interrupts"); // Setup Interrups so shifters work anytime From 6b35e295c9ae88e32ec311860c4170341407882f Mon Sep 17 00:00:00 2001 From: Markus Schneider Date: Sat, 4 Dec 2021 14:07:18 +0100 Subject: [PATCH 02/42] Added TargetWatts and ERG Mode simulation --- data/btsimulator.html | 123 +++++++++++++++++++++++++++------ include/ERG_Mode.h | 13 ++-- include/SmartSpin_parameters.h | 3 + include/settings.h | 2 +- src/ERG_Mode.cpp | 47 ++++++++----- src/HTTP_Server_Basic.cpp | 32 ++++++++- src/Main.cpp | 2 +- src/SmartSpin_parameters.cpp | 10 ++- 8 files changed, 179 insertions(+), 53 deletions(-) diff --git a/data/btsimulator.html b/data/btsimulator.html index 3d5a2933..34327707 100644 --- a/data/btsimulator.html +++ b/data/btsimulator.html @@ -23,44 +23,65 @@

BLE Device Simulator

Sim Heart Rate

-

Sim Power Output

-

Sim CAD Output

-

+ +

Trainer Simulator

+

Enable ERG

+

+ +

+

ERG Target Watts

+

+

+

+ +