Skip to content

Commit

Permalink
Merge pull request #558 from doudar/Big_Table_2
Browse files Browse the repository at this point in the history
Big table 2
  • Loading branch information
doudar authored Jul 28, 2024
2 parents 1b61d60 + 65a0045 commit 399c805
Show file tree
Hide file tree
Showing 18 changed files with 1,116 additions and 385 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"string_view": "cpp",
"set": "cpp",
"iostream": "cpp",
"*.dontuse": "cpp"
"*.dontuse": "cpp",
"core": "cpp"
},
"cSpell.words": [
"Appender",
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refactored BLE_Server into separate files for each BLE Service.
- Fixed bug in CPS service for Wahoo app (and probably others).
- Depreciated the SPIFFS->LittleFS upgrader.
- Increased ERG mode sensitivity.


### Hardware
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"board": {
"active_layer": 36,
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_nets": [],
Expand Down
6 changes: 4 additions & 2 deletions include/BLE_Custom_Characteristic.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ const uint8_t BLE_maxBrakeWatts = 0x22; // "" Maximum watts for the oth
const uint8_t BLE_restartBLE = 0x23; // Closes all connections to the BLE client - used to connect new BLE devices the user selects.
const uint8_t BLE_scanBLE = 0x24; // Scan for new BLE devices
const uint8_t BLE_firmwareVer = 0x25; // String of the current firmware version
const uint8_t BLE_resetPowerTable = 0x26; // Delete all power table information.
const uint8_t BLE_powerTableData = 0x27; // sets or requests power table data

class BLE_ss2kCustomCharacteristic {
public:
Expand All @@ -62,8 +64,8 @@ class BLE_ss2kCustomCharacteristic {
// Used internally for notify and onWrite Callback.
static void process(std::string rxValue);
// Custom Characteristic value that needs to be notified
static void notify(char _item);
// Notify any changed value in userConfig
static void notify(char _item, int tableRow = -1);
// Notify any changed value in userConfig
static void parseNemit();

private:
Expand Down
4 changes: 2 additions & 2 deletions include/BLE_Definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

#pragma once

//The .xml file is wrong, make sure to reference the actual FTMS .pdf
struct FitnessMachineIndoorBikeDataFlags {
enum Types : uint16_t {
MoreDataBit = 1U << 0,
AverageSpeedPresent = 1U << 1,
InstantaneousCadencePresent = 1U << 2,
InstantaneousCadencePresent = 1U << 2,
AverageCadencePresent = 1U << 3,
TotalDistancePresent = 1U << 4,
ResistanceLevelPresent = 1U << 5,
Expand All @@ -22,7 +23,6 @@ struct FitnessMachineIndoorBikeDataFlags {
MetabolicEquivalentPresent = 1U << 10,
ElapsedTimePresent = 1U << 11,
RemainingTimePresent = 1U << 12

};
};

Expand Down
28 changes: 28 additions & 0 deletions include/BLE_Device_Information_Service.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2020 Anthony Doud & Joel Baranick
* All rights reserved
*
* SPDX-License-Identifier: GPL-2.0-only
*/

#pragma once

#include <NimBLEDevice.h>
#include "BLE_Common.h"

class BLE_Device_Information_Service {
public:
BLE_Device_Information_Service();
void setupService(NimBLEServer* pServer);

private:
NimBLEService* pDeviceInformationService;
NimBLECharacteristic* pManufacturerNameCharacteristic;
NimBLECharacteristic* pModelNumberCharacteristic;
NimBLECharacteristic* pSerialNumberCharacteristic;
NimBLECharacteristic* pHardwareRevisionCharacteristic;
NimBLECharacteristic* pFirmwareRevisionCharacteristic;
NimBLECharacteristic* pSoftwareRevisionCharacteristic;
NimBLECharacteristic* pSystemIDCharacteristic;
NimBLECharacteristic* pPnPIDCharacteristic;
};
113 changes: 84 additions & 29 deletions include/ERG_Mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,76 +12,130 @@

#define ERG_MODE_LOG_TAG "ERG_Mode"
#define ERG_MODE_LOG_CSV_TAG "ERG_Mode_CSV"
#define TORQUETABLE_LOG_TAG "TTable"
#define POWERTABLE_LOG_TAG "PTable"
#define ERG_MODE_DELAY 700
#define RETURN_ERROR -99
#define TORQUE_CONSTANT 9.5488
#define CAD_MULTIPLIER 2.7
#define RETURN_ERROR INT16_MIN

extern TaskHandle_t ErgTask;
void setupERG();
void ergTaskLoop(void* pvParameters);

int _torqueToWatts(float torque, float cad);
float _wattsToTorque(int watts, float cad);

class TorqueEntry {
class PowerEntry {
public:
float torque;
int32_t targetPosition;
int watts;
int targetPosition;
int cad;
int readings;

TorqueEntry() {
this->torque = 0;
PowerEntry() {
this->watts = 0;
this->targetPosition = 0;
this->cad = 0;
this->readings = 0;
}
};

class TorqueBuffer {
class PowerBuffer {
public:
TorqueEntry torqueEntry[TORQUE_SAMPLES];
PowerEntry powerEntry[POWER_SAMPLES];
void set(int);
void reset();
int getReadings();
};

class TorqueTable {
// Simplifying the table to save memory since we no longer need watts and cad.
class TableEntry {
public:
int16_t targetPosition;
int8_t readings;
TableEntry() {
this->targetPosition = INT16_MIN;
this->readings = 0;
}
};

// Combine Entries to make a row.
class TableRow {
public:
TableEntry tableEntry[POWERTABLE_WATT_SIZE];
};

class TestResults {
struct Neighbor {
unsigned int found : 1;
unsigned int passedTest : 1;
int8_t i;
int8_t j;
int16_t targetPosition;

Neighbor() {
found = false;
passedTest = false;
i = INT8_MIN;
j = INT8_MIN;
targetPosition = INT16_MIN;
}
};

public:
Neighbor leftNeighbor;
Neighbor rightNeighbor;
Neighbor topNeighbor;
Neighbor bottomNeighbor;
unsigned int allNeighborsFound : 1;
unsigned int allNeighborsPassed : 1;

TestResults() {
allNeighborsFound = false;
allNeighborsPassed = false;
}
};

class PowerTable {
public:
TorqueEntry torqueEntry[TORQUETABLE_SIZE];
TableRow tableRow[POWERTABLE_CAD_SIZE];

// Pick up new torque value and put them into the torque table
void processTorqueValue(TorqueBuffer& torqueBuffer, int cadence, Measurement torque);
// Pick up new power value and put them into the power table
void processPowerValue(PowerBuffer& powerBuffer, int cadence, Measurement power);

// Sets stepper min/max value from torque table
// Sets stepper min/max value from power table
void setStepperMinMax();

// Catalogs a new entry into the torque table.
void newEntry(TorqueBuffer& torqueBuffer);
// Catalogs a new entry into the power table.
void newEntry(PowerBuffer& powerBuffer);

// returns incline for wattTarget. Null if not found.
int32_t lookup(int watts, int cad);

// automatically load or save the Torque Table
// automatically load or save the Power Table
bool _manageSaveState();

// save torquetable from littlefs
// save powertable from littlefs
bool _save();

//return number of entries in the table.
int getEntries();
// Reset the active power table and delete the saved power table.
bool reset();

// Display torque table in log
// return number of readings in the table.
int getNumReadings();

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

private:
unsigned long lastSaveTime = millis();
unsigned long lastSaveTime = millis();
bool _hasBeenLoadedThisSession = false;
TestResults testNeighbors(int i, int j, int value);
void fillTable();
void extrapFillTable();
void extrapolateDiagonal();
int getNumEntries();
// remove entries with < 1 readings
void clean();
};

class ErgMode {
public:
ErgMode(TorqueTable* torqueTable) { this->torqueTable = torqueTable; }
void computeErg();
void computeResistance();
void _writeLogHeader();
Expand All @@ -96,7 +150,6 @@ class ErgMode {
int cadence = 0;

Measurement watts;
TorqueTable* torqueTable;

// check if user is spinning, reset incline if user stops spinning
bool _userIsSpinning(int cadence, float incline);
Expand All @@ -110,3 +163,5 @@ class ErgMode {
// update localvalues + incline, creates a log
void _updateValues(int newCadence, Measurement& newWatts, float newIncline);
};

extern PowerTable* powerTable;
9 changes: 5 additions & 4 deletions include/Main.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ class SS2K {
bool externalControl;
bool syncMode;
int txCheck;
bool rebootFlag = false;
bool saveFlag = false;
bool resetDefaultsFlag = false;
bool isUpdating = false;
bool rebootFlag = false;
bool saveFlag = false;
bool resetDefaultsFlag = false;
bool resetPowerTableFlag = false;
bool isUpdating = false;

bool IRAM_ATTR deBounce();
static void IRAM_ATTR moveStepper(void *pvParameters);
Expand Down
49 changes: 31 additions & 18 deletions include/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const char * const DEFAULT_PASSWORD = "password";
#define userPWCFILENAME "/userPWC.txt"

// name of the local file to save the torque table.
#define TORQUE_TABLE_FILENAME "/TorqueTable.txt"
#define POWER_TABLE_FILENAME "/PowerTable.txt"

// Default Incline Multiplier.
// Incline multiplier is the multiple required to convert incline received from the remote client (percent grade*100)
Expand Down Expand Up @@ -117,7 +117,7 @@ const char * const DEFAULT_PASSWORD = "password";
#define DEFAULT_RESISTANCE_RANGE 2000

// Default +- Stepper Travel Limit
// This is used until the TorqueTable has enough data to compute travel limits
// This is used until the PowerTable has enough data to compute travel limits
#define DEFAULT_STEPPER_TRAVEL 200000000

// Default debounce delay for shifters. Increase if you have false shifts. Decrease if shifting takes too long.
Expand Down Expand Up @@ -253,29 +253,42 @@ const char * const DEFAULT_PASSWORD = "password";

#define RUNTIMECONFIG_JSON_SIZE 512 + DEBUG_LOG_BUFFER_SIZE

/* Number of entries in the ERG Torque Lookup Table
// PowerTable Version
#define TABLE_VERSION 4

/* Number of entries in the ERG Power Lookup Table
This is currently maintained as to keep memory usage lower and reduce the print output of the table.
It can be depreciated in the future should we decide to remove logging of the torque table. Then it should be calculated in ERG_Mode.cpp
by dividing userConfig->getMaxWatts() by TORQUETABLE_INCREMENT. */
#define TORQUETABLE_SIZE 20
by dividing userConfig->getMaxWatts() by POWERTABLE_INCREMENT. */
#define POWERTABLE_WATT_SIZE 40

// Size of the second dimension of the table. The base (starting point) is calculated off of MINUMUM_TABLE_CAD
#define POWERTABLE_CAD_SIZE 10

// Size of increments (in Nm) for the ERG Lookup Table. Needs to be one decimal place for proper calculations
#define TORQUETABLE_INCREMENT 5.31
// Size of increments (in watts) for the ERG Lookup Table. This needs to be a decimal for proper calculation.
#define POWERTABLE_WATT_INCREMENT 30

// Number of similar torque samples to take before writing to the Torque Table
#define TORQUE_SAMPLES 5
// Size of increments (in CAD) for the ERG Lookup Table. This needs to be a decimal for proper calculation.
#define POWERTABLE_CAD_INCREMENT 5

// The Array position of the most reliable Torque Table stepper position according to testing data.
#define MOST_DEPENDABLE_TORQUE_ENTRY 2
// Number of similar power samples to take before writing to the Power Table
#define POWER_SAMPLES 5

// How often in ms to save the torque table if no new data is added and user is pedaling.
#define TORQUE_TABLE_SAVE_INTERVAL 240000
// How often in ms to save the power table if no new data is added and user is pedaling.
#define POWER_TABLE_SAVE_INTERVAL 240000

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

// Where does the CAD portion of the table start?
#define MINIMUM_TABLE_CAD 60

//Minimum positions recorded in the active table before attempting to load the saved table.
//Increase this value if the offset for the loaded table is inaccurate.
#define MINIMUM_RELIABLE_POSITIONS 3

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

// Size of the Aux Serial Buffer for Peloton
#define AUX_BUF_SIZE 10
Expand All @@ -300,11 +313,11 @@ const char * const DEFAULT_PASSWORD = "password";

//Task Stack Sizes
#define MAIN_STACK 4500
#define ERG_STACK 6500
#define ERG_STACK 6000
#define HTTP_STACK 6000
#define BLE_COMM_STACK 6000
#define BLE_CLIENT_STACK 5000
#define STEPPER_STACK 1700
#define BLE_CLIENT_STACK 5500
#define STEPPER_STACK 2000

// Uncomment to enable stack size debugging info
// #define DEBUG_STACK
Expand Down
10 changes: 9 additions & 1 deletion lib/SS2K/include/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@
#define FIRMWARE_CHARACTERISTIC_OTA_UUID NimBLEUUID("62ec0272-3ec5-11eb-b378-0242ac130005")

// Device Information Service
#define DEVICEINFORMATIONSERVICE_UUID NimBLEUUID((uint16_t)0x180A)
#define DEVICE_INFORMATION_SERVICE_UUID NimBLEUUID((uint16_t)0x180A)
#define MANUFACTURER_NAME_UUID NimBLEUUID((uint16_t)0x2A29)
#define MODEL_NUMBER_UUID NimBLEUUID((uint16_t)0x2A24)
#define SERIAL_NUMBER_UUID NimBLEUUID((uint16_t)0x2A25)
#define HARDWARE_REVISION_UUID NimBLEUUID((uint16_t)0x2A27)
#define FIRMWARE_REVISION_UUID NimBLEUUID((uint16_t)0x2A26)
#define SOFTWARE_REVISION_UUID NimBLEUUID((uint16_t)0x2A28)
#define SYSTEM_ID_UUID NimBLEUUID((uint16_t)0x2A23)
#define PNP_ID_UUID NimBLEUUID((uint16_t)0x2A50)

// Heart Service
#define HEARTSERVICE_UUID NimBLEUUID((uint16_t)0x180D)
Expand Down
Loading

0 comments on commit 399c805

Please sign in to comment.