diff --git a/.DS_Store b/.DS_Store index 57caf520..0c060e8a 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.github/.DS_Store b/.github/.DS_Store index f03f63fc..6c3be0ad 100644 Binary files a/.github/.DS_Store and b/.github/.DS_Store differ diff --git a/.github/workflows/arduino.yml b/.github/workflows/arduino.yml index 41a770b9..e29bafb1 100644 --- a/.github/workflows/arduino.yml +++ b/.github/workflows/arduino.yml @@ -6,16 +6,20 @@ on: # Triggers the workflow on push or pull request events but only for the main branch push: branches: [ main ] - pull_request: - branches: [ main ] + #pull_request: + # branches: [ main ] # This is the list of jobs that will be run concurrently. # Since we use a build matrix, the actual number of jobs # started depends on how many configurations the matrix # will produce. jobs: - # This is the name of the job - can be whatever. - build: + + +######################################################################## +# Build ESP binaries +######################################################################## + buildEspCode: # Here we tell GitHub that the jobs must be determined # dynamically depending on a matrix configuration. strategy: @@ -87,12 +91,6 @@ jobs: - uses: montudor/action-zip@v1 with: args: zip -qq -r ./Arduino/Esp32/bin/esp32_0.zip ./Arduino/Esp32/bin/ - # zip plugin binaries - - uses: montudor/action-zip@v1 - with: - args: zip -qq -r ./SimHubPlugin/bin/SimHub_plugin.zip ./SimHubPlugin/bin/ - - # create a release # see https://www.youtube.com/watch?v=_ueJ3LrRqPU @@ -117,16 +115,133 @@ jobs: asset_path: ./Arduino/Esp32/bin/esp32_0.zip asset_name: esp32_0.zip asset_content_type: application/zip - # SimHub plugin binaries - - name: Upload SimHub release assets - id: upload-release-asset-plugin - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create-new-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./SimHubPlugin/bin/SimHub_plugin.zip - asset_name: SimHub_plugin.zip - asset_content_type: application/zip + + + +######################################################################## +# Build SimHub plugin +######################################################################## + buildSimhubPlugin: + runs-on: windows-2019 + needs: buildEspCode + + steps: + - uses: actions/checkout@v2 + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v1.0.5 + + - name: Setup MS Build Systems + uses: microsoft/setup-msbuild@v1.1 + + - uses: actions/cache@v3 + name: Restore Caches + id: cache + with: + path: | + innounp050.rar + SimHub.8.01.2.zip + key: SimHub.8.01.2 + + - name: Download Requirements # Used to download the SimHub DLLs - only if not in cache. + if: steps.cache.outputs.cache-hit != 'true' + run: | + aria2c -j1 -o innounp050.rar "https://sourceforge.net/projects/innounp/files/innounp/innounp%200.50/innounp050.rar/download" + aria2c -j1 -o SimHub.8.01.2.zip "https://github.com/SHWotever/SimHub/releases/download/8.1.2/SimHub.8.01.2.zip" + + - name: Extract Requirements # Used to extract the SimHub DLLs + run: | + 7z x innounp050.rar + 7z x SimHub.8.01.2.zip + dir + mkdir "C:\Program Files (x86)\SimHub\" + ${{ github.workspace }}\innounp.exe -v -x -b -e -d"C:\Program Files (x86)\SimHub\" SimHubSetup_8.1.2.exe GameReaderCommon.dll SimHub.plugins.dll + ${{ github.workspace }}\innounp.exe -v -x -b -e -d"C:\Program Files (x86)\SimHub\" SimHubSetup_8.1.2.exe + - name: List files in dir + run: | + ls "C:\Program Files (x86)\SimHub\" + + #- name: List files in dir 2 + # run: | + # ls ${{ github.workspace }} + + - name: Restore Packages + run: nuget restore "SimHubPlugin/User.PluginSdkDemo.sln" + + - name: Build solution + run: msbuild "SimHubPlugin/User.PluginSdkDemo.sln" -t:rebuild -property:Configuration=Release + + + + + # zip plugin binaries + - name: ZIP files + run: | + 7z a ./SimHubPlugin/bin/SimHub_plugin.zip ./SimHubPlugin/bin/* + + + #- name: List files in dir 3 + # run: | + # ls ${{ github.workspace }}/SimHubPlugin + #- name: List files in dir 4 + # run: | + # ls ${{ github.workspace }}/SimHubPlugin/bin + + # create a release + # see https://www.youtube.com/watch?v=_ueJ3LrRqPU + #- name: Create Release + # id: create-new-release + # uses: actions/create-release@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # tag_name: ${{ github.run_number }} + # release_name: Release ${{ github.run_number }} + + + # # SimHub plugin binaries + #- name: Upload SimHub release assets + # id: upload-release-asset-plugin + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ steps.create-new-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + # asset_path: ./SimHubPlugin/bin/SimHub_plugin.zip + # asset_name: SimHub_plugin.zip + # asset_content_type: application/zip + + + + # zip plugin binaries + #- uses: montudor/action-zip@v1 + # with: + # args: zip -qq -r ./SimHubPlugin/bin/SimHub_plugin.zip ./SimHubPlugin/bin/ + + + - name: Upload Artifact + uses: ncipollo/release-action@v1 + with: + artifacts: '${{ github.workspace }}\SimHubPlugin\bin\DiyActivePedal.dll' + prerelease: ${{ github.event.inputs.is-pre-release }} + replacesArtifacts: true + allowUpdates: true + name: ${{ github.run_number }} + tag: ${{ github.run_number }} + + # SimHub plugin binaries + #- name: Upload SimHub release assets + # id: upload-release-asset-plugin + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ steps.create-new-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + # asset_path: ./SimHubPlugin/bin/SimHub_plugin.zip + # asset_name: SimHub_plugin.zip + # asset_content_type: application/zip + diff --git a/Arduino/.DS_Store b/Arduino/.DS_Store index 48d8bc25..2d75760b 100644 Binary files a/Arduino/.DS_Store and b/Arduino/.DS_Store differ diff --git a/Arduino/Esp32/Dev/StepperWithLimits.cpp b/Arduino/Esp32/Dev/StepperWithLimits.cpp new file mode 100644 index 00000000..98c0fe2a --- /dev/null +++ b/Arduino/Esp32/Dev/StepperWithLimits.cpp @@ -0,0 +1,340 @@ +#include "StepperWithLimits.h" +#include "RTDebugOutput.h" +#include "Main.h" +#include "matrix.h" + + + +#define STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT 20 +#define MIN_POS_MAX_ENDSTOP STEPS_PER_MOTOR_REVOLUTION * 3 // servo has to drive minimum N steps before it allows the detection of the max endstop + +static const uint8_t LIMIT_TRIGGER_VALUE = LOW; // does endstop trigger high or low +static const int32_t ENDSTOP_MOVEMENT = STEPS_PER_MOTOR_REVOLUTION / 100; // how much to move between trigger checks +static const int32_t ENDSTOP_MOVEMENT_SENSORLESS = ENDSTOP_MOVEMENT * 5; + + +FastAccelStepperEngine& stepperEngine() { + static FastAccelStepperEngine myEngine = FastAccelStepperEngine(); // this is a factory and manager for all stepper instances + + static bool firstTime = true; + if (firstTime) { + myEngine.init(); + firstTime = false; + } + + return myEngine; +} + + + +StepperWithLimits::StepperWithLimits(uint8_t pinStep, uint8_t pinDirection, uint8_t pinMin, uint8_t pinMax) + : _pinMin(pinMin), _pinMax(pinMax) + , _limitMin(0), _limitMax(0) + , _posMin(0), _posMax(0) +{ + + + pinMode(pinMin, INPUT); + pinMode(pinMax, INPUT); + + + _stepper = stepperEngine().stepperConnectToPin(pinStep); + + + + // Stepper Parameters + if (_stepper) { + _stepper->setDirectionPin(pinDirection, MOTOR_INVERT_MOTOR_DIR); + _stepper->setAutoEnable(true); + _stepper->setSpeedInHz(MAXIMUM_STEPPER_SPEED); // steps/s + _stepper->setAcceleration(MAXIMUM_STEPPER_ACCELERATION); // steps/s² + +//#if defined(SUPPORT_ESP32_PULSE_COUNTER) +// _stepper->attachToPulseCounter(1, 0, 0); +//#endif + } +} + + +void StepperWithLimits::findMinMaxSensorless(isv57communication * isv57) +{ + + if (! hasValidStepper()) return; + + // obtain servo states + isv57->readServoStates(); + bool endPosDetected = abs( isv57->servo_current_percent) > STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT; + + + int32_t setPosition = _stepper->getCurrentPosition(); + while(!endPosDetected){ + delay(10); + isv57->readServoStates(); + endPosDetected = abs( isv57->servo_current_percent) > STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT; + + setPosition = setPosition - ENDSTOP_MOVEMENT_SENSORLESS; + _stepper->moveTo(setPosition, true); + + //Serial.print("Min_DetValue: "); + //Serial.println(isv57->servo_current_percent); + } + + // move away from min position to reduce servos current reading + _stepper->forceStop(); + setPosition = setPosition + 5 * ENDSTOP_MOVEMENT_SENSORLESS; + _stepper->moveTo(setPosition, true); + _stepper->forceStopAndNewPosition(0); + _stepper->moveTo(0); + _limitMin = 0; + + // wait N ms to let the endPosDetected become 0 again + //delay(300); + + // read servo states again + //isv57->readServoStates(); + endPosDetected = 0;//abs( isv57->servo_current_percent) > STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT; + + setPosition = _stepper->getCurrentPosition(); + while (!endPosDetected) { + delay(10); + isv57->readServoStates(); + + // only trigger when difference is significant + if (setPosition > MIN_POS_MAX_ENDSTOP) + { + endPosDetected = abs( isv57->servo_current_percent) > STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT; + } + + + setPosition = setPosition + ENDSTOP_MOVEMENT_SENSORLESS; + _stepper->moveTo(setPosition, true); + + //Serial.print("Max_DetValue: "); + //Serial.println(isv57->servo_current_percent); + } + + //_stepper->forceStop(); + //setPosition = setPosition - 5 * ENDSTOP_MOVEMENT; + + _limitMax = _stepper->getCurrentPosition(); + + // reduce speed and accelerartion + _stepper->setSpeedInHz(MAXIMUM_STEPPER_SPEED / 4); + _stepper->setAcceleration(MAXIMUM_STEPPER_ACCELERATION / 4); + + // move to min + _stepper->moveTo(_posMin, true); + + // increase speed and accelerartion + _stepper->setAcceleration(MAXIMUM_STEPPER_ACCELERATION); + _stepper->setSpeedInHz(MAXIMUM_STEPPER_SPEED); + + + + +#if defined(SUPPORT_ESP32_PULSE_COUNTER) + _stepper->clearPulseCounter(); +#endif + + +} + + +void StepperWithLimits::findMinMaxEndstops() { + if (! hasValidStepper()) return; + + int32_t setPosition = _stepper->getCurrentPosition(); + while(! (LIMIT_TRIGGER_VALUE == digitalRead(_pinMin))){ + setPosition = setPosition - ENDSTOP_MOVEMENT; + _stepper->moveTo(setPosition, true); + } + + + _stepper->forceStopAndNewPosition(0); + _stepper->moveTo(0); + _limitMin = 0; + + setPosition = _stepper->getCurrentPosition(); + while(! (LIMIT_TRIGGER_VALUE == digitalRead(_pinMax))){ + setPosition = setPosition + ENDSTOP_MOVEMENT; + _stepper->moveTo(setPosition, true); + } + + _limitMax = _stepper->getCurrentPosition(); + + _stepper->moveTo(_posMin, true); +#if defined(SUPPORT_ESP32_PULSE_COUNTER) + _stepper->clearPulseCounter(); +#endif +} + +void StepperWithLimits::updatePedalMinMaxPos(uint8_t pedalStartPosPct, uint8_t pedalEndPosPct) { + int32_t limitRange = _limitMax - _limitMin; + _posMin = _limitMin + ((limitRange * pedalStartPosPct) / 100); + _posMax = _limitMin + ((limitRange * pedalEndPosPct) / 100); +} + +void StepperWithLimits::refindMinLimit() { + int32_t setPosition = _stepper->getCurrentPosition(); + while(! (LIMIT_TRIGGER_VALUE == digitalRead(_pinMin))){ + setPosition = setPosition - ENDSTOP_MOVEMENT; + _stepper->moveTo(setPosition, true); + } + _stepper->forceStopAndNewPosition(_limitMin); +} + +void StepperWithLimits::refindMinLimitSensorless(isv57communication * isv57) { + + // obtain servo states + isv57->readServoStates(); + bool endPosDetected = abs( isv57->servo_current_percent) > STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT; + + + int32_t setPosition = _stepper->getCurrentPosition(); + while(!endPosDetected){ + delay(10); + isv57->readServoStates(); + endPosDetected = abs( isv57->servo_current_percent) > STEPPER_WITH_LIMITS_SENSORLESS_CURRENT_THRESHOLD_IN_PERCENT; + + setPosition = setPosition - ENDSTOP_MOVEMENT_SENSORLESS; + _stepper->moveTo(setPosition, true); + + //Serial.print("Min_DetValue: "); + //Serial.println(isv57->servo_current_percent); + } + + // move away from min position to reduce servos current reading + _stepper->forceStop(); + setPosition = setPosition + 5 * ENDSTOP_MOVEMENT_SENSORLESS; + _stepper->moveTo(setPosition, true); + _stepper->forceStopAndNewPosition(_limitMin); +} + +void StepperWithLimits::checkLimitsAndResetIfNecessary() { + // in case the stepper loses its position and therefore an endstop is triggered reset position + if (LIMIT_TRIGGER_VALUE == digitalRead(_pinMin)) { + _stepper->forceStopAndNewPosition(_limitMin); + _stepper->moveTo(_posMin, true); + } + if (LIMIT_TRIGGER_VALUE == digitalRead(_pinMax)) { + _stepper->forceStopAndNewPosition(_limitMin); + _stepper->moveTo(_posMax, true); + } +} + +int8_t StepperWithLimits::moveTo(int32_t position, bool blocking) { + return _stepper->moveTo(position, blocking); +} + +int32_t StepperWithLimits::getCurrentPositionSteps() const { + return _stepper->getCurrentPosition() - _posMin; +} + + +double StepperWithLimits::getCurrentPositionFraction() const { + return double(getCurrentPositionSteps()) / getTravelSteps(); +} + +int32_t StepperWithLimits::getTargetPositionSteps() const { + return _stepper->getPositionAfterCommandsCompleted(); +} + + +void StepperWithLimits::printStates() +{ + int32_t currentStepperPos = _stepper->getCurrentPosition(); + int32_t currentStepperVel = _stepper->getCurrentSpeedInUs(); + int32_t currentStepperVel2 = _stepper->getCurrentSpeedInMilliHz(); + + + //Serial.println(currentStepperVel); + + int32_t currentStepperAccel = _stepper->getCurrentAcceleration(); + + static RTDebugOutput rtDebugFilter({ "Pos", "Vel", "Vel2", "Accel"}); + rtDebugFilter.offerData({ currentStepperPos, currentStepperVel, currentStepperVel2, currentStepperAccel}); +} + + +void StepperWithLimits::setSpeed(uint32_t speedInStepsPerSecond) +{ + _stepper->setSpeedInHz(speedInStepsPerSecond); // steps/s +} + +bool StepperWithLimits::isAtMinPos() +{ + + bool isNotRunning = !_stepper->isRunning(); + bool isAtMinPos = getCurrentPositionSteps() == 0; + + return isAtMinPos && isNotRunning; +} +bool StepperWithLimits::correctPos(int32_t posOffset) +{ + // + int32_t stepOffset =(int32_t)constrain(posOffset, -10, 10); + + // correct pos + _stepper->setCurrentPosition(_stepper->getCurrentPosition() + stepOffset); + return 1; +} + + + + + + + +float RLS_lambda = 0.999; /* Forgetting factor */ +Matrix RLS_theta(4,1); /* The variables we want to indentify */ +Matrix RLS_in(4,1); /* Input data */ +Matrix RLS_out(1,1); /* Output data */ +Matrix RLS_gain(4,1); /* RLS gain */ +Matrix RLS_P(4,4); /* Inverse of correction estimation */ +float oldPos_fl32 = 0; +float oldInput_fl32 = 0; +bool rls_has_been_initialized_b = false; +void StepperWithLimits::identifyServo_AR(float newPos_fl32, float newInput_fl32) +{ + // Autoregressive (AR) model: estimation + // see https://www.youtube.com/watch?v=ANFOzqNCK-0 + + // Recursive Least Squares estimation with Arduino + // see https://github.com/pronenewbits/Arduino_AHRS_System/blob/master/ahrs_ekf/ahrs_ekf.ino + + // System: + // y_{k} = theta * y_{k-m} + + // init + if (rls_has_been_initialized_b == false) + { + RLS_in.vSetToZero(); + RLS_theta.vSetToZero(); + RLS_P.vSetIdentity(); + RLS_P = RLS_P * 1000; + rls_has_been_initialized_b = true; + } + + // write new observation to system output variable + RLS_out[0][0] = newPos_fl32; + + // cyclic shift of the model input + // h = [ -y_{k-1} ,-y_{k-2}, u_{k-1}, u_{k-2} ] + RLS_in[3][0] = RLS_in[2][0]; // lag the model input + RLS_in[1][0] = RLS_in[0][0]; // lag the model state + RLS_in[0][0] = -oldPos_fl32; + RLS_in[2][0] = oldInput_fl32; + + oldPos_fl32 = newPos_fl32; + oldInput_fl32 = newInput_fl32; + + // RLS the system parameters + // see https://de.wikipedia.org/wiki/RLS-Algorithmus + float err = (RLS_out - (RLS_in.Transpose() * RLS_theta))[0][0]; + RLS_gain = RLS_P*RLS_in / (RLS_lambda + RLS_in.Transpose()*RLS_P*RLS_in)[0][0]; + RLS_P = (RLS_P - RLS_gain*RLS_in.Transpose()*RLS_P)/RLS_lambda; + RLS_theta = RLS_theta + err*RLS_gain; + + +} + diff --git a/Arduino/Esp32/Main/.DS_Store b/Arduino/Esp32/Main/.DS_Store index 57ac87c1..c6179262 100644 Binary files a/Arduino/Esp32/Main/.DS_Store and b/Arduino/Esp32/Main/.DS_Store differ diff --git a/Arduino/Esp32/Main/DiyActivePedal_types.cpp b/Arduino/Esp32/Main/DiyActivePedal_types.cpp index b430eebf..f6368a59 100644 --- a/Arduino/Esp32/Main/DiyActivePedal_types.cpp +++ b/Arduino/Esp32/Main/DiyActivePedal_types.cpp @@ -61,6 +61,8 @@ void DAP_config_st::initialiseDefaults() { payLoadPedalConfig_.kf_modelNoise = 128; payLoadPedalConfig_.debug_flags_0 = 0; + + payLoadPedalConfig_.loadcell_rating = 150; } diff --git a/Arduino/Esp32/Main/DiyActivePedal_types.h b/Arduino/Esp32/Main/DiyActivePedal_types.h index 9431b27e..186bc830 100644 --- a/Arduino/Esp32/Main/DiyActivePedal_types.h +++ b/Arduino/Esp32/Main/DiyActivePedal_types.h @@ -3,7 +3,7 @@ #include -#define DAP_VERSION_CONFIG 109 +#define DAP_VERSION_CONFIG 110 #define DAP_PAYLOAD_TYPE_CONFIG 100 struct payloadHeader { @@ -81,6 +81,9 @@ struct payloadPedalConfig { // debug flags, sued to enable debug output uint8_t debug_flags_0; + + // loadcell rating in kg / 2 --> to get value in kg, muiltiply by 2 + uint8_t loadcell_rating; }; struct payloadFooter { diff --git a/Arduino/Esp32/Main/LoadCell.cpp b/Arduino/Esp32/Main/LoadCell.cpp index a1f5596b..942766cb 100644 --- a/Arduino/Esp32/Main/LoadCell.cpp +++ b/Arduino/Esp32/Main/LoadCell.cpp @@ -46,6 +46,24 @@ ADS1256& ADC() { return adc; } + +void LoadCell_ADS1256::setLoadcellRating(uint8_t loadcellRating_u8) const { + ADS1256& adc = ADC(); + double originalConversionFactor_f64 = CONVERSION_FACTOR; + double updatedConversionFactor_f64 = 2 * ((double)loadcellRating_u8) * (CONVERSION_FACTOR/LOADCELL_WEIGHT_RATING_KG); + + Serial.print("OrigConversionFactor: "); + Serial.print(originalConversionFactor_f64); + Serial.print(", NewConversionFactor:"); + Serial.println(updatedConversionFactor_f64); + + + adc.setConversionFactor( updatedConversionFactor_f64 ); +} + + + + LoadCell_ADS1256::LoadCell_ADS1256(uint8_t channel0, uint8_t channel1) : _zeroPoint(0.0), _varianceEstimate(DEFAULT_VARIANCE_ESTIMATE) { diff --git a/Arduino/Esp32/Main/LoadCell.h b/Arduino/Esp32/Main/LoadCell.h index 84a145ad..5e010ae7 100644 --- a/Arduino/Esp32/Main/LoadCell.h +++ b/Arduino/Esp32/Main/LoadCell.h @@ -12,6 +12,7 @@ class LoadCell_ADS1256 { public: LoadCell_ADS1256(uint8_t channel0=0, uint8_t channel1=1); float getReadingKg() const; + void setLoadcellRating(uint8_t loadcellRating_u8) const; public: void setZeroPoint(); diff --git a/Arduino/Esp32/Main/Main.ino b/Arduino/Esp32/Main/Main.ino index ee09044b..3924aba6 100644 --- a/Arduino/Esp32/Main/Main.ino +++ b/Arduino/Esp32/Main/Main.ino @@ -232,11 +232,21 @@ void setup() #endif + // Load config from EEPROM, if valid, overwrite initial config + EEPROM.begin(sizeof(DAP_config_st)); + dap_config_st.loadConfigFromEprom(dap_config_st); + + // interprete config values + dap_calculationVariables_st.updateFromConfig(dap_config_st); + + stepper = new StepperWithLimits(stepPinStepper, dirPinStepper, minPin, maxPin); loadcell = new LoadCell_ADS1256(); + loadcell->setLoadcellRating(dap_config_st.payLoadPedalConfig_.loadcell_rating); + loadcell->setZeroPoint(); #ifdef ESTIMATE_LOADCELL_VARIANCE loadcell->estimateVariance(); // automatically identify sensor noise for KF parameterization @@ -281,12 +291,7 @@ void setup() dap_config_st.initialiseDefaults_Accelerator(); #endif - // Load config from EEPROM, if valid, overwrite initial config - EEPROM.begin(sizeof(DAP_config_st)); - dap_config_st.loadConfigFromEprom(dap_config_st); - - // interprete config values - dap_calculationVariables_st.updateFromConfig(dap_config_st); + // activate parameter update in first cycle configUpdateAvailable = true; diff --git a/Arduino/libs/.DS_Store b/Arduino/libs/.DS_Store index 9cebcc00..20cdc8ed 100644 Binary files a/Arduino/libs/.DS_Store and b/Arduino/libs/.DS_Store differ diff --git a/Arduino/libs/Copy/.DS_Store b/Arduino/libs/Copy/.DS_Store new file mode 100644 index 00000000..9d5e4ee3 Binary files /dev/null and b/Arduino/libs/Copy/.DS_Store differ diff --git a/Arduino/libs/Copy/NimBLE-Arduino/.DS_Store b/Arduino/libs/Copy/NimBLE-Arduino/.DS_Store index 1de27d4f..a0bc459a 100644 Binary files a/Arduino/libs/Copy/NimBLE-Arduino/.DS_Store and b/Arduino/libs/Copy/NimBLE-Arduino/.DS_Store differ diff --git a/README.md b/README.md index 936d991a..8d9d719a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ A [Discord](https://discord.gg/j8QhD5hCv7) server has been created to allow join ## Electronics ## Control PCB -The embedded code of this DIY FFB pedal runs on an ESP32 microcontroller. The PCB design was developed to prove the concept. It holds the ESP32, the ADC, a level shifter, and connectors. Currently, version 3 of this PCB design is used which introduced sensorless homing of the servo. The PCB design and pinout diagram can be found [here](Wiring/Esp32_V3). +The embedded code of this DIY FFB pedal runs on an ESP32 microcontroller. The PCB design was developed to prove the concept. It holds the ESP32, the ADC, a level shifter, and connectors. Currently, version 3 of this PCB design is used which introduced sensorless homing of the servo. The PCB design and pinout diagram can be found [here](Wiring/Esp32_V3). If you use Simucube wheelbase, you can use the D15 accessory port for input, detail was list [here](Wiring/PCB_analog_output) Here is an image of the plain PCB: ![](Wiring/Esp32_V3/PCB_empty.jpeg) @@ -141,7 +141,7 @@ With the current [PCB](Wiring/Esp32_V3) design, the ESP can directly communicate ## SimHub plugin: The SimHub plugin was designed to communicate with the ESP to (a) modify the pedal configuration, e.g. the force vs. travel parameterization and (b) to trigger effects such as ABS oscillations. -![image](SimHubPlugin/Images/SimHubPluginOverview.png) +![image](SimHubPlugin/Images/Plugin-UI.png) To install the plugin, the plugin [binaries](https://github.com/ChrGri/DIY-Sim-Racing-FFB-Pedal/releases), hidden inside the SimHub_plugin.zip, have to be copied to the SimHub directory, e.g. C:/Program Files (x86)/SimHub diff --git a/SimHubPlugin/.DS_Store b/SimHubPlugin/.DS_Store index 4b9581db..8c98c133 100644 Binary files a/SimHubPlugin/.DS_Store and b/SimHubPlugin/.DS_Store differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/78a7b9ee-1969-4ba4-9423-e2c07ded9982.vsidx b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/15e5081a-2b86-4f45-befc-f6646a32af55.vsidx similarity index 82% rename from SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/78a7b9ee-1969-4ba4-9423-e2c07ded9982.vsidx rename to SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/15e5081a-2b86-4f45-befc-f6646a32af55.vsidx index 6fd0d8a1..06e25ff3 100644 Binary files a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/78a7b9ee-1969-4ba4-9423-e2c07ded9982.vsidx and b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/15e5081a-2b86-4f45-befc-f6646a32af55.vsidx differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/545dd721-bb62-4efb-9b0b-d0be8779a9ac.vsidx b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/4afd16f6-6c0d-477f-b539-ceef1f7b5f45.vsidx similarity index 97% rename from SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/545dd721-bb62-4efb-9b0b-d0be8779a9ac.vsidx rename to SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/4afd16f6-6c0d-477f-b539-ceef1f7b5f45.vsidx index 9327b6bc..1c965b48 100644 Binary files a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/545dd721-bb62-4efb-9b0b-d0be8779a9ac.vsidx and b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/4afd16f6-6c0d-477f-b539-ceef1f7b5f45.vsidx differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/966b2fe9-ebb5-4518-8dad-03c2ab19cee2.vsidx b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/966b2fe9-ebb5-4518-8dad-03c2ab19cee2.vsidx new file mode 100644 index 00000000..b5452d62 Binary files /dev/null and b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/966b2fe9-ebb5-4518-8dad-03c2ab19cee2.vsidx differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/cea315ce-364c-411d-8c94-272ea34c6fc0.vsidx b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/cea315ce-364c-411d-8c94-272ea34c6fc0.vsidx deleted file mode 100644 index 11ed7dda..00000000 Binary files a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/cea315ce-364c-411d-8c94-272ea34c6fc0.vsidx and /dev/null differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/d325bed1-ef52-4c32-8a1c-fed9739da9bb.vsidx b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/d325bed1-ef52-4c32-8a1c-fed9739da9bb.vsidx new file mode 100644 index 00000000..7121d3b4 Binary files /dev/null and b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/d325bed1-ef52-4c32-8a1c-fed9739da9bb.vsidx differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/e73c4047-d36c-43fe-8e15-7f7339595b55.vsidx b/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/e73c4047-d36c-43fe-8e15-7f7339595b55.vsidx deleted file mode 100644 index c38cbb5f..00000000 Binary files a/SimHubPlugin/.vs/User.PluginSdkDemo/FileContentIndex/e73c4047-d36c-43fe-8e15-7f7339595b55.vsidx and /dev/null differ diff --git a/SimHubPlugin/.vs/User.PluginSdkDemo/v17/.suo b/SimHubPlugin/.vs/User.PluginSdkDemo/v17/.suo index ba4dcfae..8dafa966 100644 Binary files a/SimHubPlugin/.vs/User.PluginSdkDemo/v17/.suo and b/SimHubPlugin/.vs/User.PluginSdkDemo/v17/.suo differ diff --git a/SimHubPlugin/DataPluginDemo.cs b/SimHubPlugin/DataPluginDemo.cs index 6d367d68..7cf05dcc 100644 --- a/SimHubPlugin/DataPluginDemo.cs +++ b/SimHubPlugin/DataPluginDemo.cs @@ -106,6 +106,9 @@ public struct payloadPedalConfig // debug flags, sued to enable debug output public byte debug_flags_0; + // loadcell rating in kg / 2 --> to get value in kg, muiltiply by 2 + public byte loadcell_rating; + } @@ -471,7 +474,7 @@ public void Init(PluginManager pluginManager) dap_config_initial_st.payloadHeader_.payloadType = 100; - dap_config_initial_st.payloadHeader_.version = 109; + dap_config_initial_st.payloadHeader_.version = 110; dap_config_initial_st.payloadHeader_.storeToEeprom = 0; dap_config_initial_st.payloadPedalConfig_.pedalStartPosition = 35; dap_config_initial_st.payloadPedalConfig_.pedalEndPosition = 80; @@ -514,6 +517,8 @@ public void Init(PluginManager pluginManager) dap_config_initial_st.payloadPedalConfig_.control_strategy_b = 0; + dap_config_initial_st.payloadPedalConfig_.loadcell_rating = 150; + } } diff --git a/SimHubPlugin/Images/Plugin-UI.png b/SimHubPlugin/Images/Plugin-UI.png new file mode 100644 index 00000000..7e1bc447 Binary files /dev/null and b/SimHubPlugin/Images/Plugin-UI.png differ diff --git a/SimHubPlugin/SettingsControlDemo.xaml b/SimHubPlugin/SettingsControlDemo.xaml index 4e5f347c..89d8a57a 100644 --- a/SimHubPlugin/SettingsControlDemo.xaml +++ b/SimHubPlugin/SettingsControlDemo.xaml @@ -1,79 +1,80 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - Update serial port list + Update serial port list - Connect to Pedal + Connect to Pedal - + - Reset pedal position - Send config to pedal - Read config from pedal + Reset pedal position + Send config to pedal + Read config from pedal - open config from JSON + + - + - - - - Serial monitor update - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + Serial monitor update + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + Margin="385,9,0,0" + Text="Force curve adjustment:" + Grid.Row="1" + Width="160" + Foreground="White" Grid.ColumnSpan="2" FontFamily="Arial"/> + + + + + + + + + + + + + + + + + + + System identification + + + + + + + + + + + + + + + + + + +