diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..be10e5a --- /dev/null +++ b/.clang-format @@ -0,0 +1,93 @@ +# https://github.com/zephyrproject-rtos/zephyr/blob/main/.clang-format +# SPDX-License-Identifier: Apache-2.0 +# +# Note: The list of ForEachMacros can be obtained using: +# +# git grep -h '^#define [^[:space:]]*FOR_EACH[^[:space:]]*(' include/ \ +# | sed "s,^#define \([^[:space:]]*FOR_EACH[^[:space:]]*\)(.*$, - '\1'," \ +# | sort | uniq +# +# References: +# - https://clang.llvm.org/docs/ClangFormatStyleOptions.html + +--- +BasedOnStyle: LLVM +AlignConsecutiveMacros: AcrossComments +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AttributeMacros: + - __aligned + - __deprecated + - __packed + - __printf_like + - __syscall + - __syscall_always_inline + - __subsystem +BitFieldColonSpacing: After +BreakBeforeBraces: Linux +ColumnLimit: 120 +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +ForEachMacros: + - 'FOR_EACH' + - 'FOR_EACH_FIXED_ARG' + - 'FOR_EACH_IDX' + - 'FOR_EACH_IDX_FIXED_ARG' + - 'FOR_EACH_NONEMPTY_TERM' + - 'RB_FOR_EACH' + - 'RB_FOR_EACH_CONTAINER' + - 'SYS_DLIST_FOR_EACH_CONTAINER' + - 'SYS_DLIST_FOR_EACH_CONTAINER_SAFE' + - 'SYS_DLIST_FOR_EACH_NODE' + - 'SYS_DLIST_FOR_EACH_NODE_SAFE' + - 'SYS_SFLIST_FOR_EACH_CONTAINER' + - 'SYS_SFLIST_FOR_EACH_CONTAINER_SAFE' + - 'SYS_SFLIST_FOR_EACH_NODE' + - 'SYS_SFLIST_FOR_EACH_NODE_SAFE' + - 'SYS_SLIST_FOR_EACH_CONTAINER' + - 'SYS_SLIST_FOR_EACH_CONTAINER_SAFE' + - 'SYS_SLIST_FOR_EACH_NODE' + - 'SYS_SLIST_FOR_EACH_NODE_SAFE' + - '_WAIT_Q_FOR_EACH' + - 'Z_FOR_EACH' + - 'Z_FOR_EACH_ENGINE' + - 'Z_FOR_EACH_EXEC' + - 'Z_FOR_EACH_FIXED_ARG' + - 'Z_FOR_EACH_FIXED_ARG_EXEC' + - 'Z_FOR_EACH_IDX' + - 'Z_FOR_EACH_IDX_EXEC' + - 'Z_FOR_EACH_IDX_FIXED_ARG' + - 'Z_FOR_EACH_IDX_FIXED_ARG_EXEC' + - 'Z_GENLIST_FOR_EACH_CONTAINER' + - 'Z_GENLIST_FOR_EACH_CONTAINER_SAFE' + - 'Z_GENLIST_FOR_EACH_NODE' + - 'Z_GENLIST_FOR_EACH_NODE_SAFE' + - 'STRUCT_SECTION_FOREACH' + - 'TYPE_SECTION_FOREACH' + - 'K_SPINLOCK' +IfMacros: + - 'CHECKIF' +# Disabled for now, see bug https://github.com/zephyrproject-rtos/zephyr/issues/48520 +#IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^".*\.h"$' + Priority: 0 + - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|limits|locale|math|setjmp|signal|stdarg|stdbool|stddef|stdint|stdio|stdlib|string|tgmath|time|wchar|wctype)\.h>$' + Priority: 1 + - Regex: '^\$' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: false +IndentWidth: 8 +InsertBraces: true +SpaceBeforeParens: ControlStatementsExceptControlMacros +SortIncludes: Never +UseTab: ForContinuationAndIndentation +WhitespaceSensitiveMacros: + - STRINGIFY + - Z_STRINGIFY diff --git a/.editorconfig b/.editorconfig index 680d12c..6553cf2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,9 +4,94 @@ root = true [*] -indent_style = space +indent_style = tab indent_size = 8 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +# Assembly +[*.S] +indent_style = tab +indent_size = 8 + +# C +[*.{c,h}] +indent_style = tab +indent_size = 8 + +# C++ +[*.{cpp,hpp}] +indent_style = tab +indent_size = 8 + +# Linker Script +[*.ld] +indent_style = tab +indent_size = 8 + +# Python +[*.py] +indent_style = space +indent_size = 4 + +# Perl +[*.pl] +indent_style = tab +indent_size = 8 + +# reStructuredText +[*.rst] +indent_style = space +indent_size = 3 + +# Markdown +[*.md] +indent_style = space +indent_size = 2 + +# YAML +[*.{yml,yaml}] +indent_style = space +indent_size = 2 + +# Shell Script +[*.sh] +indent_style = space +indent_size = 4 + +# Windows Command Script +[*.cmd] +end_of_line = crlf +indent_style = tab +indent_size = 8 + +# Valgrind Suppression File +[*.supp] +indent_style = space +indent_size = 3 + +# CMake +[{CMakeLists.txt,*.cmake}] +indent_style = space +indent_size = 2 + +# Makefile +[Makefile] +indent_style = tab +indent_size = 8 + +# Device tree +[*.{dts,dtsi,overlay}] +indent_style = tab +indent_size = 8 + +# Kconfig +[Kconfig*] +indent_style = tab +indent_size = 8 + +# Git commit messages +[COMMIT_EDITMSG] +max_line_length = 100 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbe7eb9..ebbd080 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,26 +1,30 @@ name: PlatformIO CI +permissions: read-all + on: - pull_request: - branches: ["main"] + push: + branches: [main] + pull_request: + branches: [main] jobs: - build: - runs-on: ubuntu-latest + build: + runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 - with: - path: | - ~/.cache/pip - ~/.platformio/.cache - key: ${{ runner.os }}-pio - - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - name: Install PlatformIO Core - run: pip install --upgrade platformio + steps: + - uses: actions/checkout@v3 + - uses: actions/cache@v3 + with: + path: | + ~/.cache/pip + ~/.platformio/.cache + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v4 + with: + python-version: "3.9" + - name: Install PlatformIO Core + run: pip install --upgrade platformio - - name: Build PlatformIO Project - run: pio run + - name: Build PlatformIO Project + run: pio run diff --git a/.gitignore b/.gitignore index c72fdc9..1c5475d 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,9 @@ dkms.conf # Executables +### Clangd ### +.cache/ + ### PlatformIO ### .pioenvs .piolibdeps diff --git a/.trunk/.gitignore b/.trunk/.gitignore new file mode 100644 index 0000000..15966d0 --- /dev/null +++ b/.trunk/.gitignore @@ -0,0 +1,9 @@ +*out +*logs +*actions +*notifications +*tools +plugins +user_trunk.yaml +user.yaml +tmp diff --git a/.trunk/configs/.markdownlint.yaml b/.trunk/configs/.markdownlint.yaml new file mode 100644 index 0000000..b40ee9d --- /dev/null +++ b/.trunk/configs/.markdownlint.yaml @@ -0,0 +1,2 @@ +# Prettier friendly markdownlint config (all formatting rules disabled) +extends: markdownlint/style/prettier diff --git a/.trunk/configs/.yamllint.yaml b/.trunk/configs/.yamllint.yaml new file mode 100644 index 0000000..184e251 --- /dev/null +++ b/.trunk/configs/.yamllint.yaml @@ -0,0 +1,7 @@ +rules: + quoted-strings: + required: only-when-needed + extra-allowed: ["{|}"] + key-duplicates: {} + octal-values: + forbid-implicit-octal: true diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml new file mode 100644 index 0000000..02596c5 --- /dev/null +++ b/.trunk/trunk.yaml @@ -0,0 +1,38 @@ +# This file controls the behavior of Trunk: https://docs.trunk.io/cli +# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml +version: 0.1 +cli: + version: 1.22.1 +# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins) +plugins: + sources: + - id: configs + ref: v1.0.4 + uri: https://github.com/trunk-io/configs + - id: trunk + ref: v1.5.0 + uri: https://github.com/trunk-io/plugins +# Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes) +runtimes: + enabled: + - node@18.12.1 + - python@3.10.8 +# This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) +lint: + enabled: + - semgrep@1.72.0 + - clang-format@16.0.3 + - actionlint@1.7.0 + - checkov@3.2.87 + - git-diff-check + - markdownlint@0.40.0 + - prettier@3.2.5 + - trivy@0.51.1 + - trufflehog@3.75.1 + - yamllint@1.35.1 +actions: + enabled: + - trunk-announce + - trunk-check-pre-push + - trunk-fmt-pre-commit + - trunk-upgrade-available diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 080e70d..1028b6c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,10 +1,6 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "platformio.platformio-ide" - ], - "unwantedRecommendations": [ - "ms-vscode.cpptools-extension-pack" - ] + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": ["platformio.platformio-ide"], + "unwantedRecommendations": ["ms-vscode.cpptools-extension-pack"] } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a03710d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "sonarlint.pathToCompileCommands": "${workspaceFolder}/compile_commands.json" +} diff --git a/README.md b/README.md index 3da66a6..238551d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ # SimpleFOC tuning -SimpleFOC auto-tuning example using [SimpleFOC](https://simplefoc.com/) with [B-G431B-ESC1](https://www.st.com/en/evaluation-tools/b-g431b-esc1.html) +SimpleFOC auto-tuning example using [SimpleFOC](https://simplefoc.com/) with +[B-G431B-ESC1](https://www.st.com/en/evaluation-tools/b-g431b-esc1.html) diff --git a/justfile b/justfile new file mode 100644 index 0000000..37ed9f8 --- /dev/null +++ b/justfile @@ -0,0 +1,19 @@ +default: + just --list + +dev: + pio run -t compiledb + +build: + pio run + +fmt: + trunk fmt -a + +check: + trunk check -a + +qa: dev fmt check + +conn: + picocom -b 115200 /dev/ttyACM0 diff --git a/src/main.cpp b/src/main.cpp index ada57e2..3a60482 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,13 +8,22 @@ // FOC classes (motor, driver, current sensor and hall sensor) BLDCMotor motor = BLDCMotor(7); BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL); -LowsideCurrentSense current_sensor = LowsideCurrentSense(0.003f, -64.0f/7.0f, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT); +LowsideCurrentSense current_sensor = LowsideCurrentSense(0.003f, -64.0f / 7.0f, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT); HallSensor hall_sensor = HallSensor(A_HALL1, A_HALL2, A_HALL3, 7); // Interrupt routine initialisation -void doA(){ hall_sensor.handleA(); } -void doB(){ hall_sensor.handleB(); } -void doC(){ hall_sensor.handleC(); } +void doA() +{ + hall_sensor.handleA(); +} +void doB() +{ + hall_sensor.handleB(); +} +void doC() +{ + hall_sensor.handleC(); +} // monitor delay #define MONITOR_DELAY_MS (20) @@ -23,126 +32,136 @@ unsigned long monitor_delay = 0; float target = 0.0f; // instantiate the commander Commander commander = Commander(Serial); -void doMotor(char* cmd) { commander.motor(&motor, cmd); } -void doRadians(char* cmd) { commander.scalar(&target, cmd); }; -void doDegrees(char* cmd) { - float angle_degrees; - commander.scalar(&angle_degrees, cmd); - target = angle_degrees * (PI / 180.0); +void doMotor(char *cmd) +{ + commander.motor(&motor, cmd); +} +void doRadians(char *cmd) +{ + commander.scalar(&target, cmd); +}; +void doDegrees(char *cmd) +{ + float angle_degrees; + commander.scalar(&angle_degrees, cmd); + target = angle_degrees * (PI / 180.0); } -void checkRC(int rc) { - if (rc == 0) { - for(;;) { - SIMPLEFOC_DEBUG("Setup failed."); - SIMPLEFOC_DEBUG("Check motor and sensor connections."); - _delay(1000); - } - } +void checkRC(int rc) +{ + if (rc == 0) { + for (;;) { + SIMPLEFOC_DEBUG("Setup failed."); + SIMPLEFOC_DEBUG("Check motor and sensor connections."); + _delay(1000); + } + } } -void setup() { - int rc = 0; - Serial.begin(115200); - SimpleFOCDebug::enable(&Serial); - - // initialize the hall sensor - hall_sensor.init(); - hall_sensor.enableInterrupts(doA, doB, doC); - // link the hall sensor to the motor - motor.linkSensor(&hall_sensor); - - // initialize the driver - driver.voltage_power_supply = 24.0f; - rc = driver.init(); - checkRC(rc); - SIMPLEFOC_DEBUG("Driver ready."); - // link the current sensor and the driver - current_sensor.linkDriver(&driver); - // link the motor and the driver - motor.linkDriver(&driver); - - // initialize the current sensor - current_sensor.skip_align = true; - rc = current_sensor.init(); - checkRC(rc); - SIMPLEFOC_DEBUG("Current sensor ready."); - // link the current sensor to the motor - motor.linkCurrentSense(¤t_sensor); - - // set motion control loop to be used - motor.controller = MotionControlType::angle; - motor.foc_modulation = FOCModulationType::SpaceVectorPWM; - - // index search velocity [rad/s] - motor.velocity_index_search = 3.0f; - // aligning voltage [V] - motor.voltage_sensor_align = 3.0f; - - // velocity PI controller - motor.PID_velocity.P = 0.2f; - motor.PID_velocity.I = 2.0f; - motor.PID_velocity.D = 0.0f; - motor.PID_velocity.output_ramp = 1000.0f; - motor.LPF_velocity.Tf = 0.05f; - - // angle P controller - motor.P_angle.P = 20.0f; - - // motor limits - motor.voltage_limit = 24.0f; - motor.velocity_limit = 200.0f; - motor.current_limit = 1.0f; - - // motion and monitoring settings - motor.motion_downsample = 0; - motor.monitor_downsample = 1; - - // use monitoring with serial - motor.monitor_separator = '\t'; - motor.monitor_decimals = 2; - motor.monitor_variables = 0b1111111; - motor.useMonitoring(Serial); - - // initialize motor - motor.init(); - // align sensor and start FOC - rc = motor.initFOC(); - checkRC(rc); - SIMPLEFOC_DEBUG("Motor ready."); - - // initialize serial communication - commander.verbose = VerboseMode::user_friendly; - commander.add('M',doMotor,"motor"); - commander.add('R', doRadians, "target [rad]"); - commander.add('D', doDegrees, "target [deg]"); - - SIMPLEFOC_DEBUG("Setup ready."); - SIMPLEFOC_DEBUG("Set the target angle using serial terminal:"); - _delay(1000); - monitor_delay = millis(); +void setup() +{ + int rc = 0; + Serial.begin(115200); + SimpleFOCDebug::enable(&Serial); + + // initialize the hall sensor + hall_sensor.init(); + hall_sensor.enableInterrupts(doA, doB, doC); + // link the hall sensor to the motor + motor.linkSensor(&hall_sensor); + + // initialize the driver + driver.voltage_power_supply = 24.0f; + rc = driver.init(); + checkRC(rc); + SIMPLEFOC_DEBUG("Driver ready."); + // link the current sensor and the driver + current_sensor.linkDriver(&driver); + // link the motor and the driver + motor.linkDriver(&driver); + + // initialize the current sensor + current_sensor.skip_align = true; + rc = current_sensor.init(); + checkRC(rc); + SIMPLEFOC_DEBUG("Current sensor ready."); + // link the current sensor to the motor + motor.linkCurrentSense(¤t_sensor); + + // set motion control loop to be used + motor.controller = MotionControlType::angle; + motor.foc_modulation = FOCModulationType::SpaceVectorPWM; + + // index search velocity [rad/s] + motor.velocity_index_search = 3.0f; + // aligning voltage [V] + motor.voltage_sensor_align = 3.0f; + + // velocity PI controller + motor.PID_velocity.P = 0.2f; + motor.PID_velocity.I = 2.0f; + motor.PID_velocity.D = 0.0f; + motor.PID_velocity.output_ramp = 1000.0f; + motor.LPF_velocity.Tf = 0.05f; + + // angle P controller + motor.P_angle.P = 20.0f; + + // motor limits + motor.voltage_limit = 24.0f; + motor.velocity_limit = 200.0f; + motor.current_limit = 1.0f; + + // motion and monitoring settings + motor.motion_downsample = 0; + motor.monitor_downsample = 1; + + // use monitoring with serial + motor.monitor_separator = '\t'; + motor.monitor_decimals = 2; + motor.monitor_variables = 0b1111111; + motor.useMonitoring(Serial); + + // initialize motor + motor.init(); + // align sensor and start FOC + rc = motor.initFOC(); + checkRC(rc); + SIMPLEFOC_DEBUG("Motor ready."); + + // initialize serial communication + commander.verbose = VerboseMode::user_friendly; + commander.add('M', doMotor, "motor"); + commander.add('R', doRadians, "target [rad]"); + commander.add('D', doDegrees, "target [deg]"); + + SIMPLEFOC_DEBUG("Setup ready."); + SIMPLEFOC_DEBUG("Set the target angle using serial terminal:"); + _delay(1000); + monitor_delay = millis(); } -void loop() { - // main FOC algorithm function - // the faster you run this function the better - // Arduino UNO loop ~1kHz (16 Mhz) - // Bluepill loop ~10kHz (72Mhz) - motor.loopFOC(); - - // Motion control function - // velocity, position or voltage (defined in motor.controller) - // this function can be run at much lower frequency than loopFOC() function - // You can also use motor.move() and set the motor.target in the code - motor.move(target); - - if (millis() - monitor_delay > MONITOR_DELAY_MS) { - monitor_delay = millis(); - // function intended to be used with serial plotter to monitor motor variables - // significantly slowing the execution down!!!! - motor.monitor(); - } - - // user communication - commander.run(); +void loop() +{ + // main FOC algorithm function + // the faster you run this function the better + // Arduino UNO loop ~1kHz (16 Mhz) + // Bluepill loop ~10kHz (72Mhz) + motor.loopFOC(); + + // Motion control function + // velocity, position or voltage (defined in motor.controller) + // this function can be run at much lower frequency than loopFOC() function + // You can also use motor.move() and set the motor.target in the code + motor.move(target); + + if (millis() - monitor_delay > MONITOR_DELAY_MS) { + monitor_delay = millis(); + // function intended to be used with serial plotter to monitor motor + // variables significantly slowing the execution down!!!! + motor.monitor(); + } + + // user communication + commander.run(); }