From a33ac39d64159bf09ec08f0e3511a86cfefc8d49 Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 13 Oct 2022 23:00:04 -0500 Subject: [PATCH 01/17] working test --- include/Main.h | 1 + include/settings.h | 4 ++-- src/Main.cpp | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/include/Main.h b/include/Main.h index 10b01d06..1f4984e7 100644 --- a/include/Main.h +++ b/include/Main.h @@ -65,6 +65,7 @@ class SS2K { } }; +void auxSerialRX(); // Users Physical Working Capacity Calculation Parameters (heartrate to Power // calculation) extern physicalWorkingCapacity userPWC; diff --git a/include/settings.h b/include/settings.h index 90497a4c..e1d3ce09 100644 --- a/include/settings.h +++ b/include/settings.h @@ -153,10 +153,10 @@ #define r2_STEPPERSERIAL_TX 19 // TMC2209 SoftwareSerial receive pin -#define r2_AUX_SERIAL_RX 21 +#define r2_AUX_SERIAL_RX 22 // TMC2209 SoftwareSerial transmit pin -#define r2_AUX_SERIAL_TX 22 +#define r2_AUX_SERIAL_TX 21 //////////////////////////////////////////////////////// // TMC2208/TMC2224 HardwareSerial port diff --git a/src/Main.cpp b/src/Main.cpp index cac15a94..095079a6 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -16,9 +16,13 @@ #include "UdpAppender.h" #include "WebsocketAppender.h" -HardwareSerial stepperSerial(2); +// Stepper Motor Serial +HardwareSerial stepperSerial(1); TMC2208Stepper driver(&SERIAL_PORT, R_SENSE); // Hardware Serial +// Peloton Serial +HardwareSerial auxSerial(2); + FastAccelStepperEngine engine = FastAccelStepperEngine(); FastAccelStepper *stepper = NULL; // Setup a task so the stepper will run on a different core than the main code @@ -42,6 +46,11 @@ WebSocketAppender webSocketAppender; ///////////// BEGIN SETUP ///////////// #ifndef UNIT_TEST +void auxSerialRX(){ +String buf = auxSerial.readString(); +Serial.printf("rx: %s", buf); +} + void SS2K::startTasks() { SS2K_LOG(MAIN_LOG_TAG, "Start BLE + ERG Tasks"); if (BLECommunicationTask == NULL) { @@ -67,7 +76,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 { @@ -75,7 +84,18 @@ void setup() { } SS2K_LOG(MAIN_LOG_TAG, "Current Board Revision is: %s", currentBoard.name); + // initialize Stepper serial port + stepperSerial.begin(57600, SERIAL_8N2, currentBoard.stepperSerialRxPin, currentBoard.stepperSerialTxPin); + // initialize aux serial port + auxSerial.setTxBufferSize(500); + auxSerial.setRxBufferSize(500); + //I had to set the last setting to true below to invert the logic for testing because all I have are USB-TTL devices. + auxSerial.begin(1200, SERIAL_8N1, currentBoard.auxSerialRxPin, currentBoard.auxSerialTxPin, true); + if(!auxSerial){ + SS2K_LOG(MAIN_LOG_TAG, "Invalid Serial Pin Configuration"); + } + //auxSerial.onReceive(auxSerialRX, true); // Initialize LittleFS SS2K_LOG(MAIN_LOG_TAG, "Mounting Filesystem"); @@ -213,6 +233,17 @@ void SS2K::maintenanceLoop(void *pvParameters) { #endif // DEBUG_STACK loopCounter = 0; } + // read from auxSerial + //if (auxSerial.available()) { + //String buf = auxSerial.readStringUntil('\n'); + //echo + //SS2K_LOG(MAIN_LOG_TAG, "aux_serial: %s", buf); + // auxSerial.write(buf.c_str()); + //auxSerial.println(auxSerial.onReceive); + //} + auxSerial.print("Peloton Works!"); + Serial.println(auxSerial.readString()); + loopCounter++; } } From 056b7e018c5f07087ded8e22d7663b161c2a767a Mon Sep 17 00:00:00 2001 From: doudar Date: Sun, 16 Oct 2022 22:22:42 -0500 Subject: [PATCH 02/17] cleared up echo back --- src/Main.cpp | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/Main.cpp b/src/Main.cpp index 095079a6..f8cc4ae7 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -46,9 +46,9 @@ WebSocketAppender webSocketAppender; ///////////// BEGIN SETUP ///////////// #ifndef UNIT_TEST -void auxSerialRX(){ -String buf = auxSerial.readString(); -Serial.printf("rx: %s", buf); +void auxSerialRX() { + String buf = auxSerial.readString(); + Serial.printf("rx: %s", buf); } void SS2K::startTasks() { @@ -88,15 +88,15 @@ void setup() { stepperSerial.begin(57600, SERIAL_8N2, currentBoard.stepperSerialRxPin, currentBoard.stepperSerialTxPin); // initialize aux serial port - auxSerial.setTxBufferSize(500); - auxSerial.setRxBufferSize(500); - //I had to set the last setting to true below to invert the logic for testing because all I have are USB-TTL devices. - auxSerial.begin(1200, SERIAL_8N1, currentBoard.auxSerialRxPin, currentBoard.auxSerialTxPin, true); - if(!auxSerial){ - SS2K_LOG(MAIN_LOG_TAG, "Invalid Serial Pin Configuration"); + if (currentBoard.auxSerialTxPin) { + auxSerial.setTxBufferSize(500); + auxSerial.setRxBufferSize(500); + auxSerial.begin(1200, SERIAL_8N1, currentBoard.auxSerialRxPin, currentBoard.auxSerialTxPin, false); + if (!auxSerial) { + SS2K_LOG(MAIN_LOG_TAG, "Invalid Serial Pin Configuration"); + } + // auxSerial.onReceive(auxSerialRX, true); } - //auxSerial.onReceive(auxSerialRX, true); - // Initialize LittleFS SS2K_LOG(MAIN_LOG_TAG, "Mounting Filesystem"); if (!LittleFS.begin(false)) { @@ -163,7 +163,7 @@ void setup() { ss2k.resetIfShiftersHeld(); SS2K_LOG(MAIN_LOG_TAG, "Creating Shifter Interrupts"); - // Setup Interrups so shifters work anytime + // Setup Interrupts so shifters work anytime attachInterrupt(digitalPinToInterrupt(currentBoard.shiftUpPin), ss2k.shiftUp, CHANGE); attachInterrupt(digitalPinToInterrupt(currentBoard.shiftDownPin), ss2k.shiftDown, CHANGE); digitalWrite(LED_PIN, HIGH); @@ -233,16 +233,17 @@ void SS2K::maintenanceLoop(void *pvParameters) { #endif // DEBUG_STACK loopCounter = 0; } - // read from auxSerial - //if (auxSerial.available()) { - //String buf = auxSerial.readStringUntil('\n'); - //echo - //SS2K_LOG(MAIN_LOG_TAG, "aux_serial: %s", buf); - // auxSerial.write(buf.c_str()); - //auxSerial.println(auxSerial.onReceive); - //} - auxSerial.print("Peloton Works!"); - Serial.println(auxSerial.readString()); + + if (currentBoard.auxSerialTxPin) { + // echo back aux serial on all interfaces + String buf = auxSerial.readString(); + if (buf) { + // new line + auxSerial.print('\n'); + SS2K_LOG(MAIN_LOG_TAG, "%s", buf); + auxSerial.print(buf); + } + } loopCounter++; } From 11ddeb7c7d9db24b82538fd25d036d0331184179 Mon Sep 17 00:00:00 2001 From: doudar Date: Sun, 16 Oct 2022 22:55:42 -0500 Subject: [PATCH 03/17] added preliminary peloton test code --- include/Main.h | 29 ++++++++++------ src/Main.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 12 deletions(-) diff --git a/include/Main.h b/include/Main.h index 1f4984e7..bbd9e7b3 100644 --- a/include/Main.h +++ b/include/Main.h @@ -51,20 +51,27 @@ class SS2K { void motorStop(bool releaseTension = false); SS2K() { - targetPosition = 0; - currentPosition = 0; - stepperIsRunning = false; - externalControl = false; - syncMode = false; - lastDebounceTime = 0; - debounceDelay = DEBOUNCE_DELAY; - lastShifterPosition = 0; - shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN; - scanDelayTime = 10000; - scanDelayStart = 0; + targetPosition = 0; + currentPosition = 0; + stepperIsRunning = false; + externalControl = false; + syncMode = false; + lastDebounceTime = 0; + debounceDelay = DEBOUNCE_DELAY; + lastShifterPosition = 0; + shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN; + scanDelayTime = 10000; + scanDelayStart = 0; } }; +// peloton Serial +#define HEADER 0xF1 +#define FOOTER 0xF6 +#define CAD_ID 0x41 +#define RES_ID 0x4A +#define POW_ID 0x44 + void auxSerialRX(); // Users Physical Working Capacity Calculation Parameters (heartrate to Power // calculation) diff --git a/src/Main.cpp b/src/Main.cpp index f8cc4ae7..456d8951 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -49,6 +49,96 @@ WebSocketAppender webSocketAppender; void auxSerialRX() { String buf = auxSerial.readString(); Serial.printf("rx: %s", buf); + + if (auxSerial.available()) // >= MESSAGE_BYTES) + { + if (auxSerial.read() == HEADER) { + int devID = auxSerial.read(); + int measDigits = auxSerial.read(); // not using this for now + if (devID == CAD_ID) { + char b3 = auxSerial.read(); + int i3 = b3 - '0'; + char b2 = auxSerial.read(); + int i2 = b2 - '0'; + char b1 = auxSerial.read(); + int i1 = b1 - '0'; + int val1 = 100 * i1 + 10 * i2 + i3; + byte checkSum = auxSerial.read(); + byte sum = b3 + b2 + b1 + measDigits + devID + HEADER; + if (sum != checkSum) { + pAndC.cadenceValid = false; // measurement is invalid + } else { + rtConfig.getSimulatedCad(val1); + //pAndC.cadenceValid = true; + } + + int footer = auxSerial.read(); + + if (footer != FOOTER) { + pAndC.cadenceValid = false; // measurement is invalid + } + } else if (devID == POW_ID) { + char b5 = auxSerial.read(); + int i5 = b5 - '0'; + char b4 = auxSerial.read(); + int i4 = b4 - '0'; + char b3 = auxSerial.read(); + int i3 = b3 - '0'; + char b2 = auxSerial.read(); + int i2 = b2 - '0'; + char b1 = auxSerial.read(); + int i1 = b1 - '0'; + float val = 1000 * i1 + 100 * i2 + 10 * i3 + i4 + 0.1 * i5; // Use a float because the last value is a tenth for some reason + byte checkSum = auxSerial.read(); + byte sum = b5 + b4 + b3 + b2 + b1 + measDigits + devID + HEADER; + if (sum != checkSum) { + //pAndC.powerValid = false; // measurement is invalid + + } else { + rtConfig.setSimulatedWatts((int16_t)val); // Convert it to an int + pAndC.powerValid = true; + } + + int footer = auxSerial.read(); + + if (footer != FOOTER) { + //pAndC.powerValid = false; + } + } else if (devID == RES_ID) { // Read the resistance + char b4 = auxSerial.read(); + int i4 = b4 - '0'; + char b3 = auxSerial.read(); + int i3 = b3 - '0'; + char b2 = auxSerial.read(); + int i2 = b2 - '0'; + char b1 = auxSerial.read(); + int i1 = b1 - '0'; + int val1 = 1000 * i1 + 100 * i2 + 10 * i3 + i4; + byte checkSum = auxSerial.read(); + byte sum = b4 + b3 + b2 + b1 + measDigits + devID + HEADER; + + if (sum != checkSum) { + //pAndC.resistanceValid = false; // measurement is invalid + } else { + //rtConfig.setShifterPosition(val1); + //pAndC.resistanceValid = true; + } + + int footer = auxSerial.read(); + + if (footer != FOOTER) { + //pAndC.resistanceValid = false; // measurement is invalid + } + } else { + // TODO - this may cause an infinite loop. Log when this happens and capture the bytes. + } + return; + } else { + return; + } + } else { + return; + } } void SS2K::startTasks() { @@ -237,7 +327,7 @@ void SS2K::maintenanceLoop(void *pvParameters) { if (currentBoard.auxSerialTxPin) { // echo back aux serial on all interfaces String buf = auxSerial.readString(); - if (buf) { + if (buf != "") { // new line auxSerial.print('\n'); SS2K_LOG(MAIN_LOG_TAG, "%s", buf); From a6a3ee60c2516e0e396c122db0155954f23fc4fc Mon Sep 17 00:00:00 2001 From: doudar Date: Sun, 16 Oct 2022 22:56:59 -0500 Subject: [PATCH 04/17] compile testing fix --- src/Main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Main.cpp b/src/Main.cpp index 456d8951..204cc8eb 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -66,16 +66,16 @@ void auxSerialRX() { byte checkSum = auxSerial.read(); byte sum = b3 + b2 + b1 + measDigits + devID + HEADER; if (sum != checkSum) { - pAndC.cadenceValid = false; // measurement is invalid + //pAndC.cadenceValid = false; // measurement is invalid } else { - rtConfig.getSimulatedCad(val1); + rtConfig.setSimulatedCad(val1); //pAndC.cadenceValid = true; } int footer = auxSerial.read(); if (footer != FOOTER) { - pAndC.cadenceValid = false; // measurement is invalid + //pAndC.cadenceValid = false; // measurement is invalid } } else if (devID == POW_ID) { char b5 = auxSerial.read(); @@ -96,7 +96,7 @@ void auxSerialRX() { } else { rtConfig.setSimulatedWatts((int16_t)val); // Convert it to an int - pAndC.powerValid = true; + //pAndC.powerValid = true; } int footer = auxSerial.read(); From 7122aaa4a0d38afb2a3b017bb8a4f9d96d0717fb Mon Sep 17 00:00:00 2001 From: doudar Date: Mon, 17 Oct 2022 15:42:25 -0500 Subject: [PATCH 05/17] somewhat working --- src/Main.cpp | 193 +++++++++++++++++++++++++++------------------------ 1 file changed, 102 insertions(+), 91 deletions(-) diff --git a/src/Main.cpp b/src/Main.cpp index 204cc8eb..7ef9bb41 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -47,98 +47,104 @@ WebSocketAppender webSocketAppender; #ifndef UNIT_TEST void auxSerialRX() { - String buf = auxSerial.readString(); - Serial.printf("rx: %s", buf); - - if (auxSerial.available()) // >= MESSAGE_BYTES) - { - if (auxSerial.read() == HEADER) { - int devID = auxSerial.read(); - int measDigits = auxSerial.read(); // not using this for now - if (devID == CAD_ID) { - char b3 = auxSerial.read(); - int i3 = b3 - '0'; - char b2 = auxSerial.read(); - int i2 = b2 - '0'; - char b1 = auxSerial.read(); - int i1 = b1 - '0'; - int val1 = 100 * i1 + 10 * i2 + i3; - byte checkSum = auxSerial.read(); - byte sum = b3 + b2 + b1 + measDigits + devID + HEADER; - if (sum != checkSum) { - //pAndC.cadenceValid = false; // measurement is invalid - } else { - rtConfig.setSimulatedCad(val1); - //pAndC.cadenceValid = true; - } + // String buf = auxSerial.readString(); + // Serial.printf("serial callback"); + + // if (auxSerial.available()) // >= MESSAGE_BYTES) + //{ + if (auxSerial.read() == HEADER) { + int devID = auxSerial.read(); + int measDigits = auxSerial.read(); // not using this for now + if (devID == CAD_ID) { + char b3 = auxSerial.read(); + int i3 = b3 - '0'; + char b2 = auxSerial.read(); + int i2 = b2 - '0'; + char b1 = auxSerial.read(); + int i1 = b1 - '0'; + int val1 = 100 * i1 + 10 * i2 + i3; + byte checkSum = auxSerial.read(); + byte sum = b3 + b2 + b1 + measDigits + devID + HEADER; + if (sum != checkSum) { + Serial.printf("bad watt checksum %s", auxSerial.readString()); + } else { + rtConfig.setSimulatedCad(val1); + rtConfig.setSimulateCad(true); + Serial.printf("Peloton CAD Set %d", val1); + // pAndC.cadenceValid = true; + } - int footer = auxSerial.read(); + int footer = auxSerial.read(); - if (footer != FOOTER) { - //pAndC.cadenceValid = false; // measurement is invalid - } - } else if (devID == POW_ID) { - char b5 = auxSerial.read(); - int i5 = b5 - '0'; - char b4 = auxSerial.read(); - int i4 = b4 - '0'; - char b3 = auxSerial.read(); - int i3 = b3 - '0'; - char b2 = auxSerial.read(); - int i2 = b2 - '0'; - char b1 = auxSerial.read(); - int i1 = b1 - '0'; - float val = 1000 * i1 + 100 * i2 + 10 * i3 + i4 + 0.1 * i5; // Use a float because the last value is a tenth for some reason - byte checkSum = auxSerial.read(); - byte sum = b5 + b4 + b3 + b2 + b1 + measDigits + devID + HEADER; - if (sum != checkSum) { - //pAndC.powerValid = false; // measurement is invalid + if (footer != FOOTER) { + // pAndC.cadenceValid = false; // measurement is invalid + } + } else if (devID == POW_ID) { + char b5 = auxSerial.read(); + int i5 = b5 - '0'; + char b4 = auxSerial.read(); + int i4 = b4 - '0'; + char b3 = auxSerial.read(); + int i3 = b3 - '0'; + char b2 = auxSerial.read(); + int i2 = b2 - '0'; + char b1 = auxSerial.read(); + int i1 = b1 - '0'; + float val = 1000 * i1 + 100 * i2 + 10 * i3 + i4 + 0.1 * i5; // Use a float because the last value is a tenth for some reason + byte checkSum = auxSerial.read(); + byte sum = b5 + b4 + b3 + b2 + b1 + measDigits + devID + HEADER; + if (sum != checkSum) { + Serial.println("bad cad checksum"); - } else { - rtConfig.setSimulatedWatts((int16_t)val); // Convert it to an int - //pAndC.powerValid = true; - } + } else { + rtConfig.setSimulatedWatts((int16_t)val); // Convert it to an int + rtConfig.setSimulateWatts(true); + } - int footer = auxSerial.read(); + int footer = auxSerial.read(); - if (footer != FOOTER) { - //pAndC.powerValid = false; - } - } else if (devID == RES_ID) { // Read the resistance - char b4 = auxSerial.read(); - int i4 = b4 - '0'; - char b3 = auxSerial.read(); - int i3 = b3 - '0'; - char b2 = auxSerial.read(); - int i2 = b2 - '0'; - char b1 = auxSerial.read(); - int i1 = b1 - '0'; - int val1 = 1000 * i1 + 100 * i2 + 10 * i3 + i4; - byte checkSum = auxSerial.read(); - byte sum = b4 + b3 + b2 + b1 + measDigits + devID + HEADER; - - if (sum != checkSum) { - //pAndC.resistanceValid = false; // measurement is invalid - } else { - //rtConfig.setShifterPosition(val1); - //pAndC.resistanceValid = true; - } + if (footer != FOOTER) { + // pAndC.powerValid = false; + } + } else if (devID == RES_ID) { // Read the resistance + char b4 = auxSerial.read(); + int i4 = b4 - '0'; + char b3 = auxSerial.read(); + int i3 = b3 - '0'; + char b2 = auxSerial.read(); + int i2 = b2 - '0'; + char b1 = auxSerial.read(); + int i1 = b1 - '0'; + int val1 = 1000 * i1 + 100 * i2 + 10 * i3 + i4; + byte checkSum = auxSerial.read(); + byte sum = b4 + b3 + b2 + b1 + measDigits + devID + HEADER; + + if (sum != checkSum) { + Serial.println("bad resistance checksum"); + } else { + // rtConfig.setShifterPosition(val1); + // pAndC.resistanceValid = true; + } - int footer = auxSerial.read(); + int footer = auxSerial.read(); - if (footer != FOOTER) { - //pAndC.resistanceValid = false; // measurement is invalid - } - } else { - // TODO - this may cause an infinite loop. Log when this happens and capture the bytes. + if (footer != FOOTER) { + // pAndC.resistanceValid = false; // measurement is invalid } - return; } else { - return; + //throw away leftover data + auxSerial.readString(); + // TODO - this may cause an infinite loop. Log when this happens and capture the bytes. } + return; } else { + String buf = auxSerial.readString(); + Serial.printf("bad watt checksum %s", buf); return; } + //} else { + // return; + //} } void SS2K::startTasks() { @@ -179,13 +185,13 @@ void setup() { stepperSerial.begin(57600, SERIAL_8N2, currentBoard.stepperSerialRxPin, currentBoard.stepperSerialTxPin); // initialize aux serial port if (currentBoard.auxSerialTxPin) { - auxSerial.setTxBufferSize(500); - auxSerial.setRxBufferSize(500); - auxSerial.begin(1200, SERIAL_8N1, currentBoard.auxSerialRxPin, currentBoard.auxSerialTxPin, false); + // auxSerial.setTxBufferSize(500); + // auxSerial.setRxBufferSize(500); + auxSerial.begin(19200, SERIAL_8N1, currentBoard.auxSerialRxPin, currentBoard.auxSerialTxPin, false); if (!auxSerial) { SS2K_LOG(MAIN_LOG_TAG, "Invalid Serial Pin Configuration"); } - // auxSerial.onReceive(auxSerialRX, true); + // auxSerial.onReceive(auxSerialRX, true); // setup callback } // Initialize LittleFS SS2K_LOG(MAIN_LOG_TAG, "Mounting Filesystem"); @@ -326,18 +332,23 @@ void SS2K::maintenanceLoop(void *pvParameters) { if (currentBoard.auxSerialTxPin) { // echo back aux serial on all interfaces - String buf = auxSerial.readString(); - if (buf != "") { - // new line - auxSerial.print('\n'); - SS2K_LOG(MAIN_LOG_TAG, "%s", buf); - auxSerial.print(buf); - } + // uint8_t buf[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + // size_t len = auxSerial.readBytes(buf, 20); + // if (len) { + // new line + // auxSerial.print('\n'); + // for (int i = 0; i < len; i++) { + // Serial.print(buf[i], HEX); + // auxSerial.print(buf); + + //} + // } + auxSerialRX(); } - loopCounter++; } } + #endif // UNIT_TEST void SS2K::restartWifi() { From 4cba01b6a561c4bc85b9099ab061fc444490f047 Mon Sep 17 00:00:00 2001 From: doudar Date: Tue, 18 Oct 2022 21:27:19 -0500 Subject: [PATCH 06/17] Added Peloton Sensor factory module --- CHANGELOG.md | 1 + include/Main.h | 20 ++- include/SensorCollector.h | 14 ++ include/settings.h | 3 + lib/SS2K/include/Constants.h | 10 ++ lib/SS2K/include/sensors/PelotonData.h | 30 +++++ lib/SS2K/src/sensors/PelotonData.cpp | 59 +++++++++ lib/SS2K/src/sensors/SensorDataFactory.cpp | 3 + src/BLE_Common.cpp | 40 +----- src/Main.cpp | 145 +++++---------------- src/SensorCollector.cpp | 54 ++++++++ 11 files changed, 217 insertions(+), 162 deletions(-) create mode 100644 include/SensorCollector.h create mode 100644 lib/SS2K/include/sensors/PelotonData.h create mode 100644 lib/SS2K/src/sensors/PelotonData.cpp create mode 100644 src/SensorCollector.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index c379af7a..a5088179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +-Added Peloton serial decoder to sensor factory. ### Changed diff --git a/include/Main.h b/include/Main.h index bbd9e7b3..3d2a6178 100644 --- a/include/Main.h +++ b/include/Main.h @@ -13,6 +13,7 @@ #include "BLE_Common.h" #include "LittleFS_Upgrade.h" #include "boards.h" +#include "SensorCollector.h" #define MAIN_LOG_TAG "Main" @@ -65,14 +66,19 @@ class SS2K { } }; -// peloton Serial -#define HEADER 0xF1 -#define FOOTER 0xF6 -#define CAD_ID 0x41 -#define RES_ID 0x4A -#define POW_ID 0x44 +class AuxSerialBuffer { + public: + uint8_t data[20]; + size_t len; + + AuxSerialBuffer() { + for (int i = 0; i < AUX_BUF_SIZE; i++) { + this->data[i] = 0; + } + this->len = 0; + } +}; -void auxSerialRX(); // Users Physical Working Capacity Calculation Parameters (heartrate to Power // calculation) extern physicalWorkingCapacity userPWC; diff --git a/include/SensorCollector.h b/include/SensorCollector.h new file mode 100644 index 00000000..027d53a2 --- /dev/null +++ b/include/SensorCollector.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2020 Anthony Doud & Joel Baranick + * All rights reserved + * + * SPDX-License-Identifier: GPL-2.0-only + */ +#include +#include +#include + +#pragma once + + +void collectAndSet(NimBLEUUID charUUID, NimBLEUUID serviceUUID, NimBLEAddress address, uint8_t *pData, size_t length); \ No newline at end of file diff --git a/include/settings.h b/include/settings.h index e1d3ce09..88f2703b 100644 --- a/include/settings.h +++ b/include/settings.h @@ -230,6 +230,9 @@ // Temperature of the ESP32 at which to start reducing the power output of the stepper motor driver. #define THROTTLE_TEMP 85 +// Size of the Aux Serial Buffer for Peloton +#define AUX_BUF_SIZE 20 + // Uncomment to enable sending Telegram debug messages back to the chat // specified in telegram_token.h // #define USE_TELEGRAM diff --git a/lib/SS2K/include/Constants.h b/lib/SS2K/include/Constants.h index c8b45714..20b7702e 100644 --- a/lib/SS2K/include/Constants.h +++ b/lib/SS2K/include/Constants.h @@ -47,3 +47,13 @@ #define ECHELON_SERVICE_UUID NimBLEUUID("0bf669f1-45f2-11e7-9598-0800200c9a66") #define ECHELON_WRITE_UUID NimBLEUUID("0bf669f2-45f2-11e7-9598-0800200c9a66") #define ECHELON_DATA_UUID NimBLEUUID("0bf669f4-45f2-11e7-9598-0800200c9a66") + +// Dummy UUID for Peloton Serial Data Interface +#define PELOTON_DATA_UUID NimBLEUUID("00000000-0000-0000-0000-0000000000321") +#define PELOTON_ADDRESS NimBLEAddress("00:00:00:00:00:00:00") +// peloton Serial +#define HEADER 0xF1 +#define FOOTER 0xF6 +#define CAD_ID 0x41 +#define RES_ID 0x4A +#define POW_ID 0x44 \ No newline at end of file diff --git a/lib/SS2K/include/sensors/PelotonData.h b/lib/SS2K/include/sensors/PelotonData.h new file mode 100644 index 00000000..311bb057 --- /dev/null +++ b/lib/SS2K/include/sensors/PelotonData.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 Anthony Doud & Joel Baranick + * All rights reserved + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#pragma once + +#include "SensorData.h" + +class PelotonData : public SensorData { + public: + PelotonData() : SensorData("PTON") {} + + bool hasHeartRate(); + bool hasCadence(); + bool hasPower(); + bool hasSpeed(); + int getHeartRate(); + float getCadence(); + int getPower(); + float getSpeed(); + void decode(uint8_t *data, size_t length); + + private: + bool hasData = false; + float cadence = nanf(""); + int power = INT_MIN; +}; \ No newline at end of file diff --git a/lib/SS2K/src/sensors/PelotonData.cpp b/lib/SS2K/src/sensors/PelotonData.cpp new file mode 100644 index 00000000..807f32c3 --- /dev/null +++ b/lib/SS2K/src/sensors/PelotonData.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 Anthony Doud & Joel Baranick + * All rights reserved + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include "endian.h" +#include "sensors/PelotonData.h" +#include "Constants.h" + +bool PelotonData::hasHeartRate() { return false; } + +bool PelotonData::hasCadence() { return this->hasData; } + +bool PelotonData::hasPower() { return this->hasData; } + +bool PelotonData::hasSpeed() { return false; } + +int PelotonData::getHeartRate() { return INT_MIN; } + +float PelotonData::getCadence() { return this->cadence; } + +int PelotonData::getPower() { return this->power; } + +float PelotonData::getSpeed() { return nanf(""); } + +void PelotonData::decode(uint8_t *data, size_t length) { + float value = 0.0; + const uint8_t payload_length = data[2]; + for (uint8_t i = 2 + payload_length; i > 2; i--) { + // -30 = Convert from ASCII to numeric + uint8_t next_digit = data[i] - 0x30; + // Check for overflow + if (value > 6553 || (value == 6553 && next_digit > 5)) { + return; + } + value = value * 10 + next_digit; + } + hasData = true; + switch (data[1]) { + case POW_ID: + power = value/10; + break; + + case CAD_ID: + cadence = value; + break; + + case RES_ID: + // we don't use resistance + break; + + default: + cadence = nanf(""); + power = INT_MIN; + hasData = false; + } +} \ No newline at end of file diff --git a/lib/SS2K/src/sensors/SensorDataFactory.cpp b/lib/SS2K/src/sensors/SensorDataFactory.cpp index dc329c9e..c93f57f6 100644 --- a/lib/SS2K/src/sensors/SensorDataFactory.cpp +++ b/lib/SS2K/src/sensors/SensorDataFactory.cpp @@ -13,6 +13,7 @@ #include "sensors/FitnessMachineIndoorBikeData.h" #include "sensors/HeartRateData.h" #include "sensors/EchelonData.h" +#include "sensors/PelotonData.h" std::shared_ptr SensorDataFactory::getSensorData(const NimBLEUUID characteristicUUID, const uint64_t peerAddress, uint8_t *data, size_t length) { for (auto &it : SensorDataFactory::knownDevices) { @@ -32,6 +33,8 @@ std::shared_ptr SensorDataFactory::getSensorData(const NimBLEUUID ch sensorData = std::shared_ptr(new FlywheelData()); } else if (characteristicUUID == ECHELON_DATA_UUID) { sensorData = std::shared_ptr(new EchelonData()); + } else if (characteristicUUID == PELOTON_DATA_UUID) { + sensorData = std::shared_ptr(new PelotonData()); } else { return NULL_SENSOR_DATA; } diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index ecde0ee2..f440436b 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -16,7 +16,6 @@ bool hr2p = false; TaskHandle_t BLECommunicationTask; -SensorDataFactory sensorDataFactory; void BLECommunications(void *pvParameters) { for (;;) { @@ -54,45 +53,8 @@ void BLECommunications(void *pvParameters) { for (size_t i = 0; i < length; i++) { pData[i] = incomingNotifyData.data[i]; } + collectAndSet(pRemoteBLECharacteristic->getUUID(), myAdvertisedDevice.serviceUUID, pRemoteBLECharacteristic->getRemoteService()->getClient()->getPeerAddress(), pData, length); - const int kLogBufMaxLength = 250; - char logBuf[kLogBufMaxLength]; - SS2K_LOGD(BLE_COMMON_LOG_TAG, "Data length: %d", length); - int logBufLength = ss2k_log_hex_to_buffer(pData, length, logBuf, 0, kLogBufMaxLength); - - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, "<- %.8s | %.8s", myAdvertisedDevice.serviceUUID.toString().c_str(), - myAdvertisedDevice.charUUID.toString().c_str()); - - std::shared_ptr sensorData = sensorDataFactory.getSensorData( - pRemoteBLECharacteristic->getUUID(), (uint64_t)pRemoteBLECharacteristic->getRemoteService()->getClient()->getPeerAddress(), pData, length); - - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " | %s[", sensorData->getId().c_str()); - if (sensorData->hasHeartRate() && !rtConfig.getSimulateHr()) { - int heartRate = sensorData->getHeartRate(); - rtConfig.setSimulatedHr(heartRate); - spinBLEClient.connectedHR |= true; - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " HR(%d)", heartRate % 1000); - } - if (sensorData->hasCadence() && !rtConfig.getSimulateCad()) { - float cadence = sensorData->getCadence(); - rtConfig.setSimulatedCad(cadence); - spinBLEClient.connectedCD |= true; - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " CD(%.2f)", fmodf(cadence, 1000.0)); - } - if (sensorData->hasPower() && !rtConfig.getSimulateWatts()) { - int power = sensorData->getPower() * userConfig.getPowerCorrectionFactor(); - rtConfig.setSimulatedWatts(power); - spinBLEClient.connectedPM |= true; - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " PW(%d)", power % 10000); - } - if (sensorData->hasSpeed()) { - float speed = sensorData->getSpeed(); - rtConfig.setSimulatedSpeed(speed); - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " SD(%.2f)", fmodf(speed, 1000.0)); - } - strncat(logBuf + logBufLength, " ]", kLogBufMaxLength - logBufLength); - SS2K_LOG(BLE_COMMON_LOG_TAG, "%s", logBuf); - SEND_TO_TELEGRAM(String(logBuf)); } } else if (!pClient->isConnected()) { // This shouldn't ever be // called... diff --git a/src/Main.cpp b/src/Main.cpp index 7ef9bb41..15ee405f 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -15,6 +15,7 @@ #include "ERG_Mode.h" #include "UdpAppender.h" #include "WebsocketAppender.h" +#include // Stepper Motor Serial HardwareSerial stepperSerial(1); @@ -22,6 +23,7 @@ TMC2208Stepper driver(&SERIAL_PORT, R_SENSE); // Hardware Serial // Peloton Serial HardwareSerial auxSerial(2); +AuxSerialBuffer auxSerialBuffer; FastAccelStepperEngine engine = FastAccelStepperEngine(); FastAccelStepper *stepper = NULL; @@ -46,107 +48,6 @@ WebSocketAppender webSocketAppender; ///////////// BEGIN SETUP ///////////// #ifndef UNIT_TEST -void auxSerialRX() { - // String buf = auxSerial.readString(); - // Serial.printf("serial callback"); - - // if (auxSerial.available()) // >= MESSAGE_BYTES) - //{ - if (auxSerial.read() == HEADER) { - int devID = auxSerial.read(); - int measDigits = auxSerial.read(); // not using this for now - if (devID == CAD_ID) { - char b3 = auxSerial.read(); - int i3 = b3 - '0'; - char b2 = auxSerial.read(); - int i2 = b2 - '0'; - char b1 = auxSerial.read(); - int i1 = b1 - '0'; - int val1 = 100 * i1 + 10 * i2 + i3; - byte checkSum = auxSerial.read(); - byte sum = b3 + b2 + b1 + measDigits + devID + HEADER; - if (sum != checkSum) { - Serial.printf("bad watt checksum %s", auxSerial.readString()); - } else { - rtConfig.setSimulatedCad(val1); - rtConfig.setSimulateCad(true); - Serial.printf("Peloton CAD Set %d", val1); - // pAndC.cadenceValid = true; - } - - int footer = auxSerial.read(); - - if (footer != FOOTER) { - // pAndC.cadenceValid = false; // measurement is invalid - } - } else if (devID == POW_ID) { - char b5 = auxSerial.read(); - int i5 = b5 - '0'; - char b4 = auxSerial.read(); - int i4 = b4 - '0'; - char b3 = auxSerial.read(); - int i3 = b3 - '0'; - char b2 = auxSerial.read(); - int i2 = b2 - '0'; - char b1 = auxSerial.read(); - int i1 = b1 - '0'; - float val = 1000 * i1 + 100 * i2 + 10 * i3 + i4 + 0.1 * i5; // Use a float because the last value is a tenth for some reason - byte checkSum = auxSerial.read(); - byte sum = b5 + b4 + b3 + b2 + b1 + measDigits + devID + HEADER; - if (sum != checkSum) { - Serial.println("bad cad checksum"); - - } else { - rtConfig.setSimulatedWatts((int16_t)val); // Convert it to an int - rtConfig.setSimulateWatts(true); - } - - int footer = auxSerial.read(); - - if (footer != FOOTER) { - // pAndC.powerValid = false; - } - } else if (devID == RES_ID) { // Read the resistance - char b4 = auxSerial.read(); - int i4 = b4 - '0'; - char b3 = auxSerial.read(); - int i3 = b3 - '0'; - char b2 = auxSerial.read(); - int i2 = b2 - '0'; - char b1 = auxSerial.read(); - int i1 = b1 - '0'; - int val1 = 1000 * i1 + 100 * i2 + 10 * i3 + i4; - byte checkSum = auxSerial.read(); - byte sum = b4 + b3 + b2 + b1 + measDigits + devID + HEADER; - - if (sum != checkSum) { - Serial.println("bad resistance checksum"); - } else { - // rtConfig.setShifterPosition(val1); - // pAndC.resistanceValid = true; - } - - int footer = auxSerial.read(); - - if (footer != FOOTER) { - // pAndC.resistanceValid = false; // measurement is invalid - } - } else { - //throw away leftover data - auxSerial.readString(); - // TODO - this may cause an infinite loop. Log when this happens and capture the bytes. - } - return; - } else { - String buf = auxSerial.readString(); - Serial.printf("bad watt checksum %s", buf); - return; - } - //} else { - // return; - //} -} - void SS2K::startTasks() { SS2K_LOG(MAIN_LOG_TAG, "Start BLE + ERG Tasks"); if (BLECommunicationTask == NULL) { @@ -185,8 +86,8 @@ void setup() { stepperSerial.begin(57600, SERIAL_8N2, currentBoard.stepperSerialRxPin, currentBoard.stepperSerialTxPin); // initialize aux serial port if (currentBoard.auxSerialTxPin) { - // auxSerial.setTxBufferSize(500); - // auxSerial.setRxBufferSize(500); + auxSerial.setTxBufferSize(500); + auxSerial.setRxBufferSize(500); auxSerial.begin(19200, SERIAL_8N1, currentBoard.auxSerialRxPin, currentBoard.auxSerialTxPin, false); if (!auxSerial) { SS2K_LOG(MAIN_LOG_TAG, "Invalid Serial Pin Configuration"); @@ -330,20 +231,32 @@ void SS2K::maintenanceLoop(void *pvParameters) { loopCounter = 0; } + // Monitor serial port for data if (currentBoard.auxSerialTxPin) { - // echo back aux serial on all interfaces - // uint8_t buf[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - // size_t len = auxSerial.readBytes(buf, 20); - // if (len) { - // new line - // auxSerial.print('\n'); - // for (int i = 0; i < len; i++) { - // Serial.print(buf[i], HEX); - // auxSerial.print(buf); - - //} - // } - auxSerialRX(); + if (auxSerial.available() >= 8) { // if at least 8 bytes are available to read from the serial port + int i = 0; + int k = 0; + auxSerialBuffer.len = auxSerial.readBytes(auxSerialBuffer.data, AUX_BUF_SIZE); + // pre-process Peloton Data. If we get more serial devices we will have to move this into sensor data factory. + // This is done here to prevent a lot of extra logging. + for (i = 0; i < auxSerialBuffer.len; i++) { // Find start of data string + if (auxSerialBuffer.data[i] == HEADER) { + for (k = i; k < auxSerialBuffer.len; k++) { // Find end of data string + if (auxSerialBuffer.data[k] == FOOTER) { + k++; + break; + } + } + size_t newLen = k - i; // find length of sub data + uint8_t newBuf[newLen]; + for (int j = i; j < k; j++) { + newBuf[j - i] = auxSerialBuffer.data[j]; + } + collectAndSet(PELOTON_DATA_UUID, PELOTON_DATA_UUID, PELOTON_ADDRESS, newBuf, newLen); + break; + } + } + } } loopCounter++; } diff --git a/src/SensorCollector.cpp b/src/SensorCollector.cpp new file mode 100644 index 00000000..5861e248 --- /dev/null +++ b/src/SensorCollector.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 Anthony Doud & Joel Baranick + * All rights reserved + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include "Main.h" +#include "SS2KLog.h" + +#include +#include + +SensorDataFactory sensorDataFactory; + +void collectAndSet(NimBLEUUID charUUID, NimBLEUUID serviceUUID, NimBLEAddress address, uint8_t *pData, size_t length) { + const int kLogBufMaxLength = 250; + char logBuf[kLogBufMaxLength]; + SS2K_LOGD(BLE_COMMON_LOG_TAG, "Data length: %d", length); + int logBufLength = ss2k_log_hex_to_buffer(pData, length, logBuf, 0, kLogBufMaxLength); + + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, "<- %.8s | %.8s", serviceUUID.toString().c_str(), + charUUID.toString().c_str()); + + std::shared_ptr sensorData = sensorDataFactory.getSensorData(charUUID, (uint64_t)address, pData, length); + + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " | %s[", sensorData->getId().c_str()); + if (sensorData->hasHeartRate() && !rtConfig.getSimulateHr()) { + int heartRate = sensorData->getHeartRate(); + rtConfig.setSimulatedHr(heartRate); + spinBLEClient.connectedHR |= true; + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " HR(%d)", heartRate % 1000); + } + if (sensorData->hasCadence() && !rtConfig.getSimulateCad()) { + float cadence = sensorData->getCadence(); + rtConfig.setSimulatedCad(cadence); + spinBLEClient.connectedCD |= true; + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " CD(%.2f)", fmodf(cadence, 1000.0)); + } + if (sensorData->hasPower() && !rtConfig.getSimulateWatts()) { + int power = sensorData->getPower() * userConfig.getPowerCorrectionFactor(); + rtConfig.setSimulatedWatts(power); + spinBLEClient.connectedPM |= true; + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " PW(%d)", power % 10000); + } + if (sensorData->hasSpeed()) { + float speed = sensorData->getSpeed(); + rtConfig.setSimulatedSpeed(speed); + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " SD(%.2f)", fmodf(speed, 1000.0)); + } + strncat(logBuf + logBufLength, " ]", kLogBufMaxLength - logBufLength); + SS2K_LOG(BLE_COMMON_LOG_TAG, "%s", logBuf); + SEND_TO_TELEGRAM(String(logBuf)); +} \ No newline at end of file From 1c64a5a542ceed1fc73ad7e793532b6a8ed35f58 Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 20 Oct 2022 17:27:51 -0500 Subject: [PATCH 07/17] fixed cad nan issue. --- lib/SS2K/src/sensors/PelotonData.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/SS2K/src/sensors/PelotonData.cpp b/lib/SS2K/src/sensors/PelotonData.cpp index 807f32c3..57dee433 100644 --- a/lib/SS2K/src/sensors/PelotonData.cpp +++ b/lib/SS2K/src/sensors/PelotonData.cpp @@ -26,7 +26,7 @@ int PelotonData::getPower() { return this->power; } float PelotonData::getSpeed() { return nanf(""); } void PelotonData::decode(uint8_t *data, size_t length) { - float value = 0.0; + float value = 0.0; const uint8_t payload_length = data[2]; for (uint8_t i = 2 + payload_length; i > 2; i--) { // -30 = Convert from ASCII to numeric @@ -40,9 +40,10 @@ void PelotonData::decode(uint8_t *data, size_t length) { hasData = true; switch (data[1]) { case POW_ID: - power = value/10; + power = value / 10; + break; - + case CAD_ID: cadence = value; break; @@ -52,8 +53,8 @@ void PelotonData::decode(uint8_t *data, size_t length) { break; default: - cadence = nanf(""); - power = INT_MIN; - hasData = false; + // cadence = nanf(""); + // power = INT_MIN; + // hasData = false; } } \ No newline at end of file From a96aee8deb71144f72057e51cc2032bc2cf75c2f Mon Sep 17 00:00:00 2001 From: doudar Date: Thu, 20 Oct 2022 19:52:28 -0500 Subject: [PATCH 08/17] fixed empty default in switch statement --- lib/SS2K/src/sensors/PelotonData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/SS2K/src/sensors/PelotonData.cpp b/lib/SS2K/src/sensors/PelotonData.cpp index 57dee433..175180fb 100644 --- a/lib/SS2K/src/sensors/PelotonData.cpp +++ b/lib/SS2K/src/sensors/PelotonData.cpp @@ -53,6 +53,7 @@ void PelotonData::decode(uint8_t *data, size_t length) { break; default: + break; // cadence = nanf(""); // power = INT_MIN; // hasData = false; From f3549572aba92953a6158aafef1d703bb70e0ee3 Mon Sep 17 00:00:00 2001 From: doudar Date: Fri, 21 Oct 2022 09:19:36 -0500 Subject: [PATCH 09/17] added check for power less than 0 --- lib/SS2K/src/sensors/PelotonData.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/SS2K/src/sensors/PelotonData.cpp b/lib/SS2K/src/sensors/PelotonData.cpp index 175180fb..5a8e2adf 100644 --- a/lib/SS2K/src/sensors/PelotonData.cpp +++ b/lib/SS2K/src/sensors/PelotonData.cpp @@ -40,7 +40,11 @@ void PelotonData::decode(uint8_t *data, size_t length) { hasData = true; switch (data[1]) { case POW_ID: - power = value / 10; + if (value >= 0) { + power = value / 10; + } else { + power = 0; + } break; From 50c7bc2f6ca8348faa3211d6e91d1a4882ad4804 Mon Sep 17 00:00:00 2001 From: doudar Date: Fri, 21 Oct 2022 19:13:39 -0500 Subject: [PATCH 10/17] added tx testing --- lib/SS2K/include/Constants.h | 2 +- src/Main.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/SS2K/include/Constants.h b/lib/SS2K/include/Constants.h index 20b7702e..e2cc3d1a 100644 --- a/lib/SS2K/include/Constants.h +++ b/lib/SS2K/include/Constants.h @@ -56,4 +56,4 @@ #define FOOTER 0xF6 #define CAD_ID 0x41 #define RES_ID 0x4A -#define POW_ID 0x44 \ No newline at end of file +#define POW_ID 0x44 diff --git a/src/Main.cpp b/src/Main.cpp index 93a5bdd8..dc1be476 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -24,6 +24,12 @@ TMC2208Stepper driver(&SERIAL_PORT, R_SENSE); // Hardware Serial // Peloton Serial HardwareSerial auxSerial(2); AuxSerialBuffer auxSerialBuffer; +// should we interrogate the bike for cadence and power? +#define PELOTON_TX true +#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}; FastAccelStepperEngine engine = FastAccelStepperEngine(); FastAccelStepper *stepper = NULL; @@ -263,6 +269,19 @@ void SS2K::maintenanceLoop(void *pvParameters) { } } } + if (PELOTON_TX) { + static bool alternate = false; + if (alternate) { + for (int i = 0; i < PELOTON_RQ_SIZE; i++) { + auxSerial.write(peloton_rq_watts[i]); + } + } else { + for (int i = 0; i < PELOTON_RQ_SIZE; i++) { + auxSerial.write(peloton_rq_cad[i]); + } + } + alternate = !alternate; + } } loopCounter++; } From aa076765fabd63e5e0b9639668f0fd6ea25e8903 Mon Sep 17 00:00:00 2001 From: doudar Date: Sun, 30 Oct 2022 12:02:31 -0500 Subject: [PATCH 11/17] Added PWR Scaler --- CHANGELOG.md | 2 ++ include/Main.h | 10 +++++- include/boards.h | 3 ++ include/settings.h | 6 ++++ src/Main.cpp | 85 +++++++++++++++++++++++----------------------- 5 files changed, 63 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4b824a5..bfa64120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added blocking for shifts above or below min/max setpoints. - Added Peloton serial decoder to sensor factory. - Added blocking for shifts above or below min/max set points. +- Added power scaler for new board. ### 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 ride-ability. raised incline multiplier and erg sensitivity, increased incline multiplier and max brake watts. - Fixed a bug in the new cadence compensation where an int should have been a float. +- Moved serial checking to own function. ### Hardware - removed duplicate directory in direct mount folder diff --git a/include/Main.h b/include/Main.h index 3d2a6178..97f59c20 100644 --- a/include/Main.h +++ b/include/Main.h @@ -50,6 +50,7 @@ class SS2K { void updateStealthchop(); void checkDriverTemperature(); void motorStop(bool releaseTension = false); + void checkSerial(); SS2K() { targetPosition = 0; @@ -86,4 +87,11 @@ extern SS2K ss2k; // Main program variable that stores most everything extern userParameters userConfig; -extern RuntimeParameters rtConfig; \ No newline at end of file +extern RuntimeParameters rtConfig; + +//Peloton Specific Parameters +#define PELOTON_TX true +#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}; \ No newline at end of file diff --git a/include/boards.h b/include/boards.h index 51b196bf..4ce4f086 100644 --- a/include/boards.h +++ b/include/boards.h @@ -27,6 +27,7 @@ class Board { int stepperSerialRxPin; int auxSerialTxPin; int auxSerialRxPin; + int pwrScaler; }; class Boards { @@ -47,6 +48,7 @@ class Boards { rev1.stepperSerialRxPin = r1_STEPPERSERIAL_RX; rev1.auxSerialTxPin = 0; rev1.auxSerialRxPin = 0; + rev1.pwrScaler = r1_PWR_SCALER; // Rev 2 rev2.name = r2_NAME; rev2.versionVoltage = r2_VERSION_VOLTAGE; @@ -59,5 +61,6 @@ class Boards { rev2.stepperSerialRxPin = r2_STEPPERSERIAL_RX; rev2.auxSerialTxPin = r2_AUX_SERIAL_TX; rev2.auxSerialRxPin = r2_AUX_SERIAL_RX; + rev2.pwrScaler = r2_PWR_SCALER; } }; \ No newline at end of file diff --git a/include/settings.h b/include/settings.h index 480f27d7..0c58a2e0 100644 --- a/include/settings.h +++ b/include/settings.h @@ -122,6 +122,9 @@ // TMC2208/TMC2224 SoftwareSerial transmit pin #define r1_STEPPERSERIAL_TX 12 + +// Reduce current setting by this divisor +#define r1_PWR_SCALER 4 //////////////////////////////////////////////////////// //////////// Defines for hardware Revision 2 //////////// @@ -157,6 +160,9 @@ // TMC2209 SoftwareSerial transmit pin #define r2_AUX_SERIAL_TX 21 + +// Reduce current setting by this divisor +#define r2_PWR_SCALER 4 //////////////////////////////////////////////////////// // TMC2208/TMC2224 HardwareSerial port diff --git a/src/Main.cpp b/src/Main.cpp index dc1be476..74bcd483 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -25,11 +25,6 @@ TMC2208Stepper driver(&SERIAL_PORT, R_SENSE); // Hardware Serial HardwareSerial auxSerial(2); AuxSerialBuffer auxSerialBuffer; // should we interrogate the bike for cadence and power? -#define PELOTON_TX true -#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}; FastAccelStepperEngine engine = FastAccelStepperEngine(); FastAccelStepper *stepper = NULL; @@ -245,43 +240,7 @@ void SS2K::maintenanceLoop(void *pvParameters) { // Monitor serial port for data if (currentBoard.auxSerialTxPin) { - if (auxSerial.available() >= 8) { // if at least 8 bytes are available to read from the serial port - int i = 0; - int k = 0; - auxSerialBuffer.len = auxSerial.readBytes(auxSerialBuffer.data, AUX_BUF_SIZE); - // pre-process Peloton Data. If we get more serial devices we will have to move this into sensor data factory. - // This is done here to prevent a lot of extra logging. - for (i = 0; i < auxSerialBuffer.len; i++) { // Find start of data string - if (auxSerialBuffer.data[i] == HEADER) { - for (k = i; k < auxSerialBuffer.len; k++) { // Find end of data string - if (auxSerialBuffer.data[k] == FOOTER) { - k++; - break; - } - } - size_t newLen = k - i; // find length of sub data - uint8_t newBuf[newLen]; - for (int j = i; j < k; j++) { - newBuf[j - i] = auxSerialBuffer.data[j]; - } - collectAndSet(PELOTON_DATA_UUID, PELOTON_DATA_UUID, PELOTON_ADDRESS, newBuf, newLen); - break; - } - } - } - if (PELOTON_TX) { - static bool alternate = false; - if (alternate) { - for (int i = 0; i < PELOTON_RQ_SIZE; i++) { - auxSerial.write(peloton_rq_watts[i]); - } - } else { - for (int i = 0; i < PELOTON_RQ_SIZE; i++) { - auxSerial.write(peloton_rq_cad[i]); - } - } - alternate = !alternate; - } + ss2k.checkSerial(); } loopCounter++; } @@ -439,6 +398,8 @@ void SS2K::setupTMCStepperDriver() { driver.mstep_reg_select(true); uint16_t msread = driver.microsteps(); + // Possibly we should use irun power scaler here instead but there's a note to keep it above 16/31 + uint16_t rmsPwr = ((float)userConfig.getStepperPower() / (float)currentBoard.pwrScaler); SS2K_LOG(MAIN_LOG_TAG, " read:ms=%ud", msread); driver.rms_current(userConfig.getStepperPower()); // Set motor RMS current @@ -499,3 +460,43 @@ void SS2K::motorStop(bool releaseTension) { stepper->moveTo(ss2k.targetPosition - userConfig.getShiftStep() * 4); } } + +void SS2K::checkSerial() { + if (auxSerial.available() >= 8) { // if at least 8 bytes are available to read from the serial port + int i = 0; + int k = 0; + auxSerialBuffer.len = auxSerial.readBytes(auxSerialBuffer.data, AUX_BUF_SIZE); + // pre-process Peloton Data. If we get more serial devices we will have to move this into sensor data factory. + // This is done here to prevent a lot of extra logging. + for (i = 0; i < auxSerialBuffer.len; i++) { // Find start of data string + if (auxSerialBuffer.data[i] == HEADER) { + for (k = i; k < auxSerialBuffer.len; k++) { // Find end of data string + if (auxSerialBuffer.data[k] == FOOTER) { + k++; + break; + } + } + size_t newLen = k - i; // find length of sub data + uint8_t newBuf[newLen]; + for (int j = i; j < k; j++) { + newBuf[j - i] = auxSerialBuffer.data[j]; + } + collectAndSet(PELOTON_DATA_UUID, PELOTON_DATA_UUID, PELOTON_ADDRESS, newBuf, newLen); + break; + } + } + } + if (PELOTON_TX) { + static bool alternate = false; + if (alternate) { + for (int i = 0; i < PELOTON_RQ_SIZE; i++) { + auxSerial.write(peloton_rq_watts[i]); + } + } else { + for (int i = 0; i < PELOTON_RQ_SIZE; i++) { + auxSerial.write(peloton_rq_cad[i]); + } + } + alternate = !alternate; + } +} From c0bb05952c6b10264b1e5038b534f56c8aa78cdb Mon Sep 17 00:00:00 2001 From: doudar Date: Sun, 30 Oct 2022 12:06:03 -0500 Subject: [PATCH 12/17] Added Main Index link to develop.html --- CHANGELOG.md | 1 + data/develop.html | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfa64120..b9ffef4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Peloton serial decoder to sensor factory. - Added blocking for shifts above or below min/max set points. - Added power scaler for new board. +- Added Main Index link to develop.html. ### Changed - PowerTable values are now adjusted to 90 RPM cad on input. diff --git a/data/develop.html b/data/develop.html index 2dddfae2..6fe06ccc 100644 --- a/data/develop.html +++ b/data/develop.html @@ -3,24 +3,28 @@ + html { + background-color: #03245c; + } + SmartSpin2K Web Server -
http://github.com/doudar/SmartSpin2k - -

Developer Tools

-

-

Replay Fit File Over BLE

-

Manual BLE Simulator

-

SmartSpin Debugging Info

-

Update Firmware

-

SS2K Help

-

+
+ http://github.com/doudar/SmartSpin2k + + +

Main Index

+

+

Developer Tools

+

+

Replay Fit File Over BLE

+

Manual BLE Simulator

+

SmartSpin Debugging Info

+

Update Firmware

+

SS2K Help

+